From e8e2e8d41461ae47395ac2d548abe0d6148b7a95 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 16 Mar 2023 10:26:44 +0100 Subject: [PATCH] move routes into workspace element --- .../document-workspace-edit.element.ts | 144 ++++++++++++++ .../workspace/document-workspace.context.ts | 11 -- .../workspace/document-workspace.element.ts | 177 +++--------------- .../workspace/document-workspace.stories.ts | 5 +- .../workspace/document-workspace.test.ts | 9 - .../documents/workspace/manifests.ts | 2 +- 6 files changed, 177 insertions(+), 171 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace-edit.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace-edit.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace-edit.element.ts new file mode 100644 index 0000000000..34a079562b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace-edit.element.ts @@ -0,0 +1,144 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, html } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { IRoute, IRoutingInfo } from 'router-slot'; +import { UmbRouterSlotInitEvent } from '@umbraco-cms/router'; +import { UmbVariantId } from '../../../shared/variants/variant-id.class'; +import { ActiveVariant } from '../../../shared/components/workspace/workspace-context/workspace-split-view-manager.class'; +import { UmbDocumentWorkspaceContext } from './document-workspace.context'; +import { UmbDocumentWorkspaceSplitViewElement } from './document-workspace-split-view.element'; +import { UmbLitElement } from '@umbraco-cms/element'; +import '../../../shared/components/workspace/workspace-variant/workspace-variant.element'; +import { VariantViewModelBaseModel } from '@umbraco-cms/backend-api'; + +@customElement('umb-document-workspace-edit') +export class UmbDocumentWorkspaceEditElement extends UmbLitElement { + static styles = [ + UUITextStyles, + css` + :host { + display: block; + width: 100%; + height: 100%; + } + `, + ]; + + //private _defaultVariant?: VariantViewModelBaseModel; + private splitViewElement = new UmbDocumentWorkspaceSplitViewElement(); + + @state() + _unique?: string; + + @state() + _routes?: Array; + + @state() + _availableVariants: Array = []; + + @state() + _workspaceSplitViews: Array = []; + + #workspaceContext?: UmbDocumentWorkspaceContext; + + constructor() { + super(); + + this.consumeContext('umbWorkspaceContext', (instance: UmbDocumentWorkspaceContext) => { + this.#workspaceContext = instance; + this.#observeVariants(); + this.#observeSplitViews(); + }); + } + + #observeVariants() { + if (!this.#workspaceContext) return; + this.observe(this.#workspaceContext.variants, (variants) => { + this._availableVariants = variants; + this._generateRoutes(); + }); + } + + #observeSplitViews() { + if (!this.#workspaceContext) return; + this.observe(this.#workspaceContext.splitView.activeVariantsInfo, (variants) => { + this._workspaceSplitViews = variants; + }); + } + + private _handleVariantFolderPart(index: number, folderPart: string) { + const variantSplit = folderPart.split('_'); + const culture = variantSplit[0]; + const segment = variantSplit[1]; + this.#workspaceContext?.splitView.setActiveVariant(index, culture, segment); + } + + private _generateRoutes() { + if (!this._availableVariants || this._availableVariants.length === 0) return; + + // Generate split view routes for all available routes + const routes: Array = []; + + // Split view routes: + this._availableVariants.forEach((variantA) => { + this._availableVariants.forEach((variantB) => { + routes.push({ + path: new UmbVariantId(variantA).toString() + '_&_' + new UmbVariantId(variantB).toString(), + //component: () => import('./document-workspace-split-view.element'), + component: this.splitViewElement, + setup: (component: HTMLElement | Promise, info: IRoutingInfo) => { + // Set split view/active info.. + const variantSplit = info.match.fragments.consumed.split('_&_'); + variantSplit.forEach((part, index) => { + this._handleVariantFolderPart(index, part); + }); + }, + }); + }); + }); + + // Single view: + this._availableVariants.forEach((variant) => { + routes.push({ + path: new UmbVariantId(variant).toString(), + //component: () => import('./document-workspace-split-view.element'), + component: this.splitViewElement, + setup: (component: HTMLElement | Promise, info: IRoutingInfo) => { + // cause we might come from a split-view, we need to reset index 1. + this.#workspaceContext?.splitView.removeActiveVariant(1); + this._handleVariantFolderPart(0, info.match.fragments.consumed); + }, + }); + }); + + if (routes.length !== 0) { + // Using first single view as the default route for now (hence the math below): + routes.push({ + path: '**', + redirectTo: routes[this._availableVariants.length * this._availableVariants.length]?.path, + }); + } + + this._routes = routes; + } + + private _gotWorkspaceRoute = (e: UmbRouterSlotInitEvent) => { + this.#workspaceContext?.splitView.setWorkspaceRoute(e.target.absoluteRouterPath); + }; + + render() { + return this._routes + ? html`${this.splitViewElement}` + : ''; + } +} + +export default UmbDocumentWorkspaceEditElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-document-workspace-edit': UmbDocumentWorkspaceEditElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.context.ts index a8e5965147..63d78083d2 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.context.ts @@ -67,17 +67,6 @@ export class UmbDocumentWorkspaceContext return data || undefined; } - async getPaths() { - return [ - { - path: 'edit/:key', - }, - { - path: 'create/:parentKey/:documentTypeKey', - }, - ]; - } - getData() { return this.#draft.getValue() || {}; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.element.ts index 609d9d38c0..d51b7ae609 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.element.ts @@ -1,159 +1,42 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { css, html } from 'lit'; -import { customElement, property, state } from 'lit/decorators.js'; +import { html } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; import { IRoute, IRoutingInfo } from 'router-slot'; -import { UmbRouterSlotInitEvent, UmbRouteLocation } from '@umbraco-cms/router'; -import type { UmbWorkspaceEntityElement } from '../../../shared/components/workspace/workspace-entity-element.interface'; -import { UmbVariantId } from '../../../shared/variants/variant-id.class'; -import { ActiveVariant } from '../../../shared/components/workspace/workspace-context/workspace-split-view-manager.class'; import { UmbDocumentWorkspaceContext } from './document-workspace.context'; -import { UmbDocumentWorkspaceSplitViewElement } from './document-workspace-split-view.element'; import { UmbLitElement } from '@umbraco-cms/element'; -import '../../../shared/components/workspace/workspace-variant/workspace-variant.element'; -import { VariantViewModelBaseModel } from '@umbraco-cms/backend-api'; -import { ManifestWorkspace } from '@umbraco-cms/extensions-registry'; + +import './document-workspace-edit.element'; @customElement('umb-document-workspace') -export class UmbDocumentWorkspaceElement extends UmbLitElement implements UmbWorkspaceEntityElement { - static styles = [ - UUITextStyles, - css` - :host { - display: block; - width: 100%; - height: 100%; - } - `, +export class UmbDocumentWorkspaceElement extends UmbLitElement { + static styles = [UUITextStyles]; + + #workspaceContext = new UmbDocumentWorkspaceContext(this); + #element = document.createElement('umb-document-workspace-edit'); + + @state() + _routes: IRoute[] = [ + { + path: 'create/:parentKey/:documentTypeKey', + component: () => this.#element, + setup: async (component: HTMLElement, info: IRoutingInfo) => { + const parentKey = info.match.params.parentKey; + const documentTypeKey = info.match.params.documentTypeKey; + this.#workspaceContext.createScaffold(documentTypeKey); + }, + }, + { + path: 'edit/:key', + component: () => this.#element, + setup: (component: HTMLElement, info: IRoutingInfo) => { + const key = info.match.params.key; + this.#workspaceContext.load(key); + }, + }, ]; - //private _defaultVariant?: VariantViewModelBaseModel; - private splitViewElement = new UmbDocumentWorkspaceSplitViewElement(); - - @property() - manifest?: ManifestWorkspace; - - @property() - location?: UmbRouteLocation; - - @state() - _unique?: string; - - @state() - _routes?: Array; - - @state() - _availableVariants: Array = []; - - @state() - _workspaceSplitViews: Array = []; - - #workspaceContext?: UmbDocumentWorkspaceContext; - - constructor() { - super(); - - this.consumeContext('umbWorkspaceContext', (instance: UmbDocumentWorkspaceContext) => { - this.#workspaceContext = instance; - this.#observeVariants(); - this.#observeSplitViews(); - this.#init(); - }); - } - - #observeVariants() { - if (!this.#workspaceContext) return; - this.observe(this.#workspaceContext.variants, (variants) => { - this._availableVariants = variants; - this._generateRoutes(); - }); - } - - #observeSplitViews() { - if (!this.#workspaceContext) return; - this.observe(this.#workspaceContext.splitView.activeVariantsInfo, (variants) => { - this._workspaceSplitViews = variants; - }); - } - - #init() { - const parentKey = this.location?.params?.parentKey; - const documentTypeKey = this.location?.params.documentTypeKey; - const key = this.location?.params?.key; - - // TODO: implement actions "events" and show loading state - if (parentKey !== undefined && documentTypeKey) { - this.#workspaceContext?.createScaffold(documentTypeKey); - } else if (key) { - this.#workspaceContext?.load(key); - } - } - - private _handleVariantFolderPart(index: number, folderPart: string) { - const variantSplit = folderPart.split('_'); - const culture = variantSplit[0]; - const segment = variantSplit[1]; - this.#workspaceContext?.splitView.setActiveVariant(index, culture, segment); - } - - private _generateRoutes() { - if (!this._availableVariants || this._availableVariants.length === 0) return; - - // Generate split view routes for all available routes - const routes: Array = []; - - // Split view routes: - this._availableVariants.forEach((variantA) => { - this._availableVariants.forEach((variantB) => { - routes.push({ - path: new UmbVariantId(variantA).toString() + '_&_' + new UmbVariantId(variantB).toString(), - //component: () => import('./document-workspace-split-view.element'), - component: this.splitViewElement, - setup: (component: HTMLElement | Promise, info: IRoutingInfo) => { - // Set split view/active info.. - const variantSplit = info.match.fragments.consumed.split('_&_'); - variantSplit.forEach((part, index) => { - this._handleVariantFolderPart(index, part); - }); - }, - }); - }); - }); - - // Single view: - this._availableVariants.forEach((variant) => { - routes.push({ - path: new UmbVariantId(variant).toString(), - //component: () => import('./document-workspace-split-view.element'), - component: this.splitViewElement, - setup: (component: HTMLElement | Promise, info: IRoutingInfo) => { - // cause we might come from a split-view, we need to reset index 1. - this.#workspaceContext?.splitView.removeActiveVariant(1); - this._handleVariantFolderPart(0, info.match.fragments.consumed); - }, - }); - }); - - if (routes.length !== 0) { - // Using first single view as the default route for now (hence the math below): - routes.push({ - path: '**', - redirectTo: routes[this._availableVariants.length * this._availableVariants.length]?.path, - }); - } - - this._routes = routes; - } - - private _gotWorkspaceRoute = (e: UmbRouterSlotInitEvent) => { - this.#workspaceContext?.splitView.setWorkspaceRoute(e.target.absoluteRouterPath); - }; - render() { - return this._routes - ? html`${this.splitViewElement}` - : ''; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.stories.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.stories.ts index 8475de493d..ce3a24444b 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.stories.ts @@ -1,7 +1,6 @@ -import './document-workspace.element'; +import './document-workspace-edit.element'; import { Meta, Story } from '@storybook/web-components'; import { html } from 'lit-html'; -import { data as documentNodes } from '../../../../core/mocks/data/document.data'; import type { UmbDocumentWorkspaceElement } from './document-workspace.element'; export default { @@ -11,5 +10,5 @@ export default { } as Meta; export const AAAOverview: Story = () => - html` `; + html` `; AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.test.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.test.ts index 3849929e42..99dbc4d512 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.test.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/document-workspace.test.ts @@ -17,13 +17,4 @@ describe('UmbDocumentWorkspaceElement', () => { // TODO: should we use shadowDom here? await expect(element).to.be.accessible(defaultA11yConfig); }); - - describe('methods', () => { - it('has a load method', () => { - expect(element).to.have.property('load').that.is.a('function'); - }); - it('has a create method', () => { - expect(element).to.have.property('create').that.is.a('function'); - }); - }); }); diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts index a8a3adf277..f8fa99081a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/documents/documents/workspace/manifests.ts @@ -13,7 +13,7 @@ const workspace: ManifestWorkspace = { type: 'workspace', alias: 'Umb.Workspace.Document', name: 'Document Workspace', - loader: () => import('./document-workspace-edit.element'), + loader: () => import('./document-workspace.element'), meta: { entityType: 'document', },