diff --git a/package.json b/package.json index a6a59c16e8..50145a4985 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "./member-group": "./dist-cms/packages/members/member-groups/index.js", "./member-type": "./dist-cms/packages/members/member-types/index.js", "./package": "./dist-cms/packages/packages/package/index.js", - "./data-type": "./dist-cms/packages/settings/data-types/index.js", + "./data-type": "./dist-cms/packages/core/data-type/index.js", "./language": "./dist-cms/packages/settings/languages/index.js", "./logviewer": "./dist-cms/packages/settings/logviewer/index.js", "./relation-type": "./dist-cms/packages/settings/relation-types/index.js", diff --git a/src/packages/core/components/property-type-based-property/property-type-based-property.element.ts b/src/packages/core/components/property-type-based-property/property-type-based-property.element.ts index 07d3dd1715..8f38482827 100644 --- a/src/packages/core/components/property-type-based-property/property-type-based-property.element.ts +++ b/src/packages/core/components/property-type-based-property/property-type-based-property.element.ts @@ -1,7 +1,7 @@ +import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type'; import { UmbPropertyEditorConfig } from '../../property-editor/index.js'; -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbDataTypeRepository } from '@umbraco-cms/backoffice/data-type'; import type { DataTypeResponseModel, PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; @@ -27,16 +27,16 @@ export class UmbPropertyTypeBasedPropertyElement extends UmbLitElement { @state() private _dataTypeData?: UmbPropertyEditorConfig; - private _dataTypeRepository: UmbDataTypeRepository = new UmbDataTypeRepository(this); + private _dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); private _dataTypeObserver?: UmbObserverController; private async _observeDataType(dataTypeId?: string) { this._dataTypeObserver?.destroy(); if (dataTypeId) { // Its not technically needed to have await here, this is only to ensure that the data is loaded before we observe it, and thereby only updating the DOM with the latest data. - await this._dataTypeRepository.requestById(dataTypeId); + await this._dataTypeDetailRepository.requestById(dataTypeId); this._dataTypeObserver = this.observe( - await this._dataTypeRepository.byId(dataTypeId), + await this._dataTypeDetailRepository.byId(dataTypeId), (dataType) => { this._dataTypeData = dataType?.values; this._propertyEditorUiAlias = dataType?.propertyEditorUiAlias || undefined; @@ -50,11 +50,11 @@ export class UmbPropertyTypeBasedPropertyElement extends UmbLitElement { this._propertyEditorUiAlias = extension?.meta.defaultPropertyEditorUiAlias; this.removeControllerByAlias('_observePropertyEditorSchema'); }, - '_observePropertyEditorSchema' + '_observePropertyEditorSchema', ); } }, - '_observeDataType' + '_observeDataType', ); } } diff --git a/src/packages/settings/data-types/components/data-type-flow-input/data-type-flow-input.element.ts b/src/packages/core/data-type/components/data-type-flow-input/data-type-flow-input.element.ts similarity index 100% rename from src/packages/settings/data-types/components/data-type-flow-input/data-type-flow-input.element.ts rename to src/packages/core/data-type/components/data-type-flow-input/data-type-flow-input.element.ts diff --git a/src/packages/settings/data-types/components/data-type-input/data-type-input.context.ts b/src/packages/core/data-type/components/data-type-input/data-type-input.context.ts similarity index 100% rename from src/packages/settings/data-types/components/data-type-input/data-type-input.context.ts rename to src/packages/core/data-type/components/data-type-input/data-type-input.context.ts diff --git a/src/packages/settings/data-types/components/data-type-input/data-type-input.element.ts b/src/packages/core/data-type/components/data-type-input/data-type-input.element.ts similarity index 100% rename from src/packages/settings/data-types/components/data-type-input/data-type-input.element.ts rename to src/packages/core/data-type/components/data-type-input/data-type-input.element.ts diff --git a/src/packages/settings/data-types/components/index.ts b/src/packages/core/data-type/components/index.ts similarity index 100% rename from src/packages/settings/data-types/components/index.ts rename to src/packages/core/data-type/components/index.ts diff --git a/src/packages/settings/data-types/components/ref-data-type/ref-data-type.element.ts b/src/packages/core/data-type/components/ref-data-type/ref-data-type.element.ts similarity index 94% rename from src/packages/settings/data-types/components/ref-data-type/ref-data-type.element.ts rename to src/packages/core/data-type/components/ref-data-type/ref-data-type.element.ts index 2329a95cc8..55e348be28 100644 --- a/src/packages/settings/data-types/components/ref-data-type/ref-data-type.element.ts +++ b/src/packages/core/data-type/components/ref-data-type/ref-data-type.element.ts @@ -1,4 +1,4 @@ -import { UmbDataTypeRepository } from '../../repository/data-type.repository.js'; +import { UmbDataTypeDetailRepository } from '../../repository/detail/data-type-detail.repository.js'; import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui'; import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; @@ -39,7 +39,7 @@ export class UmbRefDataTypeElement extends UmbElementMixin(UUIRefNodeElement) { } } - repository = new UmbDataTypeRepository(this); + repository = new UmbDataTypeDetailRepository(this); /** * Property Editor UI Alias diff --git a/src/packages/settings/data-types/components/ref-data-type/ref-data-type.stories.ts b/src/packages/core/data-type/components/ref-data-type/ref-data-type.stories.ts similarity index 100% rename from src/packages/settings/data-types/components/ref-data-type/ref-data-type.stories.ts rename to src/packages/core/data-type/components/ref-data-type/ref-data-type.stories.ts diff --git a/src/packages/settings/data-types/entities.ts b/src/packages/core/data-type/entities.ts similarity index 100% rename from src/packages/settings/data-types/entities.ts rename to src/packages/core/data-type/entities.ts diff --git a/src/packages/settings/data-types/entity-actions/copy/copy.action.ts b/src/packages/core/data-type/entity-actions/copy/copy.action.ts similarity index 89% rename from src/packages/settings/data-types/entity-actions/copy/copy.action.ts rename to src/packages/core/data-type/entity-actions/copy/copy.action.ts index 88aba1f122..5410ee0cb0 100644 --- a/src/packages/settings/data-types/entity-actions/copy/copy.action.ts +++ b/src/packages/core/data-type/entity-actions/copy/copy.action.ts @@ -1,4 +1,4 @@ -import { UmbDataTypeRepository } from '../../repository/data-type.repository.js'; +import { type UmbCopyDataTypeRepository } from '../../repository/copy/data-type-copy.repository.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { @@ -8,7 +8,7 @@ import { } from '@umbraco-cms/backoffice/modal'; // TODO: investigate what we need to make a generic copy action -export class UmbCopyDataTypeEntityAction extends UmbEntityActionBase { +export class UmbCopyDataTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { diff --git a/src/packages/settings/data-types/entity-actions/copy/manifests.ts b/src/packages/core/data-type/entity-actions/copy/manifests.ts similarity index 80% rename from src/packages/settings/data-types/entity-actions/copy/manifests.ts rename to src/packages/core/data-type/entity-actions/copy/manifests.ts index ee241a86e2..a3bd85a746 100644 --- a/src/packages/settings/data-types/entity-actions/copy/manifests.ts +++ b/src/packages/core/data-type/entity-actions/copy/manifests.ts @@ -1,5 +1,5 @@ import { DATA_TYPE_ENTITY_TYPE } from '../../entities.js'; -import { DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/manifests.js'; +import { COPY_DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/copy/manifests.js'; import { UmbCopyDataTypeEntityAction } from './copy.action.js'; import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -13,7 +13,7 @@ const entityActions: Array = [ meta: { icon: 'icon-documents', label: 'Copy to...', - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, + repositoryAlias: COPY_DATA_TYPE_REPOSITORY_ALIAS, entityTypes: [DATA_TYPE_ENTITY_TYPE], }, }, diff --git a/src/packages/settings/data-types/entity-actions/create/create.action.ts b/src/packages/core/data-type/entity-actions/create/create.action.ts similarity index 87% rename from src/packages/settings/data-types/entity-actions/create/create.action.ts rename to src/packages/core/data-type/entity-actions/create/create.action.ts index 7ec93bf46b..76f398b338 100644 --- a/src/packages/settings/data-types/entity-actions/create/create.action.ts +++ b/src/packages/core/data-type/entity-actions/create/create.action.ts @@ -1,10 +1,10 @@ -import { UmbDataTypeRepository } from '../../repository/data-type.repository.js'; +import { UmbDataTypeDetailRepository } from '../../repository/detail/data-type-detail.repository.js'; import { UMB_DATA_TYPE_CREATE_OPTIONS_MODAL } from './modal/index.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; -export class UmbCreateDataTypeEntityAction extends UmbEntityActionBase { +export class UmbCreateDataTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { diff --git a/src/packages/settings/data-types/entity-actions/create/manifests.ts b/src/packages/core/data-type/entity-actions/create/manifests.ts similarity index 85% rename from src/packages/settings/data-types/entity-actions/create/manifests.ts rename to src/packages/core/data-type/entity-actions/create/manifests.ts index f4b524ef3f..11e625e6fc 100644 --- a/src/packages/settings/data-types/entity-actions/create/manifests.ts +++ b/src/packages/core/data-type/entity-actions/create/manifests.ts @@ -1,5 +1,5 @@ import { DATA_TYPE_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE, DATA_TYPE_ROOT_ENTITY_TYPE } from '../../entities.js'; -import { DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/manifests.js'; +import { DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/detail/manifests.js'; import { UmbCreateDataTypeEntityAction } from './create.action.js'; import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -13,7 +13,7 @@ const entityActions: Array = [ meta: { icon: 'icon-add', label: 'Create...', - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, + repositoryAlias: DATA_TYPE_DETAIL_REPOSITORY_ALIAS, entityTypes: [DATA_TYPE_ENTITY_TYPE, DATA_TYPE_ROOT_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE], }, }, diff --git a/src/packages/settings/data-types/entity-actions/create/modal/data-type-create-options-modal.element.ts b/src/packages/core/data-type/entity-actions/create/modal/data-type-create-options-modal.element.ts similarity index 90% rename from src/packages/settings/data-types/entity-actions/create/modal/data-type-create-options-modal.element.ts rename to src/packages/core/data-type/entity-actions/create/modal/data-type-create-options-modal.element.ts index d23dde8e1c..fa3f8ebf77 100644 --- a/src/packages/settings/data-types/entity-actions/create/modal/data-type-create-options-modal.element.ts +++ b/src/packages/core/data-type/entity-actions/create/modal/data-type-create-options-modal.element.ts @@ -1,7 +1,7 @@ -import { DATA_TYPE_REPOSITORY_ALIAS } from '../../../repository/manifests.js'; +import { DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from '../../../repository/folder/manifests.js'; import { UmbDataTypeCreateOptionsModalData } from './index.js'; import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbModalManagerContext, UmbModalContext, @@ -30,7 +30,7 @@ export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement { #onClick(event: PointerEvent) { event.stopPropagation(); const folderModalHandler = this.#modalContext?.open(UMB_FOLDER_MODAL, { - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, + repositoryAlias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS, }); folderModalHandler?.onSubmit().then(() => this.modalContext?.submit()); } diff --git a/src/packages/settings/data-types/entity-actions/create/modal/index.ts b/src/packages/core/data-type/entity-actions/create/modal/index.ts similarity index 100% rename from src/packages/settings/data-types/entity-actions/create/modal/index.ts rename to src/packages/core/data-type/entity-actions/create/modal/index.ts diff --git a/src/packages/settings/data-types/entity-actions/manifests.ts b/src/packages/core/data-type/entity-actions/manifests.ts similarity index 82% rename from src/packages/settings/data-types/entity-actions/manifests.ts rename to src/packages/core/data-type/entity-actions/manifests.ts index bbb9ab2a56..5ba84feafe 100644 --- a/src/packages/settings/data-types/entity-actions/manifests.ts +++ b/src/packages/core/data-type/entity-actions/manifests.ts @@ -1,5 +1,5 @@ import { DATA_TYPE_FOLDER_ENTITY_TYPE, DATA_TYPE_ENTITY_TYPE } from '../entities.js'; -import { DATA_TYPE_REPOSITORY_ALIAS } from '../repository/manifests.js'; +import { DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/detail/manifests.js'; import { manifests as createManifests } from './create/manifests.js'; import { manifests as moveManifests } from './move/manifests.js'; import { manifests as copyManifests } from './copy/manifests.js'; @@ -10,6 +10,7 @@ import { UmbFolderUpdateEntityAction, } from '@umbraco-cms/backoffice/entity-action'; import { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; +import { DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from '../repository/folder/manifests.js'; const entityActions: Array = [ { @@ -21,7 +22,7 @@ const entityActions: Array = [ meta: { icon: 'icon-trash', label: 'Delete...', - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, + repositoryAlias: DATA_TYPE_DETAIL_REPOSITORY_ALIAS, entityTypes: [DATA_TYPE_ENTITY_TYPE], }, }, @@ -34,7 +35,7 @@ const entityActions: Array = [ meta: { icon: 'icon-trash', label: 'Delete Folder...', - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, + repositoryAlias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS, entityTypes: [DATA_TYPE_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE], }, }, @@ -47,7 +48,7 @@ const entityActions: Array = [ meta: { icon: 'icon-edit', label: 'Rename Folder...', - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, + repositoryAlias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS, entityTypes: [DATA_TYPE_ENTITY_TYPE, DATA_TYPE_FOLDER_ENTITY_TYPE], }, }, diff --git a/src/packages/settings/data-types/entity-actions/move/manifests.ts b/src/packages/core/data-type/entity-actions/move/manifests.ts similarity index 80% rename from src/packages/settings/data-types/entity-actions/move/manifests.ts rename to src/packages/core/data-type/entity-actions/move/manifests.ts index fe1ae6354c..67713e6092 100644 --- a/src/packages/settings/data-types/entity-actions/move/manifests.ts +++ b/src/packages/core/data-type/entity-actions/move/manifests.ts @@ -1,5 +1,5 @@ import { DATA_TYPE_ENTITY_TYPE } from '../../entities.js'; -import { DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/manifests.js'; +import { MOVE_DATA_TYPE_REPOSITORY_ALIAS } from '../../repository/move/manifests.js'; import { UmbMoveDataTypeEntityAction } from './move.action.js'; import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -13,7 +13,7 @@ const entityActions: Array = [ meta: { icon: 'icon-enter', label: 'Move to...', - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, + repositoryAlias: MOVE_DATA_TYPE_REPOSITORY_ALIAS, entityTypes: [DATA_TYPE_ENTITY_TYPE], }, }, diff --git a/src/packages/settings/data-types/entity-actions/move/move.action.ts b/src/packages/core/data-type/entity-actions/move/move.action.ts similarity index 89% rename from src/packages/settings/data-types/entity-actions/move/move.action.ts rename to src/packages/core/data-type/entity-actions/move/move.action.ts index 958a786c53..1ecd58718e 100644 --- a/src/packages/settings/data-types/entity-actions/move/move.action.ts +++ b/src/packages/core/data-type/entity-actions/move/move.action.ts @@ -1,4 +1,4 @@ -import { UmbDataTypeRepository } from '../../repository/data-type.repository.js'; +import { UmbMoveDataTypeRepository } from '../../repository/move/data-type-move.repository.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { @@ -8,7 +8,7 @@ import { } from '@umbraco-cms/backoffice/modal'; // TODO: investigate what we need to make a generic move action -export class UmbMoveDataTypeEntityAction extends UmbEntityActionBase { +export class UmbMoveDataTypeEntityAction extends UmbEntityActionBase { #modalManagerContext?: UmbModalManagerContext; constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { diff --git a/src/packages/settings/data-types/index.ts b/src/packages/core/data-type/index.ts similarity index 100% rename from src/packages/settings/data-types/index.ts rename to src/packages/core/data-type/index.ts diff --git a/src/packages/settings/data-types/manifests.ts b/src/packages/core/data-type/manifests.ts similarity index 100% rename from src/packages/settings/data-types/manifests.ts rename to src/packages/core/data-type/manifests.ts diff --git a/src/packages/settings/data-types/menu-item/manifests.ts b/src/packages/core/data-type/menu-item/manifests.ts similarity index 100% rename from src/packages/settings/data-types/menu-item/manifests.ts rename to src/packages/core/data-type/menu-item/manifests.ts diff --git a/src/packages/settings/data-types/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts b/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts similarity index 91% rename from src/packages/settings/data-types/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts rename to src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts index fe69627ffa..203de144ca 100644 --- a/src/packages/settings/data-types/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts +++ b/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-data-type-picker-modal.element.ts @@ -1,4 +1,5 @@ -import { UmbDataTypeRepository } from '../../repository/data-type.repository.js'; +import { UmbDataTypeDetailRepository } from '../../repository/detail/data-type-detail.repository.js'; +import { UmbDataTypeTreeRepository } from '../../tree/data-type-tree.repository.js'; import { css, html, customElement, property, state, repeat, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { @@ -32,26 +33,27 @@ export class UmbDataTypePickerFlowDataTypePickerModalElement extends UmbLitEleme private async _observeDataTypesOf(propertyEditorUiAlias: string) { if (!this.data) return; - const dataTypeRepository = new UmbDataTypeRepository(this); + const dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); + const dataTypeTreeRepository = new UmbDataTypeTreeRepository(this); // TODO: This is a hack to get the data types of a property editor ui alias. // TODO: Make sure filtering works data-type that does not have a property editor ui, but should be using the default property editor UI for those. // TODO: make an end-point just retrieving the data types using a given property editor ui alias. - const { data } = await dataTypeRepository.requestRootTreeItems(); + const { data } = await dataTypeTreeRepository.requestRootTreeItems(); if (!data) return; await Promise.all( data.items.map((item) => { if (item.id) { - return dataTypeRepository.requestById(item.id); + return dataTypeDetailRepository.requestById(item.id); } return Promise.resolve(); }), ); // TODO: Use the asObservable from above onces end-point has been made. - const source = await dataTypeRepository.byPropertyEditorUiAlias(propertyEditorUiAlias); + const source = await dataTypeDetailRepository.byPropertyEditorUiAlias(propertyEditorUiAlias); this.observe(source, (dataTypes) => { this._dataTypes = dataTypes; }); diff --git a/src/packages/settings/data-types/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts b/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts similarity index 97% rename from src/packages/settings/data-types/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts rename to src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts index e58b76edd6..e10e843ca6 100644 --- a/src/packages/settings/data-types/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts +++ b/src/packages/core/data-type/modals/data-type-picker-flow/data-type-picker-flow-modal.element.ts @@ -1,4 +1,4 @@ -import { UmbDataTypeRepository } from '../../repository/data-type.repository.js'; +import { UmbDataTypeTreeRepository } from '../../tree/data-type-tree.repository.js'; import { css, html, repeat, customElement, property, state, when, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; @@ -51,14 +51,14 @@ export class UmbDataTypePickerFlowModalElement extends UmbLitElement { private _createDataTypeModal: UmbModalRouteRegistrationController; - #repository; + #treeRepository; #dataTypes: Array = []; #propertyEditorUIs: Array = []; #currentFilterQuery = ''; constructor() { super(); - this.#repository = new UmbDataTypeRepository(this); + this.#treeRepository = new UmbDataTypeTreeRepository(this); new UmbModalRouteRegistrationController(this, UMB_DATA_TYPE_PICKER_FLOW_DATA_TYPE_PICKER_MODAL) .addAdditionalPath(':uiAlias') @@ -102,7 +102,7 @@ export class UmbDataTypePickerFlowModalElement extends UmbLitElement { async #init() { // TODO: Get ALL items, or traverse the structure aka. multiple recursive calls. this.observe( - (await this.#repository.requestRootTreeItems()).asObservable(), + (await this.#treeRepository.requestRootTreeItems()).asObservable(), (items) => { this.#dataTypes = items; this._performFiltering(); diff --git a/src/packages/settings/data-types/modals/manifests.ts b/src/packages/core/data-type/modals/manifests.ts similarity index 100% rename from src/packages/settings/data-types/modals/manifests.ts rename to src/packages/core/data-type/modals/manifests.ts diff --git a/src/packages/settings/data-types/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts b/src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts similarity index 100% rename from src/packages/settings/data-types/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts rename to src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.element.ts diff --git a/src/packages/settings/data-types/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts b/src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts similarity index 91% rename from src/packages/settings/data-types/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts rename to src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts index 8a28a9e4af..f3f5cdcb04 100644 --- a/src/packages/settings/data-types/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts +++ b/src/packages/core/data-type/modals/property-editor-ui-picker/property-editor-ui-picker-modal.stories.ts @@ -4,7 +4,7 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUIPickerModalData } from '@umbraco-cms/backoffice/modal'; import './property-editor-ui-picker-modal.element.js'; -import '../../../../core/components/body-layout/body-layout.element.js'; +import '../../../components/body-layout/body-layout.element.js'; export default { title: 'API/Modals/Layouts/Property Editor UI Picker', diff --git a/src/packages/settings/data-types/models.ts b/src/packages/core/data-type/models.ts similarity index 100% rename from src/packages/settings/data-types/models.ts rename to src/packages/core/data-type/models.ts diff --git a/src/packages/core/data-type/repository/copy/data-type-copy.repository.ts b/src/packages/core/data-type/repository/copy/data-type-copy.repository.ts new file mode 100644 index 0000000000..80f6b2b196 --- /dev/null +++ b/src/packages/core/data-type/repository/copy/data-type-copy.repository.ts @@ -0,0 +1,39 @@ +import { UmbDataTypeRepositoryBase } from '../data-type-repository-base.js'; +import { UmbDataTypeDetailRepository } from '../detail/data-type-detail.repository.js'; +import { UmbDataTypeCopyServerDataSource } from './data-type-copy.server.data-source.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbCopyDataSource, UmbCopyRepository } from '@umbraco-cms/backoffice/repository'; + +export class UmbCopyDataTypeRepository extends UmbDataTypeRepositoryBase implements UmbCopyRepository { + #copySource: UmbCopyDataSource; + #detailRepository: UmbDataTypeDetailRepository; + + constructor(host: UmbControllerHost) { + super(host); + this.#copySource = new UmbDataTypeCopyServerDataSource(this); + this.#detailRepository = new UmbDataTypeDetailRepository(this); + } + + async copy(id: string, targetId: string | null) { + await this._init; + const { data: dataTypeCopyId, error } = await this.#copySource.copy(id, targetId); + if (error) return { error }; + + if (dataTypeCopyId) { + const { data: dataTypeCopy } = await this.#detailRepository.requestById(dataTypeCopyId); + if (!dataTypeCopy) throw new Error('Could not find copied data type'); + + // TODO: Be aware about this responsibility. + this._treeStore!.appendItems([dataTypeCopy]); + // only update the target if its not the root + if (targetId) { + this._treeStore!.updateItem(targetId, { hasChildren: true }); + } + + const notification = { data: { message: `Data type copied` } }; + this._notificationContext!.peek('positive', notification); + } + + return { data: dataTypeCopyId }; + } +} diff --git a/src/packages/settings/data-types/repository/sources/data-type-copy.server.data.ts b/src/packages/core/data-type/repository/copy/data-type-copy.server.data-source.ts similarity index 100% rename from src/packages/settings/data-types/repository/sources/data-type-copy.server.data.ts rename to src/packages/core/data-type/repository/copy/data-type-copy.server.data-source.ts diff --git a/src/packages/core/data-type/repository/copy/index.ts b/src/packages/core/data-type/repository/copy/index.ts new file mode 100644 index 0000000000..ebabb93e18 --- /dev/null +++ b/src/packages/core/data-type/repository/copy/index.ts @@ -0,0 +1,2 @@ +export { UmbCopyDataTypeRepository } from './data-type-copy.repository.js'; +export { COPY_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/packages/core/data-type/repository/copy/manifests.ts b/src/packages/core/data-type/repository/copy/manifests.ts new file mode 100644 index 0000000000..1942b6fd74 --- /dev/null +++ b/src/packages/core/data-type/repository/copy/manifests.ts @@ -0,0 +1,13 @@ +import { UmbCopyDataTypeRepository } from './data-type-copy.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +export const COPY_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Copy'; + +const copyRepository: ManifestRepository = { + type: 'repository', + alias: COPY_DATA_TYPE_REPOSITORY_ALIAS, + name: 'Copy Data Type Repository', + api: UmbCopyDataTypeRepository, +}; + +export const manifests = [copyRepository]; diff --git a/src/packages/core/data-type/repository/data-type-repository-base.ts b/src/packages/core/data-type/repository/data-type-repository-base.ts new file mode 100644 index 0000000000..8b3fc5eb5c --- /dev/null +++ b/src/packages/core/data-type/repository/data-type-repository-base.ts @@ -0,0 +1,38 @@ +import { UMB_DATA_TYPE_TREE_STORE_CONTEXT, UmbDataTypeTreeStore } from '../tree/data-type.tree.store.js'; +import { UMB_DATA_TYPE_ITEM_STORE_CONTEXT, UmbDataTypeItemStore } from './item/data-type-item.store.js'; +import { UMB_DATA_TYPE_STORE_CONTEXT, UmbDataTypeDetailStore } from './detail/data-type-detail.store.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UMB_NOTIFICATION_CONTEXT_TOKEN, UmbNotificationContext } from '@umbraco-cms/backoffice/notification'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbDataTypeRepositoryBase extends UmbRepositoryBase { + protected _init: Promise; + + protected _detailStore?: UmbDataTypeDetailStore; + protected _treeStore?: UmbDataTypeTreeStore; + protected _itemStore?: UmbDataTypeItemStore; + + protected _notificationContext?: UmbNotificationContext; + + constructor(host: UmbControllerHost) { + super(host); + + this._init = Promise.all([ + this.consumeContext(UMB_DATA_TYPE_STORE_CONTEXT, (instance) => { + this._detailStore = instance; + }).asPromise(), + + this.consumeContext(UMB_DATA_TYPE_TREE_STORE_CONTEXT, (instance) => { + this._treeStore = instance; + }).asPromise(), + + this.consumeContext(UMB_DATA_TYPE_ITEM_STORE_CONTEXT, (instance) => { + this._itemStore = instance; + }).asPromise(), + + this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => { + this._notificationContext = instance; + }).asPromise(), + ]); + } +} diff --git a/src/packages/core/data-type/repository/detail/data-type-detail.repository.ts b/src/packages/core/data-type/repository/detail/data-type-detail.repository.ts new file mode 100644 index 0000000000..d4db832676 --- /dev/null +++ b/src/packages/core/data-type/repository/detail/data-type-detail.repository.ts @@ -0,0 +1,119 @@ +import { UmbDataTypeRepositoryBase } from '../data-type-repository-base.js'; +import { createTreeItem } from '../utils.js'; +import { UmbDataTypeServerDataSource } from './data-type-detail.server.data-source.js'; +import type { UmbDetailRepository, UmbDataSource } from '@umbraco-cms/backoffice/repository'; +import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { + CreateDataTypeRequestModel, + DataTypeResponseModel, + UpdateDataTypeRequestModel, +} from '@umbraco-cms/backoffice/backend-api'; +export class UmbDataTypeDetailRepository + extends UmbDataTypeRepositoryBase + implements UmbDetailRepository +{ + #detailSource: UmbDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#detailSource = new UmbDataTypeServerDataSource(this); + } + + async createScaffold(parentId: string | null) { + if (parentId === undefined) throw new Error('Parent id is missing'); + await this._init; + + return this.#detailSource.createScaffold(parentId); + } + + async requestById(id: string) { + if (!id) throw new Error('Key is missing'); + await this._init; + + const { data, error } = await this.#detailSource.get(id); + + if (data) { + this._detailStore!.append(data); + } + + return { data, error, asObservable: () => this._detailStore!.byId(id) }; + } + + async byId(id: string) { + if (!id) throw new Error('Key is missing'); + await this._init; + return this._detailStore!.byId(id); + } + + async byPropertyEditorUiAlias(propertyEditorUiAlias: string) { + if (!propertyEditorUiAlias) throw new Error('propertyEditorUiAlias is missing'); + await this._init; + return this._detailStore!.withPropertyEditorUiAlias(propertyEditorUiAlias); + } + + async create(dataType: CreateDataTypeRequestModel) { + if (!dataType) throw new Error('Data Type is missing'); + if (!dataType.id) throw new Error('Data Type id is missing'); + await this._init; + + const { error } = await this.#detailSource.insert(dataType); + + if (!error) { + // TODO: We need to push a new item to the tree store to update the tree. How do we want to create the tree items? + const treeItem = createTreeItem(dataType); + this._treeStore!.appendItems([treeItem]); + //this.#detailStore?.append(dataType); + + const notification = { data: { message: `Data Type created` } }; + this._notificationContext!.peek('positive', notification); + } + + return { error }; + } + + async save(id: string, updatedDataType: UpdateDataTypeRequestModel) { + if (!id) throw new Error('Data Type id is missing'); + if (!updatedDataType) throw new Error('Data Type is missing'); + await this._init; + + const { error } = await this.#detailSource.update(id, updatedDataType); + + if (!error) { + // TODO: we currently don't use the detail store for anything. + // Consider to look up the data before fetching from the server + // Consider notify a workspace if a template is updated in the store while someone is editing it. + // TODO: would be nice to align the stores on methods/methodNames. + this._detailStore!.updateItem(id, updatedDataType); + // TODO: This is parsing on the full models to the tree and item store. Those should only contain the data they need. I don't know, at this point, if thats a repository or store responsibility. + this._treeStore!.updateItem(id, updatedDataType); + this._itemStore!.updateItem(id, updatedDataType); + + const notification = { data: { message: `Data Type saved` } }; + this._notificationContext!.peek('positive', notification); + } + + return { error }; + } + + async delete(id: string) { + if (!id) throw new Error('Data Type id is missing'); + await this._init; + + const { error } = await this.#detailSource.delete(id); + + if (!error) { + // TODO: we currently don't use the detail store for anything. + // Consider to look up the data before fetching from the server. + // Consider notify a workspace if a template is deleted from the store while someone is editing it. + // TODO: would be nice to align the stores on methods/methodNames. + this._detailStore!.removeItem(id); + this._treeStore!.removeItem(id); + this._itemStore!.removeItem(id); + + const notification = { data: { message: `Data Type deleted` } }; + this._notificationContext!.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/packages/settings/data-types/repository/sources/data-type.server.data.ts b/src/packages/core/data-type/repository/detail/data-type-detail.server.data-source.ts similarity index 100% rename from src/packages/settings/data-types/repository/sources/data-type.server.data.ts rename to src/packages/core/data-type/repository/detail/data-type-detail.server.data-source.ts diff --git a/src/packages/settings/data-types/repository/data-type.store.ts b/src/packages/core/data-type/repository/detail/data-type-detail.store.ts similarity index 61% rename from src/packages/settings/data-types/repository/data-type.store.ts rename to src/packages/core/data-type/repository/detail/data-type-detail.store.ts index ecf70e9d9a..abb4b1594a 100644 --- a/src/packages/settings/data-types/repository/data-type.store.ts +++ b/src/packages/core/data-type/repository/detail/data-type-detail.store.ts @@ -4,7 +4,7 @@ import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; import { UmbStoreBase } from '@umbraco-cms/backoffice/store'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -export const UMB_DATA_TYPE_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbDataTypeStore'); +export const UMB_DATA_TYPE_STORE_CONTEXT = new UmbContextToken('UmbDataTypeStore'); /** * @export @@ -12,27 +12,14 @@ export const UMB_DATA_TYPE_STORE_CONTEXT_TOKEN = new UmbContextToken { +export class UmbDataTypeDetailStore extends UmbStoreBase { /** * Creates an instance of UmbDataTypeStore. * @param {UmbControllerHostElement} host * @memberof UmbDataTypeStore */ constructor(host: UmbControllerHostElement) { - super( - host, - UMB_DATA_TYPE_STORE_CONTEXT_TOKEN.toString(), - new UmbArrayState([], (x) => x.id) - ); - } - - /** - * Append a data-type to the store - * @param {DataTypeModel} dataType - * @memberof UmbDataTypeStore - */ - append(dataType: DataTypeResponseModel) { - this._data.append([dataType]); + super(host, UMB_DATA_TYPE_STORE_CONTEXT.toString(), new UmbArrayState([], (x) => x.id)); } /** @@ -44,19 +31,10 @@ export class UmbDataTypeStore extends UmbStoreBase { return this._data.asObservablePart((x) => x.find((y) => y.id === id)); } - /** - * Removes data-types in the store with the given uniques - * @param {string[]} uniques - * @memberof UmbDataTypeStore - */ - remove(uniques: Array) { - this._data.remove(uniques); - } - withPropertyEditorUiAlias(propertyEditorUiAlias: string) { // TODO: Use a model for the data-type tree items: ^^Most likely it should be parsed to the UmbEntityTreeStore as a generic type. return this._data.asObservablePart((items) => - items.filter((item) => (item as any).propertyEditorUiAlias === propertyEditorUiAlias) + items.filter((item) => (item as any).propertyEditorUiAlias === propertyEditorUiAlias), ); } } diff --git a/src/packages/core/data-type/repository/detail/index.ts b/src/packages/core/data-type/repository/detail/index.ts new file mode 100644 index 0000000000..b691b917b7 --- /dev/null +++ b/src/packages/core/data-type/repository/detail/index.ts @@ -0,0 +1,2 @@ +export { UmbDataTypeDetailRepository } from './data-type-detail.repository.js'; +export { DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/packages/core/data-type/repository/detail/manifests.ts b/src/packages/core/data-type/repository/detail/manifests.ts new file mode 100644 index 0000000000..eb85c2cd90 --- /dev/null +++ b/src/packages/core/data-type/repository/detail/manifests.ts @@ -0,0 +1,23 @@ +import { UmbDataTypeDetailRepository } from './data-type-detail.repository.js'; +import { UmbDataTypeDetailStore } from './data-type-detail.store.js'; +import { ManifestRepository, ManifestStore } from '@umbraco-cms/backoffice/extension-registry'; + +export const DATA_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Detail'; + +const repository: ManifestRepository = { + type: 'repository', + alias: DATA_TYPE_DETAIL_REPOSITORY_ALIAS, + name: 'Data Type Detail Repository', + api: UmbDataTypeDetailRepository, +}; + +export const DATA_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.DataType.Detail'; + +const store: ManifestStore = { + type: 'store', + alias: DATA_TYPE_DETAIL_STORE_ALIAS, + name: 'Data Type Detail Store', + api: UmbDataTypeDetailStore, +}; + +export const manifests = [repository, store]; diff --git a/src/packages/core/data-type/repository/folder/data-type-folder.repository.ts b/src/packages/core/data-type/repository/folder/data-type-folder.repository.ts new file mode 100644 index 0000000000..31fc43a1eb --- /dev/null +++ b/src/packages/core/data-type/repository/folder/data-type-folder.repository.ts @@ -0,0 +1,69 @@ +import { UmbDataTypeRepositoryBase } from '../data-type-repository-base.js'; +import { createFolderTreeItem } from '../utils.js'; +import { UmbDataTypeFolderServerDataSource } from './data-type-folder.server.data.js'; +import type { UmbFolderRepository, UmbFolderDataSource } from '@umbraco-cms/backoffice/repository'; +import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { CreateFolderRequestModel, FolderModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; +export class UmbDataTypeFolderRepository extends UmbDataTypeRepositoryBase implements UmbFolderRepository { + #folderSource: UmbFolderDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#folderSource = new UmbDataTypeFolderServerDataSource(this); + } + + async createFolderScaffold(parentId: string | null) { + if (parentId === undefined) throw new Error('Parent id is missing'); + await this._init; + return this.#folderSource.createScaffold(parentId); + } + + // TODO: temp create type until backend is ready. Remove the id addition when new types are generated. + async createFolder(folderRequest: CreateFolderRequestModel & { id?: string | undefined }) { + if (!folderRequest) throw new Error('folder request is missing'); + await this._init; + + const { error } = await this.#folderSource.insert(folderRequest); + + if (!error) { + // TODO: We need to push a new item to the tree store to update the tree. How do we want to create the tree items? + const folderTreeItem = createFolderTreeItem(folderRequest); + this._treeStore!.appendItems([folderTreeItem]); + } + + return { error }; + } + + async deleteFolder(id: string) { + if (!id) throw new Error('Key is missing'); + await this._init; + + const { error } = await this.#folderSource.delete(id); + + if (!error) { + this._treeStore!.removeItem(id); + } + + return { error }; + } + + async updateFolder(id: string, folder: FolderModelBaseModel) { + if (!id) throw new Error('Key is missing'); + if (!folder) throw new Error('Folder data is missing'); + await this._init; + + const { error } = await this.#folderSource.update(id, folder); + + if (!error) { + this._treeStore!.updateItem(id, { name: folder.name }); + } + + return { error }; + } + + async requestFolder(id: string) { + if (!id) throw new Error('Key is missing'); + await this._init; + return await this.#folderSource.get(id); + } +} diff --git a/src/packages/settings/data-types/repository/sources/data-type-folder.server.data.ts b/src/packages/core/data-type/repository/folder/data-type-folder.server.data.ts similarity index 100% rename from src/packages/settings/data-types/repository/sources/data-type-folder.server.data.ts rename to src/packages/core/data-type/repository/folder/data-type-folder.server.data.ts diff --git a/src/packages/core/data-type/repository/folder/index.ts b/src/packages/core/data-type/repository/folder/index.ts new file mode 100644 index 0000000000..ef32956db8 --- /dev/null +++ b/src/packages/core/data-type/repository/folder/index.ts @@ -0,0 +1,2 @@ +export { UmbDataTypeFolderRepository } from './data-type-folder.repository.js'; +export { DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/packages/core/data-type/repository/folder/manifests.ts b/src/packages/core/data-type/repository/folder/manifests.ts new file mode 100644 index 0000000000..2adca73033 --- /dev/null +++ b/src/packages/core/data-type/repository/folder/manifests.ts @@ -0,0 +1,13 @@ +import { UmbDataTypeFolderRepository } from './data-type-folder.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +export const DATA_TYPE_FOLDER_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Folder'; + +const folderRepository: ManifestRepository = { + type: 'repository', + alias: DATA_TYPE_FOLDER_REPOSITORY_ALIAS, + name: 'Data Type Folder Repository', + api: UmbDataTypeFolderRepository, +}; + +export const manifests = [folderRepository]; diff --git a/src/packages/core/data-type/repository/index.ts b/src/packages/core/data-type/repository/index.ts new file mode 100644 index 0000000000..52aa032705 --- /dev/null +++ b/src/packages/core/data-type/repository/index.ts @@ -0,0 +1,5 @@ +export { UmbCopyDataTypeRepository, COPY_DATA_TYPE_REPOSITORY_ALIAS } from './copy/index.js'; +export { UmbDataTypeDetailRepository, DATA_TYPE_DETAIL_REPOSITORY_ALIAS } from './detail/index.js'; +export { UmbDataTypeFolderRepository, DATA_TYPE_FOLDER_REPOSITORY_ALIAS } from './folder/index.js'; +export { UmbDataTypeItemRepository, DATA_TYPE_ITEM_REPOSITORY_ALIAS } from './item/index.js'; +export { UmbMoveDataTypeRepository, MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './move/index.js'; diff --git a/src/packages/core/data-type/repository/item/data-type-item.repository.ts b/src/packages/core/data-type/repository/item/data-type-item.repository.ts new file mode 100644 index 0000000000..faa193daad --- /dev/null +++ b/src/packages/core/data-type/repository/item/data-type-item.repository.ts @@ -0,0 +1,47 @@ +import { UmbDataTypeRepositoryBase } from '../data-type-repository-base.js'; +import { UmbDataTypeItemServerDataSource } from './data-type-item.server.data.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbItemDataSource, UmbItemRepository } from '@umbraco-cms/backoffice/repository'; +import { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; + +export class UmbDataTypeItemRepository + extends UmbDataTypeRepositoryBase + implements UmbItemRepository +{ + #itemSource: UmbItemDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#itemSource = new UmbDataTypeItemServerDataSource(host); + } + + /** + * Requests the Data Type items for the given ids + * @param {Array} ids + * @return {*} + * @memberof UmbDataTypeItemRepository + */ + async requestItems(ids: Array) { + if (!ids) throw new Error('Ids are missing'); + await this._init; + + const { data, error } = await this.#itemSource.getItems(ids); + + if (data) { + this._itemStore!.appendItems(data); + } + + return { data, error, asObservable: () => this._itemStore!.items(ids) }; + } + + /** + * Returns a promise with an observable of the Data Type items for the given ids + * @param {Array} ids + * @return {Promise>} + * @memberof UmbDataTypeItemRepository + */ + async items(ids: Array) { + await this._init; + return this._itemStore!.items(ids); + } +} diff --git a/src/packages/settings/data-types/repository/sources/data-type-item.server.data.ts b/src/packages/core/data-type/repository/item/data-type-item.server.data.ts similarity index 100% rename from src/packages/settings/data-types/repository/sources/data-type-item.server.data.ts rename to src/packages/core/data-type/repository/item/data-type-item.server.data.ts diff --git a/src/packages/core/data-type/repository/item/data-type-item.store.ts b/src/packages/core/data-type/repository/item/data-type-item.store.ts new file mode 100644 index 0000000000..85496e4315 --- /dev/null +++ b/src/packages/core/data-type/repository/item/data-type-item.store.ts @@ -0,0 +1,24 @@ +import { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbEntityItemStore } from '@umbraco-cms/backoffice/store'; + +/** + * @export + * @class UmbDataTypeItemStore + * @extends {UmbStoreBase} + * @description - Data Store for Data Type items + */ + +export class UmbDataTypeItemStore extends UmbEntityItemStore { + /** + * Creates an instance of UmbDataTypeItemStore. + * @param {UmbControllerHost} host + * @memberof UmbDataTypeItemStore + */ + constructor(host: UmbControllerHost) { + super(host, UMB_DATA_TYPE_ITEM_STORE_CONTEXT.toString()); + } +} + +export const UMB_DATA_TYPE_ITEM_STORE_CONTEXT = new UmbContextToken('UmbDataTypeItemStore'); diff --git a/src/packages/core/data-type/repository/item/index.ts b/src/packages/core/data-type/repository/item/index.ts new file mode 100644 index 0000000000..f275e6249f --- /dev/null +++ b/src/packages/core/data-type/repository/item/index.ts @@ -0,0 +1,2 @@ +export { UmbDataTypeItemRepository } from './data-type-item.repository.js'; +export { DATA_TYPE_ITEM_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/packages/core/data-type/repository/item/manifests.ts b/src/packages/core/data-type/repository/item/manifests.ts new file mode 100644 index 0000000000..e6f147f713 --- /dev/null +++ b/src/packages/core/data-type/repository/item/manifests.ts @@ -0,0 +1,22 @@ +import { UmbDataTypeItemStore } from './data-type-item.store.js'; +import { UmbDataTypeItemRepository } from './data-type-item.repository.js'; +import type { ManifestRepository, ManifestItemStore } from '@umbraco-cms/backoffice/extension-registry'; + +export const DATA_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.DataTypeItem'; +export const DATA_TYPE_STORE_ALIAS = 'Umb.Store.DataTypeItem'; + +const itemRepository: ManifestRepository = { + type: 'repository', + alias: DATA_TYPE_ITEM_REPOSITORY_ALIAS, + name: 'Data Type Item Repository', + api: UmbDataTypeItemRepository, +}; + +const itemStore: ManifestItemStore = { + type: 'itemStore', + alias: DATA_TYPE_STORE_ALIAS, + name: 'Data Type Item Store', + api: UmbDataTypeItemStore, +}; + +export const manifests = [itemRepository, itemStore]; diff --git a/src/packages/core/data-type/repository/manifests.ts b/src/packages/core/data-type/repository/manifests.ts new file mode 100644 index 0000000000..2b0f5501cf --- /dev/null +++ b/src/packages/core/data-type/repository/manifests.ts @@ -0,0 +1,7 @@ +import { manifests as copyManifests } from './copy/manifests.js'; +import { manifests as detailManifests } from './detail/manifests.js'; +import { manifests as folderManifests } from './folder/manifests.js'; +import { manifests as itemManifests } from './item/manifests.js'; +import { manifests as moveManifests } from './move/manifests.js'; + +export const manifests = [...copyManifests, ...detailManifests, ...folderManifests, ...itemManifests, ...moveManifests]; diff --git a/src/packages/core/data-type/repository/move/data-type-move.repository.ts b/src/packages/core/data-type/repository/move/data-type-move.repository.ts new file mode 100644 index 0000000000..dff65b3df0 --- /dev/null +++ b/src/packages/core/data-type/repository/move/data-type-move.repository.ts @@ -0,0 +1,32 @@ +import { UmbDataTypeRepositoryBase } from '../data-type-repository-base.js'; +import { UmbDataTypeMoveServerDataSource } from './data-type-move.server.data-source.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbMoveDataSource, UmbMoveRepository } from '@umbraco-cms/backoffice/repository'; + +export class UmbMoveDataTypeRepository extends UmbDataTypeRepositoryBase implements UmbMoveRepository { + #moveSource: UmbMoveDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#moveSource = new UmbDataTypeMoveServerDataSource(this); + } + + async move(id: string, targetId: string | null) { + await this._init; + const { error } = await this.#moveSource.move(id, targetId); + + if (!error) { + // TODO: Be aware about this responsibility. + this._treeStore!.updateItem(id, { parentId: targetId }); + // only update the target if its not the root + if (targetId) { + this._treeStore!.updateItem(targetId, { hasChildren: true }); + } + + const notification = { data: { message: `Data type moved` } }; + this._notificationContext!.peek('positive', notification); + } + + return { error }; + } +} diff --git a/src/packages/settings/data-types/repository/sources/data-type-move.server.data.ts b/src/packages/core/data-type/repository/move/data-type-move.server.data-source.ts similarity index 100% rename from src/packages/settings/data-types/repository/sources/data-type-move.server.data.ts rename to src/packages/core/data-type/repository/move/data-type-move.server.data-source.ts diff --git a/src/packages/core/data-type/repository/move/index.ts b/src/packages/core/data-type/repository/move/index.ts new file mode 100644 index 0000000000..11b6ea4a50 --- /dev/null +++ b/src/packages/core/data-type/repository/move/index.ts @@ -0,0 +1,2 @@ +export { UmbMoveDataTypeRepository } from './data-type-move.repository.js'; +export { MOVE_DATA_TYPE_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/packages/core/data-type/repository/move/manifests.ts b/src/packages/core/data-type/repository/move/manifests.ts new file mode 100644 index 0000000000..e383524891 --- /dev/null +++ b/src/packages/core/data-type/repository/move/manifests.ts @@ -0,0 +1,13 @@ +import { UmbMoveDataTypeRepository } from './data-type-move.repository.js'; +import type { ManifestRepository } from '@umbraco-cms/backoffice/extension-registry'; + +export const MOVE_DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Move'; + +const moveRepository: ManifestRepository = { + type: 'repository', + alias: MOVE_DATA_TYPE_REPOSITORY_ALIAS, + name: 'Move Data Type Repository', + api: UmbMoveDataTypeRepository, +}; + +export const manifests = [moveRepository]; diff --git a/src/packages/core/data-type/repository/utils.ts b/src/packages/core/data-type/repository/utils.ts new file mode 100644 index 0000000000..45a7297191 --- /dev/null +++ b/src/packages/core/data-type/repository/utils.ts @@ -0,0 +1,30 @@ +import { + CreateDataTypeRequestModel, + CreateFolderRequestModel, + FolderTreeItemResponseModel, +} from '@umbraco-cms/backoffice/backend-api'; + +export const createTreeItem = (item: CreateDataTypeRequestModel): FolderTreeItemResponseModel => { + if (!item) throw new Error('item is null or undefined'); + if (!item.id) throw new Error('item.id is null or undefined'); + + return { + type: 'data-type', + parentId: item.parentId, + name: item.name, + id: item.id, + isFolder: false, + isContainer: false, + hasChildren: false, + }; +}; + +export const createFolderTreeItem = (item: CreateFolderRequestModel): FolderTreeItemResponseModel => { + if (!item) throw new Error('item is null or undefined'); + if (!item.id) throw new Error('item.id is null or undefined'); + + return { + ...createTreeItem(item), + isFolder: true, + }; +}; diff --git a/src/packages/core/data-type/tree/data-type-tree.repository.ts b/src/packages/core/data-type/tree/data-type-tree.repository.ts new file mode 100644 index 0000000000..991941fa25 --- /dev/null +++ b/src/packages/core/data-type/tree/data-type-tree.repository.ts @@ -0,0 +1,68 @@ +import { DATA_TYPE_ROOT_ENTITY_TYPE } from '../entities.js'; +import { UmbDataTypeRepositoryBase } from '../repository/data-type-repository-base.js'; +import { UmbDataTypeTreeServerDataSource } from './data-type.tree.server.data.js'; +import type { UmbTreeRepository, UmbTreeDataSource } from '@umbraco-cms/backoffice/repository'; +import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { FolderTreeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbApi } from '@umbraco-cms/backoffice/extension-api'; +export class UmbDataTypeTreeRepository + extends UmbDataTypeRepositoryBase + implements UmbTreeRepository, UmbApi +{ + #treeSource: UmbTreeDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#treeSource = new UmbDataTypeTreeServerDataSource(this); + } + + async requestTreeRoot() { + await this._init; + + const data = { + id: null, + type: DATA_TYPE_ROOT_ENTITY_TYPE, + name: 'Data Types', + icon: 'icon-folder', + hasChildren: true, + }; + + return { data }; + } + + async requestRootTreeItems() { + await this._init; + + const { data, error } = await this.#treeSource.getRootItems(); + + if (data) { + this._treeStore!.appendItems(data.items); + } + + return { data, error, asObservable: () => this._treeStore!.rootItems }; + } + + async requestTreeItemsOf(parentId: string | null) { + await this._init; + if (parentId === undefined) throw new Error('Parent id is missing'); + + const { data, error } = await this.#treeSource.getChildrenOf(parentId); + + if (data) { + this._treeStore!.appendItems(data.items); + } + + return { data, error, asObservable: () => this._treeStore!.childrenOf(parentId) }; + } + + async rootTreeItems() { + await this._init; + return this._treeStore!.rootItems; + } + + async treeItemsOf(parentId: string | null) { + if (parentId === undefined) throw new Error('Parent id is missing'); + await this._init; + return this._treeStore!.childrenOf(parentId); + } +} diff --git a/src/packages/settings/data-types/repository/sources/data-type.tree.server.data.ts b/src/packages/core/data-type/tree/data-type.tree.server.data.ts similarity index 100% rename from src/packages/settings/data-types/repository/sources/data-type.tree.server.data.ts rename to src/packages/core/data-type/tree/data-type.tree.server.data.ts diff --git a/src/packages/settings/data-types/repository/data-type.tree.store.ts b/src/packages/core/data-type/tree/data-type.tree.store.ts similarity index 63% rename from src/packages/settings/data-types/repository/data-type.tree.store.ts rename to src/packages/core/data-type/tree/data-type.tree.store.ts index d2dc4686d8..4f41e6642a 100644 --- a/src/packages/settings/data-types/repository/data-type.tree.store.ts +++ b/src/packages/core/data-type/tree/data-type.tree.store.ts @@ -6,9 +6,8 @@ import { UmbEntityTreeStore } from '@umbraco-cms/backoffice/store'; * @export * @class UmbDataTypeTreeStore * @extends {UmbStoreBase} - * @description - Tree Data Store for Data-Types + * @description - Tree Data Store for Data Types */ -// TODO: consider if tree store could be turned into a general EntityTreeStore class? export class UmbDataTypeTreeStore extends UmbEntityTreeStore { /** * Creates an instance of UmbDataTypeTreeStore. @@ -16,8 +15,8 @@ export class UmbDataTypeTreeStore extends UmbEntityTreeStore { * @memberof UmbDataTypeTreeStore */ constructor(host: UmbControllerHostElement) { - super(host, UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN.toString()); + super(host, UMB_DATA_TYPE_TREE_STORE_CONTEXT.toString()); } } -export const UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbDataTypeTreeStore'); +export const UMB_DATA_TYPE_TREE_STORE_CONTEXT = new UmbContextToken('UmbDataTypeTreeStore'); diff --git a/src/packages/core/data-type/tree/manifests.ts b/src/packages/core/data-type/tree/manifests.ts new file mode 100644 index 0000000000..6b3f880fe4 --- /dev/null +++ b/src/packages/core/data-type/tree/manifests.ts @@ -0,0 +1,46 @@ +import { UmbDataTypeTreeRepository } from './data-type-tree.repository.js'; +import { UmbDataTypeTreeStore } from './data-type.tree.store.js'; +import type { + ManifestRepository, + ManifestTree, + ManifestTreeItem, + ManifestTreeStore, +} from '@umbraco-cms/backoffice/extension-registry'; + +export const DATA_TYPE_TREE_REPOSITORY_ALIAS = 'Umb.Repository.DataType.Tree'; +export const DATA_TYPE_TREE_STORE_ALIAS = 'Umb.Store.DataType.Tree'; + +const treeRepository: ManifestRepository = { + type: 'repository', + alias: DATA_TYPE_TREE_REPOSITORY_ALIAS, + name: 'Data Type Tree Repository', + api: UmbDataTypeTreeRepository, +}; + +const treeStore: ManifestTreeStore = { + type: 'treeStore', + alias: DATA_TYPE_TREE_STORE_ALIAS, + name: 'Data Type Tree Store', + api: UmbDataTypeTreeStore, +}; + +const tree: ManifestTree = { + type: 'tree', + alias: 'Umb.Tree.DataTypes', + name: 'Data Types Tree', + meta: { + repositoryAlias: DATA_TYPE_TREE_REPOSITORY_ALIAS, + }, +}; + +const treeItem: ManifestTreeItem = { + type: 'treeItem', + kind: 'entity', + alias: 'Umb.TreeItem.DataType', + name: 'Data Type Tree Item', + meta: { + entityTypes: ['data-type-root', 'data-type'], + }, +}; + +export const manifests = [treeRepository, treeStore, tree, treeItem]; diff --git a/src/packages/settings/data-types/variant-context/data-type-variant-context.token.ts b/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts similarity index 100% rename from src/packages/settings/data-types/variant-context/data-type-variant-context.token.ts rename to src/packages/core/data-type/variant-context/data-type-variant-context.token.ts diff --git a/src/packages/settings/data-types/variant-context/data-type-variant-context.ts b/src/packages/core/data-type/variant-context/data-type-variant-context.ts similarity index 100% rename from src/packages/settings/data-types/variant-context/data-type-variant-context.ts rename to src/packages/core/data-type/variant-context/data-type-variant-context.ts diff --git a/src/packages/settings/data-types/variant-context/index.ts b/src/packages/core/data-type/variant-context/index.ts similarity index 100% rename from src/packages/settings/data-types/variant-context/index.ts rename to src/packages/core/data-type/variant-context/index.ts diff --git a/src/packages/settings/data-types/workspace/data-type-workspace-editor.element.ts b/src/packages/core/data-type/workspace/data-type-workspace-editor.element.ts similarity index 100% rename from src/packages/settings/data-types/workspace/data-type-workspace-editor.element.ts rename to src/packages/core/data-type/workspace/data-type-workspace-editor.element.ts diff --git a/src/packages/settings/data-types/workspace/data-type-workspace.context.ts b/src/packages/core/data-type/workspace/data-type-workspace.context.ts similarity index 97% rename from src/packages/settings/data-types/workspace/data-type-workspace.context.ts rename to src/packages/core/data-type/workspace/data-type-workspace.context.ts index 8c91ba0078..cb84c569bd 100644 --- a/src/packages/settings/data-types/workspace/data-type-workspace.context.ts +++ b/src/packages/core/data-type/workspace/data-type-workspace.context.ts @@ -1,4 +1,4 @@ -import { UmbDataTypeRepository } from '../repository/data-type.repository.js'; +import { UmbDataTypeDetailRepository } from '../repository/detail/data-type-detail.repository.js'; import { UmbDataTypeVariantContext } from '../variant-context/data-type-variant-context.js'; import { UmbInvariantableWorkspaceContextInterface, @@ -23,7 +23,7 @@ import { import { UMB_PROPERTY_EDITOR_SCHEMA_ALIAS_DEFAULT } from '@umbraco-cms/backoffice/property-editor'; export class UmbDataTypeWorkspaceContext - extends UmbWorkspaceContext + extends UmbWorkspaceContext implements UmbInvariantableWorkspaceContextInterface { // TODO: revisit. temp solution because the create and response models are different. @@ -62,7 +62,7 @@ export class UmbDataTypeWorkspaceContext propertyEditorUiName = this.#propertyEditorUiName.asObservable(); constructor(host: UmbControllerHostElement) { - super(host, 'Umb.Workspace.DataType', new UmbDataTypeRepository(host)); + super(host, 'Umb.Workspace.DataType', new UmbDataTypeDetailRepository(host)); this.#observePropertyEditorUIAlias(); } diff --git a/src/packages/settings/data-types/workspace/data-type-workspace.element.ts b/src/packages/core/data-type/workspace/data-type-workspace.element.ts similarity index 100% rename from src/packages/settings/data-types/workspace/data-type-workspace.element.ts rename to src/packages/core/data-type/workspace/data-type-workspace.element.ts diff --git a/src/packages/settings/data-types/workspace/data-type-workspace.stories.ts b/src/packages/core/data-type/workspace/data-type-workspace.stories.ts similarity index 100% rename from src/packages/settings/data-types/workspace/data-type-workspace.stories.ts rename to src/packages/core/data-type/workspace/data-type-workspace.stories.ts diff --git a/src/packages/settings/data-types/workspace/manifests.ts b/src/packages/core/data-type/workspace/manifests.ts similarity index 100% rename from src/packages/settings/data-types/workspace/manifests.ts rename to src/packages/core/data-type/workspace/manifests.ts diff --git a/src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.element.ts b/src/packages/core/data-type/workspace/views/details/data-type-details-workspace-view.element.ts similarity index 100% rename from src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.element.ts rename to src/packages/core/data-type/workspace/views/details/data-type-details-workspace-view.element.ts diff --git a/src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.stories.ts b/src/packages/core/data-type/workspace/views/details/data-type-details-workspace-view.stories.ts similarity index 100% rename from src/packages/settings/data-types/workspace/views/details/data-type-details-workspace-view.stories.ts rename to src/packages/core/data-type/workspace/views/details/data-type-details-workspace-view.stories.ts diff --git a/src/packages/settings/data-types/workspace/views/info/workspace-view-data-type-info.element.ts b/src/packages/core/data-type/workspace/views/info/workspace-view-data-type-info.element.ts similarity index 100% rename from src/packages/settings/data-types/workspace/views/info/workspace-view-data-type-info.element.ts rename to src/packages/core/data-type/workspace/views/info/workspace-view-data-type-info.element.ts diff --git a/src/packages/settings/data-types/workspace/views/info/workspace-view-data-type-info.stories.ts b/src/packages/core/data-type/workspace/views/info/workspace-view-data-type-info.stories.ts similarity index 100% rename from src/packages/settings/data-types/workspace/views/info/workspace-view-data-type-info.stories.ts rename to src/packages/core/data-type/workspace/views/info/workspace-view-data-type-info.stories.ts diff --git a/src/packages/core/entity-action/common/delete/delete.action.ts b/src/packages/core/entity-action/common/delete/delete.action.ts index 6b8937376b..fb7cf41bae 100644 --- a/src/packages/core/entity-action/common/delete/delete.action.ts +++ b/src/packages/core/entity-action/common/delete/delete.action.ts @@ -9,7 +9,7 @@ import { import { UmbDetailRepository, UmbItemRepository } from '@umbraco-cms/backoffice/repository'; export class UmbDeleteEntityAction< - T extends UmbDetailRepository & UmbItemRepository + T extends UmbDetailRepository & UmbItemRepository, > extends UmbEntityActionBase { #modalManager?: UmbModalManagerContext; @@ -24,20 +24,17 @@ export class UmbDeleteEntityAction< async execute() { if (!this.repository || !this.#modalManager) return; - const { data } = await this.repository.requestItems([this.unique]); + // TOOD: add back when entity actions can support multiple repositories + //const { data } = await this.repository.requestItems([this.unique]); - if (data) { - const item = data[0]; - - const modalContext = this.#modalManager.open(UMB_CONFIRM_MODAL, { - headline: `Delete ${item.name}`, - content: 'Are you sure you want to delete this item?', - color: 'danger', - confirmLabel: 'Delete', - }); + const modalContext = this.#modalManager.open(UMB_CONFIRM_MODAL, { + headline: `Delete`, + content: 'Are you sure you want to delete this item?', + color: 'danger', + confirmLabel: 'Delete', + }); - await modalContext.onSubmit(); - await this.repository?.delete(this.unique); - } + await modalContext.onSubmit(); + await this.repository?.delete(this.unique); } } diff --git a/src/packages/core/index.ts b/src/packages/core/index.ts index b33a8ccec8..224ccf7bbe 100644 --- a/src/packages/core/index.ts +++ b/src/packages/core/index.ts @@ -10,6 +10,7 @@ import { manifests as modalManifests } from './modal/common/manifests.js'; import { manifests as themeManifests } from './themes/manifests.js'; import { manifests as conditionManifests } from './extension-registry/conditions/manifests.js'; import { manifests as cultureManifests } from './culture/manifests.js'; +import { manifests as dataTypeManifests } from './data-type/manifests.js'; import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; @@ -53,10 +54,10 @@ const manifests: Array = [ ...modalManifests, ...themeManifests, ...cultureManifests, + ...dataTypeManifests, ]; export const onInit: UmbEntryPointOnInit = (host, extensionRegistry) => { - new UmbExtensionsApiInitializer(host, extensionRegistry, 'globalContext', [host]); new UmbExtensionsApiInitializer(host, extensionRegistry, 'store', [host]); new UmbExtensionsApiInitializer(host, extensionRegistry, 'treeStore', [host]); diff --git a/src/packages/core/store/entity-item.store.ts b/src/packages/core/store/entity-item.store.ts new file mode 100644 index 0000000000..1dd276bb6e --- /dev/null +++ b/src/packages/core/store/entity-item.store.ts @@ -0,0 +1,29 @@ +import { ItemResponseModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; +import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbItemStore, UmbStoreBase } from '@umbraco-cms/backoffice/store'; +import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; + +/** + * @export + * @class UmbDataTypeItemStore + * @extends {UmbStoreBase} + * @description - Data Store for Data Type items + */ + +export class UmbEntityItemStore + extends UmbStoreBase + implements UmbItemStore +{ + /** + * Creates an instance of UmbEntityItemStore. + * @param {UmbControllerHost} host + * @memberof UmbDataTypeItemStore + */ + constructor(host: UmbControllerHost, storeAlias: string) { + super(host, storeAlias, new UmbArrayState([], (x) => x.id)); + } + + items(ids: Array) { + return this._data.asObservablePart((items) => items.filter((item) => ids.includes(item.id ?? ''))); + } +} diff --git a/src/packages/core/store/index.ts b/src/packages/core/store/index.ts index 0ab513ac78..e7a8e58d35 100644 --- a/src/packages/core/store/index.ts +++ b/src/packages/core/store/index.ts @@ -5,3 +5,4 @@ export * from './store-base.js'; export * from './store.interface.js'; export * from './store.js'; export * from './tree-store.interface.js'; +export * from './entity-item.store.js'; diff --git a/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts b/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts index dfa537e44d..b6ec53b101 100644 --- a/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts +++ b/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts @@ -1,3 +1,4 @@ +import { UmbDataTypeDetailRepository } from '@umbraco-cms/backoffice/data-type'; import { UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, customElement, property, state, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { PropertyTypeModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; @@ -11,7 +12,6 @@ import { } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { generateAlias } from '@umbraco-cms/backoffice/utils'; -import { UmbDataTypeRepository } from '@umbraco-cms/backoffice/data-type'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; /** @@ -53,7 +53,7 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { @property({ type: Boolean, reflect: true, attribute: 'sort-mode-active' }) public sortModeActive = false; - #dataTypeRepository = new UmbDataTypeRepository(this); + #dataTypeDetailRepository = new UmbDataTypeDetailRepository(this); #modalRegistration; private _modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT_TOKEN.TYPE; @@ -80,7 +80,7 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { async setDataType(dataTypeId: string | undefined) { if (!dataTypeId) return; - this.#dataTypeRepository.requestById(dataTypeId).then((x) => (this._dataTypeName = x?.data?.name)); + this.#dataTypeDetailRepository.requestById(dataTypeId).then((x) => (this._dataTypeName = x?.data?.name)); } constructor() { diff --git a/src/packages/settings/data-types/repository/data-type-item.store.ts b/src/packages/settings/data-types/repository/data-type-item.store.ts deleted file mode 100644 index 80784cfef4..0000000000 --- a/src/packages/settings/data-types/repository/data-type-item.store.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { DataTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -import { UmbItemStore, UmbStoreBase } from '@umbraco-cms/backoffice/store'; -import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; - -/** - * @export - * @class UmbDataTypeItemStore - * @extends {UmbStoreBase} - * @description - Data Store for Data Type items - */ - -export class UmbDataTypeItemStore - extends UmbStoreBase - implements UmbItemStore -{ - /** - * Creates an instance of UmbDataTypeItemStore. - * @param {UmbControllerHostElement} host - * @memberof UmbDataTypeItemStore - */ - constructor(host: UmbControllerHostElement) { - super( - host, - UMB_DATA_TYPE_ITEM_STORE_CONTEXT_TOKEN.toString(), - new UmbArrayState([], (x) => x.id) - ); - } - - items(ids: Array) { - return this._data.asObservablePart((items) => items.filter((item) => ids.includes(item.id ?? ''))); - } -} - -export const UMB_DATA_TYPE_ITEM_STORE_CONTEXT_TOKEN = new UmbContextToken('UmbDataTypeItemStore'); diff --git a/src/packages/settings/data-types/repository/data-type.repository.ts b/src/packages/settings/data-types/repository/data-type.repository.ts deleted file mode 100644 index 1c029417fa..0000000000 --- a/src/packages/settings/data-types/repository/data-type.repository.ts +++ /dev/null @@ -1,385 +0,0 @@ -import { DATA_TYPE_ROOT_ENTITY_TYPE } from '../entities.js'; -import { UmbDataTypeTreeServerDataSource } from './sources/data-type.tree.server.data.js'; -import { UmbDataTypeMoveServerDataSource } from './sources/data-type-move.server.data.js'; -import { UmbDataTypeStore, UMB_DATA_TYPE_STORE_CONTEXT_TOKEN } from './data-type.store.js'; -import { UmbDataTypeServerDataSource } from './sources/data-type.server.data.js'; -import { UmbDataTypeTreeStore, UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN } from './data-type.tree.store.js'; -import { UmbDataTypeFolderServerDataSource } from './sources/data-type-folder.server.data.js'; -import { UmbDataTypeItemServerDataSource } from './sources/data-type-item.server.data.js'; -import { UMB_DATA_TYPE_ITEM_STORE_CONTEXT_TOKEN, UmbDataTypeItemStore } from './data-type-item.store.js'; -import { UmbDataTypeCopyServerDataSource } from './sources/data-type-copy.server.data.js'; -import type { - UmbTreeRepository, - UmbDetailRepository, - UmbItemRepository, - UmbFolderRepository, - UmbMoveRepository, - UmbCopyRepository, - UmbTreeDataSource, - UmbDataSource, - UmbFolderDataSource, - UmbItemDataSource, - UmbMoveDataSource, - UmbCopyDataSource, -} from '@umbraco-cms/backoffice/repository'; -import { UmbBaseController, type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { - CreateDataTypeRequestModel, - CreateFolderRequestModel, - DataTypeItemResponseModel, - DataTypeResponseModel, - FolderModelBaseModel, - FolderTreeItemResponseModel, - UpdateDataTypeRequestModel, -} from '@umbraco-cms/backoffice/backend-api'; -import { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/notification'; -import { UmbApi } from '@umbraco-cms/backoffice/extension-api'; -export class UmbDataTypeRepository extends UmbBaseController - implements - UmbItemRepository, - UmbTreeRepository, - UmbDetailRepository, - UmbFolderRepository, - UmbMoveRepository, - UmbCopyRepository, - UmbApi -{ - #init: Promise; - - #treeSource: UmbTreeDataSource; - #detailSource: UmbDataSource; - #folderSource: UmbFolderDataSource; - #itemSource: UmbItemDataSource; - #moveSource: UmbMoveDataSource; - #copySource: UmbCopyDataSource; - - #detailStore?: UmbDataTypeStore; - #treeStore?: UmbDataTypeTreeStore; - #itemStore?: UmbDataTypeItemStore; - - #notificationContext?: UmbNotificationContext; - - constructor(host: UmbControllerHost) { - super(host); - - // TODO: figure out how spin up get the correct data source - this.#treeSource = new UmbDataTypeTreeServerDataSource(this); - this.#detailSource = new UmbDataTypeServerDataSource(this); - this.#folderSource = new UmbDataTypeFolderServerDataSource(this); - this.#itemSource = new UmbDataTypeItemServerDataSource(this); - this.#moveSource = new UmbDataTypeMoveServerDataSource(this); - this.#copySource = new UmbDataTypeCopyServerDataSource(this); - - // TODO: Make a method that takes the controllers and returns a promise, just to simplify this: - this.#init = Promise.all([ - this.consumeContext(UMB_DATA_TYPE_STORE_CONTEXT_TOKEN, (instance) => { - this.#detailStore = instance; - }).asPromise(), - - this.consumeContext(UMB_DATA_TYPE_TREE_STORE_CONTEXT_TOKEN, (instance) => { - this.#treeStore = instance; - }).asPromise(), - - this.consumeContext(UMB_DATA_TYPE_ITEM_STORE_CONTEXT_TOKEN, (instance) => { - this.#itemStore = instance; - }).asPromise(), - - this.consumeContext(UMB_NOTIFICATION_CONTEXT_TOKEN, (instance) => { - this.#notificationContext = instance; - }).asPromise(), - ]); - } - - // TREE: - async requestTreeRoot() { - await this.#init; - - const data = { - id: null, - type: DATA_TYPE_ROOT_ENTITY_TYPE, - name: 'Data Types', - icon: 'icon-folder', - hasChildren: true, - }; - - return { data }; - } - - async requestRootTreeItems() { - await this.#init; - - const { data, error } = await this.#treeSource.getRootItems(); - - if (data) { - this.#treeStore?.appendItems(data.items); - } - - return { data, error, asObservable: () => this.#treeStore!.rootItems }; - } - - async requestTreeItemsOf(parentId: string | null) { - await this.#init; - if (parentId === undefined) throw new Error('Parent id is missing'); - - const { data, error } = await this.#treeSource.getChildrenOf(parentId); - - if (data) { - this.#treeStore?.appendItems(data.items); - } - - return { data, error, asObservable: () => this.#treeStore!.childrenOf(parentId) }; - } - - async rootTreeItems() { - await this.#init; - return this.#treeStore!.rootItems; - } - - async treeItemsOf(parentId: string | null) { - if (parentId === undefined) throw new Error('Parent id is missing'); - await this.#init; - return this.#treeStore!.childrenOf(parentId); - } - - // ITEMS: - async requestItems(ids: Array) { - if (!ids) throw new Error('Keys are missing'); - await this.#init; - - const { data, error } = await this.#itemSource.getItems(ids); - - if (data) { - this.#itemStore?.appendItems(data); - } - - return { data, error, asObservable: () => this.#itemStore!.items(ids) }; - } - - async items(ids: Array) { - await this.#init; - return this.#itemStore!.items(ids); - } - - // DETAILS: - async createScaffold(parentId: string | null) { - if (parentId === undefined) throw new Error('Parent id is missing'); - await this.#init; - - return this.#detailSource.createScaffold(parentId); - } - - async requestById(id: string) { - if (!id) throw new Error('Key is missing'); - await this.#init; - - const { data, error } = await this.#detailSource.get(id); - - if (data) { - this.#detailStore?.append(data); - } - - return { data, error, asObservable: () => this.#detailStore!.byId(id) }; - } - - async byId(id: string) { - if (!id) throw new Error('Key is missing'); - await this.#init; - return this.#detailStore!.byId(id); - } - - async byPropertyEditorUiAlias(propertyEditorUiAlias: string) { - if (!propertyEditorUiAlias) throw new Error('propertyEditorUiAlias is missing'); - await this.#init; - return this.#detailStore!.withPropertyEditorUiAlias(propertyEditorUiAlias); - } - - async create(dataType: CreateDataTypeRequestModel) { - if (!dataType) throw new Error('Data Type is missing'); - if (!dataType.id) throw new Error('Data Type id is missing'); - await this.#init; - - const { error } = await this.#detailSource.insert(dataType); - - if (!error) { - // TODO: We need to push a new item to the tree store to update the tree. How do we want to create the tree items? - const treeItem = createTreeItem(dataType); - this.#treeStore?.appendItems([treeItem]); - //this.#detailStore?.append(dataType); - - const notification = { data: { message: `Data Type created` } }; - this.#notificationContext?.peek('positive', notification); - } - - return { error }; - } - - async save(id: string, updatedDataType: UpdateDataTypeRequestModel) { - if (!id) throw new Error('Data Type id is missing'); - if (!updatedDataType) throw new Error('Data Type is missing'); - await this.#init; - - const { error } = await this.#detailSource.update(id, updatedDataType); - - if (!error) { - // TODO: we currently don't use the detail store for anything. - // Consider to look up the data before fetching from the server - // Consider notify a workspace if a template is updated in the store while someone is editing it. - // TODO: would be nice to align the stores on methods/methodNames. - this.#detailStore?.updateItem(id, updatedDataType); - // TODO: This is parsing on the full models to the tree and item store. Those should only contain the data they need. I don't know, at this point, if thats a repository or store responsibility. - this.#treeStore?.updateItem(id, updatedDataType); - this.#itemStore?.updateItem(id, updatedDataType); - - const notification = { data: { message: `Data Type saved` } }; - this.#notificationContext?.peek('positive', notification); - } - - return { error }; - } - - async delete(id: string) { - if (!id) throw new Error('Data Type id is missing'); - await this.#init; - - const { error } = await this.#detailSource.delete(id); - - if (!error) { - // TODO: we currently don't use the detail store for anything. - // Consider to look up the data before fetching from the server. - // Consider notify a workspace if a template is deleted from the store while someone is editing it. - // TODO: would be nice to align the stores on methods/methodNames. - this.#detailStore?.remove([id]); - this.#treeStore?.removeItem(id); - this.#itemStore?.removeItem(id); - - const notification = { data: { message: `Data Type deleted` } }; - this.#notificationContext?.peek('positive', notification); - } - - return { error }; - } - - // Folder: - async createFolderScaffold(parentId: string | null) { - if (parentId === undefined) throw new Error('Parent id is missing'); - await this.#init; - return this.#folderSource.createScaffold(parentId); - } - - // TODO: temp create type until backend is ready. Remove the id addition when new types are generated. - async createFolder(folderRequest: CreateFolderRequestModel & { id?: string | undefined }) { - if (!folderRequest) throw new Error('folder request is missing'); - await this.#init; - - const { error } = await this.#folderSource.insert(folderRequest); - - if (!error) { - // TODO: We need to push a new item to the tree store to update the tree. How do we want to create the tree items? - const folderTreeItem = createFolderTreeItem(folderRequest); - this.#treeStore?.appendItems([folderTreeItem]); - } - - return { error }; - } - - async deleteFolder(id: string) { - if (!id) throw new Error('Key is missing'); - await this.#init; - - const { error } = await this.#folderSource.delete(id); - - if (!error) { - this.#treeStore?.removeItem(id); - } - - return { error }; - } - - async updateFolder(id: string, folder: FolderModelBaseModel) { - if (!id) throw new Error('Key is missing'); - if (!folder) throw new Error('Folder data is missing'); - await this.#init; - - const { error } = await this.#folderSource.update(id, folder); - - if (!error) { - this.#treeStore?.updateItem(id, { name: folder.name }); - } - - return { error }; - } - - async requestFolder(id: string) { - if (!id) throw new Error('Key is missing'); - await this.#init; - return await this.#folderSource.get(id); - } - - // Actions - async move(id: string, targetId: string | null) { - await this.#init; - const { error } = await this.#moveSource.move(id, targetId); - - if (!error) { - // TODO: Be aware about this responsibility. - this.#treeStore?.updateItem(id, { parentId: targetId }); - // only update the target if its not the root - if (targetId) { - this.#treeStore?.updateItem(targetId, { hasChildren: true }); - } - - const notification = { data: { message: `Data type moved` } }; - this.#notificationContext?.peek('positive', notification); - } - - return { error }; - } - - async copy(id: string, targetId: string | null) { - await this.#init; - const { data: dataTypeCopyId, error } = await this.#copySource.copy(id, targetId); - if (error) return { error }; - - if (dataTypeCopyId) { - const { data: dataTypeCopy } = await this.requestById(dataTypeCopyId); - if (!dataTypeCopy) throw new Error('Could not find copied data type'); - - // TODO: Be aware about this responsibility. - this.#treeStore?.appendItems([dataTypeCopy]); - // only update the target if its not the root - if (targetId) { - this.#treeStore?.updateItem(targetId, { hasChildren: true }); - } - - const notification = { data: { message: `Data type copied` } }; - this.#notificationContext?.peek('positive', notification); - } - - return { data: dataTypeCopyId }; - } -} - -export const createTreeItem = (item: CreateDataTypeRequestModel): FolderTreeItemResponseModel => { - if (!item) throw new Error('item is null or undefined'); - if (!item.id) throw new Error('item.id is null or undefined'); - - return { - type: 'data-type', - parentId: item.parentId, - name: item.name, - id: item.id, - isFolder: false, - isContainer: false, - hasChildren: false, - }; -}; - -export const createFolderTreeItem = (item: CreateFolderRequestModel): FolderTreeItemResponseModel => { - if (!item) throw new Error('item is null or undefined'); - if (!item.id) throw new Error('item.id is null or undefined'); - - return { - ...createTreeItem(item), - isFolder: true, - }; -}; diff --git a/src/packages/settings/data-types/repository/index.ts b/src/packages/settings/data-types/repository/index.ts deleted file mode 100644 index 1d069d1139..0000000000 --- a/src/packages/settings/data-types/repository/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { UmbDataTypeRepository } from './data-type.repository.js'; diff --git a/src/packages/settings/data-types/repository/manifests.ts b/src/packages/settings/data-types/repository/manifests.ts deleted file mode 100644 index c50c8b6d3d..0000000000 --- a/src/packages/settings/data-types/repository/manifests.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { UmbDataTypeRepository } from './data-type.repository.js'; -import { UmbDataTypeItemStore } from './data-type-item.store.js'; -import { UmbDataTypeStore } from './data-type.store.js'; -import { UmbDataTypeTreeStore } from './data-type.tree.store.js'; -import type { - ManifestStore, - ManifestTreeStore, - ManifestRepository, - ManifestItemStore, -} from '@umbraco-cms/backoffice/extension-registry'; - -export const DATA_TYPE_REPOSITORY_ALIAS = 'Umb.Repository.DataType'; - -const repository: ManifestRepository = { - type: 'repository', - alias: DATA_TYPE_REPOSITORY_ALIAS, - name: 'Data Type Repository', - api: UmbDataTypeRepository, -}; - -export const DATA_TYPE_STORE_ALIAS = 'Umb.Store.DataType'; -export const DATA_TYPE_TREE_STORE_ALIAS = 'Umb.Store.DataTypeTree'; -export const DATA_TYPE_ITEM_STORE_ALIAS = 'Umb.Store.DataTypeItem'; - -const store: ManifestStore = { - type: 'store', - alias: DATA_TYPE_STORE_ALIAS, - name: 'Data Type Store', - api: UmbDataTypeStore, -}; - -const treeStore: ManifestTreeStore = { - type: 'treeStore', - alias: DATA_TYPE_TREE_STORE_ALIAS, - name: 'Data Type Tree Store', - api: UmbDataTypeTreeStore, -}; - -const itemStore: ManifestItemStore = { - type: 'itemStore', - alias: DATA_TYPE_ITEM_STORE_ALIAS, - name: 'Data Type Item Store', - api: UmbDataTypeItemStore, -}; - -export const manifests = [repository, store, treeStore, itemStore]; diff --git a/src/packages/settings/data-types/tree/manifests.ts b/src/packages/settings/data-types/tree/manifests.ts deleted file mode 100644 index e6094e847c..0000000000 --- a/src/packages/settings/data-types/tree/manifests.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { DATA_TYPE_REPOSITORY_ALIAS } from '../repository/manifests.js'; -import type { ManifestTree, ManifestTreeItem } from '@umbraco-cms/backoffice/extension-registry'; - -const tree: ManifestTree = { - type: 'tree', - alias: 'Umb.Tree.DataTypes', - name: 'Data Types Tree', - meta: { - repositoryAlias: DATA_TYPE_REPOSITORY_ALIAS, - }, -}; - -const treeItem: ManifestTreeItem = { - type: 'treeItem', - kind: 'entity', - alias: 'Umb.TreeItem.DataType', - name: 'Data Type Tree Item', - meta: { - entityTypes: ['data-type-root', 'data-type'], - }, -}; - -export const manifests = [tree, treeItem]; diff --git a/src/packages/settings/manifests.ts b/src/packages/settings/manifests.ts index 31b0d628c7..3e1e34d012 100644 --- a/src/packages/settings/manifests.ts +++ b/src/packages/settings/manifests.ts @@ -1,5 +1,4 @@ import { manifests as dashboardManifests } from './dashboards/manifests.js'; -import { manifests as dataTypeManifests } from './data-types/manifests.js'; import { manifests as extensionManifests } from './extensions/manifests.js'; import { manifests as languageManifests } from './languages/manifests.js'; import { manifests as relationTypeManifests } from './relation-types/manifests.js'; @@ -8,7 +7,6 @@ import { manifests as settingsSectionManifests } from './section.manifests.js'; export const manifests = [ ...dashboardManifests, - ...dataTypeManifests, ...extensionManifests, ...languageManifests, ...relationTypeManifests, diff --git a/tsconfig.json b/tsconfig.json index 2d036fc825..d46a301fec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -82,7 +82,7 @@ "@umbraco-cms/backoffice/workspace": ["src/packages/core/workspace"], "@umbraco-cms/backoffice/culture": ["src/packages/core/culture"], - "@umbraco-cms/backoffice/data-type": ["./src/packages/settings/data-types/index.ts"], + "@umbraco-cms/backoffice/data-type": ["./src/packages/core/data-type/index.ts"], "@umbraco-cms/backoffice/language": ["./src/packages/settings/languages/index.ts"], "@umbraco-cms/backoffice/logviewer": ["src/packages/log-viewer/index.ts"], "@umbraco-cms/backoffice/relation-type": ["./src/packages/settings/relation-types/index.ts"], diff --git a/web-test-runner.config.mjs b/web-test-runner.config.mjs index fb036d48c2..6fe5b8c426 100644 --- a/web-test-runner.config.mjs +++ b/web-test-runner.config.mjs @@ -97,7 +97,7 @@ export default { '@umbraco-cms/backoffice/member-type': './src/packages/members/member-types/index.ts', '@umbraco-cms/backoffice/package': './src/packages/packages/package/index.ts', - '@umbraco-cms/backoffice/data-type': './src/packages/settings/data-types/index.ts', + '@umbraco-cms/backoffice/data-type': './src/packages/core/data-type/index.ts', '@umbraco-cms/backoffice/language': './src/packages/settings/languages/index.ts', '@umbraco-cms/backoffice/logviewer': './src/packages/settings/logviewer/index.ts', '@umbraco-cms/backoffice/relation-type': './src/packages/settings/relation-types/index.ts',