move routes into workspace element

This commit is contained in:
Mads Rasmussen
2023-03-16 10:26:44 +01:00
parent 47465e870a
commit e8e2e8d414
6 changed files with 177 additions and 171 deletions

View File

@@ -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<IRoute>;
@state()
_availableVariants: Array<VariantViewModelBaseModel> = [];
@state()
_workspaceSplitViews: Array<ActiveVariant> = [];
#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<IRoute> = [];
// 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<HTMLElement>, 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<HTMLElement>, 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`<umb-router-slot .routes=${this._routes} @init=${this._gotWorkspaceRoute}
>${this.splitViewElement}</umb-router-slot
>`
: '';
}
}
export default UmbDocumentWorkspaceEditElement;
declare global {
interface HTMLElementTagNameMap {
'umb-document-workspace-edit': UmbDocumentWorkspaceEditElement;
}
}

View File

@@ -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() || {};
}

View File

@@ -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<IRoute>;
@state()
_availableVariants: Array<VariantViewModelBaseModel> = [];
@state()
_workspaceSplitViews: Array<ActiveVariant> = [];
#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<IRoute> = [];
// 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<HTMLElement>, 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<HTMLElement>, 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`<umb-router-slot .routes=${this._routes} @init=${this._gotWorkspaceRoute}
>${this.splitViewElement}</umb-router-slot
>`
: '';
return html`<umb-router-slot .routes="${this._routes}"></umb-router-slot>`;
}
}

View File

@@ -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<UmbDocumentWorkspaceElement> = () =>
html` <umb-document-workspace id="${documentNodes[0].key}"></umb-document-workspace>`;
html` <umb-document-workspace></umb-document-workspace>`;
AAAOverview.storyName = 'Overview';

View File

@@ -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');
});
});
});

View File

@@ -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',
},