diff --git a/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts b/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts index 04f2894b39..7715d5a61e 100644 --- a/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/libs/repository/repository-detail-data-source.interface.ts @@ -5,5 +5,5 @@ export interface RepositoryDetailDataSource { get(key: string): Promise>; insert(data: DetailType): Promise>; update(data: DetailType): Promise>; - trash(key: string): Promise>; + delete(key: string): Promise>; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index dae0f7ba21..53474073fb 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -38,7 +38,7 @@ import { UmbDataTypeTreeStore } from './settings/data-types/repository/data-type import { UmbTemplateTreeStore } from './templating/templates/tree/data/template.tree.store'; import { UmbTemplateDetailStore } from './templating/templates/workspace/data/template.detail.store'; import { UmbThemeContext } from './themes/theme.context'; -import { UmbLanguageStore } from './settings/languages/language.store'; +import { UmbLanguageStore } from './settings/languages/repository/language.store'; import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification'; import '@umbraco-cms/router'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/index.ts new file mode 100644 index 0000000000..c7cc44fc92 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/repository/sources/index.ts @@ -0,0 +1,7 @@ +import { DocumentModel } from '@umbraco-cms/backend-api'; +import type { DataSourceResponse } from '@umbraco-cms/models'; +import { RepositoryDetailDataSource } from '@umbraco-cms/repository'; + +export interface UmbDocumentDataSource extends RepositoryDetailDataSource { + trash(key: string): Promise>; +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/manifests.ts new file mode 100644 index 0000000000..2bd802ce9c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/manifests.ts @@ -0,0 +1,3 @@ +import { manifests as repositoryManifests } from './repository/manifests'; + +export const manifests = [...repositoryManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/culture.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/culture.repository.ts new file mode 100644 index 0000000000..abdd4e6e72 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/culture.repository.ts @@ -0,0 +1,29 @@ +import { UmbCultureServerDataSource } from './sources/culture.server.data'; +import { UmbControllerHostInterface } from '@umbraco-cms/controller'; +import { UmbContextConsumerController } from '@umbraco-cms/context-api'; +import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification'; + +export class UmbCultureRepository { + #init!: Promise; + #host: UmbControllerHostInterface; + + #dataSource: UmbCultureServerDataSource; + + #notificationService?: UmbNotificationService; + + constructor(host: UmbControllerHostInterface) { + this.#host = host; + + this.#dataSource = new UmbCultureServerDataSource(this.#host); + + this.#init = Promise.all([ + new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN, (instance) => { + this.#notificationService = instance; + }), + ]); + } + + requestCultures({ skip, take } = { skip: 0, take: 1000 }) { + return this.#dataSource.getCollection({ skip, take }); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/manifests.ts new file mode 100644 index 0000000000..0bc2ae18bd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/manifests.ts @@ -0,0 +1,13 @@ +import { UmbCultureRepository } from '../repository/culture.repository'; +import { ManifestRepository } from 'libs/extensions-registry/repository.models'; + +export const CULTURE_REPOSITORY_ALIAS = 'Umb.Repository.Cultures'; + +const repository: ManifestRepository = { + type: 'repository', + alias: CULTURE_REPOSITORY_ALIAS, + name: 'Cultures Repository', + class: UmbCultureRepository, +}; + +export const manifests = [repository]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/sources/culture.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/sources/culture.server.data.ts new file mode 100644 index 0000000000..02ac62a9bb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/sources/culture.server.data.ts @@ -0,0 +1,32 @@ +import { UmbCultureDataSource } from '.'; +import { CultureResource } from '@umbraco-cms/backend-api'; +import { UmbControllerHostInterface } from '@umbraco-cms/controller'; +import { tryExecuteAndNotify } from '@umbraco-cms/resources'; + +/** + * A data source for the Language that fetches data from the server + * @export + * @class UmbLanguageServerDataSource + * @implements {RepositoryDetailDataSource} + */ +export class UmbCultureServerDataSource implements UmbCultureDataSource { + #host: UmbControllerHostInterface; + + /** + * Creates an instance of UmbLanguageServerDataSource. + * @param {UmbControllerHostInterface} host + * @memberof UmbLanguageServerDataSource + */ + constructor(host: UmbControllerHostInterface) { + this.#host = host; + } + + /** + * Get a list of cultures on the server + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async getCollection({ skip, take }: { skip: number; take: number }) { + return tryExecuteAndNotify(this.#host, CultureResource.getCulture({ skip, take })); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/sources/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/sources/index.ts new file mode 100644 index 0000000000..8b3555ed3f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/cultures/repository/sources/index.ts @@ -0,0 +1,12 @@ +import { PagedCultureModel } from '@umbraco-cms/backend-api'; +import type { DataSourceResponse } from '@umbraco-cms/models'; + +// TODO: This is a temporary solution until we have a proper paging interface +type paging = { + skip: number; + take: number; +}; + +export interface UmbCultureDataSource { + getCollection(paging: paging): Promise>; +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts index de60d18c58..43ef6bfa40 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/index.ts @@ -2,6 +2,7 @@ import { manifests as settingsSectionManifests } from './section.manifests'; import { manifests as dashboardManifests } from './dashboards/manifests'; import { manifests as dataTypeManifests } from './data-types/manifests'; import { manifests as extensionManifests } from './extensions/manifests'; +import { manifests as cultureManifests } from './cultures/manifests'; import { manifests as languageManifests } from './languages/manifests'; import { manifests as logviewerManifests } from './logviewer/manifests'; @@ -20,6 +21,7 @@ registerExtensions([ ...dashboardManifests, ...dataTypeManifests, ...extensionManifests, + ...cultureManifests, ...languageManifests, ...logviewerManifests, ]); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/language.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/language.store.ts deleted file mode 100644 index ffc3f178ba..0000000000 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/language.store.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Observable } from 'rxjs'; -import { CultureModel, CultureResource, LanguageModel, LanguageResource } from '@umbraco-cms/backend-api'; -import { tryExecuteAndNotify } from '@umbraco-cms/resources'; -import { UmbContextToken } from '@umbraco-cms/context-api'; -import { UmbStoreBase } from '@umbraco-cms/store'; -import { ArrayState } from '@umbraco-cms/observable-api'; -import { UmbControllerHostInterface } from '@umbraco-cms/controller'; - -export type UmbLanguageStoreItemType = LanguageModel; -export const UMB_LANGUAGE_STORE_CONTEXT_TOKEN = new UmbContextToken('umbLanguageStore'); - -/** - * @export - * @class UmbLanguageStore - * @extends {UmbStoreBase} - * @description - Data Store for languages - */ -export class UmbLanguageStore extends UmbStoreBase { - #data = new ArrayState([], (x) => x.isoCode); - #availableLanguages = new ArrayState([], (x) => x.name); - - public readonly availableLanguages = this.#availableLanguages.asObservable(); - - constructor(host: UmbControllerHostInterface) { - super(host, UMB_LANGUAGE_STORE_CONTEXT_TOKEN.toString()); - } - - getByIsoCode(isoCode: string) { - tryExecuteAndNotify(this._host, LanguageResource.getLanguageByIsoCode({ isoCode })).then(({ data }) => { - if (data) { - this.#data.appendOne(data); - } - }); - - return this.#data.getObservablePart((items) => items.find((item) => item.isoCode === isoCode)); - } - - getAll(): Observable> { - tryExecuteAndNotify(this._host, LanguageResource.getLanguage({ skip: 0, take: 1000 })).then(({ data }) => { - this.#data.append(data?.items ?? []); - }); - - return this.#data; - } - - getAvailableCultures() { - tryExecuteAndNotify(this._host, CultureResource.getCulture({ skip: 0, take: 1000 })).then(({ data }) => { - if (!data) return; - this.#availableLanguages.append(data.items); - }); - - return this.availableLanguages; - } - - async save(language: UmbLanguageStoreItemType): Promise { - if (language.isoCode) { - const { data: updatedLanguage } = await tryExecuteAndNotify( - this._host, - LanguageResource.putLanguageByIsoCode({ isoCode: language.isoCode, requestBody: language }) - ); - if (updatedLanguage) { - this.#data.appendOne(updatedLanguage); - } - } else { - const { data: newLanguage } = await tryExecuteAndNotify( - this._host, - LanguageResource.postLanguage({ requestBody: language }) - ); - if (newLanguage) { - this.#data.appendOne(newLanguage); - } - } - } - - async delete(isoCodes: Array) { - // TODO: revisit this. It looks a bit weird with the nested tryExecuteAndNotify - const queue = isoCodes.map((isoCode) => - tryExecuteAndNotify( - this._host, - tryExecuteAndNotify(this._host, LanguageResource.deleteLanguageByIsoCode({ isoCode })).then(() => isoCode) - ) - ); - const results = await Promise.all(queue); - const filtered = results.filter((x) => !!x).map((result) => result.data); - this.#data.remove(filtered); - } -} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/language.repository.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/language.repository.ts new file mode 100644 index 0000000000..ee727facb9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/language.repository.ts @@ -0,0 +1,68 @@ +import { UmbLanguageServerDataSource } from './sources/language.server.data'; +import { UmbLanguageStore, UMB_LANGUAGE_STORE_CONTEXT_TOKEN } from './language.store'; +import { UmbControllerHostInterface } from '@umbraco-cms/controller'; +import { UmbContextConsumerController } from '@umbraco-cms/context-api'; +import { UmbNotificationService, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN } from '@umbraco-cms/notification'; +import { ProblemDetailsModel } from '@umbraco-cms/backend-api'; + +export class UmbLanguageRepository { + #init!: Promise; + + #host: UmbControllerHostInterface; + + #detailDataSource: UmbLanguageServerDataSource; + #languageStore?: UmbLanguageStore; + + #notificationService?: UmbNotificationService; + + constructor(host: UmbControllerHostInterface) { + this.#host = host; + + // TODO: figure out how spin up get the correct data source + this.#detailDataSource = new UmbLanguageServerDataSource(this.#host); + + this.#init = Promise.all([ + new UmbContextConsumerController(this.#host, UMB_NOTIFICATION_SERVICE_CONTEXT_TOKEN, (instance) => { + this.#notificationService = instance; + }), + + new UmbContextConsumerController(this.#host, UMB_LANGUAGE_STORE_CONTEXT_TOKEN, (instance) => { + this.#languageStore = instance; + }), + ]); + } + + /** + * Creates a new Language scaffold + * @param + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async createDetailsScaffold() { + return this.#detailDataSource.createScaffold(); + } + + async requestByIsoCode(isoCode: string) { + await this.#init; + + if (!isoCode) { + const error: ProblemDetailsModel = { title: 'Iso code is missing' }; + return { error }; + } + + return this.#detailDataSource.get(isoCode); + } + + async requestLanguages({ skip, take } = { skip: 0, take: 1000 }) { + await this.#init; + + const { data, error } = await this.#detailDataSource.getCollection({ skip, take }); + + if (data) { + // TODO: allow to append an array of items to the store + data.items.forEach((x) => this.#languageStore?.append(x)); + } + + return { data, error, asObservable: () => this.#languageStore!.data }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/language.store.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/language.store.ts new file mode 100644 index 0000000000..eb5e1c3163 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/language.store.ts @@ -0,0 +1,30 @@ +import { UmbContextToken } from '@umbraco-cms/context-api'; +import { UmbStoreBase } from '@umbraco-cms/store'; +import { UmbControllerHostInterface } from '@umbraco-cms/controller'; +import { ArrayState } from '@umbraco-cms/observable-api'; +import { LanguageModel } from '@umbraco-cms/backend-api'; + +/** + * @export + * @class UmbLanguageStore + * @extends {UmbStoreBase} + * @description - Details Data Store for Languages + */ +export class UmbLanguageStore extends UmbStoreBase { + #data = new ArrayState([], (x) => x.isoCode); + data = this.#data.asObservable(); + + constructor(host: UmbControllerHostInterface) { + super(host, UmbLanguageStore.name); + } + + append(language: LanguageModel) { + this.#data.append([language]); + } + + remove(uniques: string[]) { + this.#data.remove(uniques); + } +} + +export const UMB_LANGUAGE_STORE_CONTEXT_TOKEN = new UmbContextToken(UmbLanguageStore.name); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/index.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/index.ts new file mode 100644 index 0000000000..81efc0303f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/index.ts @@ -0,0 +1,16 @@ +import { LanguageModel, PagedLanguageModel } from '@umbraco-cms/backend-api'; +import type { DataSourceResponse } from '@umbraco-cms/models'; +import { RepositoryDetailDataSource } from '@umbraco-cms/repository'; + +// TODO: This is a temporary solution until we have a proper paging interface +type paging = { + skip: number; + take: number; +}; + +export interface UmbLanguageDataSource extends RepositoryDetailDataSource { + createScaffold(): Promise>; + get(isoCode: string): Promise>; + delete(isoCode: string): Promise>; + getCollection(paging: paging): Promise>; +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/language.server.data.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/language.server.data.ts new file mode 100644 index 0000000000..6cc694ba15 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/repository/sources/language.server.data.ts @@ -0,0 +1,116 @@ +import { ProblemDetailsModel, LanguageResource, LanguageModel } from '@umbraco-cms/backend-api'; +import { UmbControllerHostInterface } from '@umbraco-cms/controller'; +import { tryExecuteAndNotify } from '@umbraco-cms/resources'; + +/** + * A data source for the Language that fetches data from the server + * @export + * @class UmbLanguageServerDataSource + * @implements {RepositoryDetailDataSource} + */ +export class UmbLanguageServerDataSource implements UmbLanguageServerDataSource { + #host: UmbControllerHostInterface; + + /** + * Creates an instance of UmbLanguageServerDataSource. + * @param {UmbControllerHostInterface} host + * @memberof UmbLanguageServerDataSource + */ + constructor(host: UmbControllerHostInterface) { + this.#host = host; + } + + /** + * Fetches a Language with the given iso code from the server + * @param {string} isoCode + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async get(isoCode: string) { + if (!isoCode) { + const error: ProblemDetailsModel = { title: 'Iso Code is missing' }; + return { error }; + } + + return tryExecuteAndNotify( + this.#host, + LanguageResource.getLanguageByIsoCode({ + isoCode, + }) + ); + } + + /** + * Creates a new Language scaffold + * @param + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async createScaffold() { + const data: LanguageModel = { + isoCode: '', + }; + + return { data }; + } + + /** + * Inserts a new Language on the server + * @param {LanguageModel} language + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async insert(language: LanguageModel) { + if (!language.isoCode) { + const error: ProblemDetailsModel = { title: 'Language iso code is missing' }; + return { error }; + } + + return tryExecuteAndNotify(this.#host, LanguageResource.postLanguage({ requestBody: language })); + } + + /** + * Updates a Language on the server + * @param {LanguageModel} language + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async update(language: LanguageModel) { + if (!language.isoCode) { + const error: ProblemDetailsModel = { title: 'Language iso code is missing' }; + return { error }; + } + + return tryExecuteAndNotify( + this.#host, + LanguageResource.putLanguageByIsoCode({ isoCode: language.isoCode, requestBody: language }) + ); + } + + /** + * Deletes a Language on the server + * @param {string} isoCode + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async delete(isoCode: string) { + if (!isoCode) { + const error: ProblemDetailsModel = { title: 'Iso code is missing' }; + return { error }; + } + + return tryExecuteAndNotify( + this.#host, + tryExecuteAndNotify(this.#host, LanguageResource.deleteLanguageByIsoCode({ isoCode })).then(() => isoCode) + ); + } + + /** + * Get a list of Languages on the server + * @return {*} + * @memberof UmbLanguageServerDataSource + */ + async getCollection({ skip, take }: { skip: number; take: number }) { + return tryExecuteAndNotify(this.#host, LanguageResource.getLanguage({ skip, take })); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-table-delete-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-table-delete-column-layout.element.ts index ac3b22a1f4..6ed6993d44 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-table-delete-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-table-delete-column-layout.element.ts @@ -1,7 +1,11 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html, nothing } from 'lit'; import { customElement, property } from 'lit/decorators.js'; -import { UmbLanguageStore, UmbLanguageStoreItemType, UMB_LANGUAGE_STORE_CONTEXT_TOKEN } from '../../language.store'; +import { + UmbLanguageStore, + UmbLanguageStoreItemType, + UMB_LANGUAGE_STORE_CONTEXT_TOKEN, +} from '../../repository/language.store'; import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '../../../../../core/modal'; import { UmbLitElement } from '@umbraco-cms/element'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-workspace.element.ts index 28e918ee79..de838499d4 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language-root/language-root-workspace.element.ts @@ -1,7 +1,11 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html } from 'lit'; import { customElement, state } from 'lit/decorators.js'; -import { UmbLanguageStore, UmbLanguageStoreItemType, UMB_LANGUAGE_STORE_CONTEXT_TOKEN } from '../../language.store'; +import { + UmbLanguageStore, + UmbLanguageStoreItemType, + UMB_LANGUAGE_STORE_CONTEXT_TOKEN, +} from '../../repository/language.store'; import { UmbTableColumn, UmbTableConfig, UmbTableItem } from '../../../../shared/components/table'; import { UmbWorkspaceEntityElement } from '../../../../shared/components/workspace/workspace-entity-element.interface'; import { UmbLitElement } from '@umbraco-cms/element'; @@ -9,6 +13,7 @@ import { UmbLitElement } from '@umbraco-cms/element'; import '../language/language-workspace.element'; import './language-root-table-delete-column-layout.element'; import './language-root-table-name-column-layout.element'; +import { UmbLanguageRepository } from '../../repository/language.repository'; @customElement('umb-language-root-workspace') export class UmbLanguageRootWorkspaceElement extends UmbLitElement implements UmbWorkspaceEntityElement { @@ -65,29 +70,22 @@ export class UmbLanguageRootWorkspaceElement extends UmbLitElement implements Um @state() private _tableItems: Array = []; - #languageStore?: UmbLanguageStore; - - constructor() { - super(); - - this.consumeContext(UMB_LANGUAGE_STORE_CONTEXT_TOKEN, (instance) => { - this.#languageStore = instance; - this.#observeLanguages(); - }); - } + #languageRepository = new UmbLanguageRepository(this); load(): void { - // Not relevant for this workspace + this.#observeLanguages(); } create(): void { // Not relevant for this workspace } - #observeLanguages() { - this.#languageStore?.getAll().subscribe((languages) => { - this.#createTableItems(languages); - }); + async #observeLanguages() { + const { asObservable } = await this.#languageRepository.requestLanguages(); + + if (asObservable) { + this.observe(asObservable(), (languages) => this.#createTableItems(languages)); + } } #createTableItems(languages: Array) { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.context.ts index abd98b217b..a5a6502a7a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.context.ts @@ -1,70 +1,45 @@ -import { UmbLanguageStore, UmbLanguageStoreItemType, UMB_LANGUAGE_STORE_CONTEXT_TOKEN } from '../../language.store'; +import { UmbLanguageRepository } from '../../repository/language.repository'; +import type { LanguageModel } from '@umbraco-cms/backend-api'; +import { ObjectState } from '@umbraco-cms/observable-api'; import { UmbControllerHostInterface } from '@umbraco-cms/controller'; -import { ObjectState, UmbObserverController } from '@umbraco-cms/observable-api'; -import { UmbContextConsumerController } from '@umbraco-cms/context-api'; +import { UmbWorkspaceContext } from 'src/backoffice/shared/components/workspace/workspace-context/workspace-context'; -const DefaultLanguageData: UmbLanguageStoreItemType = { - name: '', - isoCode: '', - isDefault: false, - isMandatory: false, -}; +export class UmbLanguageWorkspaceContext extends UmbWorkspaceContext { + #host: UmbControllerHostInterface; + #data = new ObjectState(undefined); + #languageRepository: UmbLanguageRepository; + #isNew = false; -export class UmbWorkspaceLanguageContext { - public host: UmbControllerHostInterface; - - #entityKey: string | null; - - #data; - public readonly data; - - #store: UmbLanguageStore | null = null; - protected _storeObserver?: UmbObserverController; - - constructor(host: UmbControllerHostInterface, entityKey: string | null) { - this.host = host; - this.#entityKey = entityKey; - - this.#data = new ObjectState(DefaultLanguageData); - this.data = this.#data.asObservable(); - - new UmbContextConsumerController(host, UMB_LANGUAGE_STORE_CONTEXT_TOKEN, (_instance: UmbLanguageStore) => { - this.#store = _instance; - this.#observeStore(); - }); + constructor(host: UmbControllerHostInterface) { + super(host); + this.#host = host; + this.#languageRepository = new UmbLanguageRepository(this.#host); } - #observeStore(): void { - if (!this.#store || this.#entityKey === null) { - return; + async load(isoCode: string) { + const { data } = await this.#languageRepository.requestByIsoCode(isoCode); + if (data) { + this.#isNew = false; + this.#data.update(data); } - - this._storeObserver?.destroy(); - this._storeObserver = new UmbObserverController(this.host, this.#store.getByIsoCode(this.#entityKey), (content) => { - if (!content) return; // TODO: Handle nicely if there is no content data. - this.update(content); - }); } - public getData() { + async createScaffold() { + const { data } = await this.#languageRepository.createDetailsScaffold(); + if (!data) return; + this.#isNew = true; + this.#data.update(data); + } + + getData() { return this.#data.getValue(); } - public getAvailableCultures() { - //TODO: Don't use !, however this will be changed with the introduction of repositories. - return this.#store!.getAvailableCultures(); + getEntityType() { + return 'language'; } - public update(data: Partial) { - this.#data.next({ ...this.getData(), ...data }); - } - - public save(): Promise { - if (!this.#store) { - // TODO: more beautiful error: - console.error('Could not save cause workspace context has no store.'); - return Promise.resolve(); - } - return this.#store.save(this.getData()); + public destroy(): void { + this.#data.complete(); } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.element.ts index 7bf01a12ef..28a2ccc6db 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/language-workspace.element.ts @@ -2,9 +2,9 @@ import { UUITextStyles } from '@umbraco-ui/uui-css'; import { css, html, nothing } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import { UUIInputElement, UUIInputEvent } from '@umbraco-ui/uui'; -import { UmbLanguageStoreItemType } from '../../language.store'; +import { UmbLanguageStoreItemType } from '../../repository/language.store'; import { UmbWorkspaceEntityElement } from '../../../../shared/components/workspace/workspace-entity-element.interface'; -import { UmbWorkspaceLanguageContext } from './language-workspace.context'; +import { UmbLanguageWorkspaceContext } from './language-workspace.context'; import { UmbLitElement } from '@umbraco-cms/element'; import '../../../../shared/components/workspace/workspace-action/save/workspace-action-node-save.element.ts'; @@ -28,7 +28,7 @@ export class UmbLanguageWorkspaceElement extends UmbLitElement implements UmbWor @property() language?: UmbLanguageStoreItemType; - #languageWorkspaceContext?: UmbWorkspaceLanguageContext; + #languageWorkspaceContext?: UmbLanguageWorkspaceContext; load(key: string): void { this.provideLanguageWorkspaceContext(key); @@ -39,7 +39,7 @@ export class UmbLanguageWorkspaceElement extends UmbLitElement implements UmbWor } public provideLanguageWorkspaceContext(entityKey: string | null) { - this.#languageWorkspaceContext = new UmbWorkspaceLanguageContext(this, entityKey); + this.#languageWorkspaceContext = new UmbLanguageWorkspaceContext(this, entityKey); this.provideContext('umbWorkspaceContext', this.#languageWorkspaceContext); this.#languageWorkspaceContext.data.subscribe((language) => { this.language = language; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/workspace-view-language-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/workspace-view-language-edit.element.ts index 831f403ca0..0b134088ec 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/workspace-view-language-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/settings/languages/workspace/language/views/edit/workspace-view-language-edit.element.ts @@ -4,12 +4,12 @@ import { css, html, nothing } from 'lit'; import { repeat } from 'lit/directives/repeat.js'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; -import { UmbWorkspaceLanguageContext } from '../../language-workspace.context'; +import { UmbLanguageWorkspaceContext } from '../../language-workspace.context'; import { UmbLanguageStore, UmbLanguageStoreItemType, UMB_LANGUAGE_STORE_CONTEXT_TOKEN, -} from '../../../../language.store'; +} from '../../../../repository/language.store'; import { UmbLitElement } from '@umbraco-cms/element'; import { CultureModel, LanguageModel } from '@umbraco-cms/backend-api'; @@ -64,12 +64,12 @@ export class UmbWorkspaceViewLanguageEditElement extends UmbLitElement { @state() private _startData: LanguageModel | null = null; - #languageWorkspaceContext?: UmbWorkspaceLanguageContext; + #languageWorkspaceContext?: UmbLanguageWorkspaceContext; constructor() { super(); - this.consumeContext('umbWorkspaceContext', (instance) => { + this.consumeContext('umbWorkspaceContext', (instance) => { this.#languageWorkspaceContext = instance; if (!this.#languageWorkspaceContext) return; diff --git a/src/Umbraco.Web.UI.Client/src/core/mocks/data/languages.data.ts b/src/Umbraco.Web.UI.Client/src/core/mocks/data/languages.data.ts index f693df0fee..2b1f16d2b1 100644 --- a/src/Umbraco.Web.UI.Client/src/core/mocks/data/languages.data.ts +++ b/src/Umbraco.Web.UI.Client/src/core/mocks/data/languages.data.ts @@ -1,4 +1,4 @@ -import { UmbLanguageStoreItemType } from '../../../backoffice/settings/languages/language.store'; +import { UmbLanguageStoreItemType } from '../../../backoffice/settings/languages/repository/language.store'; import { UmbData } from './data'; // Temp mocked database