diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer-database.element.ts b/src/Umbraco.Web.UI.Client/src/installer/installer-database.element.ts index da3f1e8f5b..a40adc1cfd 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/installer-database.element.ts +++ b/src/Umbraco.Web.UI.Client/src/installer/installer-database.element.ts @@ -1,7 +1,8 @@ import { css, CSSResultGroup, html, LitElement } from 'lit'; -import { customElement, state } from 'lit/decorators.js'; +import { customElement, property, state } from 'lit/decorators.js'; +import { UUIBooleanInputEvent, UUISelectElement } from '@umbraco-ui/uui'; +import { PostInstallRequest, UmbracoInstallerDatabaseModel } from '../models'; -import { UUISelectElement } from '@umbraco-ui/uui'; @customElement('umb-installer-database') export class UmbInstallerDatabase extends LitElement { static styles: CSSResultGroup = [ @@ -34,14 +35,29 @@ export class UmbInstallerDatabase extends LitElement { `, ]; - options = [ - { name: 'SQLite', value: 'sqlite', selected: true }, - { name: 'Microsoft SQL Server', value: 'msqls' }, - { name: 'Custom connection string', value: 'custom' }, - ]; + @property({ attribute: false }) + public get databases(): UmbracoInstallerDatabaseModel[] | undefined { + return this._databases; + } + public set databases(value: UmbracoInstallerDatabaseModel[] | undefined) { + const oldValue = value; + this._databases = value; + this._options = value?.map((x, i) => ({ name: x.displayName, value: x.id, selected: i === 0 })); + this._selectedDatabase = value?.[0]; + this.requestUpdate('databases', oldValue); + } @state() - databaseType = 'sqlite'; + private _options?: { name: string; value: string }[]; + + @state() + private _databases?: UmbracoInstallerDatabaseModel[] = []; + + @state() + private _selectedDatabase?: UmbracoInstallerDatabaseModel; + + @state() + private _useIntegratedAuthentication = false; // Used to hide credentials when integrated authentication is selected private _handleSubmit = (e: SubmitEvent) => { e.preventDefault(); @@ -52,37 +68,54 @@ export class UmbInstallerDatabase extends LitElement { const isValid = form.checkValidity(); if (!isValid) return; - const formData = new FormData(form); + const database: Record = {}; - this.dispatchEvent(new CustomEvent('install', { bubbles: true, composed: true })); + const formData = new FormData(form); + for (const pair of formData.entries()) { + database[pair[0]] = pair[1]; + } + + this.dispatchEvent(new CustomEvent('submit', { detail: { database } })); }; private _onBack() { - this.dispatchEvent(new CustomEvent('user', { bubbles: true, composed: true })); + this.dispatchEvent(new CustomEvent('previous', { bubbles: true, composed: true })); } private _renderSettings() { - switch (this.databaseType) { - case 'msqls': - return this._renderSqlServer(); - case 'sqlite': - return this._renderSQLite(); - default: - return this._renderCustom(); + if (!this._selectedDatabase) return; + + if (this._selectedDatabase.providerName === 'Microsoft.Data.SQLite') { + return this._renderSQLite(); } + + if (this._selectedDatabase.providerName === null) { + return this._renderCustom(); + } + + const result = []; + + if (this._selectedDatabase.requiresServer) { + result.push(this._renderServer()); + } + if (this._selectedDatabase.requiresCredentials) { + result.push(this._renderCredentials()); + } + + return result; } private _renderSQLite = () => html` Database file name `; - private _renderSqlServer = () => html` + private _renderServer = () => html`

Connection


@@ -91,7 +124,7 @@ export class UmbInstallerDatabase extends LitElement { type="text" id="server" name="server" - placeholder="(local)SQLEXPRESS" + .placeholder=${this._selectedDatabase?.serverPlaceholder || ''} required required-message="Server is required"> @@ -100,29 +133,48 @@ export class UmbInstallerDatabase extends LitElement { + `; + + private _renderCredentials = () => html`

Credentials


- Use integrated authentication - - - Username - + (this._useIntegratedAuthentication = e.target.checked)} + .checked=${this._useIntegratedAuthentication} + >Use integrated authentication - - Password - - + ${!this._useIntegratedAuthentication + ? html` + Username + + + + + Password + + ` + : ''} `; private _renderCustom = () => html` @@ -131,14 +183,14 @@ export class UmbInstallerDatabase extends LitElement { `; private _handleDatabaseTypeChange = (e: CustomEvent) => { - this.databaseType = (e.target as UUISelectElement).value.toString(); + this._selectedDatabase = this.databases?.find((db) => db.id === (e.target as UUISelectElement).value); }; render() { @@ -148,7 +200,11 @@ export class UmbInstallerDatabase extends LitElement {
Database type - + ${this._renderSettings()} diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer-user.element.ts b/src/Umbraco.Web.UI.Client/src/installer/installer-user.element.ts index 611531fe85..4bbc979476 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/installer-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/installer/installer-user.element.ts @@ -1,7 +1,6 @@ import { css, CSSResultGroup, html, LitElement } from 'lit'; -import { customElement } from 'lit/decorators.js'; - -import { postInstall } from '../api/fetcher'; +import { customElement, property } from 'lit/decorators.js'; +import { PostInstallRequest, UmbracoInstallerUserModel } from '../models'; @customElement('umb-installer-user') export class UmbInstallerUser extends LitElement { @@ -33,6 +32,12 @@ export class UmbInstallerUser extends LitElement { `, ]; + @property({ attribute: false }) + public userModel?: UmbracoInstallerUserModel; //TODO: Use this to validate the form + + @property({ attribute: false }) + public data?: PostInstallRequest; + private _handleSubmit = (e: SubmitEvent) => { e.preventDefault(); @@ -42,58 +47,42 @@ export class UmbInstallerUser extends LitElement { const isValid = form.checkValidity(); if (!isValid) return; + const user: Record = {}; + const formData = new FormData(form); + for (const pair of formData.entries()) { + user[pair[0]] = pair[1]; + } - const name = formData.get('name') as string; - const email = formData.get('email') as string; - const password = formData.get('password') as string; - const news = formData.has('news'); - - this._next(name, email, password, news); + this.dispatchEvent(new CustomEvent('submit', { detail: user })); }; - private async _next(name: string, email: string, password: string, subscribeToNewsletter: boolean) { - console.log('Next', name, email, password, subscribeToNewsletter); - - try { - await postInstall({ - name, - email, - password, - telemetryLevel: 'Basic', - subscribeToNewsletter, - database: { - connectionString: '', - databaseProviderMetadataId: '1', - integratedAuth: false, - providerName: 'SQLite', - }, - }); - - // TODO: Change to redirect when router has been added. - this.dispatchEvent(new CustomEvent('database', { bubbles: true, composed: true })); - } catch (error) { - console.log(error); - } - } - - private _onCustomize() { - this.dispatchEvent(new CustomEvent('customize', { bubbles: true, composed: true })); - } - render() { + console.log('data?', this.data); return html`

Install Umbraco

Name - + Email - + @@ -101,12 +90,16 @@ export class UmbInstallerUser extends LitElement { - + Keep me updated on Umbraco Versions, Security Bulletins and Community News diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer.element.ts b/src/Umbraco.Web.UI.Client/src/installer/installer.element.ts index 2f0efa2a0f..d71e2b0e02 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/installer.element.ts +++ b/src/Umbraco.Web.UI.Client/src/installer/installer.element.ts @@ -6,54 +6,82 @@ import './installer-user.element'; import { css, CSSResultGroup, html, LitElement } from 'lit'; import { customElement, state } from 'lit/decorators.js'; -import { getInstall } from '../api/fetcher'; +import { getInstall, postInstall } from '../api/fetcher'; +import { PostInstallRequest, UmbracoInstaller } from '../models'; @customElement('umb-installer') export class UmbInstaller extends LitElement { static styles: CSSResultGroup = [css``]; @state() - step = 2; + step = 1; @state() user = {}; @state() - database = {}; + data?: PostInstallRequest; + + private _handleSubmit(e: CustomEvent) { + this.data = { ...this.data, ...e.detail }; + this._goToNextStep(); + console.log('data', this.data); + } + + @state() + installerSettings?: UmbracoInstaller; private _renderSection() { switch (this.step) { case 2: - return html``; + return html``; case 3: return html``; default: - return html``; + return html``; } } connectedCallback(): void { super.connectedCallback(); - this.addEventListener('install', () => this._handleInstall()); - this.addEventListener('database', () => this._handleDatabase()); - this.addEventListener('user', () => this._handleUser()); + this.addEventListener('next', () => this._goToNextStep()); + this.addEventListener('previous', () => this._goToPreviousStep()); getInstall({}).then(({ data }) => { - console.log('install data', data); + this.installerSettings = data; + console.log('Install data response', data); }); } - private _handleUser() { - this.step = 1; + private _goToNextStep() { + //TODO: Fix with router + if (this.step === 2) { + if (this.data) { + this._postInstall(this.data); + } + } else { + this.step++; + } } - private _handleDatabase() { - this.step = 2; + private _goToPreviousStep() { + this.step--; } - private _handleInstall() { - this.step = 3; + private async _postInstall(data: PostInstallRequest) { + try { + await postInstall(data); + this.step = 3; //TODO: Fix with router + } catch (error) { + console.log(error); + } } render() {