diff --git a/src/Umbraco.Web.UI.Client/.vscode/settings.json b/src/Umbraco.Web.UI.Client/.vscode/settings.json index 88fb1f27a3..d611a3d7d6 100644 --- a/src/Umbraco.Web.UI.Client/.vscode/settings.json +++ b/src/Umbraco.Web.UI.Client/.vscode/settings.json @@ -14,6 +14,7 @@ "pickable", "popovertarget", "Registrator", + "Routable", "stylesheet", "svgs", "templating", diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts index a7d4f28535..d0cffbd4d9 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/incrementor-workspace-action.ts @@ -5,9 +5,8 @@ import { EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context'; export class ExampleIncrementorWorkspaceAction extends UmbWorkspaceActionBase implements UmbWorkspaceAction { // This method is executed async execute() { - await this.consumeContext(EXAMPLE_COUNTER_CONTEXT, (context) => { - context.increment(); - }).asPromise(); + const context = await this.getContext(EXAMPLE_COUNTER_CONTEXT); + context.increment(); } } diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts index dbfc623ded..243ac89485 100644 --- a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/index.ts @@ -15,6 +15,7 @@ export const manifests: Array = [ }, { type: 'workspaceAction', + kind: 'default', name: 'Example Count Incerementor Workspace Action', alias: 'example.workspaceAction.incrementor', weight: 1000, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts index 1cd00a2c24..cc6956638d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/extension-with-api-slot/extension-with-api-slot.element.ts @@ -172,7 +172,7 @@ export class UmbExtensionWithApiSlotElement extends UmbLitElement { this._permitted, (ext) => ext.alias, (ext) => (this.renderMethod ? this.renderMethod(ext) : ext.component), - ) + ) : html``; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts index fe55f13d4a..f513625afd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/index.ts @@ -39,7 +39,7 @@ import type { ManifestLocalization } from './localization.model.js'; import type { ManifestTree } from './tree.model.js'; import type { ManifestTreeItem } from './tree-item.model.js'; import type { ManifestUserProfileApp } from './user-profile-app.model.js'; -import type { ManifestWorkspace } from './workspace.model.js'; +import type { ManifestWorkspace, ManifestWorkspaceRoutableKind } from './workspace.model.js'; import type { ManifestWorkspaceAction, ManifestWorkspaceActionDefaultKind } from './workspace-action.model.js'; import type { ManifestWorkspaceActionMenuItem } from './workspace-action-menu-item.model.js'; import type { ManifestWorkspaceContext } from './workspace-context.model.js'; @@ -114,6 +114,7 @@ export type ManifestPropertyActions = ManifestPropertyAction | ManifestPropertyA export type ManifestWorkspaceActions = ManifestWorkspaceAction | ManifestWorkspaceActionDefaultKind; +export type ManifestWorkspaces = ManifestWorkspace | ManifestWorkspaceRoutableKind; export type ManifestWorkspaceViews = ManifestWorkspaceView | ManifestWorkspaceViewContentTypeDesignEditorKind; export type ManifestTypes = @@ -157,7 +158,7 @@ export type ManifestTypes = | ManifestTreeItem | ManifestTreeStore | ManifestUserProfileApp - | ManifestWorkspace + | ManifestWorkspaces | ManifestWorkspaceActions | ManifestWorkspaceActionMenuItem | ManifestWorkspaceContext diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/workspace.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/workspace.model.ts index 7218c9bb92..e4d674f53f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/workspace.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/workspace.model.ts @@ -1,12 +1,26 @@ +import type { UmbRoutableWorkspaceContext } from '../../workspace/contexts/routable-workspace-context.interface.js'; +import type { UmbWorkspaceContextInterface } from '../../workspace/contexts/workspace-context.interface.js'; import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; -import type { ManifestElementAndApi, UmbApi } from '@umbraco-cms/backoffice/extension-api'; +import type { ManifestElementAndApi } from '@umbraco-cms/backoffice/extension-api'; // TODO: Missing Extension API Interface: -export interface ManifestWorkspace extends ManifestElementAndApi { +export interface ManifestWorkspace< + MetaType extends MetaWorkspace = MetaWorkspace, + ElementType extends UmbControllerHostElement = UmbControllerHostElement, + ApiType extends UmbWorkspaceContextInterface = UmbWorkspaceContextInterface, +> extends ManifestElementAndApi { type: 'workspace'; - meta: MetaWorkspace; + meta: MetaType; } export interface MetaWorkspace { entityType: string; } + +export interface ManifestWorkspaceRoutableKind + extends ManifestWorkspace { + type: 'workspace'; + kind: 'routable'; +} + +export interface MetaWorkspaceRoutableKind extends MetaWorkspace {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-action/common/save/save.action.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-action/common/save/save.action.ts index fd4fe5107b..d106cae3e5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-action/common/save/save.action.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-action/common/save/save.action.ts @@ -1,4 +1,4 @@ -import type { UmbSaveableWorkspaceContextInterface } from '../../../../workspace-context/saveable-workspace-context.interface.js'; +import type { UmbSaveableWorkspaceContextInterface } from '../../../../contexts/saveable-workspace-context.interface.js'; import { UmbWorkspaceActionBase } from '../../workspace-action-base.controller.js'; import { UMB_SAVEABLE_WORKSPACE_CONTEXT, type UmbWorkspaceActionArgs } from '@umbraco-cms/backoffice/workspace'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts index 2a11e8d8ad..f91a2858f4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.element.ts @@ -1,4 +1,4 @@ -import { UMB_SAVEABLE_WORKSPACE_CONTEXT } from '../../saveable-workspace.context-token.js'; +import { UMB_SAVEABLE_WORKSPACE_CONTEXT } from '../../contexts/saveable-workspace.context-token.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts index 3039616715..dd740aedb1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view.context.ts @@ -1,4 +1,4 @@ -import { UMB_VARIANT_WORKSPACE_CONTEXT } from '../../workspace-context/index.js'; +import { UMB_VARIANT_WORKSPACE_CONTEXT } from '../../contexts/index.js'; import { UmbVariantId } from '@umbraco-cms/backoffice/variant'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/index.ts new file mode 100644 index 0000000000..028680ae5f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/index.ts @@ -0,0 +1,3 @@ +export type { WorkspaceAliasConditionConfig } from './workspace-alias.condition.js'; +export type { WorkspaceEntityTypeConditionConfig } from './workspace-entity-type.condition.js'; +export type { WorkspaceHasCollectionConditionConfig } from './workspace-has-collection.condition.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/manifests.ts new file mode 100644 index 0000000000..0df9d50486 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/manifests.ts @@ -0,0 +1,5 @@ +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 = [workspaceAliasCondition, workspaceEntityTypeCondition, workspaceHasCollectionCondition]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-alias.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts index 6006ddedf1..46b33dc39d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-alias.condition.ts @@ -1,4 +1,4 @@ -import { UMB_WORKSPACE_CONTEXT, type UmbWorkspaceContextInterface } from './workspace-context/index.js'; +import { UMB_WORKSPACE_CONTEXT, type UmbWorkspaceContextInterface } from '../contexts/index.js'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { ManifestCondition, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-entity-type.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-type.condition.ts similarity index 94% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-entity-type.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-type.condition.ts index 7fb321bc35..661a8a136a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-entity-type.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-entity-type.condition.ts @@ -1,4 +1,4 @@ -import { UMB_WORKSPACE_CONTEXT } from './workspace-context/index.js'; +import { UMB_WORKSPACE_CONTEXT } from '../contexts/index.js'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { ManifestCondition, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-has-collection.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-has-collection.condition.ts similarity index 84% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-has-collection.condition.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-has-collection.condition.ts index 03555f0019..d30c8ea65e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-has-collection.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/conditions/workspace-has-collection.condition.ts @@ -1,3 +1,4 @@ +import { UMB_WORKSPACE_COLLECTION_CONTEXT } from '../contexts/workspace-collection-context.token.js'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; import type { ManifestCondition, @@ -6,16 +7,12 @@ import type { 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 implements UmbExtensionCondition { - constructor( - host: UmbControllerHost, - args: UmbConditionControllerArguments, - ) { + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { super(host, args); this.consumeContext(UMB_WORKSPACE_COLLECTION_CONTEXT, (context) => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/editable-workspace-context-base.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/editable-workspace-context-base.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/editable-workspace-context-base.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/editable-workspace-context-base.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/index.ts similarity index 78% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/index.ts index 269d85792a..369542bd14 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/index.ts @@ -1,11 +1,14 @@ +export * from './editable-workspace-context-base.js'; export * from './property-structure-workspace-context.interface.js'; export * from './publishable-workspace-context.interface.js'; +export * from './publishable-workspace.context-token.js'; +export * from './routable-workspace-context.interface.js'; export * from './saveable-workspace-context.interface.js'; +export * from './saveable-workspace.context-token.js'; +export * from './variant-workspace-context.token.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'; export * from './workspace-context.token.js'; export * from './workspace-invariantable-context.interface.js'; export * from './workspace-variantable-context.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/property-structure-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/property-structure-workspace-context.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/property-structure-workspace-context.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/property-structure-workspace-context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/publishable-workspace-context.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/publishable-workspace-context.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/publishable-workspace-context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/publishable-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/publishable-workspace.context-token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/publishable-workspace.context-token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/publishable-workspace.context-token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/routable-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/routable-workspace-context.interface.ts new file mode 100644 index 0000000000..c6a0a16e36 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/routable-workspace-context.interface.ts @@ -0,0 +1,6 @@ +import type { UmbWorkspaceRouteManager } from '../index.js'; +import type { UmbWorkspaceContextInterface } from './workspace-context.interface.js'; + +export interface UmbRoutableWorkspaceContext extends UmbWorkspaceContextInterface { + readonly routes: UmbWorkspaceRouteManager; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/saveable-workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/saveable-workspace-context.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/saveable-workspace-context.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/saveable-workspace-context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/saveable-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/saveable-workspace.context-token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/saveable-workspace.context-token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/saveable-workspace.context-token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/variant-workspace-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/variant-workspace-context.token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/variant-workspace-context.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/variant-workspace-context.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-collection-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-collection-context.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-collection-context.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-collection-context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-collection-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-collection-context.token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-collection-context.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-collection-context.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-context.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-context.token.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-context.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-invariantable-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-invariantable-context.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-invariantable-context.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-invariantable-context.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-variantable-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-variantable-context.interface.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-variantable-context.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-variantable-context.interface.ts index 764f370182..4f488e9d22 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-variantable-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/contexts/workspace-variantable-context.interface.ts @@ -1,4 +1,4 @@ -import type { UmbWorkspaceSplitViewManager } from '../workspace-split-view-manager.class.js'; +import type { UmbWorkspaceSplitViewManager } from '../controllers/workspace-split-view-manager.controller.js'; import type { UmbPropertyDatasetContext } from '../../property/property-dataset/property-dataset-context.interface.js'; import type { UmbSaveableWorkspaceContextInterface } from './saveable-workspace-context.interface.js'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/index.ts new file mode 100644 index 0000000000..fce8ba5e87 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/index.ts @@ -0,0 +1,3 @@ +export * from './workspace-is-new-redirect.controller.js'; +export * from './workspace-split-view-manager.controller.js'; +export * from './workspace-route-manager.controller.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-is-new-redirect-controller/workspace-is-new-redirect-controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-is-new-redirect-controller/workspace-is-new-redirect-controller.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts index a38a724724..1157df8c8e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-is-new-redirect-controller/workspace-is-new-redirect-controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-is-new-redirect.controller.ts @@ -1,4 +1,4 @@ -import type { UmbEditableWorkspaceContextBase } from '../workspace-context/index.js'; +import type { UmbEditableWorkspaceContextBase } from '../contexts/index.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { createRoutePathBuilder, type UmbRouterSlotElement } from '@umbraco-cms/backoffice/router'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-route-manager.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-route-manager.controller.ts new file mode 100644 index 0000000000..6fedc8a00e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-route-manager.controller.ts @@ -0,0 +1,13 @@ +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbRoute } from '@umbraco-cms/backoffice/router'; + +export class UmbWorkspaceRouteManager extends UmbControllerBase { + // + #routes = new UmbArrayState([], (x) => x.path); + public readonly routes = this.#routes.asObservable(); + + setRoutes(routes: Array) { + this.#routes.setValue(routes); + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-split-view-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-split-view-manager.controller.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-split-view-manager.class.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/controllers/workspace-split-view-manager.controller.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts index 1b12cbf033..e31957d8fb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/index.ts @@ -1,10 +1,6 @@ export * from './components/index.js'; -export * from './publishable-workspace.context-token.js'; -export * from './saveable-workspace.context-token.js'; -export * from './workspace-context/index.js'; -export * from './workspace-is-new-redirect-controller/index.js'; -export * from './workspace-modal/index.js'; +export * from './contexts/index.js'; +export * from './controllers/index.js'; +export type * from './conditions/index.js'; +export * from './modals/index.js'; export * from './workspace-property-dataset/index.js'; -export * from './workspace-split-view-manager.class.js'; -export type { WorkspaceAliasConditionConfig } from './workspace-alias.condition.js'; -export type { WorkspaceEntityTypeConditionConfig } from './workspace-entity-type.condition.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/manifests.ts new file mode 100644 index 0000000000..0c129d12fc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/manifests.ts @@ -0,0 +1,3 @@ +import { manifest as routableKindManifest } from './routable-workspace.kind.js'; + +export const manifests = [routableKindManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.element.ts new file mode 100644 index 0000000000..1efc8622ea --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.element.ts @@ -0,0 +1,26 @@ +import type { UmbRoutableWorkspaceContext } from '../contexts/routable-workspace-context.interface.js'; +import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbRoute } from '@umbraco-cms/backoffice/router'; + +@customElement('umb-routable-workspace') +export class UmbRoutableWorkspaceElement extends UmbLitElement { + @state() + _routes: UmbRoute[] = []; + + public set api(api: UmbRoutableWorkspaceContext) { + this.observe(api.routes.routes, (routes) => (this._routes = routes)); + } + + render() { + return html``; + } +} + +export default UmbRoutableWorkspaceElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-routable-workspace': UmbRoutableWorkspaceElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.kind.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.kind.ts new file mode 100644 index 0000000000..68840c0a51 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.kind.ts @@ -0,0 +1,13 @@ +import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifest: UmbBackofficeManifestKind = { + type: 'kind', + alias: 'Umb.Kind.Workspace.Routable', + matchKind: 'routable', + matchType: 'workspace', + manifest: { + type: 'workspace', + kind: 'routable', + element: () => import('./routable-workspace.element.js'), + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.test.ts similarity index 61% rename from src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.test.ts index 5e4ae77f02..114af22913 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/kinds/routable-workspace.test.ts @@ -1,16 +1,16 @@ import { expect, fixture, html } from '@open-wc/testing'; -import { UmbDocumentWorkspaceElement } from './document-workspace.element.js'; +import { UmbRoutableWorkspaceElement } from './routable-workspace.element.js'; import { type UmbTestRunnerWindow, defaultA11yConfig } from '@umbraco-cms/internal/test-utils'; -describe('UmbDocumentWorkspaceElement', () => { - let element: UmbDocumentWorkspaceElement; +describe('UmbRoutableWorkspaceElement', () => { + let element: UmbRoutableWorkspaceElement; beforeEach(async () => { - element = await fixture(html``); + element = await fixture(html``); }); it('is defined with its own instance', () => { - expect(element).to.be.instanceOf(UmbDocumentWorkspaceElement); + expect(element).to.be.instanceOf(UmbRoutableWorkspaceElement); }); if ((window as UmbTestRunnerWindow).__UMBRACO_TEST_RUN_A11Y_TEST) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/manifests.ts index d7a4ef36ca..69da627331 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/manifests.ts @@ -1,13 +1,6 @@ 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'; +import { manifests as workspaceKinds } from './kinds/manifests.js'; +import { manifests as workspaceModals } from './modals/manifests.js'; +import { manifests as workspaceConditions } from './conditions/manifests.js'; -export const manifests = [ - ...componentManifests, - ...workspaceModals, - workspaceAliasCondition, - workspaceEntityTypeCondition, - workspaceHasCollectionCondition, -]; +export const manifests = [...workspaceConditions, ...workspaceKinds, ...componentManifests, ...workspaceModals]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/manifests.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/manifests.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/workspace-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-modal/workspace-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/workspace/modals/workspace-modal.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-is-new-redirect-controller/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-is-new-redirect-controller/index.ts deleted file mode 100644 index 6485b3d126..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-is-new-redirect-controller/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './workspace-is-new-redirect-controller.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace.element.ts index bd14d3a535..2ec06f3848 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace.element.ts @@ -9,9 +9,10 @@ export class UmbWorkspaceElement extends UmbLitElement { render() { if (!this.entityType) return nothing; - return html` manifest.meta.entityType === this.entityType}>`; + .filter=${(manifest: ManifestWorkspace) => + manifest.meta.entityType === this.entityType}>`; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index 134348bcf6..52c45a507c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -18,13 +18,20 @@ import { import { UmbDocumentPublishingRepository } from '../repository/publishing/index.js'; import { UmbUnpublishDocumentEntityAction } from '../entity-actions/unpublish.action.js'; import { UMB_DOCUMENT_WORKSPACE_ALIAS } from './manifests.js'; +import { UmbDocumentWorkspaceEditorElement } from './document-workspace-editor.element.js'; import { UMB_INVARIANT_CULTURE, UmbVariantId } from '@umbraco-cms/backoffice/variant'; import { UmbContentTypeStructureManager } from '@umbraco-cms/backoffice/content-type'; -import { UmbEditableWorkspaceContextBase, UmbWorkspaceSplitViewManager } from '@umbraco-cms/backoffice/workspace'; +import { + UmbEditableWorkspaceContextBase, + UmbWorkspaceIsNewRedirectController, + UmbWorkspaceRouteManager, + UmbWorkspaceSplitViewManager, +} from '@umbraco-cms/backoffice/workspace'; import type { UmbWorkspaceCollectionContextInterface, UmbVariantableWorkspaceContextInterface, UmbPublishableWorkspaceContextInterface, + UmbRoutableWorkspaceContext, } from '@umbraco-cms/backoffice/workspace'; import { appendToFrozenArray, @@ -46,6 +53,7 @@ type EntityType = UmbDocumentDetailModel; export class UmbDocumentWorkspaceContext extends UmbEditableWorkspaceContextBase implements + UmbRoutableWorkspaceContext, UmbVariantableWorkspaceContextInterface, UmbPublishableWorkspaceContextInterface, UmbWorkspaceCollectionContextInterface @@ -90,6 +98,7 @@ export class UmbDocumentWorkspaceContext ); #varies?: boolean; + readonly routes = new UmbWorkspaceRouteManager(this); readonly splitView = new UmbWorkspaceSplitViewManager(); readonly variantOptions = mergeObservables( @@ -129,6 +138,33 @@ export class UmbDocumentWorkspaceContext this.observe(this.contentTypeUnique, (unique) => this.structure.loadType(unique)); this.observe(this.varies, (varies) => (this.#varies = varies)); + this.routes.setRoutes([ + { + path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique', + component: () => new UmbDocumentWorkspaceEditorElement(), + setup: async (_component, info) => { + const parentEntityType = info.match.params.entityType; + const parentUnique = info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique; + const documentTypeUnique = info.match.params.documentTypeUnique; + this.create({ entityType: parentEntityType, unique: parentUnique }, documentTypeUnique); + + new UmbWorkspaceIsNewRedirectController( + this, + this, + this.getHostElement().shadowRoot!.querySelector('umb-router-slot')!, + ); + }, + }, + { + path: 'edit/:unique', + component: () => new UmbDocumentWorkspaceEditorElement(), + setup: (_component, info) => { + const unique = info.match.params.unique; + this.load(unique); + }, + }, + ]); + this.loadLanguages(); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.element.ts deleted file mode 100644 index e4768b55e4..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.element.ts +++ /dev/null @@ -1,74 +0,0 @@ -import type { UmbDocumentWorkspaceContext } from './document-workspace.context.js'; -import { UmbDocumentWorkspaceEditorElement } from './document-workspace-editor.element.js'; -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbExtensionsApiInitializer, createExtensionApi } from '@umbraco-cms/backoffice/extension-api'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace'; -import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry'; -import type { UmbApi } from '@umbraco-cms/backoffice/extension-api'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; - -@customElement('umb-document-workspace') -export class UmbDocumentWorkspaceElement extends UmbLitElement { - #workspaceContext?: UmbDocumentWorkspaceContext; - #editorElement = () => new UmbDocumentWorkspaceEditorElement(); - - @state() - _routes: UmbRoute[] = []; - - public set manifest(manifest: ManifestWorkspace) { - createExtensionApi(this, manifest).then((context) => { - if (context) { - this.#gotWorkspaceContext(context); - } - }); - } - - #gotWorkspaceContext(context: UmbApi) { - this.#workspaceContext = context as UmbDocumentWorkspaceContext; - - this._routes = [ - { - path: 'create/parent/:entityType/:parentUnique/:documentTypeUnique', - component: this.#editorElement, - setup: async (_component, info) => { - // TODO: Remember the perspective of permissions here, we need to check if the user has access to create a document of this type under this parent? - const parentEntityType = info.match.params.entityType; - const parentUnique = info.match.params.parentUnique === 'null' ? null : info.match.params.parentUnique; - const documentTypeUnique = info.match.params.documentTypeUnique; - this.#workspaceContext!.create({ entityType: parentEntityType, unique: parentUnique }, documentTypeUnique); - - new UmbWorkspaceIsNewRedirectController( - this, - this.#workspaceContext!, - this.shadowRoot!.querySelector('umb-router-slot')!, - ); - }, - }, - { - path: 'edit/:unique', - component: this.#editorElement, - setup: (_component, info) => { - const unique = info.match.params.unique; - this.#workspaceContext!.load(unique); - }, - }, - ]; - - // TODO: We need to recreate when ID changed? - new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [this, this.#workspaceContext]); - } - - render() { - return html``; - } -} - -export default UmbDocumentWorkspaceElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-document-workspace': UmbDocumentWorkspaceElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.stories.ts deleted file mode 100644 index 7381b9b633..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.stories.ts +++ /dev/null @@ -1,14 +0,0 @@ -import './document-workspace-editor.element.js'; -import type { Meta, Story } from '@storybook/web-components'; -import type { UmbDocumentWorkspaceElement } from './document-workspace.element.js'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Workspaces/Document', - component: 'umb-document-workspace', - id: 'umb-document-workspace', -} as Meta; - -export const AAAOverview: Story = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts index 3734303e67..344e7ac8b7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts @@ -5,7 +5,7 @@ import { UmbDocumentSaveAndPublishWorkspaceAction } from './actions/save-and-pub import { UmbDocumentPublishWithDescendantsWorkspaceAction } from './actions/publish-with-descendants.action.js'; import { UmbSaveWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import type { - ManifestWorkspace, + ManifestWorkspaces, ManifestWorkspaceActions, ManifestWorkspaceActionMenuItem, ManifestWorkspaceView, @@ -13,11 +13,11 @@ import type { export const UMB_DOCUMENT_WORKSPACE_ALIAS = 'Umb.Workspace.Document'; -const workspace: ManifestWorkspace = { +const workspace: ManifestWorkspaces = { type: 'workspace', + kind: 'routable', alias: UMB_DOCUMENT_WORKSPACE_ALIAS, name: 'Document Workspace', - element: () => import('./document-workspace.element.js'), api: () => import('./document-workspace.context.js'), meta: { entityType: UMB_DOCUMENT_ENTITY_TYPE,