From 0f66e490f899a847b4ffc76001d714a44c9e7dbd Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 16 Feb 2023 15:22:08 +0100 Subject: [PATCH] abstract culture selection into its own component --- .../edit-language-workspace-view.element.ts | 84 +++++------------ .../src/backoffice/shared/components/index.ts | 1 + .../input-culture-select.element.ts | 90 +++++++++++++++++++ 3 files changed, 113 insertions(+), 62 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-culture-select/input-culture-select.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/edit-language-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/edit-language-workspace-view.element.ts index 1671dddcd7..7c5bd3e7f2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/edit-language-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/edit-language-workspace-view.element.ts @@ -5,9 +5,10 @@ import { repeat } from 'lit/directives/repeat.js'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; import { UmbLanguageWorkspaceContext } from '../../language-workspace.context'; -import { UmbCultureRepository } from '../../../../../cultures/repository/culture.repository'; import { UmbLitElement } from '@umbraco-cms/element'; -import { CultureModel, LanguageModel } from '@umbraco-cms/backend-api'; +import { LanguageModel } from '@umbraco-cms/backend-api'; +import { UmbChangeEvent } from 'src/core/events'; +import UmbInputCultureSelectElement from 'src/backoffice/shared/components/input-culture-select/input-culture-select.element'; @customElement('umb-edit-language-workspace-view') export class UmbEditLanguageWorkspaceViewElement extends UmbLitElement { @@ -51,17 +52,10 @@ export class UmbEditLanguageWorkspaceViewElement extends UmbLitElement { @state() private _languages: LanguageModel[] = []; - @state() - private _cultures: CultureModel[] = []; - - @state() - private _search = ''; - @state() private _startData: LanguageModel | null = null; #languageWorkspaceContext?: UmbLanguageWorkspaceContext; - #cultureRepository = new UmbCultureRepository(this); constructor() { super(); @@ -75,29 +69,13 @@ export class UmbEditLanguageWorkspaceViewElement extends UmbLitElement { }); } - protected async firstUpdated() { - const { data } = await this.#cultureRepository.requestCultures(); - if (data) { - this._cultures = data.items; - } - } - - #handleLanguageChange(event: Event) { - if (event instanceof UUIComboboxEvent) { - const target = event.composedPath()[0] as UUIComboboxElement; + #handleCultureChange(event: Event) { + if (event instanceof UmbChangeEvent) { + const target = event.target as UmbInputCultureSelectElement; const isoCode = target.value.toString(); + const cultureName = target.selectedCultureName; - if (isoCode) { - this.#languageWorkspaceContext?.setCulture(isoCode); - - // If the language name is not set, we set it to the name of the selected language. - if (!this.language?.name) { - const culture = this._cultures.find((culture) => culture.name === isoCode); - if (culture && culture.englishName) { - this.#languageWorkspaceContext?.setName(culture.englishName); - } - } - } else { + if (!isoCode) { // If the isoCode is empty, we reset the value to the original value. // Provides a way better UX //TODO: Maybe the combobox should implement something similar? @@ -107,15 +85,18 @@ export class UmbEditLanguageWorkspaceViewElement extends UmbLitElement { target.addEventListener('close', resetFunction, { once: true }); target.addEventListener('blur', resetFunction, { once: true }); + return; + } + + this.#languageWorkspaceContext?.setCulture(isoCode); + + // If the language name is not set, we set it to the name of the selected language. + if (!this.language?.name && cultureName) { + this.#languageWorkspaceContext?.setName(cultureName); } } } - #handleSearchChange(event: Event) { - const target = event.composedPath()[0] as UUIComboboxElement; - this._search = target.search; - } - #handleDefaultChange(event: UUIBooleanInputEvent) { if (event instanceof UUIBooleanInputEvent) { const target = event.composedPath()[0] as UUIToggleElement; @@ -137,12 +118,6 @@ export class UmbEditLanguageWorkspaceViewElement extends UmbLitElement { } } - get #filteredCultures(): Array { - return this._cultures.filter((culture) => { - return culture.englishName?.toLowerCase().includes(this._search.toLowerCase()); - }); - } - get #fallbackLanguages() { return this._languages.filter((language) => { return language.isoCode !== this.language?.isoCode; @@ -153,10 +128,6 @@ export class UmbEditLanguageWorkspaceViewElement extends UmbLitElement { return this.#fallbackLanguages.find((language) => language.isoCode === this.language?.fallbackIsoCode); } - get #fromAvailableCultures() { - return this._cultures.find((culture) => culture.name === this.language?.isoCode); - } - #renderCultureWarning() { if (!this._startData?.isoCode || this._startData?.isoCode === this.language?.isoCode) return nothing; @@ -181,29 +152,17 @@ export class UmbEditLanguageWorkspaceViewElement extends UmbLitElement {
- - - ${repeat( - this.#filteredCultures, - (language) => language.name, - (language) => - html` - ${language.englishName} - ` - )} - - + ${this.#renderCultureWarning()}
+
${this.language.isoCode}
+
+ diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts index 565fd6e060..6b46d30149 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/index.ts @@ -28,6 +28,7 @@ import '../entity-actions/entity-action-list.element'; import './input-media-picker/input-media-picker.element'; import './input-document-picker/input-document-picker.element'; +import './input-culture-select/input-culture-select.element'; import './empty-state/empty-state.element'; import './color-picker/color-picker.element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-culture-select/input-culture-select.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-culture-select/input-culture-select.element.ts new file mode 100644 index 0000000000..d6fbf4da05 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/shared/components/input-culture-select/input-culture-select.element.ts @@ -0,0 +1,90 @@ +import { css, html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, state } from 'lit/decorators.js'; +import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins'; +import { ifDefined } from 'lit-html/directives/if-defined.js'; +import { repeat } from 'lit/directives/repeat.js'; +import { UUIComboboxElement } from '@umbraco-ui/uui'; +import { UmbCultureRepository } from '../../../settings/cultures/repository/culture.repository'; +import { UmbLitElement } from '@umbraco-cms/element'; +import { CultureModel } from '@umbraco-cms/backend-api'; +import { UmbChangeEvent } from 'src/core/events'; + +@customElement('umb-input-culture-select') +export class UmbInputCultureSelectElement extends FormControlMixin(UmbLitElement) { + static styles = [UUITextStyles, css``]; + + @state() + private _cultures: CultureModel[] = []; + + @state() + private _search = ''; + + public selectedCultureName?: string; + + #cultureRepository = new UmbCultureRepository(this); + + protected getFormElement() { + return undefined; + } + + protected async firstUpdated() { + const { data } = await this.#cultureRepository.requestCultures(); + if (data) { + this._cultures = data.items; + } + } + + #onSearchChange(event: Event) { + event.stopPropagation(); + const target = event.composedPath()[0] as UUIComboboxElement; + this._search = target.search; + } + + #onCultureChange(event: Event) { + event.stopPropagation(); + const target = event.composedPath()[0] as UUIComboboxElement; + this._value = target.value; + const culture = this._cultures.find((culture) => culture.name === this._value); + this.selectedCultureName = culture?.englishName; + this.dispatchEvent(new UmbChangeEvent()); + } + + get #filteredCultures(): Array { + return this._cultures.filter((culture) => { + return culture.englishName?.toLowerCase().includes(this._search.toLowerCase()); + }); + } + + get #fromAvailableCultures() { + return this._cultures.find((culture) => culture.name === this.value); + } + + render() { + return html` + + ${repeat( + this.#filteredCultures, + (culture) => culture.name, + (culture) => + html` + ${culture.englishName} + ` + )} + + `; + } +} + +export default UmbInputCultureSelectElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-input-culture-select': UmbInputCultureSelectElement; + } +}