From 8289a732fbee96f12be186f276c6f6812827ea37 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 12 Apr 2024 10:11:43 +0200 Subject: [PATCH] create document from blueprint --- .../documents/document-blueprints/types.ts | 26 +--- .../document-create-options-modal.element.ts | 115 ++++++++++++++---- .../workspace/document-workspace.context.ts | 63 ++++++++-- 3 files changed, 152 insertions(+), 52 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts index 09965e112f..c1e4723937 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-blueprints/types.ts @@ -1,7 +1,7 @@ import type { UmbDocumentBlueprintEntityType } from './entity.js'; -import type { UmbVariantModel, UmbVariantOptionModel } from '@umbraco-cms/backoffice/variant'; import type { UmbReferenceByUnique } from '@umbraco-cms/backoffice/models'; import { DocumentVariantStateModel as UmbDocumentBlueprintVariantState } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbDocumentValueModel, UmbDocumentVariantModel } from '@umbraco-cms/backoffice/document'; export { UmbDocumentBlueprintVariantState }; export interface UmbDocumentBlueprintDetailModel { @@ -11,26 +11,6 @@ export interface UmbDocumentBlueprintDetailModel { }; entityType: UmbDocumentBlueprintEntityType; unique: string; - values: Array; - variants: Array; + values: Array; + variants: Array; } - -export interface UmbDocumentBlueprintVariantModel extends UmbVariantModel { - state?: UmbDocumentBlueprintVariantState | null; - publishDate?: string | null; -} - -export interface UmbDocumentBlueprintUrlInfoModel { - culture: string | null; - url: string; -} - -export interface UmbDocumentBlueprintValueModel { - culture: string | null; - segment: string | null; - alias: string; - value: ValueType; -} - -export interface UmbDocumentBlueprintVariantOptionModel - extends UmbVariantOptionModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts index 6f0a2d5e7b..4dbfe9cf67 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts @@ -3,13 +3,17 @@ import type { UmbDocumentCreateOptionsModalData, UmbDocumentCreateOptionsModalValue, } from './document-create-options-modal.token.js'; -import { html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { html, nothing, customElement, state, ifDefined, repeat, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbDocumentTypeStructureRepository, type UmbAllowedDocumentTypeModel, } from '@umbraco-cms/backoffice/document-type'; +import { + type UmbDocumentBlueprintItemModel, + UmbDocumentBlueprintItemRepository, +} from '@umbraco-cms/backoffice/document-blueprint'; @customElement('umb-document-create-options-modal') export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< @@ -18,12 +22,20 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< > { #documentTypeStructureRepository = new UmbDocumentTypeStructureRepository(this); #documentItemRepository = new UmbDocumentItemRepository(this); + #documentBlueprintItemRepository = new UmbDocumentBlueprintItemRepository(this); + + #documentTypeUnique = ''; + #documentTypeIcon = ''; @state() private _allowedDocumentTypes: UmbAllowedDocumentTypeModel[] = []; @state() - private _headline: string = 'Create'; + private _headline: string = + `${this.localize.term('create_createUnder')} ${this.localize.term('actionCategories_content')}`; + + @state() + private _availableBlueprints: Array = []; async firstUpdated() { const parentUnique = this.data?.parent.unique; @@ -50,40 +62,99 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< const { data } = await this.#documentItemRepository.requestItems([parentUnique]); if (data) { // TODO: we need to get the correct variant context here - this._headline = `Create at ${data[0].variants?.[0].name}`; + this._headline = `${this.localize.term('create_createUnder')} ${data[0].variants?.[0].name ?? this.localize.term('actionCategories_content')}`; } } // close the modal when navigating to data type - #onNavigate() { + #onNavigate(documentTypeUnique: string, blueprintUnique?: string) { + if (!blueprintUnique) { + history.pushState( + null, + '', + `section/content/workspace/document/create/parent/${this.data?.parent.entityType}/${this.data?.parent.unique ?? 'null'}/${documentTypeUnique}`, + ); + } else { + history.pushState( + null, + '', + `section/content/workspace/document/create/parent/${this.data?.parent.entityType}/${this.data?.parent.unique ?? 'null'}/${documentTypeUnique}/${blueprintUnique}`, + ); + } this._submitModal(); } + async #onSelectDocumentType(documentTypeUnique: string) { + this.#documentTypeUnique = documentTypeUnique; + this.#documentTypeIcon = this._allowedDocumentTypes.find((dt) => dt.unique === documentTypeUnique)?.icon ?? ''; + + const { data } = await this.#documentBlueprintItemRepository.requestItems([]); + if (!data?.length) return; + + this._availableBlueprints = data.filter((blueprint) => blueprint.documentType.unique === documentTypeUnique); + + if (!this._availableBlueprints.length) { + this.#onNavigate(documentTypeUnique); + return; + } + } + render() { return html` - - - ${this._allowedDocumentTypes.length === 0 ? html`

No allowed types

` : nothing} - ${this._allowedDocumentTypes.map( - (documentType) => html` - - > ${documentType.icon ? html`` : nothing} - - `, - )} -
+ + ${this._availableBlueprints.length && this.#documentTypeUnique + ? this.#renderBlueprints() + : this.#renderDocumentTypes()} `; } - static styles = [UmbTextStyles]; + #renderDocumentTypes() { + return html` + ${this._allowedDocumentTypes.length === 0 ? html`

No allowed types

` : nothing} + ${this._allowedDocumentTypes.map( + (documentType) => html` + this.#onSelectDocumentType(documentType.unique)}> + + + `, + )} +
`; + } + + #renderBlueprints() { + return html` + this.#onNavigate(this.#documentTypeUnique)}> + + + ${repeat( + this._availableBlueprints, + (blueprint) => blueprint.unique, + (blueprint) => + html` this.#onNavigate(this.#documentTypeUnique, blueprint.unique)}> + + `, + )} `; + } + + static styles = [ + UmbTextStyles, + css` + #blank { + border-bottom: 1px solid var(--uui-color-border); + } + `, + ]; } export default UmbDocumentCreateOptionsModalElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 1ab4c387a1..b7fb65ee67 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -48,6 +48,7 @@ import { UmbRequestReloadTreeItemChildrenEvent } from '@umbraco-cms/backoffice/t import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type'; +import { UmbDocumentBlueprintDetailRepository } from '@umbraco-cms/backoffice/document-blueprint'; type EntityType = UmbDocumentDetailModel; export class UmbDocumentWorkspaceContext @@ -75,6 +76,10 @@ export class UmbDocumentWorkspaceContext #languages = new UmbArrayState([], (x) => x.unique); public readonly languages = this.#languages.asObservable(); + #blueprintRepository = new UmbDocumentBlueprintDetailRepository(this); + /*#blueprint = new UmbObjectState(undefined); + public readonly blueprint = this.#blueprint.asObservable();*/ + public isLoaded() { return this.#getDataPromise; } @@ -145,6 +150,24 @@ export class UmbDocumentWorkspaceContext this.loadLanguages(); this.routes.setRoutes([ + { + path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique/:blueprintUnique', + component: () => import('./document-workspace-editor.element.js'), + setup: async (_component, info) => { + const parentEntityType = info.match.params.entityType; + const parentUnique: string | null = + info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique; + const documentTypeUnique = info.match.params.documentTypeUnique; + const blueprintUnique = info.match.params.blueprintUnique; + + this.create({ entityType: parentEntityType, unique: parentUnique }, documentTypeUnique, blueprintUnique); + new UmbWorkspaceIsNewRedirectController( + this, + this, + this.getHostElement().shadowRoot!.querySelector('umb-router-slot')!, + ); + }, + }, { path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique', component: () => import('./document-workspace-editor.element.js'), @@ -208,15 +231,41 @@ export class UmbDocumentWorkspaceContext } } - async create(parent: { entityType: string; unique: string | null }, documentTypeUnique: string) { + async create( + parent: { entityType: string; unique: string | null }, + documentTypeUnique: string, + blueprintUnique?: string, + ) { this.resetState(); this.#parent.setValue(parent); - this.#getDataPromise = this.repository.createScaffold({ - documentType: { - unique: documentTypeUnique, - collection: null, - }, - }); + + if (blueprintUnique) { + /**TODO Right now it always goes into this if statement, because it thinks the unique is "invariant" when none are given */ + const { data } = await this.#blueprintRepository.requestByUnique(blueprintUnique); + if (data) { + this.#getDataPromise = this.repository.createScaffold({ + documentType: data?.documentType, + values: data?.values, + variants: data?.variants, + }); + } + // Remove this when issue fixed + this.#getDataPromise = this.repository.createScaffold({ + documentType: { + unique: documentTypeUnique, + collection: null, + }, + }); + // + } else { + this.#getDataPromise = this.repository.createScaffold({ + documentType: { + unique: documentTypeUnique, + collection: null, + }, + }); + } + const { data } = await this.#getDataPromise; if (!data) return undefined;