Merge pull request #1408 from umbraco/refactor/workspace-collection-condition-token

Refactor: Workspace Collection Condition (plus new Context token)
This commit is contained in:
Lee Kelleher
2024-03-14 08:42:30 +00:00
committed by GitHub
20 changed files with 117 additions and 137 deletions

View File

@@ -8,7 +8,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element';
import { UMB_DOCUMENT_COLLECTION_ALIAS } from '@umbraco-cms/backoffice/document';
import { UMB_MEDIA_COLLECTION_ALIAS } from '@umbraco-cms/backoffice/media';
import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property';
import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { UMB_WORKSPACE_CONTEXT, UMB_WORKSPACE_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import type { UmbDocumentWorkspaceContext } from '@umbraco-cms/backoffice/document';
import type { UmbMediaWorkspaceContext } from '@umbraco-cms/backoffice/media';
import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry';
@@ -35,28 +35,16 @@ export class UmbPropertyEditorUICollectionViewElement extends UmbLitElement impl
constructor() {
super();
// Gets the Data Type ID for the current property.
this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => {
this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
// TODO: [LK:2024-02-22] We need a solution that will allow the Collection property-editor
// to work in any workspace (that supports `unique` and `structure.getPropertyStructureByAlias`).
const entityType = workspaceContext.getEntityType();
const contentWorkspaceContext =
entityType === 'media'
? (workspaceContext as UmbMediaWorkspaceContext)
: (workspaceContext as UmbDocumentWorkspaceContext);
this.consumeContext(UMB_WORKSPACE_COLLECTION_CONTEXT, (workspaceContext) => {
this._collectionAlias = workspaceContext.getCollectionAlias();
this._collectionAlias = entityType === 'media' ? UMB_MEDIA_COLLECTION_ALIAS : UMB_DOCUMENT_COLLECTION_ALIAS;
this.observe(contentWorkspaceContext.unique, (unique) => {
if (this._config) {
this._config.unique = unique;
}
});
this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => {
this.observe(propertyContext.alias, async (propertyAlias) => {
if (propertyAlias) {
const property = await contentWorkspaceContext.structure.getPropertyStructureByAlias(propertyAlias);
// Gets the Data Type ID for the current property.
const property = await workspaceContext.structure.getPropertyStructureByAlias(propertyAlias);
if (property && this._config) {
this._config.unique = workspaceContext.getUnique();
this._config.dataTypeId = property.dataType.unique;
this.requestUpdate('_config');
}

View File

@@ -2,10 +2,12 @@ import { manifests as componentManifests } from './components/manifests.js';
import { manifests as workspaceModals } from './workspace-modal/manifests.js';
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';
export const manifests = [
...componentManifests,
...workspaceModals,
workspaceAliasCondition,
workspaceEntityTypeCondition,
workspaceHasCollectionCondition,
];

View File

@@ -1,6 +1,8 @@
export * from './property-structure-workspace-context.interface.js';
export * from './publishable-workspace-context.interface.js';
export * from './saveable-workspace-context.interface.js';
export * from './workspace-collection-context.interface.js';
export * from './workspace-collection-context.token.js';
export * from './variant-workspace-context.token.js';
export * from './workspace-context.interface.js';
export * from './editable-workspace-context-base.js';

View File

@@ -0,0 +1,10 @@
import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js';
import type { Observable } from '@umbraco-cms/backoffice/external/rxjs';
import type { UmbContentTypeModel, UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
export interface UmbWorkspaceCollectionContextInterface<T extends UmbContentTypeModel>
extends UmbWorkspaceContextInterface {
contentTypeHasCollection: Observable<boolean>;
getCollectionAlias(): string;
structure: UmbContentTypePropertyStructureManager<T>;
}

View File

@@ -0,0 +1,16 @@
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type';
import type {
UmbWorkspaceContextInterface,
UmbWorkspaceCollectionContextInterface,
} from '@umbraco-cms/backoffice/workspace';
export const UMB_WORKSPACE_COLLECTION_CONTEXT = new UmbContextToken<
UmbWorkspaceContextInterface,
UmbWorkspaceCollectionContextInterface<UmbContentTypeModel>
>(
'UmbWorkspaceContext',
undefined,
(context): context is UmbWorkspaceCollectionContextInterface<UmbContentTypeModel> =>
(context as UmbWorkspaceCollectionContextInterface<UmbContentTypeModel>).contentTypeHasCollection !== undefined,
);

View File

@@ -0,0 +1,44 @@
import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry';
import type {
ManifestCondition,
UmbConditionConfigBase,
UmbConditionControllerArguments,
UmbExtensionCondition,
} from '@umbraco-cms/backoffice/extension-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UMB_WORKSPACE_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/workspace';
export class UmbWorkspaceHasCollectionCondition
extends UmbConditionBase<WorkspaceHasCollectionConditionConfig>
implements UmbExtensionCondition
{
constructor(
host: UmbControllerHost,
args: UmbConditionControllerArguments<WorkspaceHasCollectionConditionConfig>,
) {
super(host, args);
this.consumeContext(UMB_WORKSPACE_COLLECTION_CONTEXT, (context) => {
this.observe(
context.contentTypeHasCollection,
(hasCollection) => {
this.permitted = hasCollection;
},
'observeHasCollection',
);
});
}
}
export type WorkspaceHasCollectionConditionConfig = UmbConditionConfigBase<
typeof UMB_WORKSPACE_HAS_COLLECTION_CONDITION
>;
export const UMB_WORKSPACE_HAS_COLLECTION_CONDITION = 'Umb.Condition.WorkspaceHasCollection';
export const manifest: ManifestCondition = {
type: 'condition',
name: 'Workspace Has Collection Condition',
alias: UMB_WORKSPACE_HAS_COLLECTION_CONDITION,
api: UmbWorkspaceHasCollectionCondition,
};

View File

@@ -1,44 +0,0 @@
import { UMB_DOCUMENT_WORKSPACE_CONTEXT } from '../workspace/document-workspace.context-token.js';
import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry';
import type {
ManifestCondition,
UmbConditionConfigBase,
UmbConditionControllerArguments,
UmbExtensionCondition,
} from '@umbraco-cms/backoffice/extension-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
export class UmbDocumentWorkspaceHasCollectionCondition
extends UmbConditionBase<DocumentWorkspaceHasCollectionConditionConfig>
implements UmbExtensionCondition
{
constructor(
host: UmbControllerHost,
args: UmbConditionControllerArguments<DocumentWorkspaceHasCollectionConditionConfig>,
) {
super(host, args);
this.consumeContext(UMB_DOCUMENT_WORKSPACE_CONTEXT, (context) => {
this.observe(
context.contentTypeHasCollection,
(hasCollection) => {
this.permitted = hasCollection;
},
'observeCollection',
);
});
}
}
export type DocumentWorkspaceHasCollectionConditionConfig = UmbConditionConfigBase<
typeof UMB_DOCUMENT_WORKSPACE_HAS_COLLECTION_CONDITION
>;
export const UMB_DOCUMENT_WORKSPACE_HAS_COLLECTION_CONDITION = 'Umb.Condition.DocumentWorkspaceHasCollection';
export const manifest: ManifestCondition = {
type: 'condition',
name: 'Document Workspace Has Collection Condition',
alias: UMB_DOCUMENT_WORKSPACE_HAS_COLLECTION_CONDITION,
api: UmbDocumentWorkspaceHasCollectionCondition,
};

View File

@@ -1 +0,0 @@
export { UMB_DOCUMENT_WORKSPACE_HAS_COLLECTION_CONDITION } from './document-workspace-has-collection.condition.js';

View File

@@ -1,3 +0,0 @@
import { manifest as docummentWorkspaceHasCollectionCondition } from './document-workspace-has-collection.condition.js';
export const manifests = [docummentWorkspaceHasCollectionCondition];

View File

@@ -8,7 +8,6 @@ export * from './user-permissions/index.js';
export * from './components/index.js';
export * from './entity.js';
export * from './entity-actions/index.js';
export * from './conditions/index.js';
export * from './modals/index.js';
export * from './tree/index.js';

View File

@@ -1,6 +1,5 @@
import { manifests as breadcrumbManifests } from './breadcrumb/manifests.js';
import { manifests as collectionManifests } from './collection/manifests.js';
import { manifests as conditionManifests } from './conditions/manifests.js';
import { manifests as entityActionManifests } from './entity-actions/manifests.js';
import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js';
import { manifests as menuItemManifests } from './menu-item/manifests.js';
@@ -16,7 +15,6 @@ import { manifests as workspaceManifests } from './workspace/manifests.js';
export const manifests = [
...breadcrumbManifests,
...collectionManifests,
...conditionManifests,
...entityActionManifests,
...entityBulkActionManifests,
...menuItemManifests,

View File

@@ -14,11 +14,11 @@ import { UmbUnpublishDocumentEntityAction } from '../entity-actions/unpublish.ac
import { UMB_DOCUMENT_WORKSPACE_ALIAS } from './manifests.js';
import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant';
import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
import {
UmbEditableWorkspaceContextBase,
UmbWorkspaceSplitViewManager,
type UmbVariantableWorkspaceContextInterface,
type UmbPublishableWorkspaceContextInterface,
import { UmbEditableWorkspaceContextBase, UmbWorkspaceSplitViewManager } from '@umbraco-cms/backoffice/workspace';
import type {
UmbWorkspaceCollectionContextInterface,
UmbVariantableWorkspaceContextInterface,
UmbPublishableWorkspaceContextInterface,
} from '@umbraco-cms/backoffice/workspace';
import {
appendToFrozenArray,
@@ -33,11 +33,15 @@ import { type Observable, firstValueFrom } from '@umbraco-cms/backoffice/externa
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree';
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/event';
import type { UmbDocumentTypeDetailModel } from '@umbraco-cms/backoffice/document-type';
type EntityType = UmbDocumentDetailModel;
export class UmbDocumentWorkspaceContext
extends UmbEditableWorkspaceContextBase<EntityType>
implements UmbVariantableWorkspaceContextInterface<UmbDocumentVariantModel>, UmbPublishableWorkspaceContextInterface
implements
UmbVariantableWorkspaceContextInterface<UmbDocumentVariantModel>,
UmbPublishableWorkspaceContextInterface,
UmbWorkspaceCollectionContextInterface<UmbDocumentTypeDetailModel>
{
//
public readonly repository = new UmbDocumentDetailRepository(this);
@@ -64,6 +68,7 @@ export class UmbDocumentWorkspaceContext
readonly contentTypeUnique = this.#currentData.asObservablePart((data) => data?.documentType.unique);
readonly contentTypeHasCollection = this.#currentData.asObservablePart((data) => !!data?.documentType.collection);
readonly variants = this.#currentData.asObservablePart((data) => data?.variants ?? []);
readonly urls = this.#currentData.asObservablePart((data) => data?.urls || []);
@@ -163,6 +168,10 @@ export class UmbDocumentWorkspaceContext
return data;
}
getCollectionAlias() {
return 'Umb.Collection.Document';
}
getData() {
return this.#currentData.getValue();
}

View File

@@ -1,5 +1,4 @@
import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js';
import { UMB_DOCUMENT_WORKSPACE_HAS_COLLECTION_CONDITION } from '../conditions/document-workspace-has-collection.condition.js';
//import { UmbUnpublishDocumentEntityAction } from '../entity-actions/unpublish.action.js';
//import { UmbPublishDocumentEntityAction } from '../entity-actions/publish.action.js';
import { UmbDocumentSaveAndPublishWorkspaceAction } from './actions/save-and-publish.action.js';
@@ -40,7 +39,11 @@ const workspaceViews: Array<ManifestWorkspaceView> = [
},
conditions: [
{
alias: UMB_DOCUMENT_WORKSPACE_HAS_COLLECTION_CONDITION,
alias: 'Umb.Condition.WorkspaceAlias',
match: workspace.alias,
},
{
alias: 'Umb.Condition.WorkspaceHasCollection',
},
],
},

View File

@@ -1 +0,0 @@
export { UMB_MEDIA_WORKSPACE_HAS_COLLECTION_CONDITION } from './media-workspace-has-collection.condition.js';

View File

@@ -1,3 +0,0 @@
import { manifest as mediaWorkspaceHasCollectionCondition } from './media-workspace-has-collection.condition.js';
export const manifests = [mediaWorkspaceHasCollectionCondition];

View File

@@ -1,44 +0,0 @@
import { UMB_MEDIA_WORKSPACE_CONTEXT } from '../workspace/media-workspace.context-token.js';
import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry';
import type {
ManifestCondition,
UmbConditionConfigBase,
UmbConditionControllerArguments,
UmbExtensionCondition,
} from '@umbraco-cms/backoffice/extension-api';
import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
export class UmbMediaWorkspaceHasCollectionCondition
extends UmbConditionBase<MediaWorkspaceHasCollectionConditionConfig>
implements UmbExtensionCondition
{
constructor(
host: UmbControllerHost,
args: UmbConditionControllerArguments<MediaWorkspaceHasCollectionConditionConfig>,
) {
super(host, args);
this.consumeContext(UMB_MEDIA_WORKSPACE_CONTEXT, (context) => {
this.observe(
context.contentTypeCollection,
(collection) => {
this.permitted = !!collection?.unique;
},
'observeCollection',
);
});
}
}
export type MediaWorkspaceHasCollectionConditionConfig = UmbConditionConfigBase<
typeof UMB_MEDIA_WORKSPACE_HAS_COLLECTION_CONDITION
>;
export const UMB_MEDIA_WORKSPACE_HAS_COLLECTION_CONDITION = 'Umb.Condition.MediaWorkspaceHasCollection';
export const manifest: ManifestCondition = {
type: 'condition',
name: 'Media Workspace Has Collection Condition',
alias: UMB_MEDIA_WORKSPACE_HAS_COLLECTION_CONDITION,
api: UmbMediaWorkspaceHasCollectionCondition,
};

View File

@@ -6,7 +6,6 @@ export * from './tracked-reference/index.js';
export * from './components/index.js';
export * from './entity.js';
export * from './utils/index.js';
export * from './conditions/index.js';
export { UMB_MEDIA_TREE_ALIAS } from './tree/index.js';
export { UMB_MEDIA_COLLECTION_ALIAS } from './collection/index.js';

View File

@@ -1,5 +1,4 @@
import { manifests as collectionManifests } from './collection/manifests.js';
import { manifests as conditionManifests } from './conditions/manifests.js';
import { manifests as entityActionsManifests } from './entity-actions/manifests.js';
import { manifests as entityBulkActionsManifests } from './entity-bulk-actions/manifests.js';
import { manifests as menuItemManifests } from './menu-item/manifests.js';
@@ -11,7 +10,6 @@ import { manifests as workspaceManifests } from './workspace/manifests.js';
export const manifests = [
...collectionManifests,
...conditionManifests,
...entityActionsManifests,
...entityBulkActionsManifests,
...menuItemManifests,

View File

@@ -1,4 +1,3 @@
import { UMB_MEDIA_WORKSPACE_HAS_COLLECTION_CONDITION } from '../conditions/media-workspace-has-collection.condition.js';
import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace';
import type {
ManifestWorkspace,
@@ -31,7 +30,11 @@ const workspaceViews: Array<ManifestWorkspaceView> = [
},
conditions: [
{
alias: UMB_MEDIA_WORKSPACE_HAS_COLLECTION_CONDITION,
alias: 'Umb.Condition.WorkspaceAlias',
match: workspace.alias,
},
{
alias: 'Umb.Condition.WorkspaceHasCollection',
},
],
},

View File

@@ -5,11 +5,11 @@ import { UmbMediaDetailRepository } from '../repository/index.js';
import type { UmbMediaDetailModel, UmbMediaVariantModel, UmbMediaVariantOptionModel } from '../types.js';
import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant';
import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
import {
UmbEditableWorkspaceContextBase,
UmbWorkspaceSplitViewManager,
type UmbVariantableWorkspaceContextInterface,
import type {
UmbWorkspaceCollectionContextInterface,
UmbVariantableWorkspaceContextInterface,
} from '@umbraco-cms/backoffice/workspace';
import { UmbEditableWorkspaceContextBase, UmbWorkspaceSplitViewManager } from '@umbraco-cms/backoffice/workspace';
import {
appendToFrozenArray,
jsonStringComparison,
@@ -23,11 +23,12 @@ import { UmbLanguageCollectionRepository, type UmbLanguageDetailModel } from '@u
import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action';
import { UmbReloadTreeItemChildrenRequestEntityActionEvent } from '@umbraco-cms/backoffice/tree';
import { UmbRequestReloadStructureForEntityEvent } from '@umbraco-cms/backoffice/event';
import type { UmbMediaTypeDetailModel } from '@umbraco-cms/backoffice/media-type';
type EntityType = UmbMediaDetailModel;
export class UmbMediaWorkspaceContext
extends UmbEditableWorkspaceContextBase<EntityType>
implements UmbVariantableWorkspaceContextInterface
implements UmbVariantableWorkspaceContextInterface, UmbWorkspaceCollectionContextInterface<UmbMediaTypeDetailModel>
{
//
public readonly repository = new UmbMediaDetailRepository(this);
@@ -51,7 +52,7 @@ export class UmbMediaWorkspaceContext
readonly unique = this.#currentData.asObservablePart((data) => data?.unique);
readonly contentTypeUnique = this.#currentData.asObservablePart((data) => data?.mediaType.unique);
readonly contentTypeCollection = this.#currentData.asObservablePart((data) => data?.mediaType.collection);
readonly contentTypeHasCollection = this.#currentData.asObservablePart((data) => !!data?.mediaType.collection);
readonly variants = this.#currentData.asObservablePart((data) => data?.variants || []);
@@ -146,6 +147,10 @@ export class UmbMediaWorkspaceContext
return data;
}
getCollectionAlias() {
return 'Umb.Collection.Media';
}
getData() {
return this.#currentData.getValue();
}