router for edit-tabs
This commit is contained in:
@@ -2,7 +2,11 @@ import { UmbWorkspaceContext } from '../../../shared/components/workspace/worksp
|
||||
import { UmbDocumentRepository } from '../repository/document.repository';
|
||||
import type { UmbWorkspaceEntityContextInterface } from '../../../shared/components/workspace/workspace-context/workspace-entity-context.interface';
|
||||
import { UmbDocumentTypeRepository } from '../../document-types/repository/document-type.repository';
|
||||
import type { DocumentModel, DocumentTypeModel } from '@umbraco-cms/backend-api';
|
||||
import type {
|
||||
DocumentModel,
|
||||
DocumentTypeModel,
|
||||
DocumentTypePropertyTypeContainerModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
import {
|
||||
partialUpdateFrozenArray,
|
||||
ObjectState,
|
||||
@@ -31,6 +35,10 @@ export class UmbDocumentWorkspaceContext
|
||||
#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);
|
||||
//containers = this.#containers.asObservable();
|
||||
|
||||
constructor(host: UmbControllerHostInterface) {
|
||||
super(host);
|
||||
this.#host = host;
|
||||
@@ -69,14 +77,31 @@ export class UmbDocumentWorkspaceContext
|
||||
}
|
||||
});
|
||||
|
||||
new UmbObserverController(this._host, await this.#documentTypeRepository.byKey(key), (data) => {
|
||||
if (data) {
|
||||
this.#documentTypes.appendOne(data);
|
||||
this.loadDataTypeOfDocumentType(data);
|
||||
new UmbObserverController(this._host, await this.#documentTypeRepository.byKey(key), (docType) => {
|
||||
if (docType) {
|
||||
this.#documentTypes.appendOne(docType);
|
||||
this.initDocumentTypeContainers(docType);
|
||||
this.loadDocumentTypeCompositions(docType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async loadDocumentTypeCompositions(documentType: DocumentTypeModel) {
|
||||
documentType.compositions?.forEach((composition) => {
|
||||
this.loadDocumentType(composition.key);
|
||||
});
|
||||
}
|
||||
|
||||
async initDocumentTypeContainers(documentType: DocumentTypeModel) {
|
||||
documentType.containers?.forEach((container) => {
|
||||
console.log('add container', container);
|
||||
this.#containers.appendOne(container);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
No need for this currently. The data types are loaded by the properties.
|
||||
async loadDataTypeOfDocumentType(documentType?: DocumentTypeModel) {
|
||||
if (!documentType) return;
|
||||
|
||||
@@ -93,12 +118,13 @@ export class UmbDocumentWorkspaceContext
|
||||
|
||||
//const { data } = await this.#dataTypeRepository.requestDetails(key);
|
||||
|
||||
/*new UmbObserverController(this._host, await this.#documentTypeRepository.byKey(key), (data) => {
|
||||
if (data) {
|
||||
this.#documentTypes.appendOne(data);
|
||||
}
|
||||
});*/
|
||||
// new UmbObserverController(this._host, await this.#documentTypeRepository.byKey(key), (data) => {
|
||||
// if (data) {
|
||||
// this.#documentTypes.appendOne(data);
|
||||
// }
|
||||
//});
|
||||
}
|
||||
*/
|
||||
|
||||
getData() {
|
||||
return this.#data.getValue();
|
||||
@@ -150,15 +176,36 @@ export class UmbDocumentWorkspaceContext
|
||||
}
|
||||
*/
|
||||
|
||||
propertiesOf(culture: string | null, segment: string | null) {
|
||||
propertyValuesOf(culture: string | null, segment: string | null) {
|
||||
return this.#data.getObservablePart((data) =>
|
||||
data?.properties?.filter((p) => (culture === p.culture || null) && (segment === p.segment || null))
|
||||
);
|
||||
}
|
||||
|
||||
propertyStructure() {
|
||||
// TODO: handle composition of document types.
|
||||
return this.#documentTypes.getObservablePart((data) => data[0]?.properties);
|
||||
propertyStructuresOf(containerKey: string | null) {
|
||||
return this.#documentTypes.getObservablePart((data) =>
|
||||
// TODO: some merging of properties across document types here:
|
||||
data[0]?.properties?.filter((p) => containerKey === p.containerKey || null)
|
||||
);
|
||||
}
|
||||
|
||||
rootContainers(containerType: 'Group' | 'Tab') {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.parentKey === null && x.type === containerType);
|
||||
});
|
||||
}
|
||||
|
||||
containerByKey(key: DocumentTypePropertyTypeContainerModel['key']) {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
return data.filter((x) => x.key === key);
|
||||
});
|
||||
}
|
||||
|
||||
containersOf(parentKey: DocumentTypePropertyTypeContainerModel['parentKey'], containerType: 'Group' | 'Tab') {
|
||||
return this.#containers.getObservablePart((data) => {
|
||||
console.log(data, parentKey, containerType);
|
||||
return data.filter((x) => x.parentKey === parentKey && x.type === containerType);
|
||||
});
|
||||
}
|
||||
|
||||
setPropertyValue(alias: string, value: unknown) {
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { UmbDocumentWorkspaceContext } from '../document-workspace.context';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import { DocumentPropertyModel, PropertyTypeContainerViewModelBaseModel } from '@umbraco-cms/backend-api';
|
||||
|
||||
@customElement('umb-document-workspace-view-edit-tab')
|
||||
export class UmbDocumentWorkspaceViewEditTabElement extends UmbLitElement {
|
||||
static styles = [
|
||||
UUITextStyles,
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
margin: var(--uui-size-layout-1);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
private _tabName?: string | undefined;
|
||||
|
||||
@property({ type: String })
|
||||
public get tabName(): string | undefined {
|
||||
return this._tabName;
|
||||
}
|
||||
public set tabName(value: string | undefined) {
|
||||
if (this._tabName === value) return;
|
||||
this._tabName = value;
|
||||
this._observeContainers();
|
||||
}
|
||||
|
||||
@state()
|
||||
_propertyData: DocumentPropertyModel[] = [];
|
||||
|
||||
@state()
|
||||
_groups: PropertyTypeContainerViewModelBaseModel[] = [];
|
||||
|
||||
_propertiesObservables: Map<string, unknown> = new Map();
|
||||
|
||||
private _workspaceContext?: UmbDocumentWorkspaceContext;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
// TODO: Figure out how to get the magic string for the workspace context.
|
||||
this.consumeContext<UmbDocumentWorkspaceContext>('umbWorkspaceContext', (workspaceContext) => {
|
||||
this._workspaceContext = workspaceContext;
|
||||
this._observeContainers();
|
||||
//this._observeContent();
|
||||
});
|
||||
}
|
||||
|
||||
private _observeProperties() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
/*
|
||||
Just get the properties for the current containers. (and eventually variants later)
|
||||
*/
|
||||
this.observe(
|
||||
this._workspaceContext.propertyValuesOf(null, null),
|
||||
(properties) => {
|
||||
this._propertyData = properties || [];
|
||||
//this._data = content?.data || [];
|
||||
|
||||
/*
|
||||
Maybe we should not give the value(Data), but the umb-content-property should get the context and observe its own data.
|
||||
This would become a more specific Observer therefor better performance?.. Note to self: Debate with Mads how he sees this perspective.
|
||||
*/
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
}
|
||||
|
||||
private _observeContainers() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
this.observe(
|
||||
this._workspaceContext.containersOf(this.tabName, 'Group'),
|
||||
(groups) => {
|
||||
this._groups = groups || [];
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
}
|
||||
|
||||
private _getPropertiesOfGroup(group: PropertyTypeContainerViewModelBaseModel) {
|
||||
if (!this._workspaceContext) return undefined;
|
||||
|
||||
this.observe(
|
||||
this._workspaceContext.propertyValuesOf(null, null),
|
||||
(properties) => {
|
||||
this._propertyData = properties || [];
|
||||
//this._data = content?.data || [];
|
||||
|
||||
/*
|
||||
Maybe we should not give the value(Data), but the umb-content-property should get the context and observe its own data.
|
||||
This would become a more specific Observer therefor better performance?.. Note to self: Debate with Mads how he sees this perspective.
|
||||
*/
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
|
||||
// cache observable
|
||||
}
|
||||
|
||||
render() {
|
||||
return 'hello worlds' + this._tabName;
|
||||
/*repeat(
|
||||
this._groups,
|
||||
(group) => group.key,
|
||||
(group) =>
|
||||
html`
|
||||
<uui-box>
|
||||
${repeat(
|
||||
this._getPropertiesOfGroup(group),
|
||||
(property) => property.alias,
|
||||
(property) =>
|
||||
html`<umb-content-property
|
||||
.property=${property}
|
||||
.value=${this._propertyData.find((x) => x.alias === property.alias)?.value}></umb-content-property> `
|
||||
)}
|
||||
</uui-box>
|
||||
`
|
||||
)
|
||||
);*/
|
||||
}
|
||||
}
|
||||
|
||||
export default UmbDocumentWorkspaceViewEditTabElement;
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'umb-document-workspace-view-edit-tab': UmbDocumentWorkspaceViewEditTabElement;
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,11 @@ import { css, html } from 'lit';
|
||||
import { UUITextStyles } from '@umbraco-ui/uui-css/lib';
|
||||
import { customElement, state } from 'lit/decorators.js';
|
||||
import { repeat } from 'lit/directives/repeat.js';
|
||||
import { IRoute } from 'router-slot';
|
||||
import { UmbDocumentWorkspaceContext } from '../document-workspace.context';
|
||||
import { UmbLitElement } from '@umbraco-cms/element';
|
||||
import {
|
||||
DocumentPropertyModel,
|
||||
DocumentTypePropertyTypeModel,
|
||||
PropertyTypeContainerViewModelBaseModel,
|
||||
} from '@umbraco-cms/backend-api';
|
||||
import { PropertyTypeContainerViewModelBaseModel } from '@umbraco-cms/backend-api';
|
||||
import { UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/router';
|
||||
|
||||
@customElement('umb-document-workspace-view-edit')
|
||||
export class UmbDocumentWorkspaceViewEditElement extends UmbLitElement {
|
||||
@@ -23,14 +21,17 @@ export class UmbDocumentWorkspaceViewEditElement extends UmbLitElement {
|
||||
];
|
||||
|
||||
@state()
|
||||
_propertyData: DocumentPropertyModel[] = [];
|
||||
|
||||
@state()
|
||||
_propertyStructures: DocumentTypePropertyTypeModel[] = [];
|
||||
private _routes: IRoute[] = [];
|
||||
|
||||
@state()
|
||||
_tabs: PropertyTypeContainerViewModelBaseModel[] = [];
|
||||
|
||||
@state()
|
||||
private _routerPath?: string;
|
||||
|
||||
@state()
|
||||
private _activePath = '';
|
||||
|
||||
private _workspaceContext?: UmbDocumentWorkspaceContext;
|
||||
|
||||
constructor() {
|
||||
@@ -39,64 +40,75 @@ export class UmbDocumentWorkspaceViewEditElement extends UmbLitElement {
|
||||
// TODO: Figure out how to get the magic string for the workspace context.
|
||||
this.consumeContext<UmbDocumentWorkspaceContext>('umbWorkspaceContext', (workspaceContext) => {
|
||||
this._workspaceContext = workspaceContext;
|
||||
this._observeContent();
|
||||
this._observeTabs();
|
||||
});
|
||||
}
|
||||
|
||||
private _observeContent() {
|
||||
private _observeTabs() {
|
||||
if (!this._workspaceContext) return;
|
||||
|
||||
/*
|
||||
TODO: Property-Context: This observer gets all changes, We need to fix this. it should be simpler.
|
||||
An idea to optimize this would be for this to only care about layout, meaning to property data should be watched here.
|
||||
As the properties could handle their own data on their own?
|
||||
|
||||
Should use a Observable for example: this._workspaceContext.properties
|
||||
*/
|
||||
this.observe(
|
||||
this._workspaceContext.propertyValuesOf(null, null),
|
||||
(properties) => {
|
||||
this._propertyData = properties || [];
|
||||
//this._data = content?.data || [];
|
||||
|
||||
/*
|
||||
Maybe we should not give the value(Data), but the umb-content-property should get the context and observe its own data.
|
||||
This would become a more specific Observer therefor better performance?.. Note to self: Debate with Mads how he sees this perspective.
|
||||
*/
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
/*
|
||||
this.observe(
|
||||
this._workspaceContext.propertyStructure(),
|
||||
(propertyStructure) => {
|
||||
this._propertyStructures = propertyStructure || [];
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
*/
|
||||
|
||||
this.observe(
|
||||
this._workspaceContext.containersOf(null, 'tab'),
|
||||
this._workspaceContext.containersOf(null, 'Tab'),
|
||||
(tabs) => {
|
||||
// TODO: make tabs unique based on name.
|
||||
this._tabs = tabs || [];
|
||||
this._createRoutes();
|
||||
},
|
||||
'observeWorkspaceContextData'
|
||||
);
|
||||
}
|
||||
|
||||
private _createRoutes() {
|
||||
const routes: any[] = [];
|
||||
|
||||
if (this._tabs.length > 0) {
|
||||
this._tabs?.forEach((tab) => {
|
||||
routes.push({
|
||||
path: `tab/${encodeURI(tab.name || '').toString()}`,
|
||||
component: () => import('./document-workspace-view-edit-tab.element'),
|
||||
setup: (component: Promise<HTMLElement>) => {
|
||||
(component as any).tabName = tab.name;
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
routes.push({
|
||||
path: '',
|
||||
redirectTo: routes[0]?.path,
|
||||
});
|
||||
routes.push({
|
||||
path: '**',
|
||||
redirectTo: routes[0]?.path,
|
||||
});
|
||||
}
|
||||
|
||||
this._routes = routes;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<uui-box>
|
||||
<uui-tab-group>
|
||||
${repeat(
|
||||
this._propertyStructures,
|
||||
(property) => property.alias,
|
||||
(property) =>
|
||||
html`<umb-content-property
|
||||
.property=${property}
|
||||
.value=${this._propertyData.find((x) => x.alias === property.alias)?.value}></umb-content-property> `
|
||||
this._tabs,
|
||||
(tab) => tab.key,
|
||||
(tab) => {
|
||||
const path = this._routerPath + '/tab/' + encodeURI(tab.name || '');
|
||||
return html`<uui-tab label=${tab.name!} .active=${path === this._activePath} href=${path}
|
||||
>${tab.name}</uui-tab
|
||||
>`;
|
||||
}
|
||||
)}
|
||||
</uui-box>
|
||||
</uui-tab-group>
|
||||
|
||||
<umb-router-slot
|
||||
.routes=${this._routes}
|
||||
@init=${(event: UmbRouterSlotInitEvent) => {
|
||||
this._routerPath = event.target.absoluteRouterPath;
|
||||
}}
|
||||
@change=${(event: UmbRouterSlotChangeEvent) => {
|
||||
this._activePath = event.target.localActiveViewPath || '';
|
||||
}}>
|
||||
</umb-router-slot>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user