diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts index d12714c73b..a40f574a34 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/extensions-element-initializer.controller.ts @@ -27,7 +27,7 @@ export class UmbExtensionsElementInitializer< > { // #extensionRegistry; - private _defaultElement?: string; + #defaultElement?: string; #props?: Record; public get properties() { @@ -50,7 +50,7 @@ export class UmbExtensionsElementInitializer< ) { super(host, extensionRegistry, type, filter, onChange); this.#extensionRegistry = extensionRegistry; - this._defaultElement = defaultElement; + this.#defaultElement = defaultElement; this._init(); } @@ -60,7 +60,7 @@ export class UmbExtensionsElementInitializer< this.#extensionRegistry, manifest.alias, this._extensionChanged, - this._defaultElement, + this.#defaultElement, ) as ControllerType; extController.properties = this.#props; diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts index 5b71839a8d..a9976a2bda 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts @@ -512,6 +512,7 @@ export const data: Array = [ { label: 'Mocked Block Type for Block List', contentElementTypeKey: '4f68ba66-6fb2-4778-83b8-6ab4ca3a7c5c', + settingsElementTypeKey: 'all-property-editors-document-type-id', icon: 'icon-server-alt', }, { @@ -551,7 +552,7 @@ export const data: Array = [ }, { alias: 'useInlineEditingAsDefault', - value: true, + value: false, }, { alias: 'useLiveEditing', diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts index 4623f19f4e..d58041c511 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts @@ -188,6 +188,7 @@ export const data: Array = [ 'Umbraco.BlockList': [ { contentUdi: '1234', + settingsUdi: '5678', }, ], }, @@ -198,7 +199,13 @@ export const data: Array = [ elementProperty: 'Hello world', }, ], - settingsData: [], + settingsData: [ + { + udi: '5678', + contentTypeKey: 'all-property-editors-document-type-id', + elementProperty: 'Hello world', + }, + ], }, }, { 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 6af4a4da1f..897f888b4c 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 @@ -28,6 +28,9 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl @state() _contentUdi?: string; + @state() + _hasSettings = false; + @state() _label = ''; @@ -37,6 +40,12 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl @state() _inlineEditingMode?: boolean; + // TODO: Move type for the Block Properties, and use it on the Element Interface for the Manifest. + @state() + _blockViewProps: { + label?: string; + } = {}; + constructor() { super(); @@ -46,7 +55,11 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl this.observe(this.#context.contentUdi, (contentUdi) => { this._contentUdi = contentUdi; }); + this.observe(this.#context.blockTypeSettingsElementTypeKey, (blockTypeSettingsElementTypeKey) => { + this._hasSettings = !!blockTypeSettingsElementTypeKey; + }); this.observe(this.#context.label, (label) => { + this._blockViewProps.label = label; this._label = label; }); this.observe(this.#context.inlineEditingMode, (inlineEditingMode) => { @@ -70,22 +83,32 @@ export class UmbPropertyEditorUIBlockListBlockElement extends UmbLitElement impl } #renderRefBlock() { - return html``; + return html``; } #renderInlineBlock() { - return html``; + return html``; } #renderBlock() { return html` - ${this._inlineEditingMode ? this.#renderInlineBlock() : this.#renderRefBlock()} + ${this._inlineEditingMode ? this.#renderInlineBlock() : this.#renderRefBlock()} ${this._workspaceEditPath ? html` ` : ''} + ${this._workspaceEditPath && this._hasSettings + ? html` + + ` + : ''} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts index c25d52faef..e177087318 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/inline-list-block/inline-list-block.element.ts @@ -3,7 +3,7 @@ import type { UMB_BLOCK_WORKSPACE_CONTEXT } from '../../../block/index.js'; import { UMB_BLOCK_WORKSPACE_ALIAS } from '../../../block/index.js'; import { UmbExtensionsApiInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { css, customElement, html, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import '../../../block/workspace/views/edit/block-workspace-view-edit-no-router.element.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; @@ -17,8 +17,8 @@ export class UmbInlineListBlockElement extends UmbLitElement { #workspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; #contentUdi?: string; - @state() - _label = ''; + @property({ type: String }) + label?: string; @state() _isOpen = false; @@ -36,9 +36,6 @@ export class UmbInlineListBlockElement extends UmbLitElement { }, 'observeContentUdi', ); - this.observe(blockContext.label, (label) => { - this._label = label; - }); }); this.observe(umbExtensionsRegistry.getByTypeAndAlias('workspace', UMB_BLOCK_WORKSPACE_ALIAS), (manifest) => { if (manifest) { @@ -73,7 +70,7 @@ export class UmbInlineListBlockElement extends UmbLitElement { }}> - ${this._label} + ${this.label} ${this._isOpen === true ? html`` @@ -82,6 +79,7 @@ export class UmbInlineListBlockElement extends UmbLitElement { } static styles = [ + UmbTextStyles, css` #accordion-button { display: flex; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts index 7dc6d20276..dce78e9855 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/ref-list-block/ref-list-block.element.ts @@ -1,6 +1,5 @@ import { UMB_BLOCK_LIST_CONTEXT } from '../../context/block-list.context-token.js'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; -import { UUIRefNodeElement } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; /** @@ -10,7 +9,7 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; export class UmbRefListBlockElement extends UmbLitElement { // @property({ type: String }) - name?: string; + label?: string; @state() _workspaceEditPath?: string; @@ -31,13 +30,12 @@ export class UmbRefListBlockElement extends UmbLitElement { render() { // href=${this._workspaceEditPath ?? '#'} - return html``; + return html``; } static styles = [ - ...UUIRefNodeElement.styles, css` - :host { + uui-ref-node { min-height: var(--uui-size-16); } `, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-has-settings.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-has-settings.condition.ts new file mode 100644 index 0000000000..23966c42eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/block-workspace-has-settings.condition.ts @@ -0,0 +1,42 @@ +import { UMB_BLOCK_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/block'; +import { UmbBaseController } from '@umbraco-cms/backoffice/class-api'; +import type { + ManifestCondition, + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; + +export class UmbBlockWorkspaceHasSettingsCondition extends UmbBaseController implements UmbExtensionCondition { + config: BlockWorkspaceHasSettingsConditionConfig; + permitted = false; + #onChange: () => void; + + constructor(args: UmbConditionControllerArguments) { + super(args.host); + this.config = args.config; + this.#onChange = args.onChange; + + // TODO: Rename the Block Context, so it gets a name.. like Block Entry Context or something. + this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (context) => { + this.observe( + context.settings.contentTypeId, + (settingsContentTypeId) => { + this.permitted = !!settingsContentTypeId; + this.#onChange(); + }, + 'observeSettingsElementTypeId', + ); + }); + } +} + +export type BlockWorkspaceHasSettingsConditionConfig = + UmbConditionConfigBase<'Umb.Condition.BlockWorkspaceHasSettings'>; + +export const manifest: ManifestCondition = { + type: 'condition', + name: 'Block Has Settings Condition', + alias: 'Umb.Condition.BlockWorkspaceHasSettings', + api: UmbBlockWorkspaceHasSettingsCondition, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/index.ts new file mode 100644 index 0000000000..0c6d9fc984 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/conditions/index.ts @@ -0,0 +1 @@ +export * from './block-workspace-has-settings.condition.js'; 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-entity.context.ts similarity index 98% rename from src/Umbraco.Web.UI.Client/src/packages/block/block/context/block.context.ts rename to src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entity.context.ts index 7df7769388..9f9d417e10 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-entity.context.ts @@ -60,7 +60,7 @@ export abstract class UmbBlockContext< } constructor(host: UmbControllerHost, blockManagerContextToken: BlockManagerContextTokenType) { - super(host, UMB_BLOCK_CONTEXT.toString()); + super(host, UMB_BLOCK_ENTITY_CONTEXT.toString()); // Consume block manager: this.consumeContext(blockManagerContextToken, (manager) => { @@ -198,6 +198,6 @@ export abstract class UmbBlockContext< } } -export const UMB_BLOCK_CONTEXT = new UmbContextToken< +export const UMB_BLOCK_ENTITY_CONTEXT = new UmbContextToken< UmbBlockContext >('UmbBlockContext'); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/index.ts index 69c858f894..689c247d82 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/index.ts @@ -1 +1 @@ -export * from './block.context.js'; +export * from './block-entity.context.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts index 258f163605..abccb4df2a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/index.ts @@ -1,5 +1,6 @@ +export * from './conditions/index.js'; export * from './context/index.js'; export * from './manager/index.js'; export * from './modals/index.js'; -export * from './workspace/index.js'; export * from './types.js'; +export * from './workspace/index.js'; 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 2d9f9c9fa4..0ab646f59a 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 @@ -4,13 +4,8 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, UmbClassState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { buildUdi, getKeyFromUdi } from '@umbraco-cms/backoffice/utils'; -import type { - UmbBlockTypeBaseModel, - UmbBlockWorkspaceData} from '@umbraco-cms/backoffice/block'; -import { - UMB_BLOCK_MANAGER_CONTEXT, - UMB_BLOCK_WORKSPACE_MODAL -} from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel, UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; +import { UMB_BLOCK_MANAGER_CONTEXT, UMB_BLOCK_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/block'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbId } from '@umbraco-cms/backoffice/id'; @@ -72,6 +67,7 @@ export abstract class UmbBlockManagerContext< constructor(host: UmbControllerHost) { super(host, UMB_BLOCK_MANAGER_CONTEXT); + // TODO: This might will need the property alias as part of the URL, to avoid collision if multiple of these Editor on same Node. // IDEA: Make a Workspace registration controller that can be used to register a workspace, which does both edit and create?. new UmbModalRouteRegistrationController(this, UMB_BLOCK_WORKSPACE_MODAL) .addAdditionalPath('block') 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 e3939d3921..1582d740af 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,4 +1,5 @@ +import { manifest as blockWorkspaceHasSettingsConditionManifest } from './conditions/block-workspace-has-settings.condition.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -export const manifests = [...modalManifests, ...workspaceManifests]; +export const manifests = [...modalManifests, ...workspaceManifests, blockWorkspaceHasSettingsConditionManifest]; 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 7fe74f0be1..327498248a 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 @@ -10,6 +10,7 @@ import { UMB_BLOCK_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/block'; import { buildUdi } from '@umbraco-cms/backoffice/utils'; import { UMB_MODAL_CONTEXT } from '@umbraco-cms/backoffice/modal'; +export type UmbBlockWorkspaceElementManagerNames = 'content' | 'settings'; export class UmbBlockWorkspaceContext< LayoutDataType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, > extends UmbEditableWorkspaceContextBase { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.element.ts index 0bcca9b580..5e080011fe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/block-workspace.element.ts @@ -6,9 +6,9 @@ import type { UmbRoute } from '@umbraco-cms/backoffice/router'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace'; -import type { UmbApi} from '@umbraco-cms/backoffice/extension-api'; +import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionsApiInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; -import type { ManifestWorkspace} from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { decodeFilePath } from '@umbraco-cms/backoffice/utils'; @@ -31,7 +31,7 @@ export class UmbBlockWorkspaceElement extends UmbLitElement { createExtensionApi(manifest, [this, { manifest: manifest }]).then((context) => { if (context) { this.#gotWorkspaceContext(context); - // TODO: We need to recreate when ID changed? + // TODO: Do we need to recreate when ID changed? Or is that a responsibility of the context it self? new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [ this, this.#workspaceContext, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts index 3afce80e47..9617a2bdcc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/manifests.ts @@ -41,6 +41,7 @@ export const manifests: Array = [ label: 'Content', pathname: 'content', icon: 'icon-document', + blockElementManagerName: 'content', }, conditions: [ { @@ -48,5 +49,27 @@ export const manifests: Array = [ match: UMB_BLOCK_WORKSPACE_ALIAS, }, ], - }, + } as any, + { + type: 'workspaceView', + alias: 'Umb.WorkspaceView.Block.Settings', + name: 'Block Workspace Settings View', + js: () => import('./views/edit/block-workspace-view-edit.element.js'), + weight: 1000, + meta: { + label: 'Settings', + pathname: 'settings', + icon: 'icon-settings', + blockElementManagerName: 'settings', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: UMB_BLOCK_WORKSPACE_ALIAS, + }, + { + alias: 'Umb.Condition.BlockWorkspaceHasSettings', + }, + ], + } as any, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-no-router.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-no-router.element.ts index 3a216eb3c9..e6c7aa0e48 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-no-router.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-no-router.element.ts @@ -39,7 +39,6 @@ export class UmbBlockWorkspaceViewEditNoRouterElement extends UmbLitElement impl this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspaceContext) => { this._workspaceContext = workspaceContext; - console.log('workspaceContext.content.structure', workspaceContext.content.structure); this._tabsStructureHelper.setStructureManager(workspaceContext.content.structure); this._observeRootGroups(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts index 4095d6167a..d35fa40231 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-properties.element.ts @@ -1,4 +1,5 @@ import { UMB_BLOCK_WORKSPACE_CONTEXT } from '../../block-workspace.context-token.js'; +import type { UmbBlockWorkspaceElementManagerNames } from '../../block-workspace.context.js'; import { css, html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { @@ -11,24 +12,34 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-block-workspace-view-edit-properties') export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { + @property({ attribute: false }) + public get managerName(): UmbBlockWorkspaceElementManagerNames | undefined { + return this.#managerName; + } + public set managerName(value: UmbBlockWorkspaceElementManagerNames | undefined) { + this.#managerName = value; + this.#setStructureManager(); + } + #managerName?: UmbBlockWorkspaceElementManagerNames; + #blockWorkspace?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; + #propertyStructureHelper = new UmbContentTypePropertyStructureHelper(this); + @property({ type: String, attribute: 'container-name', reflect: false }) public get containerName(): string | undefined { - return this._propertyStructureHelper.getContainerName(); + return this.#propertyStructureHelper.getContainerName(); } public set containerName(value: string | undefined) { - this._propertyStructureHelper.setContainerName(value); + this.#propertyStructureHelper.setContainerName(value); } @property({ type: String, attribute: 'container-type', reflect: false }) public get containerType(): UmbPropertyContainerTypes | undefined { - return this._propertyStructureHelper.getContainerType(); + return this.#propertyStructureHelper.getContainerType(); } public set containerType(value: UmbPropertyContainerTypes | undefined) { - this._propertyStructureHelper.setContainerType(value); + this.#propertyStructureHelper.setContainerType(value); } - _propertyStructureHelper = new UmbContentTypePropertyStructureHelper(this); - @state() _propertyStructure: Array = []; @@ -36,13 +47,23 @@ export class UmbBlockWorkspaceViewEditPropertiesElement extends UmbLitElement { super(); this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspaceContext) => { - this._propertyStructureHelper.setStructureManager(workspaceContext.content.structure); - }); - this.observe(this._propertyStructureHelper.propertyStructure, (propertyStructure) => { - this._propertyStructure = propertyStructure; + this.#blockWorkspace = workspaceContext; + this.#setStructureManager(); }); } + #setStructureManager() { + if (!this.#blockWorkspace || !this.#managerName) return; + this.#propertyStructureHelper.setStructureManager(this.#blockWorkspace[this.#managerName].structure); + this.observe( + this.#propertyStructureHelper.propertyStructure, + (propertyStructure) => { + this._propertyStructure = propertyStructure; + }, + 'observePropertyStructure', + ); + } + render() { return repeat( this._propertyStructure, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-tab.element.ts index 3cac991532..03a27f78bc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/workspace/views/edit/block-workspace-view-edit-tab.element.ts @@ -7,29 +7,42 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { PropertyTypeContainerModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; import './block-workspace-view-edit-properties.element.js'; +// eslint-disable-next-line import/order +import type { UmbBlockWorkspaceElementManagerNames } from '../../block-workspace.context.js'; @customElement('umb-block-workspace-view-edit-tab') export class UmbBlockWorkspaceViewEditTabElement extends UmbLitElement { - private _tabName?: string | undefined; + @property({ attribute: false }) + public get managerName(): UmbBlockWorkspaceElementManagerNames | undefined { + return this.#managerName; + } + public set managerName(value: UmbBlockWorkspaceElementManagerNames | undefined) { + this.#managerName = value; + this.#setStructureManager(); + } + #managerName?: UmbBlockWorkspaceElementManagerNames; + #blockWorkspace?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; + #groupStructureHelper = new UmbContentTypeContainerStructureHelper(this); @property({ type: String }) public get tabName(): string | undefined { - return this._groupStructureHelper.getName(); + return this.#groupStructureHelper.getName(); } public set tabName(value: string | undefined) { if (value === this._tabName) return; const oldValue = this._tabName; this._tabName = value; - this._groupStructureHelper.setName(value); + this.#groupStructureHelper.setName(value); this.requestUpdate('tabName', oldValue); } + private _tabName?: string | undefined; @property({ type: Boolean }) public get noTabName(): boolean { - return this._groupStructureHelper.getIsRoot(); + return this.#groupStructureHelper.getIsRoot(); } public set noTabName(value: boolean) { - this._groupStructureHelper.setIsRoot(value); + this.#groupStructureHelper.setIsRoot(value); } private _ownerTabId?: string | null; @@ -40,7 +53,7 @@ export class UmbBlockWorkspaceViewEditTabElement extends UmbLitElement { public set ownerTabId(value: string | null | undefined) { if (value === this._ownerTabId) return; this._ownerTabId = value; - this._groupStructureHelper.setOwnerId(value); + this.#groupStructureHelper.setOwnerId(value); } /** @@ -50,8 +63,6 @@ export class UmbBlockWorkspaceViewEditTabElement extends UmbLitElement { @property({ type: Boolean, reflect: false }) hideSingleGroup = false; - _groupStructureHelper = new UmbContentTypeContainerStructureHelper(this); - @state() _groups: Array = []; @@ -62,16 +73,30 @@ export class UmbBlockWorkspaceViewEditTabElement extends UmbLitElement { super(); this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspaceContext) => { - this._groupStructureHelper.setStructureManager(workspaceContext.content.structure); - }); - this.observe(this._groupStructureHelper.containers, (groups) => { - this._groups = groups; - }); - this.observe(this._groupStructureHelper.hasProperties, (hasProperties) => { - this._hasProperties = hasProperties; + this.#blockWorkspace = workspaceContext; + this.#setStructureManager(); }); } + #setStructureManager() { + if (!this.#blockWorkspace || !this.#managerName) return; + this.#groupStructureHelper.setStructureManager(this.#blockWorkspace[this.#managerName].structure); + this.observe( + this.#groupStructureHelper.containers, + (groups) => { + this._groups = groups; + }, + 'observeGroups', + ); + this.observe( + this.#groupStructureHelper.hasProperties, + (hasProperties) => { + this._hasProperties = hasProperties; + }, + 'observeHasProperties', + ); + } + render() { return html` ${this._hasProperties ? this.#renderPart(this._tabName) : ''} @@ -86,11 +111,13 @@ export class UmbBlockWorkspaceViewEditTabElement extends UmbLitElement { #renderPart(groupName: string | null | undefined, boxName?: string | null | undefined) { return this.hideSingleGroup && this._groups.length === 1 ? html` ` : html` (this); + + //@state() //private _hasRootProperties = false; + + @state() private _hasRootGroups = false; @state() @@ -32,44 +43,44 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U @state() private _activePath = ''; - private _workspaceContext?: typeof UMB_BLOCK_WORKSPACE_CONTEXT.TYPE; - - private _tabsStructureHelper = new UmbContentTypeContainerStructureHelper(this); - constructor() { super(); - this._tabsStructureHelper.setIsRoot(true); - this._tabsStructureHelper.setContainerChildType('Tab'); - this.observe(this._tabsStructureHelper.containers, (tabs) => { - this._tabs = tabs; - this._createRoutes(); - }); + this.#tabsStructureHelper.setIsRoot(true); + this.#tabsStructureHelper.setContainerChildType('Tab'); // _hasRootProperties can be gotten via _tabsStructureHelper.hasProperties. But we do not support root properties currently. this.consumeContext(UMB_BLOCK_WORKSPACE_CONTEXT, (workspaceContext) => { - this._workspaceContext = workspaceContext; - this._tabsStructureHelper.setStructureManager(workspaceContext.content.structure); - this._observeRootGroups(); + this.#blockWorkspace = workspaceContext; + this.#setStructureManager(); }); } - private _observeRootGroups() { - if (!this._workspaceContext) return; + #setStructureManager() { + if (!this.#blockWorkspace || !this.#managerName) return; + this.#tabsStructureHelper.setStructureManager(this.#blockWorkspace[this.#managerName].structure); this.observe( - this._workspaceContext.content.structure.hasRootContainers('Group'), + this.#blockWorkspace![this.#managerName!].structure.hasRootContainers('Group'), (hasRootGroups) => { this._hasRootGroups = hasRootGroups; this._createRoutes(); }, - '_observeGroups', + 'observeGroups', + ); + this.observe( + this.#tabsStructureHelper.containers, + (tabs) => { + this._tabs = tabs; + this._createRoutes(); + }, + 'observeTabs', ); } private _createRoutes() { - if (!this._tabs || !this._workspaceContext) return; + if (!this._tabs || !this.#blockWorkspace) return; const routes: UmbRoute[] = []; if (this._tabs.length > 0) { @@ -79,10 +90,11 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U path: `tab/${encodeFolderName(tabName).toString()}`, component: () => import('./block-workspace-view-edit-tab.element.js'), setup: (component) => { + (component as UmbBlockWorkspaceViewEditTabElement).managerName = this.#managerName; (component as UmbBlockWorkspaceViewEditTabElement).tabName = tabName; // TODO: Consider if we can link these more simple, and not parse this on. // Instead have the structure manager looking at wether one of the OwnerALikecontainers is in the owner document. - (component as UmbBlockWorkspaceViewEditTabElement).ownerTabId = this._tabsStructureHelper.isOwnerContainer( + (component as UmbBlockWorkspaceViewEditTabElement).ownerTabId = this.#tabsStructureHelper.isOwnerContainer( tab.id!, ) ? tab.id @@ -97,6 +109,7 @@ export class UmbBlockWorkspaceViewEditElement extends UmbLitElement implements U path: '', component: () => import('./block-workspace-view-edit-tab.element.js'), setup: (component) => { + (component as UmbBlockWorkspaceViewEditTabElement).managerName = this.#managerName; (component as UmbBlockWorkspaceViewEditTabElement).noTabName = true; (component as UmbBlockWorkspaceViewEditTabElement).ownerTabId = null; }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts index 645ff5d263..155ab0333d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-slot/extension-slot.element.ts @@ -1,6 +1,6 @@ import { type ManifestTypes, umbExtensionsRegistry } from '../../extension-registry/index.js'; import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; -import { css, repeat, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, repeat, customElement, property, state, html } from '@umbraco-cms/backoffice/external/lit'; import { type UmbExtensionElementInitializer, UmbExtensionsElementInitializer, @@ -122,11 +122,13 @@ export class UmbExtensionSlotElement extends UmbLitElement { } render() { - return repeat( - this._permittedExts, - (ext) => ext.alias, - (ext) => (this.renderMethod ? this.renderMethod(ext) : ext.component), - ); + return this._permittedExts.length > 0 + ? repeat( + this._permittedExts, + (ext) => ext.alias, + (ext) => (this.renderMethod ? this.renderMethod(ext) : ext.component), + ) + : html``; } static styles = css` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts index 4931a9977e..de68f3e1cd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts @@ -1,4 +1,5 @@ -import { manifest as switchConditionManifest } from './switch.condition.js'; +import { manifest as menuAliasConditionManifest } from './menu-alias.condition.js'; import { manifest as sectionAliasConditionManifest } from './section-alias.condition.js'; +import { manifest as switchConditionManifest } from './switch.condition.js'; -export const manifests = [switchConditionManifest, sectionAliasConditionManifest]; +export const manifests = [menuAliasConditionManifest, sectionAliasConditionManifest, switchConditionManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts index 74dc170c54..24801fd5e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts @@ -2,6 +2,7 @@ import type { CollectionAliasConditionConfig } from '../../collection/collection import type { SectionAliasConditionConfig } from './section-alias.condition.js'; import type { SwitchConditionConfig } from './switch.condition.js'; import type { UserPermissionConditionConfig } from '@umbraco-cms/backoffice/user-permission'; +import type { BlockWorkspaceHasSettingsConditionConfig } from '@umbraco-cms/backoffice/block'; import type { WorkspaceAliasConditionConfig, WorkspaceEntityTypeConditionConfig, @@ -16,6 +17,7 @@ export type ConditionTypes = | CollectionAliasConditionConfig | SectionAliasConditionConfig | WorkspaceAliasConditionConfig + | BlockWorkspaceHasSettingsConditionConfig | WorkspaceEntityTypeConditionConfig | SwitchConditionConfig | UserPermissionConditionConfig diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts new file mode 100644 index 0000000000..da338c1c27 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts @@ -0,0 +1,6 @@ +import type { UmbPropertyEditorUiElement } from '../interfaces/index.js'; +import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; + +export interface ManifestBlockEditorCustomView extends ManifestElement { + type: 'bockEditorCustomView'; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index c5378f48cd..768e0f6b88 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -1,3 +1,4 @@ +import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; import type { ManifestCollection } from './collection.models.js'; import type { ManifestCollectionView } from './collection-view.model.js'; import type { ManifestDashboard } from './dashboard.model.js'; @@ -40,6 +41,7 @@ import type { ManifestEntryPoint, } from '@umbraco-cms/backoffice/extension-api'; +export type * from './block-editor-custom-view.model.js'; export type * from './collection.models.js'; export type * from './collection-action.model.js'; export type * from './collection-view.model.js'; @@ -79,6 +81,7 @@ export type * from './workspace.model.js'; export type ManifestTypes = | ManifestBundle | ManifestCondition + | ManifestBlockEditorCustomView | ManifestCollection | ManifestCollectionView | ManifestCollectionAction diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/workspace-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/workspace-modal.element.ts index de53c48aa7..e5c77d98da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/workspace-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/workspace-modal.element.ts @@ -1,5 +1,5 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { CSSResultGroup} from '@umbraco-cms/backoffice/external/lit'; +import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import type { UmbWorkspaceData } from '@umbraco-cms/backoffice/modal'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/edit/document-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/edit/document-workspace-view-edit.element.ts index 5ea21b444f..68a60a2bc6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/edit/document-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/edit/document-workspace-view-edit.element.ts @@ -11,14 +11,17 @@ import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension- @customElement('umb-document-workspace-view-edit') export class UmbDocumentWorkspaceViewEditElement extends UmbLitElement implements UmbWorkspaceViewElement { + //@state() //private _hasRootProperties = false; + + @state() private _hasRootGroups = false; @state() private _routes: UmbRoute[] = []; @state() - _tabs?: Array; + private _tabs?: Array; @state() private _routerPath?: string;