From cc3310cc0c2516be51fc1edb2f32f68bc14abd16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 16 Jan 2024 13:27:45 +0100 Subject: [PATCH] simple block list editor implementation --- .../src/mocks/data/document.data.ts | 1 + .../block-list-block.element.ts | 17 +++++++++++ .../property-editor-ui-block-list.element.ts | 10 ++++++- .../block/block/context/block.context.ts | 10 +++++++ .../block/manager/block-manager.context.ts | 30 ++++++++++++++----- .../src/packages/block/block/manifests.ts | 3 +- .../workspace/block-workspace.context.ts | 24 +++++++++++++-- 7 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document.data.ts index c96160d14c..2073ead14a 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document.data.ts @@ -183,6 +183,7 @@ export const data: Array = [ { udi: '1234', contentTypeKey: '4f68ba66-6fb2-4778-83b8-6ab4ca3a7c5c', + elementProperty: 'Hello world', }, ], settingsData: [], diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts index 86e118e519..a05882a878 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-block/block-list-block.element.ts @@ -24,12 +24,24 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl #context = new UmbBlockContext(this); + @state() + _contentUdi?: string; + @state() _label = ''; + @state() + _workspacePath?: string; + constructor() { super(); + this.observe(this.#context.workspacePath, (workspacePath) => { + this._workspacePath = workspacePath; + }); + this.observe(this.#context.contentUdi, (contentUdi) => { + this._contentUdi = contentUdi; + }); this.observe(this.#context.label, (label) => { this._label = label; }); @@ -65,6 +77,11 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl return html` ${this.#renderRefBlock()} + ${this._workspacePath + ? html` + + ` + : ''} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index bcf54a602c..59ae5b03eb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -15,7 +15,12 @@ import '../../components/block-list-block/index.js'; import { buildUdi } from '@umbraco-cms/backoffice/utils'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { NumberRangeValueType } from '@umbraco-cms/backoffice/models'; -import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; +import { + UMB_MODAL_MANAGER_CONTEXT_TOKEN, + UMB_WORKSPACE_MODAL, + UmbModalManagerContext, + UmbModalRouteRegistrationController, +} from '@umbraco-cms/backoffice/modal'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {} @@ -78,6 +83,9 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement @state() _layouts: Array = []; + @state() + _workspacePath?: string; + #modalContext?: UmbModalManagerContext; constructor() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block.context.ts index 8c1fe6f41c..01e19fab1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block.context.ts @@ -19,6 +19,9 @@ export class UmbBlockContext< #label = new UmbStringState(''); public readonly label = this.#label.asObservable(); + #workspacePath = new UmbStringState(undefined); + public readonly workspacePath = this.#workspacePath.asObservable(); + #blockType = new UmbObjectState(undefined); public readonly blockType = this.#blockType.asObservable(); public readonly blockTypeContentElementTypeKey = this.#blockType.asObservablePart((x) => x?.contentElementTypeKey); @@ -51,6 +54,13 @@ export class UmbBlockContext< // Consume block manager: this.consumeContext(UMB_BLOCK_MANAGER_CONTEXT, (manager) => { this.#manager = manager; + this.observe( + manager.workspacePath, + (workspacePath) => { + this.#workspacePath.next(workspacePath); + }, + 'observeWorkspacePath', + ); this.#observeBlockType(); this.#observeData(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts index cbda82520e..6a665b4c3b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/manager/block-manager.context.ts @@ -2,11 +2,12 @@ import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '..//types.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbArrayState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { DocumentTypeResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { getKeyFromUdi } from '@umbraco-cms/backoffice/utils'; import { UmbBlockTypeBase } from '@umbraco-cms/backoffice/block'; +import { UMB_WORKSPACE_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; // TODO: We are using backend model here, I think we should get our own model: type ElementTypeModel = DocumentTypeResponseModel; @@ -18,6 +19,9 @@ export class UmbBlockManagerContext< // #contentTypeRepository = new UmbDocumentTypeDetailRepository(this); + #workspacePath = new UmbStringState(undefined); + workspacePath = this.#workspacePath.asObservable(); + #contentTypes = new UmbArrayState(>[], (x) => x.id); public readonly contentTypes = this.#contentTypes.asObservable(); @@ -53,6 +57,18 @@ export class UmbBlockManagerContext< constructor(host: UmbControllerHost) { super(host, UMB_BLOCK_MANAGER_CONTEXT); + + // TODO: Make specific modal token that requires data. + // IDEA: Make a Workspace registration controller that can be used to register a workspace, which does both edit and create?. + new UmbModalRouteRegistrationController(this, UMB_WORKSPACE_MODAL) + .addAdditionalPath('block') + .onSetup(() => { + return { data: { entityType: 'block', preset: {} }, modal: { size: 'medium' } }; + }) + .observeRouteBuilder((routeBuilder) => { + const newPath = routeBuilder({}); + this.#workspacePath.next(newPath); + }); } async ensureContentType(id?: string) { @@ -99,14 +115,14 @@ export class UmbBlockManagerContext< return this.#settings.asObservablePart((source) => source.find((x) => x.udi === udi)); } - updateLayout(contentUdi: string, layoutData: Partial) { - return this.#layouts.updateOne(contentUdi, layoutData); + setOneLayout(layoutData: BlockLayoutType) { + return this.#layouts.appendOne(layoutData); } - updateContent(udi: string, contentData: Partial) { - return this.#contents.updateOne(udi, contentData); + setOneContent(contentData: UmbBlockDataType) { + this.#contents.appendOne(contentData); } - updateSettings(udi: string, settingsData: Partial) { - return this.#settings.updateOne(udi, settingsData); + setOneSettings(settingsData: UmbBlockDataType) { + this.#settings.appendOne(settingsData); } createBlock(layoutEntry: BlockLayoutType, contentElementTypeKey: string) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/manifests.ts index 684effeb51..e3939d3921 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/manifests.ts @@ -1,3 +1,4 @@ import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as workspaceManifests } from './workspace/manifests.js'; -export const manifests = [...modalManifests]; +export const manifests = [...modalManifests, ...workspaceManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts index 972e7dfdb0..5dd401feee 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.context.ts @@ -21,13 +21,17 @@ export class UmbBlockWorkspaceContext(undefined); readonly isNew = this.#isNew.asObservable(); #layout = new UmbObjectState(undefined); readonly layout = this.#layout.asObservable(); + //readonly unique = this.#layout.asObservablePart((x) => x?.contentUdi); readonly contentUdi = this.#layout.asObservablePart((x) => x?.contentUdi); readonly content = new UmbBlockElementManager(this); @@ -37,16 +41,21 @@ export class UmbBlockWorkspaceContext(undefined); readonly name = this.#label.asObservable(); - readonly unique = this.#layout.asObservablePart((data) => data?.contentUdi); constructor(host: UmbControllerHost, workspaceArgs: { manifest: ManifestWorkspace }) { // TODO: We don't need a repo here, so maybe we should not require this of the UmbEditableWorkspaceContextBase super(host, 'Umb.Workspace.Block'); this.#entityType = workspaceArgs.manifest.meta?.entityType; + + this.observe(this.contentUdi, (contentUdi) => { + this.#contentUdi = contentUdi ?? ''; + }); } async load(unique: string) { this.consumeContext(UMB_BLOCK_MANAGER_CONTEXT, (context) => { + this.#blockManager = context; + this.observe( context.layoutOf(unique), (layoutData) => { @@ -146,9 +155,20 @@ export class UmbBlockWorkspaceContext