diff --git a/src/Umbraco.Web.UI.Client/libs/backend-api/src/models/DocumentTypeResponseModel.ts b/src/Umbraco.Web.UI.Client/libs/backend-api/src/models/DocumentTypeResponseModel.ts index 8712b46d1f..9f9209bf85 100644 --- a/src/Umbraco.Web.UI.Client/libs/backend-api/src/models/DocumentTypeResponseModel.ts +++ b/src/Umbraco.Web.UI.Client/libs/backend-api/src/models/DocumentTypeResponseModel.ts @@ -5,9 +5,9 @@ import type { ContentTypeCleanupModel } from './ContentTypeCleanupModel'; import type { ContentTypeResponseModelBaseDocumentTypePropertyTypeResponseModelDocumentTypePropertyTypeContainerResponseModel } from './ContentTypeResponseModelBaseDocumentTypePropertyTypeResponseModelDocumentTypePropertyTypeContainerResponseModel'; -export type DocumentTypeResponseModel = (ContentTypeResponseModelBaseDocumentTypePropertyTypeResponseModelDocumentTypePropertyTypeContainerResponseModel & { - allowedTemplateIds?: Array; - defaultTemplateId?: string | null; - cleanup?: ContentTypeCleanupModel; -}); - +export type DocumentTypeResponseModel = + ContentTypeResponseModelBaseDocumentTypePropertyTypeResponseModelDocumentTypePropertyTypeContainerResponseModel & { + allowedTemplateIds?: Array; + defaultTemplateId?: string | null; + cleanup?: ContentTypeCleanupModel; + }; diff --git a/src/Umbraco.Web.UI.Client/libs/content-type/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/libs/content-type/content-type-structure-manager.class.ts index 126fe4ca4e..d94959e8bd 100644 --- a/src/Umbraco.Web.UI.Client/libs/content-type/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/libs/content-type/content-type-structure-manager.class.ts @@ -66,10 +66,10 @@ export class UmbContentTypePropertyStructureManager x.id === id)) return; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type-picker/input-document-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type-picker/input-document-type-picker.element.ts index 8fad412c29..990e021039 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type-picker/input-document-type-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type-picker/input-document-type-picker.element.ts @@ -27,7 +27,7 @@ export class UmbInputDocumentTypePickerElement extends FormControlMixin(UmbLitEl } public set selectedIds(ids: Array) { this._selectedIds = ids ?? []; - super.value = ids.join(','); + super.value = this._selectedIds.join(','); this._observePickedDocuments(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts new file mode 100644 index 0000000000..a91e509654 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/create.action.ts @@ -0,0 +1,27 @@ +import { UmbDocumentTypeRepository } from '../../repository/document-type.repository'; +import { UMB_DOCUMENT_TYPE_CREATE_OPTIONS_MODAL } from './modal'; +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; +import { UmbModalContext, UMB_MODAL_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal'; +import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; + +export class UmbCreateDataTypeEntityAction extends UmbEntityActionBase { + #modalContext?: UmbModalContext; + + constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) { + super(host, repositoryAlias, unique); + + new UmbContextConsumerController(this.host, UMB_MODAL_CONTEXT_TOKEN, (instance) => { + this.#modalContext = instance; + }); + } + + async execute() { + if (!this.#modalContext) throw new Error('Modal context is not available'); + if (!this.repository) throw new Error('Repository is not available'); + + this.#modalContext?.open(UMB_DOCUMENT_TYPE_CREATE_OPTIONS_MODAL, { + parentKey: this.unique, + }); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/manifests.ts new file mode 100644 index 0000000000..7ab1a15250 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/manifests.ts @@ -0,0 +1,30 @@ +import { DOCUMENT_TYPE_ENTITY_TYPE, DOCUMENT_TYPE_FOLDER_ENTITY_TYPE, DOCUMENT_TYPE_ROOT_ENTITY_TYPE } from '../..'; +import { DOCUMENT_TYPE_REPOSITORY_ALIAS } from '../../repository/manifests'; +import { UmbCreateDataTypeEntityAction } from './create.action'; +import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +const entityActions: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.DocumentType.Create', + name: 'Create Document Type Entity Action', + weight: 1000, + meta: { + icon: 'umb:add', + label: 'Create...', + repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS, + api: UmbCreateDataTypeEntityAction, + }, + conditions: { + entityTypes: [DOCUMENT_TYPE_ENTITY_TYPE, DOCUMENT_TYPE_ROOT_ENTITY_TYPE, DOCUMENT_TYPE_FOLDER_ENTITY_TYPE], + }, + }, + { + type: 'modal', + alias: 'Umb.Modal.DocumentTypeCreateOptions', + name: 'Document Type Create Options Modal', + loader: () => import('./modal/document-type-create-options-modal.element'), + }, +]; + +export const manifests = [...entityActions]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/modal/document-type-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/modal/document-type-create-options-modal.element.ts new file mode 100644 index 0000000000..a8dc20db9c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/modal/document-type-create-options-modal.element.ts @@ -0,0 +1,77 @@ +import { html } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property } from 'lit/decorators.js'; +import { DOCUMENT_TYPE_REPOSITORY_ALIAS } from '../../../repository/manifests'; +import { UmbDocumentTypeCreateOptionsModalData } from '.'; +import { + UmbModalContext, + UmbModalHandler, + UMB_FOLDER_MODAL, + UMB_MODAL_CONTEXT_TOKEN, +} from '@umbraco-cms/backoffice/modal'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; + +@customElement('umb-document-type-create-options-modal') +export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement { + @property({ attribute: false }) + modalHandler?: UmbModalHandler; + + @property({ type: Object }) + data?: UmbDocumentTypeCreateOptionsModalData; + + #modalContext?: UmbModalContext; + + constructor() { + super(); + this.consumeContext(UMB_MODAL_CONTEXT_TOKEN, (instance) => { + this.#modalContext = instance; + }); + } + + #onClick(event: PointerEvent) { + event.stopPropagation(); + const folderModalHandler = this.#modalContext?.open(UMB_FOLDER_MODAL, { + repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS, + }); + folderModalHandler?.onSubmit().then(() => this.modalHandler?.submit()); + } + + // close the modal when navigating to data type + #onNavigate() { + this.modalHandler?.submit(); + } + + #onCancel() { + this.modalHandler?.reject(); + } + + render() { + return html` + + + + + } + + + } + + + Cancel + + `; + } + + static styles = [UUITextStyles]; +} + +export default UmbDataTypeCreateOptionsModalElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-type-create-options-modal': UmbDataTypeCreateOptionsModalElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/modal/index.ts new file mode 100644 index 0000000000..25864e9b3b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/create/modal/index.ts @@ -0,0 +1,13 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbDocumentTypeCreateOptionsModalData { + parentKey: string | null; +} + +export const UMB_DOCUMENT_TYPE_CREATE_OPTIONS_MODAL = new UmbModalToken( + 'Umb.Modal.DocumentTypeCreateOptions', + { + type: 'sidebar', + size: 'small', + } +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts new file mode 100644 index 0000000000..85b9e3d4d7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/entity-actions/manifests.ts @@ -0,0 +1,76 @@ +import { DOCUMENT_TYPE_REPOSITORY_ALIAS } from '../repository/manifests'; +import { manifests as createManifests } from './create/manifests'; +import { + UmbCopyEntityAction, + UmbMoveEntityAction, + UmbTrashEntityAction, + UmbSortChildrenOfEntityAction, +} from '@umbraco-cms/backoffice/entity-action'; +import { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; + +const entityType = 'document-type'; + +const entityActions: Array = [ + { + type: 'entityAction', + alias: 'Umb.EntityAction.DocumentType.Trash', + name: 'Trash Document-Type Entity Action', + weight: 900, + meta: { + icon: 'umb:trash', + label: 'Trash', + repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS, + api: UmbTrashEntityAction, + }, + conditions: { + entityTypes: [entityType], + }, + }, + { + type: 'entityAction', + alias: 'Umb.EntityAction.DocumentType.Move', + name: 'Move Document-Type Entity Action', + weight: 700, + meta: { + icon: 'umb:enter', + label: 'Move', + repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS, + api: UmbMoveEntityAction, + }, + conditions: { + entityTypes: [entityType], + }, + }, + { + type: 'entityAction', + alias: 'Umb.EntityAction.DocumentType.Copy', + name: 'Copy Document-Type Entity Action', + weight: 600, + meta: { + icon: 'umb:documents', + label: 'Copy', + repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS, + api: UmbCopyEntityAction, + }, + conditions: { + entityTypes: [entityType], + }, + }, + { + type: 'entityAction', + alias: 'Umb.EntityAction.DocumentType.Sort', + name: 'Sort Document-Type Entity Action', + weight: 500, + meta: { + icon: 'umb:navigation-vertical', + label: 'Sort', + repositoryAlias: DOCUMENT_TYPE_REPOSITORY_ALIAS, + api: UmbSortChildrenOfEntityAction, + }, + conditions: { + entityTypes: [entityType], + }, + }, +]; + +export const manifests = [...entityActions, ...createManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts new file mode 100644 index 0000000000..6d7112b528 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/index.ts @@ -0,0 +1,5 @@ +import './components'; + +export const DOCUMENT_TYPE_ROOT_ENTITY_TYPE = 'document-type-root'; +export const DOCUMENT_TYPE_ENTITY_TYPE = 'document-type'; +export const DOCUMENT_TYPE_FOLDER_ENTITY_TYPE = 'document-type-folder'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts index 5a38adea8f..7d4b460fcd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/manifests.ts @@ -1,13 +1,15 @@ +import { manifests as entityActionsManifests } from './entity-actions/manifests'; import { manifests as menuItemManifests } from './menu-item/manifests'; +import { manifests as modalManifests } from './modals/manifests'; +import { manifests as repositoryManifests } from './repository/manifests'; import { manifests as treeManifests } from './tree/manifests'; import { manifests as workspaceManifests } from './workspace/manifests'; -import { manifests as repositoryManifests } from './repository/manifests'; -import { manifests as modalManifests } from './modals/manifests'; export const manifests = [ + ...entityActionsManifests, ...menuItemManifests, - ...treeManifests, - ...repositoryManifests, - ...workspaceManifests, ...modalManifests, + ...repositoryManifests, + ...treeManifests, + ...workspaceManifests, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/document-type.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/document-type.repository.ts index a72dd3461d..87ea1616a3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/document-type.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/document-type.repository.ts @@ -125,7 +125,13 @@ export class UmbDocumentTypeRepository async createScaffold(parentId: string | null) { if (parentId === undefined) throw new Error('Parent id is missing'); await this.#init; - return this.#detailDataSource.createScaffold(parentId); + + const { data } = await this.#detailDataSource.createScaffold(parentId); + + if (data) { + this.#detailStore?.append(data); + } + return { data }; } async requestById(id: string) { @@ -166,7 +172,7 @@ export class UmbDocumentTypeRepository const treeItem = createTreeItem(documentType); this.#treeStore?.appendItems([treeItem]); - const notification = { data: { message: `Document created` } }; + const notification = { data: { message: `Document Type created` } }; this.#notificationContext?.peek('positive', notification); // TODO: we currently don't use the detail store for anything. @@ -204,13 +210,13 @@ export class UmbDocumentTypeRepository // General: async delete(id: string) { - if (!id) throw new Error('Document id is missing'); + if (!id) throw new Error('Document Type id is missing'); await this.#init; const { error } = await this.#detailDataSource.delete(id); if (!error) { - const notification = { data: { message: `Document deleted` } }; + const notification = { data: { message: `Document Type deleted` } }; this.#notificationContext?.peek('positive', notification); // TODO: we currently don't use the detail store for anything. @@ -232,7 +238,7 @@ export const createTreeItem = (item: ItemType): FolderTreeItemResponseModel => { // TODO: needs parentID, this is missing in the current model. Should be good when updated to a createModel. return { $type: 'FolderTreeItemResponseModel', - type: 'data-type', + type: 'document-type', parentId: null, name: item.name, id: item.id, diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/sources/document-type.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/sources/document-type.server.data.ts index efb34fccf6..150ea27ebb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/sources/document-type.server.data.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/sources/document-type.server.data.ts @@ -2,6 +2,7 @@ import type { UmbDataSource } from '@umbraco-cms/backoffice/repository'; import { DocumentTypeResource, DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import { UmbId } from '@umbraco-cms/backoffice/id'; /** * A data source for the Document Type that fetches data from the server @@ -48,7 +49,20 @@ export class UmbDocumentTypeServerDataSource implements UmbDataSource this.#element, + setup: (_component, info) => { + const parentId = info.match.params.parentId === 'null' ? null : info.match.params.parentId; + this.#workspaceContext.createScaffold(parentId); + }, + }, { path: 'edit/:id', component: () => this.#element, diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/components/data-type-flow-input/data-type-flow-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/components/data-type-flow-input/data-type-flow-input.element.ts index bd2378c830..9405ddbcc0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/components/data-type-flow-input/data-type-flow-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/data-types/components/data-type-flow-input/data-type-flow-input.element.ts @@ -32,11 +32,11 @@ export class UmbInputDataTypeElement extends FormControlMixin(UmbLitElement) { */ @property({ attribute: false }) get value(): string { - return super.value.toString(); + return super.value?.toString() ?? ''; } set value(dataTypeId: string) { - super.value = dataTypeId; - this.#itemsManager.setUniques(dataTypeId.split(',')); + super.value = dataTypeId ?? ''; + this.#itemsManager.setUniques(super.value.split(',')); } @state()