diff --git a/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/content-type-alias-condition-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/content-type-alias-condition-workspace-view.element.ts new file mode 100644 index 000000000000..0df9c4c0082d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/content-type-alias-condition-workspace-view.element.ts @@ -0,0 +1,48 @@ +import { UMB_CONTENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content'; +import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; + +@customElement('example-content-type-alias-condition-workspace-view') +export class ExampleContentTypeAliasConditionWorkspaceViewElement extends UmbLitElement { + @state() + private _contentTypeAliases: string[] = []; + + constructor() { + super(); + + this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => { + this.observe(context?.structure.contentTypeAliases, (contentTypeAliases) => { + this._contentTypeAliases = contentTypeAliases || []; + }); + }); + } + + override render() { + return html` +

Content Type Alias Condition Example

+

+ Content Type ${this._contentTypeAliases.length > 1 ? 'aliases' : 'alias'}: + ${this._contentTypeAliases} +

+
`; + } + + static override styles = [ + UmbTextStyles, + css` + :host { + display: block; + margin: var(--uui-size-layout-2); + } + `, + ]; +} + +export { ExampleContentTypeAliasConditionWorkspaceViewElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'example-content-type-alias-condition-workspace-view': ExampleContentTypeAliasConditionWorkspaceViewElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/content-type-unique-condition-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/content-type-unique-condition-workspace-view.element.ts new file mode 100644 index 000000000000..6ce9bc9eec03 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/content-type-unique-condition-workspace-view.element.ts @@ -0,0 +1,48 @@ +import { UMB_CONTENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content'; +import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; + +@customElement('example-content-type-unique-condition-workspace-view') +export class ExampleContentTypeUniqueConditionWorkspaceViewElement extends UmbLitElement { + @state() + private _contentTypeUniques: string[] = []; + + constructor() { + super(); + + this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => { + this.observe(context?.structure.contentTypeUniques, (contentTypeUniques) => { + this._contentTypeUniques = contentTypeUniques || []; + }); + }); + } + + override render() { + return html` +

Content Type Unique Condition Example

+

+ Content Type ${this._contentTypeUniques.length > 1 ? 'ids' : 'id'}: + ${this._contentTypeUniques} +

+
`; + } + + static override styles = [ + UmbTextStyles, + css` + :host { + display: block; + margin: var(--uui-size-layout-2); + } + `, + ]; +} + +export { ExampleContentTypeUniqueConditionWorkspaceViewElement as element }; + +declare global { + interface HTMLElementTagNameMap { + 'example-content-type-unique-condition-workspace-view': ExampleContentTypeUniqueConditionWorkspaceViewElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/index.ts b/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/index.ts index 43cc3a71a366..f4322158ff99 100644 --- a/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/index.ts @@ -1,22 +1,43 @@ -import { UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS } from '@umbraco-cms/backoffice/content-type'; +import { + UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS, + UMB_WORKSPACE_CONTENT_TYPE_UNIQUE_CONDITION, +} from '@umbraco-cms/backoffice/content-type'; -const workspace: UmbExtensionManifest = { +const workspaceViewAlias: UmbExtensionManifest = { type: 'workspaceView', - alias: 'Example.WorkspaceView.EntityContentTypeCondition', - name: 'Example Workspace View With Entity Content Type Condition', - element: () => import('./workspace-view.element.js'), + alias: 'Example.WorkspaceView.EntityContentTypeAliasCondition', + name: 'Example Workspace View With Entity Content Type Alias Condition', + element: () => import('./content-type-alias-condition-workspace-view.element.js'), meta: { icon: 'icon-bus', - label: 'Conditional', - pathname: 'conditional', + label: 'Conditional (Alias)', + pathname: 'conditional-alias', }, conditions: [ { alias: UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS, - //match : 'blogPost' + //match: 'blogPost', oneOf: ['blogPost', 'mediaType1'], }, ], }; -export const manifests = [workspace]; +const workspaceViewUnique: UmbExtensionManifest = { + type: 'workspaceView', + alias: 'Example.WorkspaceView.EntityContentTypeUniqueCondition', + name: 'Example Workspace View With Content Type Unique Condition', + element: () => import('./content-type-unique-condition-workspace-view.element.js'), + meta: { + icon: 'icon-science', + label: 'Conditional (Unique)', + pathname: 'conditional-unique', + }, + conditions: [ + { + alias: UMB_WORKSPACE_CONTENT_TYPE_UNIQUE_CONDITION, + oneOf: ['721e85d3-0a2d-4f99-be55-61a5c5ed5c14', '1b88975d-60d0-4b84-809a-4a4deff38a66'], // Example uniques + }, + ], +}; + +export const manifests = [workspaceViewAlias, workspaceViewUnique]; diff --git a/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/workspace-view.element.ts b/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/workspace-view.element.ts deleted file mode 100644 index b4390f0f625f..000000000000 --- a/src/Umbraco.Web.UI.Client/examples/entity-content-type-condition/workspace-view.element.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; - -@customElement('umb-example-entity-content-type-condition') -export class UmbWorkspaceExampleViewElement extends UmbLitElement { - override render() { - return html`

- This is a conditional element that is only shown in workspaces based on it's entities content type. -

`; - } -} - -export default UmbWorkspaceExampleViewElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-example-entity-content-type-condition': UmbWorkspaceExampleViewElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/constants.ts index 0bf665f7712c..8c5bd4462ece 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/constants.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/constants.ts @@ -1,4 +1,2 @@ -/** - * Workspace Content Type Alias condition alias - */ -export const UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS = 'Umb.Condition.WorkspaceContentTypeAlias'; +export * from './workspace-content-type-alias/constants.js'; +export * from './workspace-content-type-unique/constants.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/manifests.ts index 0e4865bde973..de68f5ce2632 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/manifests.ts @@ -1,3 +1,4 @@ -import { manifest as workspaceContentTypeAliasCondition } from './workspace-content-type-alias.condition.js'; +import { manifests as workspaceAliasCondition } from './workspace-content-type-alias/manifests.js'; +import { manifests as WorkspaceContentTypeUnique } from './workspace-content-type-unique/manifests.js'; -export const manifests: Array = [workspaceContentTypeAliasCondition]; +export const manifests: Array = [...workspaceAliasCondition, ...WorkspaceContentTypeUnique]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/types.ts index e0a50062e2f9..e6fbd340f910 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/types.ts @@ -1,25 +1,2 @@ -import type { UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS } from './constants.js'; -import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; - -export type UmbWorkspaceContentTypeAliasConditionConfig = UmbConditionConfigBase< - typeof UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS -> & { - /** - * Define a content type alias in which workspace this extension should be available - * @example - * Depends on implementation, but i.e. "article", "image", "blockPage" - */ - match?: string; - /** - * Define one or more content type aliases in which workspace this extension should be available - * @example - * ["article", "image", "blockPage"] - */ - oneOf?: Array; -}; - -declare global { - interface UmbExtensionConditionConfigMap { - umbWorkspaceContentTypeAliasConditionConfig: UmbWorkspaceContentTypeAliasConditionConfig; - } -} +export type * from './workspace-content-type-alias/types.js'; +export type * from './workspace-content-type-unique/types.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/constants.ts new file mode 100644 index 000000000000..0bf665f7712c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/constants.ts @@ -0,0 +1,4 @@ +/** + * Workspace Content Type Alias condition alias + */ +export const UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS = 'Umb.Condition.WorkspaceContentTypeAlias'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/manifests.ts new file mode 100644 index 000000000000..dc0707b60b9e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS } from './constants.js'; +import { UmbWorkspaceContentTypeAliasCondition } from './workspace-content-type-alias.condition.js'; + +export const manifests: Array = [ + { + type: 'condition', + name: 'Workspace Content Type Alias Condition', + alias: UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS, + api: UmbWorkspaceContentTypeAliasCondition, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/types.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/types.ts new file mode 100644 index 000000000000..e0a50062e2f9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/types.ts @@ -0,0 +1,25 @@ +import type { UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +export type UmbWorkspaceContentTypeAliasConditionConfig = UmbConditionConfigBase< + typeof UMB_WORKSPACE_CONTENT_TYPE_ALIAS_CONDITION_ALIAS +> & { + /** + * Define a content type alias in which workspace this extension should be available + * @example + * Depends on implementation, but i.e. "article", "image", "blockPage" + */ + match?: string; + /** + * Define one or more content type aliases in which workspace this extension should be available + * @example + * ["article", "image", "blockPage"] + */ + oneOf?: Array; +}; + +declare global { + interface UmbExtensionConditionConfigMap { + umbWorkspaceContentTypeAliasConditionConfig: UmbWorkspaceContentTypeAliasConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/workspace-content-type-alias.condition.ts similarity index 85% rename from src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/workspace-content-type-alias.condition.ts index 532489b6255b..da85548886b8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-alias/workspace-content-type-alias.condition.ts @@ -1,8 +1,8 @@ -import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '../contexts/index.js'; import type { UmbWorkspaceContentTypeAliasConditionConfig } from './types.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '../../contexts/property-structure-workspace.context-token.js'; const ObserveSymbol = Symbol(); @@ -44,10 +44,3 @@ export class UmbWorkspaceContentTypeAliasCondition } } } - -export const manifest: UmbExtensionManifest = { - type: 'condition', - name: 'Workspace Content Type Alias Condition', - alias: 'Umb.Condition.WorkspaceContentTypeAlias', - api: UmbWorkspaceContentTypeAliasCondition, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/constants.ts new file mode 100644 index 000000000000..15db97c106b9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/constants.ts @@ -0,0 +1,4 @@ +/** + * Workspace Content Type Unique condition + */ +export const UMB_WORKSPACE_CONTENT_TYPE_UNIQUE_CONDITION = 'Umb.Condition.WorkspaceContentTypeUnique'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/manifests.ts new file mode 100644 index 000000000000..bc20852f0e69 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/manifests.ts @@ -0,0 +1,11 @@ +import { UMB_WORKSPACE_CONTENT_TYPE_UNIQUE_CONDITION } from './constants.js'; +import { UmbWorkspaceContentTypeUniqueCondition } from './workspace-content-type-unique.condition.js'; + +export const manifests: Array = [ + { + type: 'condition', + name: 'Workspace Content Type Unique Condition', + alias: UMB_WORKSPACE_CONTENT_TYPE_UNIQUE_CONDITION, + api: UmbWorkspaceContentTypeUniqueCondition, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/types.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/types.ts new file mode 100644 index 000000000000..e41bbfd84e41 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/types.ts @@ -0,0 +1,25 @@ +import type { UMB_WORKSPACE_CONTENT_TYPE_UNIQUE_CONDITION } from './constants.js'; +import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; + +export type UmbWorkspaceContentTypeUniqueConditionConfig = UmbConditionConfigBase< + typeof UMB_WORKSPACE_CONTENT_TYPE_UNIQUE_CONDITION +> & { + /** + * Define a content type unique (GUID) in which workspace this extension should be available + * @example + * Depends on implementation, but i.e. "d59be02f-1df9-4228-aa1e-01917d806cda" + */ + match?: string; + /** + * Define one or more content type unique (GUIDs) in which workspace this extension should be available + * @example + * ["d59be02f-1df9-4228-aa1e-01917d806cda", "42d7572e-1ba1-458d-a765-95b60040c3ac"] + */ + oneOf?: Array; +}; + +declare global { + interface UmbExtensionConditionConfigMap { + umbWorkspaceContentTypeUniqueConditionConfig: UmbWorkspaceContentTypeUniqueConditionConfig; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/workspace-content-type-unique.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/workspace-content-type-unique.condition.ts new file mode 100644 index 000000000000..6d18dd772174 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content-type/conditions/workspace-content-type-unique/workspace-content-type-unique.condition.ts @@ -0,0 +1,47 @@ +import type { UmbWorkspaceContentTypeUniqueConditionConfig } from './types.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbConditionControllerArguments, UmbExtensionCondition } from '@umbraco-cms/backoffice/extension-api'; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '../../contexts/property-structure-workspace.context-token.js'; + +const ObserveSymbol = Symbol(); + +/** + * Condition to apply workspace extension based on a content type unique (GUID) + */ +export class UmbWorkspaceContentTypeUniqueCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor( + host: UmbControllerHost, + args: UmbConditionControllerArguments, + ) { + super(host, args); + + let permissionCheck: ((contentTypeUniques: string[]) => boolean) | undefined = undefined; + if (this.config.match) { + permissionCheck = (contentTypeUniques: string[]) => contentTypeUniques.includes(this.config.match!); + } else if (this.config.oneOf) { + permissionCheck = (contentTypeUniques: string[]) => + contentTypeUniques.some((item) => this.config.oneOf!.includes(item)); + } + + if (permissionCheck !== undefined) { + this.consumeContext(UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT, (context) => { + this.observe( + context?.structure.contentTypeUniques, + (contentTypeUniques) => { + const result = contentTypeUniques ? permissionCheck!(contentTypeUniques) : false; + this.permitted = result; + }, + ObserveSymbol, + ); + }); + } else { + throw new Error( + 'Condition `Umb.Condition.WorkspaceContentTypeUnique` could not be initialized properly. Either "match" or "oneOf" must be defined', + ); + } + } +}