more property structure into its own class/manager
This commit is contained in:
@@ -3,12 +3,8 @@ import { UmbDocumentRepository } from '../repository/document.repository';
|
||||
import { UmbDocumentTypeRepository } from '../../document-types/repository/document-type.repository';
|
||||
import { UmbWorkspaceVariableEntityContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-variable-entity-context.interface';
|
||||
import { UmbVariantId } from '../../../shared/variants/variant-id.class';
|
||||
import type {
|
||||
DocumentModel,
|
||||
DocumentTypeModel,
|
||||
DocumentTypePropertyTypeContainerModel,
|
||||
DocumentTypePropertyTypeModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
import { UmbWorkspacePropertyStructureManager } from '../../../shared/components/workspace/workspace-context/workspace-property-structure-manager.class';
|
||||
import type { DocumentModel } from '@umbraco-cms/backend-api';
|
||||
import { partialUpdateFrozenArray, ObjectState, ArrayState, UmbObserverController } from '@umbraco-cms/observable-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
|
||||
@@ -28,7 +24,6 @@ export class UmbDocumentWorkspaceContext
|
||||
{
|
||||
#host: UmbControllerHostInterface;
|
||||
#documentRepository: UmbDocumentRepository;
|
||||
#documentTypeRepository: UmbDocumentTypeRepository;
|
||||
|
||||
/**
|
||||
* The document is the current stored version of the document.
|
||||
@@ -50,19 +45,17 @@ export class UmbDocumentWorkspaceContext
|
||||
#activeVariantsInfo = new ArrayState<ActiveVariant>([], (x) => x.index);
|
||||
activeVariantsInfo = this.#activeVariantsInfo.asObservable();
|
||||
|
||||
#documentTypes = new ArrayState<DocumentTypeModel>([], (x) => x.key);
|
||||
documentTypes = this.#documentTypes.asObservable();
|
||||
|
||||
// Notice the DocumentTypePropertyTypeContainerModel is equivalent to PropertyTypeContainerViewModelBaseModel, making it easy to generalize.
|
||||
#containers = new ArrayState<DocumentTypePropertyTypeContainerModel>([], (x) => x.key);
|
||||
readonly structure;
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host);
|
||||
this.#host = host;
|
||||
this.#documentRepository = new UmbDocumentRepository(this.#host);
|
||||
this.#documentTypeRepository = new UmbDocumentTypeRepository(this.#host);
|
||||
|
||||
new UmbObserverController(this._host, this.documentTypeKey, (key) => this._loadDocumentType(key));
|
||||
this.#documentRepository = new UmbDocumentRepository(this.#host);
|
||||
|
||||
this.structure = new UmbWorkspacePropertyStructureManager(this.#host, new UmbDocumentTypeRepository(this.#host));
|
||||
|
||||
new UmbObserverController(this._host, this.documentTypeKey, (key) => this.structure.loadType(key));
|
||||
}
|
||||
|
||||
async load(entityKey: string) {
|
||||
@@ -85,40 +78,6 @@ export class UmbDocumentWorkspaceContext
|
||||
return data || undefined;
|
||||
}
|
||||
|
||||
private async _loadDocumentType(key?: string) {
|
||||
if (!key) return;
|
||||
|
||||
const { data } = await this.#documentTypeRepository.requestByKey(key);
|
||||
if (!data) return;
|
||||
|
||||
// Load inherited and composed types:
|
||||
await data?.compositions?.forEach(async (composition) => {
|
||||
if (composition.key) {
|
||||
this._loadDocumentType(composition.key);
|
||||
}
|
||||
});
|
||||
|
||||
new UmbObserverController(this._host, await this.#documentTypeRepository.byKey(key), (docType) => {
|
||||
if (docType) {
|
||||
this.#documentTypes.appendOne(docType);
|
||||
this._initDocumentTypeContainers(docType);
|
||||
this._loadDocumentTypeCompositions(docType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _loadDocumentTypeCompositions(documentType: DocumentTypeModel) {
|
||||
documentType.compositions?.forEach((composition) => {
|
||||
this._loadDocumentType(composition.key);
|
||||
});
|
||||
}
|
||||
|
||||
private async _initDocumentTypeContainers(documentType: DocumentTypeModel) {
|
||||
documentType.containers?.forEach((container) => {
|
||||
this.#containers.appendOne(container);
|
||||
});
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.#draft.getValue() || {};
|
||||
}
|
||||
@@ -193,61 +152,6 @@ export class UmbDocumentWorkspaceContext
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Structure methods:
|
||||
|
||||
hasPropertyStructuresOf(containerKey: string | null) {
|
||||
return this.#documentTypes.getObservablePart((docTypes) => {
|
||||
return (
|
||||
docTypes.find((docType) => {
|
||||
return docType.properties?.find((property) => property.containerKey === containerKey);
|
||||
}) !== undefined
|
||||
);
|
||||
});
|
||||
}
|
||||
rootPropertyStructures() {
|
||||
return this.propertyStructuresOf(null);
|
||||
}
|
||||
propertyStructuresOf(containerKey: string | null) {
|
||||
return this.#documentTypes.getObservablePart((docTypes) => {
|
||||
const props: DocumentTypePropertyTypeModel[] = [];
|
||||
docTypes.forEach((docType) => {
|
||||
docType.properties?.forEach((property) => {
|
||||
if (property.containerKey === containerKey) {
|
||||
props.push(property);
|
||||
}
|
||||
});
|
||||
});
|
||||
return props;
|
||||
});
|
||||
}
|
||||
|
||||
rootContainers(containerType: 'Group' | 'Tab') {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.parentKey === null && x.type === containerType);
|
||||
});
|
||||
}
|
||||
|
||||
hasRootContainers(containerType: 'Group' | 'Tab') {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.parentKey === null && x.type === containerType).length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
containersOfParentKey(
|
||||
parentKey: DocumentTypePropertyTypeContainerModel['parentKey'],
|
||||
containerType: 'Group' | 'Tab'
|
||||
) {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.parentKey === parentKey && x.type === containerType);
|
||||
});
|
||||
}
|
||||
|
||||
containersByNameAndType(name: string, containerType: 'Group' | 'Tab') {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.name === name && x.type === containerType);
|
||||
});
|
||||
}
|
||||
|
||||
getPropertyValue(alias: string, variantId?: UmbVariantId): void {
|
||||
const currentData = this.#draft.value;
|
||||
if (currentData) {
|
||||
@@ -259,7 +163,6 @@ export class UmbDocumentWorkspaceContext
|
||||
}
|
||||
setPropertyValue(alias: string, value: unknown, variantId?: UmbVariantId) {
|
||||
const partialEntry = { value };
|
||||
console.log('€€€€€setPropertyValue', alias, value, variantId?.toString());
|
||||
const currentData = this.#draft.value;
|
||||
if (currentData) {
|
||||
const values = partialUpdateFrozenArray(
|
||||
|
||||
@@ -67,7 +67,7 @@ export class UmbDocumentWorkspaceViewEditPropertiesElement extends UmbLitElement
|
||||
|
||||
// TODO: Should be no need to update this observable if its already there.
|
||||
this.observe(
|
||||
this._workspaceContext!.containersByNameAndType(this._containerName, this._containerType),
|
||||
this._workspaceContext!.structure.containersByNameAndType(this._containerName, this._containerType),
|
||||
(groupContainers) => {
|
||||
this._groupContainers = groupContainers || [];
|
||||
groupContainers.forEach((group) => {
|
||||
@@ -86,7 +86,7 @@ export class UmbDocumentWorkspaceViewEditPropertiesElement extends UmbLitElement
|
||||
|
||||
// TODO: Should be no need to update this observable if its already there.
|
||||
this.observe(
|
||||
this._workspaceContext.propertyStructuresOf(group.key),
|
||||
this._workspaceContext.structure.propertyStructuresOf(group.key),
|
||||
(properties) => {
|
||||
// If this need to be able to remove properties, we need to clean out the ones of this group.key before inserting them:
|
||||
this._propertyStructure = this._propertyStructure.filter((x) => x.containerKey !== group.key);
|
||||
|
||||
@@ -80,7 +80,7 @@ export class UmbDocumentWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
|
||||
this._tabContainers.forEach((container) => {
|
||||
this.observe(
|
||||
this._workspaceContext!.hasPropertyStructuresOf(container.key!),
|
||||
this._workspaceContext!.structure.hasPropertyStructuresOf(container.key!),
|
||||
(hasTabProperties) => {
|
||||
this._hasTabProperties = hasTabProperties;
|
||||
},
|
||||
@@ -95,7 +95,7 @@ export class UmbDocumentWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
if (this._tabName) {
|
||||
this._groups = [];
|
||||
this.observe(
|
||||
this._workspaceContext.containersByNameAndType(this._tabName, 'Tab'),
|
||||
this._workspaceContext.structure.containersByNameAndType(this._tabName, 'Tab'),
|
||||
(tabContainers) => {
|
||||
this._tabContainers = tabContainers || [];
|
||||
if (this._tabContainers.length > 0) {
|
||||
@@ -116,7 +116,7 @@ export class UmbDocumentWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
|
||||
this._tabContainers.forEach((container) => {
|
||||
this.observe(
|
||||
this._workspaceContext!.containersOfParentKey(container.key, 'Group'),
|
||||
this._workspaceContext!.structure.containersOfParentKey(container.key, 'Group'),
|
||||
this._insertGroupContainers,
|
||||
'_observeGroupsOf_' + container.key
|
||||
);
|
||||
@@ -127,7 +127,11 @@ export class UmbDocumentWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
if (!this._workspaceContext || !this._noTabName) return;
|
||||
|
||||
// This is where we potentially could observe root properties as well.
|
||||
this.observe(this._workspaceContext!.rootContainers('Group'), this._insertGroupContainers, '_observeRootGroups');
|
||||
this.observe(
|
||||
this._workspaceContext!.structure.rootContainers('Group'),
|
||||
this._insertGroupContainers,
|
||||
'_observeRootGroups'
|
||||
);
|
||||
}
|
||||
|
||||
private _insertGroupContainers = (groupContainers: PropertyTypeContainerViewModelBaseModel[]) => {
|
||||
|
||||
@@ -19,8 +19,6 @@ export class UmbDocumentWorkspaceViewEditElement extends UmbLitElement {
|
||||
`,
|
||||
];
|
||||
|
||||
// TODO: get variant information via variant-content?
|
||||
|
||||
//private _hasRootProperties = false;
|
||||
private _hasRootGroups = false;
|
||||
|
||||
@@ -52,7 +50,7 @@ export class UmbDocumentWorkspaceViewEditElement extends UmbLitElement {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
this.observe(
|
||||
this._workspaceContext.rootContainers('Tab'),
|
||||
this._workspaceContext.structure.rootContainers('Tab'),
|
||||
(tabs) => {
|
||||
tabs.forEach((tab) => {
|
||||
// Only add each tab name once, as our containers merge on name:
|
||||
@@ -79,7 +77,7 @@ export class UmbDocumentWorkspaceViewEditElement extends UmbLitElement {
|
||||
*/
|
||||
|
||||
this.observe(
|
||||
this._workspaceContext.hasRootContainers('Group'),
|
||||
this._workspaceContext.structure.hasRootContainers('Group'),
|
||||
(hasRootGroups) => {
|
||||
this._hasRootGroups = hasRootGroups;
|
||||
this._createRoutes();
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
import { UmbDocumentTypeRepository } from '../../../../documents/document-types/repository/document-type.repository';
|
||||
import {
|
||||
DocumentTypeModel,
|
||||
DocumentTypePropertyTypeModel,
|
||||
PropertyTypeContainerViewModelBaseModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
import { UmbControllerHostInterface } from '@umbraco-cms/controller';
|
||||
import { ArrayState, UmbObserverController } from '@umbraco-cms/observable-api';
|
||||
|
||||
export type PropertyContainerTypes = 'Group' | 'Tab';
|
||||
|
||||
// TODO: get this type from the repository, or use some generic type.
|
||||
type T = DocumentTypeModel;
|
||||
|
||||
// TODO: make general interface for NodeTypeRepository, to replace UmbDocumentTypeRepository:
|
||||
export class UmbWorkspacePropertyStructureManager<R extends UmbDocumentTypeRepository = UmbDocumentTypeRepository> {
|
||||
#host: UmbControllerHostInterface;
|
||||
|
||||
#documentTypeRepository: R;
|
||||
|
||||
#documentTypes = new ArrayState<T>([], (x) => x.key);
|
||||
|
||||
#containers = new ArrayState<PropertyTypeContainerViewModelBaseModel>([], (x) => x.key);
|
||||
|
||||
constructor(host: UmbControllerHostInterface, typeRepository: R) {
|
||||
this.#host = host;
|
||||
this.#documentTypeRepository = typeRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* loadType will load the node type and all inherited and composed types.
|
||||
* This will give us all the structure for properties and containers.
|
||||
*/
|
||||
public async loadType(key?: string) {
|
||||
// TODO: I guess it would make sense to clean up, in this case we most likely don't need any of the old document types:
|
||||
//this.#documentTypes.next([]);
|
||||
await this._loadType(key);
|
||||
}
|
||||
|
||||
private async _loadType(key?: string) {
|
||||
if (!key) return;
|
||||
|
||||
const { data } = await this.#documentTypeRepository.requestByKey(key);
|
||||
if (!data) return;
|
||||
|
||||
// Load inherited and composed types:
|
||||
await data?.compositions?.forEach(async (composition) => {
|
||||
if (composition.key) {
|
||||
this.loadType(composition.key);
|
||||
}
|
||||
});
|
||||
|
||||
new UmbObserverController(this.#host, await this.#documentTypeRepository.byKey(key), (docType) => {
|
||||
if (docType) {
|
||||
this.#documentTypes.appendOne(docType);
|
||||
this._initDocumentTypeContainers(docType);
|
||||
this._loadDocumentTypeCompositions(docType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _loadDocumentTypeCompositions(documentType: T) {
|
||||
documentType.compositions?.forEach((composition) => {
|
||||
this._loadType(composition.key);
|
||||
});
|
||||
}
|
||||
|
||||
private async _initDocumentTypeContainers(documentType: T) {
|
||||
documentType.containers?.forEach((container) => {
|
||||
this.#containers.appendOne(container);
|
||||
});
|
||||
}
|
||||
|
||||
hasPropertyStructuresOf(containerKey: string | null) {
|
||||
return this.#documentTypes.getObservablePart((docTypes) => {
|
||||
return (
|
||||
docTypes.find((docType) => {
|
||||
return docType.properties?.find((property) => property.containerKey === containerKey);
|
||||
}) !== undefined
|
||||
);
|
||||
});
|
||||
}
|
||||
rootPropertyStructures() {
|
||||
return this.propertyStructuresOf(null);
|
||||
}
|
||||
propertyStructuresOf(containerKey: string | null) {
|
||||
return this.#documentTypes.getObservablePart((docTypes) => {
|
||||
const props: DocumentTypePropertyTypeModel[] = [];
|
||||
docTypes.forEach((docType) => {
|
||||
docType.properties?.forEach((property) => {
|
||||
if (property.containerKey === containerKey) {
|
||||
props.push(property);
|
||||
}
|
||||
});
|
||||
});
|
||||
return props;
|
||||
});
|
||||
}
|
||||
|
||||
rootContainers(containerType: PropertyContainerTypes) {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.parentKey === null && x.type === containerType);
|
||||
});
|
||||
}
|
||||
|
||||
hasRootContainers(containerType: PropertyContainerTypes) {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.parentKey === null && x.type === containerType).length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
containersOfParentKey(
|
||||
parentKey: PropertyTypeContainerViewModelBaseModel['parentKey'],
|
||||
containerType: PropertyContainerTypes
|
||||
) {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.parentKey === parentKey && x.type === containerType);
|
||||
});
|
||||
}
|
||||
|
||||
containersByNameAndType(name: string, containerType: PropertyContainerTypes) {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.name === name && x.type === containerType);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import { customElement, property, query } from 'lit/decorators.js';
|
||||
import { FormControlMixin } from '@umbraco-ui/uui-base/lib/mixins';
|
||||
import { UUIInputEvent } from '@umbraco-ui/uui-input';
|
||||
import { UUIInputElement } from '@umbraco-ui/uui';
|
||||
import { UmbChangeEvent, UmbInputEvent, UmbDeleteEvent } from '@umbraco-cms/events';
|
||||
import { UmbModalService, UMB_MODAL_SERVICE_CONTEXT_TOKEN } from '../../../../../../core/modal';
|
||||
import { UmbChangeEvent, UmbInputEvent, UmbDeleteEvent } from '@umbraco-cms/events';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user