diff --git a/examples/entity-content-type-condition/index.ts b/examples/entity-content-type-condition/index.ts new file mode 100644 index 0000000000..4d0972cc7f --- /dev/null +++ b/examples/entity-content-type-condition/index.ts @@ -0,0 +1,22 @@ +import type { ManifestWorkspaceView } from '@umbraco-cms/backoffice/extension-registry'; + +const workspace: ManifestWorkspaceView = { + type: 'workspaceView', + alias: 'Example.WorkspaceView.EntityContentTypeCondition', + name: 'Example Workspace View With Entity Content Type Condition', + element: () => import('./workspace-view.element.js'), + meta: { + icon: 'icon-bus', + label: 'Conditional', + pathname: 'conditional', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceContentTypeAlias', + //match : 'blogPost' + oneOf: ['blogPost', 'mediaType1'], + }, + ], +}; + +export const manifests = [workspace]; diff --git a/examples/entity-content-type-condition/workspace-view.element.ts b/examples/entity-content-type-condition/workspace-view.element.ts new file mode 100644 index 0000000000..cd6a518e36 --- /dev/null +++ b/examples/entity-content-type-condition/workspace-view.element.ts @@ -0,0 +1,19 @@ +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 UmbWorkspaceViewElement 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 UmbWorkspaceViewElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-example-entity-content-type-condition': UmbWorkspaceViewElement; + } +} diff --git a/src/packages/core/extension-registry/conditions/types.ts b/src/packages/core/extension-registry/conditions/types.ts index f1e92fbe34..e288f3ad94 100644 --- a/src/packages/core/extension-registry/conditions/types.ts +++ b/src/packages/core/extension-registry/conditions/types.ts @@ -7,6 +7,7 @@ import type { UmbMultipleAppLanguageConditionConfig } from './multiple-app-langu import type { WorkspaceAliasConditionConfig, WorkspaceEntityTypeConditionConfig, + WorkspaceContentTypeAliasConditionConfig, } from '@umbraco-cms/backoffice/workspace'; import type { UmbConditionConfigBase } from '@umbraco-cms/backoffice/extension-api'; import type { UmbDocumentUserPermissionConditionConfig } from '@umbraco-cms/backoffice/document'; @@ -35,4 +36,6 @@ export type ConditionTypes = | UmbMultipleAppLanguageConditionConfig | UmbSectionUserPermissionConditionConfig | WorkspaceAliasConditionConfig - | WorkspaceEntityTypeConditionConfig; + | WorkspaceEntityTypeConditionConfig + | WorkspaceContentTypeAliasConditionConfig + | UmbConditionConfigBase; diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index 3adb526942..adc53de04c 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -71,8 +71,8 @@ import type { ManifestBackofficeEntryPoint } from './backoffice-entry-point.mode import type { ManifestEntryPoint } from './entry-point.model.js'; import type { ManifestMonacoMarkdownEditorAction } from './monaco-markdown-editor-action.model.js'; import type { ManifestSectionRoute } from './section-route.model.js'; -import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; import type { ManifestPickerSearchResultItem } from './picker-search-result-item.model.js'; +import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; export type * from './app-entry-point.model.js'; export type * from './auth-provider.model.js'; diff --git a/src/packages/core/property-type/workspace/property-type-workspace.context.ts b/src/packages/core/property-type/workspace/property-type-workspace.context.ts index 822676a46c..5311ea844f 100644 --- a/src/packages/core/property-type/workspace/property-type-workspace.context.ts +++ b/src/packages/core/property-type/workspace/property-type-workspace.context.ts @@ -189,6 +189,7 @@ export class UmbPropertyTypeWorkspaceContext} value - value can be a promise resolving into the actual value or the raw value it self. * @returns {Promise} * @description Set the value of this property. diff --git a/src/packages/core/workspace/conditions/index.ts b/src/packages/core/workspace/conditions/index.ts index 028680ae5f..9ec898b193 100644 --- a/src/packages/core/workspace/conditions/index.ts +++ b/src/packages/core/workspace/conditions/index.ts @@ -1,3 +1,5 @@ export type { WorkspaceAliasConditionConfig } from './workspace-alias.condition.js'; export type { WorkspaceEntityTypeConditionConfig } from './workspace-entity-type.condition.js'; export type { WorkspaceHasCollectionConditionConfig } from './workspace-has-collection.condition.js'; +export type { WorkspaceContentTypeAliasConditionConfig as WorkspaceEntityContentTypeConditionConfig } from './workspace-content-type-alias.condition.js'; +export type { WorkspaceContentTypeAliasConditionConfig } from './workspace-content-type-alias.condition.js'; diff --git a/src/packages/core/workspace/conditions/manifests.ts b/src/packages/core/workspace/conditions/manifests.ts index 78ced4ccc8..68593d2174 100644 --- a/src/packages/core/workspace/conditions/manifests.ts +++ b/src/packages/core/workspace/conditions/manifests.ts @@ -1,10 +1,12 @@ import { manifest as workspaceAliasCondition } from './workspace-alias.condition.js'; import { manifest as workspaceEntityTypeCondition } from './workspace-entity-type.condition.js'; import { manifest as workspaceHasCollectionCondition } from './workspace-has-collection.condition.js'; +import { manifest as workspaceContentTypeAliasCondition } from './workspace-content-type-alias.condition.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ workspaceAliasCondition, workspaceEntityTypeCondition, workspaceHasCollectionCondition, + workspaceContentTypeAliasCondition, ]; diff --git a/src/packages/core/workspace/conditions/workspace-content-type-alias.condition.ts b/src/packages/core/workspace/conditions/workspace-content-type-alias.condition.ts new file mode 100644 index 0000000000..eefd16baa0 --- /dev/null +++ b/src/packages/core/workspace/conditions/workspace-content-type-alias.condition.ts @@ -0,0 +1,73 @@ +import { UmbConditionBase } from '../../extension-registry/conditions/condition-base.controller.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import type { + ManifestCondition, + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; + +const ObserveSymbol = Symbol(); + +/** + * Condition to apply workspace extension based on a content type alias + */ +export class UmbWorkspaceContentTypeAliasCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor( + host: UmbControllerHost, + args: UmbConditionControllerArguments, + ) { + super(host, args); + + let permissionCheck: ((contentTypeAliases: string[]) => boolean) | undefined = undefined; + if (this.config.match) { + permissionCheck = (contentTypeAliases: string[]) => contentTypeAliases.includes(this.config.match!); + } else if (this.config.oneOf) { + permissionCheck = (contentTypeAliases: string[]) => + contentTypeAliases.some((item) => this.config.oneOf!.includes(item)); + } + + if (permissionCheck !== undefined) { + this.consumeContext(UMB_PROPERTY_STRUCTURE_WORKSPACE_CONTEXT, (context) => { + this.observe( + context.structure.contentTypeAliases, + (contentTypeAliases) => { + this.permitted = contentTypeAliases ? permissionCheck!(contentTypeAliases) : false; + }, + ObserveSymbol, + ); + }); + } else { + throw new Error( + 'Condition `Umb.Condition.WorkspaceContentTypeAlias` could not be initialized properly. Either "match" or "oneOf" must be defined', + ); + } + } +} + +export type WorkspaceContentTypeAliasConditionConfig = + UmbConditionConfigBase<'Umb.Condition.WorkspaceContentTypeAlias'> & { + /** + * 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; + }; + +export const manifest: ManifestCondition = { + type: 'condition', + name: 'Workspace Content Type Alias Condition', + alias: 'Umb.Condition.WorkspaceContentTypeAlias', + api: UmbWorkspaceContentTypeAliasCondition, +}; diff --git a/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts b/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts index 857419aa90..c8587320b7 100644 --- a/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts +++ b/src/packages/documents/document-blueprints/workspace/document-blueprint-workspace.context.ts @@ -253,6 +253,7 @@ export class UmbDocumentBlueprintWorkspaceContext } /** * @function propertyValueByAlias + * @param variantId * @param {string} propertyAlias * @returns {Promise | undefined>} * @description Get an Observable for the value of this property.