;
+
+ @state()
+ private _routerPath?: string;
+
+ @state()
+ private _activePath = '';
+
+ @state()
+ private sortModeActive?: boolean;
+
+ @state()
+ private _buttonDisabled: boolean = false;
+
+ private _workspaceContext?: UmbMediaTypeWorkspaceContext;
+
+ private _tabsStructureHelper = new UmbContentTypeContainerStructureHelper(this);
+
+ private _modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT_TOKEN.TYPE;
+
+ constructor() {
+ super();
+ this.sorter = new UmbSorterController(this, this.config);
+
+ //TODO: We need to differentiate between local and composition tabs (and hybrids)
+
+ this._tabsStructureHelper.setIsRoot(true);
+ this._tabsStructureHelper.setContainerChildType('Tab');
+ this.observe(this._tabsStructureHelper.containers, (tabs) => {
+ this._tabs = tabs;
+ this._createRoutes();
+ });
+
+ // _hasRootProperties can be gotten via _tabsStructureHelper.hasProperties. But we do not support root properties currently.
+
+ this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => {
+ this._workspaceContext = workspaceContext as UmbMediaTypeWorkspaceContext;
+ this._tabsStructureHelper.setStructureManager((workspaceContext as UmbMediaTypeWorkspaceContext).structure);
+ this.observe(
+ this._workspaceContext.isSorting,
+ (isSorting) => (this.sortModeActive = isSorting),
+ '_observeIsSorting',
+ );
+ this._observeRootGroups();
+ });
+
+ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (context) => {
+ this._modalManagerContext = context;
+ });
+ }
+
+ private _observeRootGroups() {
+ if (!this._workspaceContext) return;
+
+ this.observe(
+ this._workspaceContext.structure.hasRootContainers('Group'),
+ (hasRootGroups) => {
+ this._hasRootGroups = hasRootGroups;
+ this._createRoutes();
+ },
+ '_observeGroups',
+ );
+ }
+
+ #changeMode() {
+ this._workspaceContext?.setIsSorting(!this.sortModeActive);
+
+ if (this.sortModeActive && this._tabs) {
+ this.sorter?.setModel(this._tabs);
+ } else {
+ this.sorter?.setModel([]);
+ }
+ }
+
+ private _createRoutes() {
+ if (!this._workspaceContext || !this._tabs) return;
+ const routes: UmbRoute[] = [];
+
+ if (this._tabs.length > 0) {
+ this._tabs?.forEach((tab) => {
+ const tabName = tab.name ?? '';
+ routes.push({
+ path: `tab/${encodeFolderName(tabName).toString()}`,
+ component: () => import('./media-type-workspace-view-edit-tab.element.js'),
+ setup: (component) => {
+ (component as UmbMediaTypeWorkspaceViewEditTabElement).tabName = tabName;
+ (component as UmbMediaTypeWorkspaceViewEditTabElement).ownerTabId =
+ this._workspaceContext?.structure.isOwnerContainer(tab.id!) ? tab.id : undefined;
+ },
+ });
+ });
+ }
+
+ routes.push({
+ path: 'root',
+ component: () => import('./media-type-workspace-view-edit-tab.element.js'),
+ setup: (component) => {
+ (component as UmbMediaTypeWorkspaceViewEditTabElement).noTabName = true;
+ (component as UmbMediaTypeWorkspaceViewEditTabElement).ownerTabId = null;
+ },
+ });
+
+ if (this._hasRootGroups) {
+ routes.push({
+ path: '',
+ redirectTo: 'root',
+ });
+ } else if (routes.length !== 0) {
+ routes.push({
+ path: '',
+ redirectTo: routes[0]?.path,
+ });
+ }
+
+ this._routes = routes;
+ }
+
+ #requestRemoveTab(tab: PropertyTypeContainerModelBaseModel | undefined) {
+ const Message: UmbConfirmModalData = {
+ headline: 'Delete tab',
+ content: html`
+ Are you sure you want to delete the tab ${tab?.name ?? tab?.id}
+
+
+
+ This will delete all items that doesn't belong to a composition.
+
+
`,
+ confirmLabel: this.localize.term('actions_delete'),
+ color: 'danger',
+ };
+
+ // TODO: If this tab is composed of other tabs, then notify that it will only delete the local tab.
+
+ const modalHandler = this._modalManagerContext?.open(UMB_CONFIRM_MODAL, Message);
+
+ modalHandler?.onSubmit().then(() => {
+ this.#remove(tab?.id);
+ });
+ }
+ #remove(tabId?: string) {
+ if (!tabId) return;
+ this._workspaceContext?.structure.removeContainer(null, tabId);
+ this._tabsStructureHelper?.isOwnerContainer(tabId)
+ ? window.history.replaceState(null, '', this._routerPath + this._routes[0]?.path ?? '/root')
+ : '';
+ }
+ async #addTab() {
+ if (
+ (this.shadowRoot?.querySelector('uui-tab[active] uui-input') as UUIInputElement) &&
+ (this.shadowRoot?.querySelector('uui-tab[active] uui-input') as UUIInputElement).value === ''
+ ) {
+ this.#focusInput();
+ return;
+ }
+
+ const tab = await this._workspaceContext?.structure.createContainer(null, null, 'Tab');
+ if (tab) {
+ const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || '');
+ window.history.replaceState(null, '', path);
+ this.#focusInput();
+ }
+ }
+
+ async #focusInput() {
+ setTimeout(() => {
+ (this.shadowRoot?.querySelector('uui-tab[active] uui-input') as UUIInputElement | undefined)?.focus();
+ }, 100);
+ }
+
+ async #tabNameChanged(event: InputEvent, tab: PropertyTypeContainerModelBaseModel) {
+ if (this._buttonDisabled) this._buttonDisabled = !this._buttonDisabled;
+ let newName = (event.target as HTMLInputElement).value;
+
+ if (newName === '') {
+ newName = 'Unnamed';
+ (event.target as HTMLInputElement).value = 'Unnamed';
+ }
+
+ const changedName = this._workspaceContext?.structure.makeContainerNameUniqueForOwnerContentType(
+ newName,
+ 'Tab',
+ tab.id,
+ );
+
+ // Check if it collides with another tab name of this same media-type, if so adjust name:
+ if (changedName) {
+ newName = changedName;
+ (event.target as HTMLInputElement).value = newName;
+ }
+
+ this._tabsStructureHelper.partialUpdateContainer(tab.id!, {
+ name: newName,
+ });
+
+ // Update the current URL, so we are still on this specific tab:
+ window.history.replaceState(null, '', this._routerPath + '/tab/' + encodeFolderName(newName));
+ }
+
+ render() {
+ return html`
+
+
+ {
+ this._routerPath = event.target.absoluteRouterPath;
+ }}
+ @change=${(event: UmbRouterSlotChangeEvent) => {
+ this._activePath = event.target.absoluteActiveViewPath || '';
+ }}>
+
+
+ `;
+ }
+
+ renderAddButton() {
+ if (this.sortModeActive) return;
+ return html`
+
+ Add tab
+ `;
+ }
+
+ renderActions() {
+ const sortButtonText = this.sortModeActive
+ ? this.localize.term('general_reorderDone')
+ : this.localize.term('general_reorder');
+
+ return html`
+
+
+ ${this.localize.term('contentTypeEditor_compositions')}
+
+
+
+ ${sortButtonText}
+
+
`;
+ }
+
+ renderTabsNavigation() {
+ if (!this._tabs) return;
+
+ return html`
+
+ ${this.renderRootTab()}
+ ${repeat(
+ this._tabs,
+ (tab) => tab.id! + tab.name,
+ (tab) => this.renderTab(tab),
+ )}
+
+
`;
+ }
+
+ renderRootTab() {
+ const rootTabPath = this._routerPath + '/root';
+ const rootTabActive = rootTabPath === this._activePath;
+ return html`
+ ${this.localize.term('general_content')}
+ `;
+ }
+
+ renderTab(tab: PropertyTypeContainerModelBaseModel) {
+ const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || '');
+ const tabActive = path === this._activePath;
+ const tabInherited = !this._tabsStructureHelper.isOwnerContainer(tab.id!);
+
+ return html`
+ ${this.renderTabInner(tab, tabActive, tabInherited)}
+ `;
+ }
+
+ renderTabInner(tab: PropertyTypeContainerModelBaseModel, tabActive: boolean, tabInherited: boolean) {
+ if (this.sortModeActive) {
+ return html`
+ ${tabInherited
+ ? html`${tab.name!}`
+ : html` ${tab.name!}
+ this.#changeOrderNumber(tab, e)}>`}
+
`;
+ }
+
+ if (tabActive && !tabInherited) {
+ return html`
+ this.#tabNameChanged(e, tab)}
+ @blur=${(e: InputEvent) => this.#tabNameChanged(e, tab)}
+ @input=${() => (this._buttonDisabled = true)}
+ @focus=${(e: UUIInputEvent) => (e.target.value ? nothing : (this._buttonDisabled = true))}>
+ ${this.renderDeleteFor(tab)}
+
+
`;
+ }
+
+ if (tabInherited) {
+ return html`${tab.name!}
`;
+ } else {
+ return html`${tab.name!} ${this.renderDeleteFor(tab)}
`;
+ }
+ }
+
+ #changeOrderNumber(tab: PropertyTypeContainerModelBaseModel, e: UUIInputEvent) {
+ if (!e.target.value || !tab.id) return;
+ const sortOrder = Number(e.target.value);
+ this._tabsStructureHelper.partialUpdateContainer(tab.id, { sortOrder });
+ }
+
+ renderDeleteFor(tab: PropertyTypeContainerModelBaseModel) {
+ return html` this.#requestRemoveTab(tab)}
+ compact>
+
+ `;
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ #buttons-wrapper {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ align-items: stretch;
+ }
+
+ :host {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ --uui-tab-background: var(--uui-color-surface);
+ }
+
+ /* TODO: This should be replaced with a general workspace bar — naming is hard */
+ #header {
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ flex-wrap: nowrap;
+ }
+
+ .flex {
+ display: flex;
+ }
+ uui-tab-group {
+ flex-wrap: nowrap;
+ }
+
+ .content-tab-is-empty {
+ align-self: center;
+ border-radius: 3px;
+ --uui-tab-text: var(--uui-color-text-alt);
+ border: dashed 1px var(--uui-color-border-emphasis);
+ }
+
+ uui-tab {
+ position: relative;
+ border-left: 1px hidden transparent;
+ border-right: 1px solid var(--uui-color-border);
+ }
+
+ .no-edit uui-input {
+ pointer-events: auto;
+ }
+
+ .no-edit {
+ pointer-events: none;
+ display: inline-flex;
+ padding-left: var(--uui-size-space-3);
+ border: 1px solid transparent;
+ align-items: center;
+ gap: var(--uui-size-space-3);
+ }
+
+ .trash {
+ opacity: 1;
+ transition: opacity 120ms;
+ }
+
+ uui-tab:not(:hover, :focus) .trash {
+ opacity: 0;
+ transition: opacity 120ms;
+ }
+
+ uui-input:not(:focus, :hover) {
+ border: 1px solid transparent;
+ }
+
+ .inherited {
+ vertical-align: sub;
+ }
+
+ .--umb-sorter-placeholder > * {
+ visibility: hidden;
+ }
+
+ .--umb-sorter-placeholder::after {
+ content: '';
+ position: absolute;
+ inset: 2px;
+ border: 1px dashed var(--uui-color-divider-emphasis);
+ }
+ `,
+ ];
+}
+
+export default UmbMediaTypeWorkspaceViewEditElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-media-type-workspace-view-edit': UmbMediaTypeWorkspaceViewEditElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-design-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-design-workspace-view.element.ts
deleted file mode 100644
index 77b9b97f99..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-design-workspace-view.element.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { UMB_MEDIA_TYPE_WORKSPACE_CONTEXT } from '../../media-type-workspace.context.js';
-import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
-import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
-import {
- UmbModalManagerContext,
- UMB_MODAL_MANAGER_CONTEXT_TOKEN,
- UMB_PROPERTY_EDITOR_UI_PICKER_MODAL,
-} from '@umbraco-cms/backoffice/modal';
-import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
-import type { MediaTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
-import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
-
-@customElement('umb-media-type-design-workspace-view')
-export class UmbMediaTypeDesignWorkspaceViewEditElement
- extends UmbLitElement
- implements UmbWorkspaceEditorViewExtensionElement
-{
- @state()
- _mediaType?: MediaTypeResponseModel;
-
- private _workspaceContext?: typeof UMB_MEDIA_TYPE_WORKSPACE_CONTEXT.TYPE;
-
- constructor() {
- super();
-
- this.consumeContext(UMB_MEDIA_TYPE_WORKSPACE_CONTEXT, (_instance) => {
- this._workspaceContext = _instance;
- this._observeMediaType();
- });
- }
-
- private _observeMediaType() {
- if (!this._workspaceContext) {
- return;
- }
-
- this.observe(this._workspaceContext.data, (mediaType) => {
- this._mediaType = mediaType;
- });
- }
-
- render() {
- return html` ${this._mediaType?.alias}`;
- }
-
- static styles = [
- UmbTextStyles,
- css`
- :host {
- display: block;
- margin: var(--uui-size-layout-1);
- padding-bottom: var(--uui-size-layout-1);
- }
-
- uui-box {
- margin-top: var(--uui-size-layout-1);
- }
- `,
- ];
-}
-
-export default UmbMediaTypeDesignWorkspaceViewEditElement;
-
-declare global {
- interface HTMLElementTagNameMap {
- 'umb-media-type-design-workspace-view': UmbMediaTypeDesignWorkspaceViewEditElement;
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-list-view-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-list-view-workspace-view.element.ts
deleted file mode 100644
index 46a63c562c..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-list-view-workspace-view.element.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { UMB_MEDIA_TYPE_WORKSPACE_CONTEXT } from '../../media-type-workspace.context.js';
-import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
-import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
-import {
- UmbModalManagerContext,
- UMB_MODAL_MANAGER_CONTEXT_TOKEN,
- UMB_PROPERTY_EDITOR_UI_PICKER_MODAL,
-} from '@umbraco-cms/backoffice/modal';
-import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
-import type { MediaTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
-import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
-
-@customElement('umb-media-type-list-view-workspace-view')
-export class UmbMediaTypeListViewWorkspaceViewEditElement
- extends UmbLitElement
- implements UmbWorkspaceEditorViewExtensionElement
-{
- @state()
- _mediaType?: MediaTypeResponseModel;
-
- private _workspaceContext?: typeof UMB_MEDIA_TYPE_WORKSPACE_CONTEXT.TYPE;
-
- constructor() {
- super();
-
- this.consumeContext(UMB_MEDIA_TYPE_WORKSPACE_CONTEXT, (_instance) => {
- this._workspaceContext = _instance;
- this._observeMediaType();
- });
- }
-
- private _observeMediaType() {
- if (!this._workspaceContext) {
- return;
- }
-
- this.observe(this._workspaceContext.data, (mediaType) => {
- this._mediaType = mediaType;
- });
- }
-
- render() {
- return html` List View view for ${this._mediaType?.alias}`;
- }
-
- static styles = [
- UmbTextStyles,
- css`
- :host {
- display: block;
- margin: var(--uui-size-layout-1);
- padding-bottom: var(--uui-size-layout-1);
- }
-
- uui-box {
- margin-top: var(--uui-size-layout-1);
- }
- `,
- ];
-}
-
-export default UmbMediaTypeListViewWorkspaceViewEditElement;
-
-declare global {
- interface HTMLElementTagNameMap {
- 'umb-media-type-list-view-workspace-view': UmbMediaTypeListViewWorkspaceViewEditElement;
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-permissions-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-permissions-workspace-view.element.ts
deleted file mode 100644
index 5dc1a4eab3..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/details/media-type-permissions-workspace-view.element.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { UMB_MEDIA_TYPE_WORKSPACE_CONTEXT } from '../../media-type-workspace.context.js';
-import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
-import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit';
-import {
- UmbModalManagerContext,
- UMB_MODAL_MANAGER_CONTEXT_TOKEN,
- UMB_PROPERTY_EDITOR_UI_PICKER_MODAL,
-} from '@umbraco-cms/backoffice/modal';
-import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
-import type { MediaTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
-import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
-
-@customElement('umb-media-type-permissions-workspace-view')
-export class UmbMediaTypePermissionsWorkspaceViewEditElement
- extends UmbLitElement
- implements UmbWorkspaceEditorViewExtensionElement
-{
- @state()
- _mediaType?: MediaTypeResponseModel;
-
- private _workspaceContext?: typeof UMB_MEDIA_TYPE_WORKSPACE_CONTEXT.TYPE;
-
- constructor() {
- super();
-
- this.consumeContext(UMB_MEDIA_TYPE_WORKSPACE_CONTEXT, (_instance) => {
- this._workspaceContext = _instance;
- this._observeMediaType();
- });
- }
-
- private _observeMediaType() {
- if (!this._workspaceContext) {
- return;
- }
-
- this.observe(this._workspaceContext.data, (mediaType) => {
- this._mediaType = mediaType;
- });
- }
-
- render() {
- return html`Permissions View for ${this._mediaType?.alias}`;
- }
-
- static styles = [
- UmbTextStyles,
- css`
- :host {
- display: block;
- margin: var(--uui-size-layout-1);
- padding-bottom: var(--uui-size-layout-1);
- }
-
- uui-box {
- margin-top: var(--uui-size-layout-1);
- }
- `,
- ];
-}
-
-export default UmbMediaTypePermissionsWorkspaceViewEditElement;
-
-declare global {
- interface HTMLElementTagNameMap {
- 'umb-media-type-permissions-workspace-view': UmbMediaTypePermissionsWorkspaceViewEditElement;
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/structure/media-type-workspace-view-structure.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/structure/media-type-workspace-view-structure.element.ts
new file mode 100644
index 0000000000..46a2206a8b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/views/structure/media-type-workspace-view-structure.element.ts
@@ -0,0 +1,117 @@
+import { UmbMediaTypeWorkspaceContext } from '../../media-type-workspace.context.js';
+import type { UmbMediaTypeInputElement } from '../../../components/media-type-input/media-type-input.element.js';
+import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import type { UUIToggleElement } from '@umbraco-cms/backoffice/external/uui';
+import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
+import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
+import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry';
+
+@customElement('umb-media-type-workspace-view-structure')
+export class UmbMediaTypeWorkspaceViewStructureElement
+ extends UmbLitElement
+ implements UmbWorkspaceEditorViewExtensionElement
+{
+ #workspaceContext?: UmbMediaTypeWorkspaceContext;
+
+ @state()
+ private _allowedAsRoot?: boolean;
+
+ @state()
+ private _allowedContentTypeIDs?: Array;
+
+ constructor() {
+ super();
+
+ // TODO: Figure out if this is the best way to consume the context or if it can be strongly typed with an UmbContextToken
+ this.consumeContext(UMB_WORKSPACE_CONTEXT, (mediaTypeContext) => {
+ this.#workspaceContext = mediaTypeContext as UmbMediaTypeWorkspaceContext;
+ this._observeMediaType();
+ });
+ }
+
+ private _observeMediaType() {
+ if (!this.#workspaceContext) return;
+ this.observe(this.#workspaceContext.allowedAsRoot, (allowedAsRoot) => (this._allowedAsRoot = allowedAsRoot));
+ this.observe(this.#workspaceContext.allowedContentTypes, (allowedContentTypes) => {
+ const oldValue = this._allowedContentTypeIDs;
+ this._allowedContentTypeIDs = allowedContentTypes
+ ?.map((x) => x.id)
+ .filter((x) => x !== undefined) as Array;
+ this.requestUpdate('_allowedContentTypeIDs', oldValue);
+ });
+ }
+
+ render() {
+ return html`
+
+
+ ${this.localize.term('contentTypeEditor_allowAsRootDescription')}
+
+ {
+ this.#workspaceContext?.updateProperty('allowedAsRoot', (e.target as UUIToggleElement).checked);
+ }}>
+
+
+
+
+ Allow content of the specified types to be created underneath content of this type.
+
+
+
+ {
+ const sortedContentTypesList = (e.target as UmbMediaTypeInputElement).selectedIds.map((id, index) => ({
+ id: id,
+ sortOrder: index,
+ }));
+ this.#workspaceContext?.updateProperty('allowedContentTypes', sortedContentTypesList);
+ }}">
+
+
+
+
+
+
+ Provides an overview of child content and hides it in the tree.
+
+
+
+ `;
+ }
+
+ static styles = [
+ UmbTextStyles,
+ css`
+ :host {
+ display: block;
+ margin: var(--uui-size-layout-1);
+ padding-bottom: var(--uui-size-layout-1); // To enforce some distance to the bottom of the scroll-container.
+ }
+ uui-box {
+ margin-top: var(--uui-size-layout-1);
+ }
+ uui-label,
+ umb-property-editor-ui-number {
+ display: block;
+ }
+
+ // TODO: is this necessary?
+ uui-toggle {
+ display: flex;
+ }
+ `,
+ ];
+}
+
+export default UmbMediaTypeWorkspaceViewStructureElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-media-type-workspace-view-structure': UmbMediaTypeWorkspaceViewStructureElement;
+ }
+}
From 62727fce9b813b959abbca834eaa1a3201d52db0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 16 Nov 2023 19:08:02 +1300
Subject: [PATCH 04/25] create action
---
.../entity-actions/create.action.ts | 14 ----
.../entity-actions/create/create.action.ts | 26 +++++++
.../entity-actions/create/manifests.ts | 28 +++++++
.../entity-actions/create/modal/index.ts | 13 ++++
...media-type-create-options-modal.element.ts | 76 +++++++++++++++++++
.../media-types/entity-actions/manifests.ts | 19 +----
.../entity-actions/reload.action.ts | 16 ----
7 files changed, 146 insertions(+), 46 deletions(-)
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create.action.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/index.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts
delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/reload.action.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create.action.ts
deleted file mode 100644
index 01cb440514..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create.action.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { UmbMediaTypeRepository } from '../repository/media-type.repository.js';
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
-
-export class UmbCreateMediaTypeEntityAction extends UmbEntityActionBase {
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
- }
-
- async execute() {
- console.log(`execute for: ${this.unique}`);
- alert('open create dialog');
- }
-}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts
new file mode 100644
index 0000000000..84d6ecf8f0
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/create.action.ts
@@ -0,0 +1,26 @@
+import { UmbMediaTypeDetailRepository } from '../../repository/detail/media-type-detail.repository.js';
+import { UMB_MEDIA_TYPE_CREATE_OPTIONS_MODAL } from './modal/index.js';
+import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
+import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import { UmbModalManagerContext, UMB_MODAL_MANAGER_CONTEXT_TOKEN } from '@umbraco-cms/backoffice/modal';
+
+export class UmbCreateMediaTypeEntityAction extends UmbEntityActionBase {
+ #modalManagerContext?: UmbModalManagerContext;
+
+ constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
+ super(host, repositoryAlias, unique);
+
+ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
+ this.#modalManagerContext = instance;
+ });
+ }
+
+ async execute() {
+ if (!this.#modalManagerContext) throw new Error('Modal manager context is not available');
+ if (!this.repository) throw new Error('Repository is not available');
+
+ this.#modalManagerContext?.open(UMB_MEDIA_TYPE_CREATE_OPTIONS_MODAL, {
+ parentKey: this.unique,
+ });
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
new file mode 100644
index 0000000000..cb4410d7e5
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
@@ -0,0 +1,28 @@
+import { MEDIA_TYPE_ENTITY_TYPE, MEDIA_TYPE_FOLDER_ENTITY_TYPE, MEDIA_TYPE_ROOT_ENTITY_TYPE } from '../../index.js';
+import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UmbCreateMediaTypeEntityAction } from './create.action.js';
+import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
+
+const entityActions: Array = [
+ {
+ type: 'entityAction',
+ alias: 'Umb.EntityAction.MediaType.Create',
+ name: 'Create Media Type Entity Action',
+ weight: 1000,
+ api: UmbCreateMediaTypeEntityAction,
+ meta: {
+ icon: 'icon-add',
+ label: 'Create...',
+ repositoryAlias: MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ entityTypes: [MEDIA_TYPE_ENTITY_TYPE, MEDIA_TYPE_ROOT_ENTITY_TYPE, MEDIA_TYPE_FOLDER_ENTITY_TYPE],
+ },
+ },
+ {
+ type: 'modal',
+ alias: 'Umb.Modal.MediaTypeCreateOptions',
+ name: 'Media Type Create Options Modal',
+ loader: () => import('./modal/media-type-create-options-modal.element.js'),
+ },
+];
+
+export const manifests = [...entityActions];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/index.ts
new file mode 100644
index 0000000000..dcc72118a7
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/index.ts
@@ -0,0 +1,13 @@
+import { UmbModalToken } from '@umbraco-cms/backoffice/modal';
+
+export interface UmbMediaTypeCreateOptionsModalData {
+ parentKey: string | null;
+}
+
+export const UMB_MEDIA_TYPE_CREATE_OPTIONS_MODAL = new UmbModalToken(
+ 'Umb.Modal.MediaTypeCreateOptions',
+ {
+ type: 'sidebar',
+ size: 'small',
+ },
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts
new file mode 100644
index 0000000000..b7bb4b9865
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts
@@ -0,0 +1,76 @@
+import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../../repository/index.js';
+import { UmbMediaTypeCreateOptionsModalData } from './index.js';
+import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
+import {
+ UmbModalManagerContext,
+ UmbModalContext,
+ UMB_FOLDER_MODAL,
+ UMB_MODAL_MANAGER_CONTEXT_TOKEN,
+} from '@umbraco-cms/backoffice/modal';
+import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
+
+@customElement('umb-media-type-create-options-modal')
+export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement {
+ @property({ attribute: false })
+ modalContext?: UmbModalContext;
+
+ @property({ type: Object })
+ data?: UmbMediaTypeCreateOptionsModalData;
+
+ #modalContext?: UmbModalManagerContext;
+
+ constructor() {
+ super();
+ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => {
+ this.#modalContext = instance;
+ });
+ }
+
+ #onClick(event: PointerEvent) {
+ event.stopPropagation();
+ const folderModalHandler = this.#modalContext?.open(UMB_FOLDER_MODAL, {
+ repositoryAlias: MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ });
+ folderModalHandler?.onSubmit().then(() => this.modalContext?.submit());
+ }
+
+ // close the modal when navigating to data type
+ #onNavigate() {
+ this.modalContext?.submit();
+ }
+
+ #onCancel() {
+ this.modalContext?.reject();
+ }
+
+ render() {
+ return html`
+
+
+
+
+
+
+
+
+
+
+ Cancel
+
+ `;
+ }
+
+ static styles = [UmbTextStyles];
+}
+
+export default UmbDataTypeCreateOptionsModalElement;
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'umb-media-type-create-options-modal': UmbDataTypeCreateOptionsModalElement;
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts
index 0d68d6334b..f66e7b6d40 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts
@@ -1,6 +1,6 @@
import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../index.js';
-import { UmbCreateMediaTypeEntityAction } from './create.action.js';
-import UmbReloadMediaTypeEntityAction from './reload.action.js';
+import { UmbCreateMediaTypeEntityAction } from './create/create.action.js';
+import { manifests as createManifests } from './create/manifests.js';
import { UmbDeleteEntityAction, UmbMoveEntityAction, UmbCopyEntityAction } from '@umbraco-cms/backoffice/entity-action';
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
@@ -60,19 +60,6 @@ const entityActions: Array = [
entityTypes: [entityType],
},
},
- {
- type: 'entityAction',
- alias: 'Umb.EntityAction.MediaType.Reload',
- name: 'Reload Media Type Entity Action',
- weight: 100,
- api: UmbReloadMediaTypeEntityAction,
- meta: {
- icon: 'icon-refresh',
- label: 'Reload',
- repositoryAlias,
- entityTypes: [entityType],
- },
- },
];
-export const manifests = [...entityActions];
+export const manifests = [...entityActions, ...createManifests];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/reload.action.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/reload.action.ts
deleted file mode 100644
index 5fc349832a..0000000000
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/reload.action.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { UmbMediaTypeRepository } from '../repository/media-type.repository.js';
-import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
-import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
-
-export default class UmbReloadMediaTypeEntityAction extends UmbEntityActionBase {
- static styles = [UmbTextStyles];
-
- constructor(host: UmbControllerHostElement, repositoryAlias: string, unique: string) {
- super(host, repositoryAlias, unique);
- }
-
- async execute() {
- alert('refresh');
- }
-}
From 664837a59f5cbbace114a9c46ca2b9c5bd419271 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Thu, 16 Nov 2023 19:11:40 +1300
Subject: [PATCH 05/25] create route
---
.../workspace/media-type-workspace.element.ts | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.element.ts
index c5d3a1f6f9..6986325317 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.element.ts
@@ -4,6 +4,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
+import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-media-type-workspace')
export class UmbMediaTypeWorkspaceElement extends UmbLitElement {
@@ -12,6 +13,20 @@ export class UmbMediaTypeWorkspaceElement extends UmbLitElement {
@state()
_routes: UmbRoute[] = [
+ {
+ path: 'create/:parentId',
+ component: import('./media-type-workspace-editor.element.js'),
+ setup: (_component, info) => {
+ const parentId = info.match.params.parentId === 'null' ? null : info.match.params.parentId;
+ this.#workspaceContext.create(parentId);
+
+ new UmbWorkspaceIsNewRedirectController(
+ this,
+ this.#workspaceContext,
+ this.shadowRoot!.querySelector('umb-router-slot')!,
+ );
+ },
+ },
{
path: 'edit/:id',
component: () => this.#element,
From 12e28f4c1e093cae56ac0c88bf0b25dbd426b441 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 15:30:10 +1300
Subject: [PATCH 06/25] correct scaffolding icon
---
.../media-types/repository/detail/media-type.server.data.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts
index c54ad99532..4abebc0f57 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts
@@ -62,7 +62,7 @@ export class UmbMediaTypeServerDataSource
name: '',
alias: '',
description: '',
- icon: 'icon-media',
+ icon: 'icon-picture',
allowedAsRoot: false,
variesByCulture: false,
variesBySegment: false,
From dfe0f52965fa2a1809e6bd6c308351fb929b15c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 22:20:13 +1300
Subject: [PATCH 07/25] fix merge
---
.../entity-actions/create/manifests.ts | 10 +-
.../detail/media-type-detail.repository.ts | 11 +-
.../detail/media-type.server.data.ts | 147 ++++++++++++++++++
.../tree/media-type-tree.repository.ts | 4 +-
.../media/media-types/workspace/manifests.ts | 4 +-
.../workspace/media-type-workspace.context.ts | 16 +-
6 files changed, 166 insertions(+), 26 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
index cb4410d7e5..f8af53e68f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
@@ -1,4 +1,8 @@
-import { MEDIA_TYPE_ENTITY_TYPE, MEDIA_TYPE_FOLDER_ENTITY_TYPE, MEDIA_TYPE_ROOT_ENTITY_TYPE } from '../../index.js';
+import {
+ UMB_MEDIA_TYPE_ENTITY_TYPE,
+ MEDIA_TYPE_FOLDER_ENTITY_TYPE,
+ UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE,
+} from '../../index.js';
import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js';
import { UmbCreateMediaTypeEntityAction } from './create.action.js';
import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
@@ -14,14 +18,14 @@ const entityActions: Array = [
icon: 'icon-add',
label: 'Create...',
repositoryAlias: MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
- entityTypes: [MEDIA_TYPE_ENTITY_TYPE, MEDIA_TYPE_ROOT_ENTITY_TYPE, MEDIA_TYPE_FOLDER_ENTITY_TYPE],
+ entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE, UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE, MEDIA_TYPE_FOLDER_ENTITY_TYPE],
},
},
{
type: 'modal',
alias: 'Umb.Modal.MediaTypeCreateOptions',
name: 'Media Type Create Options Modal',
- loader: () => import('./modal/media-type-create-options-modal.element.js'),
+ js: () => import('./modal/media-type-create-options-modal.element.js'),
},
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
index 11f09fa0ed..987ad2957f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
@@ -76,7 +76,7 @@ export class UmbMediaTypeDetailRepository
if (!id) throw new Error('Id is missing');
await this.#init;
- const { data, error } = await this.#detailDataSource.get(id);
+ const { data, error } = await this.#detailDataSource.read(id);
if (data) {
this.#detailStore?.append(data);
@@ -91,20 +91,13 @@ export class UmbMediaTypeDetailRepository
return this.#detailStore!.byId(id);
}
- // TODO: we need to figure out where to put this
- async requestAllowedChildTypesOf(id: string) {
- if (!id) throw new Error('Id is missing');
- await this.#init;
- return this.#detailDataSource.getAllowedChildrenOf(id);
- }
-
// Could potentially be general methods:
async create(mediaType: ItemType) {
if (!mediaType || !mediaType.id) throw new Error('Media Type is missing');
await this.#init;
- const { error } = await this.#detailDataSource.insert(mediaType);
+ const { error } = await this.#detailDataSource.create(mediaType);
if (!error) {
this.#detailStore?.append(mediaType);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts
new file mode 100644
index 0000000000..0e4d12fe2c
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts
@@ -0,0 +1,147 @@
+import type { UmbDataSource } from '@umbraco-cms/backoffice/repository';
+import {
+ CreateMediaTypeRequestModel,
+ MediaTypeResource,
+ MediaTypeResponseModel,
+ UpdateMediaTypeRequestModel,
+} from '@umbraco-cms/backoffice/backend-api';
+import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
+import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources';
+import { UmbId } from '@umbraco-cms/backoffice/id';
+
+/**
+ * A data source for the Media Type that fetches data from the server
+ * @export
+ * @class UmbMediaTypeServerDataSource
+ * @implements {RepositoryDetailDataSource}
+ */
+export class UmbMediaTypeServerDataSource
+ implements UmbDataSource
+{
+ #host: UmbControllerHost;
+
+ /**
+ * Creates an instance of UmbMediaServerDataSource.
+ * @param {UmbControllerHost} host
+ * @memberof UmbMediaServerDataSource
+ */
+ constructor(host: UmbControllerHost) {
+ this.#host = host;
+ }
+
+ /**
+ * Fetches a Media with the given id from the server
+ * @param {string} id
+ * @return {*}
+ * @memberof UmbMediaTypeServerDataSource
+ */
+ async read(id: string) {
+ if (!id) {
+ throw new Error('Id is missing');
+ }
+
+ return tryExecuteAndNotify(
+ this.#host,
+ MediaTypeResource.getMediaTypeById({
+ id: id,
+ }),
+ );
+ }
+
+ /**
+ * Creates a new Media scaffold
+ * @param {(string | null)} parentId
+ * @return {*}
+ * @memberof UmbMediaTypeServerDataSource
+ */
+ async createScaffold(parentId: string | null) {
+ //, parentId: string | null
+ const data: MediaTypeResponseModel = {
+ id: UmbId.new(),
+ //parentId: parentId,
+ name: '',
+ alias: '',
+ description: '',
+ icon: 'icon-picture',
+ allowedAsRoot: false,
+ variesByCulture: false,
+ variesBySegment: false,
+ isElement: false,
+ allowedContentTypes: [],
+ compositions: [],
+ properties: [],
+ containers: [],
+ };
+
+ return { data };
+ }
+
+ /**
+ * Creates a new Media Type on the server
+ * @param {CreateMediaTypeRequestModel} mediaType
+ * @return {*}
+ * @memberof UmbMediaTypeServerDataSource
+ */
+ async create(mediaType: CreateMediaTypeRequestModel) {
+ if (!mediaType) throw new Error('Media Type is missing');
+ return tryExecuteAndNotify(
+ this.#host,
+ MediaTypeResource.postMediaType({
+ requestBody: mediaType,
+ }),
+ );
+ }
+
+ /**
+ * Updates a Media Type on the server
+ * @param {string} id
+ * @param {Media} mediaType
+ * @return {*}
+ * @memberof UmbMediaTypeServerDataSource
+ */
+ async update(id: string, mediaType: UpdateMediaTypeRequestModel) {
+ if (!id) throw new Error('Id is missing');
+
+ mediaType = { ...mediaType };
+
+ // TODO: Hack to remove some props that ruins the media-type post end-point.
+ (mediaType as any).id = undefined;
+
+ return tryExecuteAndNotify(this.#host, MediaTypeResource.putMediaTypeById({ id, requestBody: mediaType }));
+ }
+
+ /**
+ * Deletes a Template on the server
+ * @param {string} id
+ * @return {*}
+ * @memberof UmbMediaTypeServerDataSource
+ */
+ async delete(id: string) {
+ if (!id) {
+ throw new Error('Id is missing');
+ }
+
+ // TODO: Hack the type to avoid type-error here:
+ return tryExecuteAndNotify(this.#host, MediaTypeResource.deleteMediaTypeById({ id })) as any;
+ }
+
+ /**
+ * Get the allowed media types for a given parent id
+ * @param {string} id
+ * @return {*}
+ * @memberof UmbMediaTypeServerDataSource
+ */
+ async getAllowedChildrenOf(id: string) {
+ if (!id) throw new Error('Id is missing');
+
+ return tryExecuteAndNotify(
+ this.#host,
+ fetch(`/umbraco/management/api/v1/media-type/allowed-children-of/${id}`, {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ }).then((res) => res.json()),
+ );
+ }
+}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts
index 8096edbcf6..68258e60f7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts
@@ -1,4 +1,4 @@
-import { MEDIA_TYPE_ROOT_ENTITY_TYPE } from '../index.js';
+import { UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE } from '../index.js';
import { UmbMediaTypeTreeServerDataSource } from './media-type.tree.server.data-source.js';
import { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT } from './media-type.tree.store.js';
import { UmbMediaTypeTreeItemModel, UmbMediaTypeTreeRootModel } from './types.js';
@@ -17,7 +17,7 @@ export class UmbMediaTypeTreeRepository
async requestTreeRoot() {
const data = {
id: null,
- type: MEDIA_TYPE_ROOT_ENTITY_TYPE,
+ type: UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE,
name: 'Media Types',
icon: 'icon-folder',
hasChildren: true,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts
index f4533f6825..729234545a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts
@@ -22,7 +22,7 @@ const workspaceEditorViews: Array = [
type: 'workspaceEditorView',
alias: 'Umb.WorkspaceView.MediaType.Design',
name: 'Media Type Workspace Design View',
- loader: () => import('./views/design/media-type-workspace-view-edit.element.js'),
+ js: () => import('./views/design/media-type-workspace-view-edit.element.js'),
weight: 1000,
meta: {
label: 'Design',
@@ -40,7 +40,7 @@ const workspaceEditorViews: Array = [
type: 'workspaceEditorView',
alias: 'Umb.WorkspaceView.MediaType.Structure',
name: 'Media Type Workspace Structure View',
- loader: () => import('./views/structure/media-type-workspace-view-structure.element.js'),
+ js: () => import('./views/structure/media-type-workspace-view-structure.element.js'),
weight: 800,
meta: {
label: 'Structure',
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
index 253f4b18a2..650b0eb401 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
@@ -1,21 +1,17 @@
-import { UmbMediaTypeRepository } from '../repository/media-type.repository.js';
-import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
import { UmbMediaTypeDetailRepository } from '../repository/detail/media-type-detail.repository.js';
+import {
+ UmbSaveableWorkspaceContextInterface,
+ UmbEditableWorkspaceContextBase,
+} from '@umbraco-cms/backoffice/workspace';
import { UmbContentTypePropertyStructureManager } from '@umbraco-cms/backoffice/content-type';
-import { UmbWorkspaceContext, UmbSaveableWorkspaceContextInterface } from '@umbraco-cms/backoffice/workspace';
-import type {
- ContentTypeCompositionModel,
- ContentTypeSortModel,
- MediaTypeResponseModel,
-} from '@umbraco-cms/backoffice/backend-api';
+import { type MediaTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api';
type EntityType = MediaTypeResponseModel;
export class UmbMediaTypeWorkspaceContext
- extends UmbEditableWorkspaceContextBase
- extends UmbWorkspaceContext
+ extends UmbEditableWorkspaceContextBase
implements UmbSaveableWorkspaceContextInterface
{
// Draft is located in structure manager
From e42818f8ea3a13c8dfc25136caebf9de77c2671f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 22:21:09 +1300
Subject: [PATCH 08/25] reanme
---
.../media/media-types/entity-actions/create/manifests.ts | 4 ++--
.../src/packages/media/media-types/index.ts | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
index f8af53e68f..133fee928d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
@@ -1,6 +1,6 @@
import {
UMB_MEDIA_TYPE_ENTITY_TYPE,
- MEDIA_TYPE_FOLDER_ENTITY_TYPE,
+ UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE,
UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE,
} from '../../index.js';
import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js';
@@ -18,7 +18,7 @@ const entityActions: Array = [
icon: 'icon-add',
label: 'Create...',
repositoryAlias: MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
- entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE, UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE, MEDIA_TYPE_FOLDER_ENTITY_TYPE],
+ entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE, UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE, UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE],
},
},
{
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts
index 97f2c76252..44a4d20d5a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts
@@ -2,6 +2,6 @@ import './components/index.js';
export * from './repository/index.js';
-export const MEDIA_TYPE_ROOT_ENTITY_TYPE = 'media-type-root';
-export const MEDIA_TYPE_ENTITY_TYPE = 'media-type';
-export const MEDIA_TYPE_FOLDER_ENTITY_TYPE = 'media-type-folder';
+export const UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE = 'media-type-root';
+export const UMB_MEDIA_TYPE_ENTITY_TYPE = 'media-type';
+export const UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE = 'media-type-folder';
From 047062528637b79aec4901105e58a1113ae90bba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 22:22:07 +1300
Subject: [PATCH 09/25] lint happy
---
.../media/media-types/menu-item/manifests.ts | 4 ++--
.../media/media-types/repository/detail/index.ts | 5 ++++-
.../media-types/repository/detail/manifests.ts | 8 ++++----
.../media/media-types/repository/item/index.ts | 5 ++++-
.../media/media-types/repository/item/manifests.ts | 8 ++++----
.../packages/media/media-types/tree/manifests.ts | 14 +++++++-------
6 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu-item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu-item/manifests.ts
index 0213b79f29..4e0f69b5f5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu-item/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/menu-item/manifests.ts
@@ -1,4 +1,4 @@
-import { MEDIA_TYPE_TREE_ALIAS } from '../tree/manifests.js';
+import { UMB_MEDIA_TYPE_TREE_ALIAS } from '../tree/manifests.js';
import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
const menuItem: ManifestTypes = {
@@ -10,7 +10,7 @@ const menuItem: ManifestTypes = {
meta: {
label: 'Media Types',
icon: 'icon-folder',
- treeAlias: MEDIA_TYPE_TREE_ALIAS,
+ treeAlias: UMB_MEDIA_TYPE_TREE_ALIAS,
menus: ['Umb.Menu.Settings'],
},
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts
index 50410ebfa6..16fd2692c6 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts
@@ -1,3 +1,6 @@
export { UmbMediaTypeDetailRepository } from './media-type-detail.repository.js';
-export { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS, MEDIA_TYPE_DETAIL_STORE_ALIAS } from './manifests.js';
+export {
+ UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS as MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ UMB_MEDIA_TYPE_DETAIL_STORE_ALIAS as MEDIA_TYPE_DETAIL_STORE_ALIAS,
+} from './manifests.js';
export { UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT } from './media-type-detail.store.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/manifests.ts
index 386a16c384..614536af72 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/manifests.ts
@@ -2,19 +2,19 @@ import { UmbMediaTypeDetailRepository } from './media-type-detail.repository.js'
import { UmbMediaTypeDetailStore } from './media-type-detail.store.js';
import { ManifestRepository, ManifestStore } from '@umbraco-cms/backoffice/extension-registry';
-export const MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Detail';
-export const MEDIA_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.MediaType.Detail';
+export const UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Detail';
+export const UMB_MEDIA_TYPE_DETAIL_STORE_ALIAS = 'Umb.Store.MediaType.Detail';
const detailRepository: ManifestRepository = {
type: 'repository',
- alias: MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ alias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
name: 'Media Types Repository',
api: UmbMediaTypeDetailRepository,
};
const detailStore: ManifestStore = {
type: 'store',
- alias: MEDIA_TYPE_DETAIL_STORE_ALIAS,
+ alias: UMB_MEDIA_TYPE_DETAIL_STORE_ALIAS,
name: 'Media Type Store',
api: UmbMediaTypeDetailStore,
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts
index eb23683fec..2277e6c66b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts
@@ -1,3 +1,6 @@
export { UmbMediaTypeItemRepository } from './media-type-item.repository.js';
-export { MEDIA_TYPE_ITEM_REPOSITORY_ALIAS, MEDIA_TYPE_ITEM_STORE_ALIAS } from './manifests.js';
+export {
+ UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS as MEDIA_TYPE_ITEM_REPOSITORY_ALIAS,
+ UMB_MEDIA_TYPE_ITEM_STORE_ALIAS as MEDIA_TYPE_ITEM_STORE_ALIAS,
+} from './manifests.js';
export * from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/manifests.ts
index 0793bcbf34..f267e9e3db 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/manifests.ts
@@ -2,19 +2,19 @@ import { UmbMediaTypeItemRepository } from './media-type-item.repository.js';
import { UmbMediaTypeItemStore } from './media-type-item.store.js';
import { ManifestItemStore, ManifestRepository } from '@umbraco-cms/backoffice/extension-registry';
-export const MEDIA_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Item';
-export const MEDIA_TYPE_ITEM_STORE_ALIAS = 'Umb.Store.MediaType.Item';
+export const UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Item';
+export const UMB_MEDIA_TYPE_ITEM_STORE_ALIAS = 'Umb.Store.MediaType.Item';
const itemRepository: ManifestRepository = {
type: 'repository',
- alias: MEDIA_TYPE_ITEM_REPOSITORY_ALIAS,
+ alias: UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS,
name: 'Media Type Item Repository',
api: UmbMediaTypeItemRepository,
};
const itemStore: ManifestItemStore = {
type: 'itemStore',
- alias: MEDIA_TYPE_ITEM_STORE_ALIAS,
+ alias: UMB_MEDIA_TYPE_ITEM_STORE_ALIAS,
name: 'Media Type Item Store',
api: UmbMediaTypeItemStore,
};
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts
index bbde15f412..fba8faea74 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts
@@ -7,30 +7,30 @@ import type {
ManifestTreeStore,
} from '@umbraco-cms/backoffice/extension-registry';
-export const MEDIA_TYPE_TREE_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Tree';
-export const MEDIA_TYPE_TREE_STORE_ALIAS = 'Umb.Store.MediaType.Tree';
-export const MEDIA_TYPE_TREE_ALIAS = 'Umb.Tree.MediaType';
+export const UMB_MEDIA_TYPE_TREE_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Tree';
+export const UMB_MEDIA_TYPE_TREE_STORE_ALIAS = 'Umb.Store.MediaType.Tree';
+export const UMB_MEDIA_TYPE_TREE_ALIAS = 'Umb.Tree.MediaType';
const treeRepository: ManifestRepository = {
type: 'repository',
- alias: MEDIA_TYPE_TREE_REPOSITORY_ALIAS,
+ alias: UMB_MEDIA_TYPE_TREE_REPOSITORY_ALIAS,
name: 'Media Type Tree Repository',
api: UmbMediaTypeTreeRepository,
};
const treeStore: ManifestTreeStore = {
type: 'treeStore',
- alias: MEDIA_TYPE_TREE_STORE_ALIAS,
+ alias: UMB_MEDIA_TYPE_TREE_STORE_ALIAS,
name: 'Media Type Tree Store',
api: UmbMediaTypeTreeStore,
};
const tree: ManifestTree = {
type: 'tree',
- alias: MEDIA_TYPE_TREE_ALIAS,
+ alias: UMB_MEDIA_TYPE_TREE_ALIAS,
name: 'Media Type Tree',
meta: {
- repositoryAlias: MEDIA_TYPE_TREE_REPOSITORY_ALIAS,
+ repositoryAlias: UMB_MEDIA_TYPE_TREE_REPOSITORY_ALIAS,
},
};
From 70c768175e03545df140f9df5067cc8715b2fb16 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 22:44:34 +1300
Subject: [PATCH 10/25] fix exports and types and naming
---
.../src/packages/media/media-types/entity.ts | 3 +++
.../src/packages/media/media-types/index.ts | 15 +++++++++++----
.../media/media-types/repository/detail/index.ts | 5 +----
.../detail/media-type-detail.repository.ts | 4 ++--
...ts => media-type-detail.server.data-source.ts} | 0
.../media/media-types/repository/detail/types.ts | 4 ++++
.../media/media-types/repository/item/index.ts | 8 +++-----
.../src/packages/media/media-types/tree/index.ts | 10 ++++++++++
.../packages/media/media-types/tree/manifests.ts | 2 +-
.../tree/media-type-tree.repository.ts | 4 ++--
...e.ts => media-type-tree.server.data-source.ts} | 0
...ype.tree.store.ts => media-type-tree.store.ts} | 0
.../workspace/media-type-workspace.context.ts | 5 +++--
13 files changed, 40 insertions(+), 20 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity.ts
rename src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/{media-type.server.data.ts => media-type-detail.server.data-source.ts} (100%)
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/types.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts
rename src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/{media-type.tree.server.data-source.ts => media-type-tree.server.data-source.ts} (100%)
rename src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/{media-type.tree.store.ts => media-type-tree.store.ts} (100%)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity.ts
new file mode 100644
index 0000000000..fdae21ac4a
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity.ts
@@ -0,0 +1,3 @@
+export const UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE = 'media-type-root';
+export const UMB_MEDIA_TYPE_ENTITY_TYPE = 'media-type';
+export const UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE = 'media-type-folder';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts
index 44a4d20d5a..8cf991d68a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts
@@ -1,7 +1,14 @@
import './components/index.js';
-export * from './repository/index.js';
+export {
+ UmbMediaTypeItemRepository,
+ UMB_MEDIA_TYPE_ITEM_STORE_ALIAS,
+ UMB_MEDIA_TYPE_DETAIL_STORE_ALIAS,
+ UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT,
+} from './repository/index.js';
-export const UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE = 'media-type-root';
-export const UMB_MEDIA_TYPE_ENTITY_TYPE = 'media-type';
-export const UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE = 'media-type-folder';
+export {
+ UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE,
+ UMB_MEDIA_TYPE_ENTITY_TYPE,
+ UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE,
+} from './entity.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts
index 16fd2692c6..6b844c13ad 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/index.ts
@@ -1,6 +1,3 @@
export { UmbMediaTypeDetailRepository } from './media-type-detail.repository.js';
-export {
- UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS as MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
- UMB_MEDIA_TYPE_DETAIL_STORE_ALIAS as MEDIA_TYPE_DETAIL_STORE_ALIAS,
-} from './manifests.js';
+export { UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS, UMB_MEDIA_TYPE_DETAIL_STORE_ALIAS } from './manifests.js';
export { UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT } from './media-type-detail.store.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
index 987ad2957f..8ca70c649f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
@@ -1,6 +1,6 @@
-import { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT, UmbMediaTypeTreeStore } from '../../tree/media-type.tree.store.js';
+import { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT, UmbMediaTypeTreeStore } from '../../tree/media-type-tree.store.js';
import { UMB_MEDIA_TYPE_ITEM_STORE_CONTEXT, UmbMediaTypeItemStore } from '../item/media-type-item.store.js';
-import { UmbMediaTypeServerDataSource } from './media-type.server.data.js';
+import { UmbMediaTypeServerDataSource } from './media-type-detail.server.data-source.js';
import { UmbMediaTypeDetailStore, UMB_MEDIA_TYPE_DETAIL_STORE_CONTEXT } from './media-type-detail.store.js';
import { type UmbDetailRepository } from '@umbraco-cms/backoffice/repository';
import { UmbBaseController, type UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type.server.data.ts
rename to src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.server.data-source.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/types.ts
new file mode 100644
index 0000000000..e461548b00
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/types.ts
@@ -0,0 +1,4 @@
+import { UMB_MEDIA_TYPE_ENTITY_TYPE } from '../../entity.js';
+import { MediaTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
+
+export type UmbMediaTypeDetailModel = MediaTypeResponseModel & { entityType: typeof UMB_MEDIA_TYPE_ENTITY_TYPE };
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts
index 2277e6c66b..48354e1b73 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/index.ts
@@ -1,6 +1,4 @@
export { UmbMediaTypeItemRepository } from './media-type-item.repository.js';
-export {
- UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS as MEDIA_TYPE_ITEM_REPOSITORY_ALIAS,
- UMB_MEDIA_TYPE_ITEM_STORE_ALIAS as MEDIA_TYPE_ITEM_STORE_ALIAS,
-} from './manifests.js';
-export * from './types.js';
+export { UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS, UMB_MEDIA_TYPE_ITEM_STORE_ALIAS } from './manifests.js';
+export { UMB_MEDIA_TYPE_ITEM_STORE_CONTEXT } from './media-type-item.store.js';
+export type { UmbMediaTypeItemModel } from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts
new file mode 100644
index 0000000000..c1e6582874
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/index.ts
@@ -0,0 +1,10 @@
+export {
+ UMB_MEDIA_TYPE_TREE_ALIAS,
+ UMB_MEDIA_TYPE_TREE_STORE_ALIAS,
+ UMB_MEDIA_TYPE_TREE_REPOSITORY_ALIAS,
+} from './manifests.js';
+
+export { UmbMediaTypeTreeRepository } from './media-type-tree.repository.js';
+export { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT } from './media-type-tree.store.js';
+
+export type { UmbMediaTypeTreeItemModel, UmbMediaTypeTreeRootModel } from './types.js';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts
index fba8faea74..03cbfddbcf 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/manifests.ts
@@ -1,5 +1,5 @@
import { UmbMediaTypeTreeRepository } from './media-type-tree.repository.js';
-import { UmbMediaTypeTreeStore } from './media-type.tree.store.js';
+import { UmbMediaTypeTreeStore } from './media-type-tree.store.js';
import type {
ManifestRepository,
ManifestTree,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts
index 68258e60f7..125d2ef283 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.repository.ts
@@ -1,6 +1,6 @@
import { UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE } from '../index.js';
-import { UmbMediaTypeTreeServerDataSource } from './media-type.tree.server.data-source.js';
-import { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT } from './media-type.tree.store.js';
+import { UmbMediaTypeTreeServerDataSource } from './media-type-tree.server.data-source.js';
+import { UMB_MEDIA_TYPE_TREE_STORE_CONTEXT } from './media-type-tree.store.js';
import { UmbMediaTypeTreeItemModel, UmbMediaTypeTreeRootModel } from './types.js';
import { UmbTreeRepositoryBase } from '@umbraco-cms/backoffice/tree';
import { type UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type.tree.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.server.data-source.ts
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type.tree.server.data-source.ts
rename to src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.server.data-source.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type.tree.store.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.store.ts
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type.tree.store.ts
rename to src/Umbraco.Web.UI.Client/src/packages/media/media-types/tree/media-type-tree.store.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
index 650b0eb401..1a7272354c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
@@ -1,4 +1,5 @@
import { UmbMediaTypeDetailRepository } from '../repository/detail/media-type-detail.repository.js';
+import { UMB_MEDIA_TYPE_ENTITY_TYPE } from '../index.js';
import {
UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
@@ -65,7 +66,7 @@ export class UmbMediaTypeWorkspaceContext
}
getEntityType() {
- return 'media-type';
+ return UMB_MEDIA_TYPE_ENTITY_TYPE;
}
updateProperty(propertyName: PropertyName, value: EntityType[PropertyName]) {
@@ -120,5 +121,5 @@ export const UMB_MEDIA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMediaTypeWorkspaceContext
>(
'UmbWorkspaceContext',
- (context): context is UmbMediaTypeWorkspaceContext => context.getEntityType?.() === 'media-type',
+ (context): context is UmbMediaTypeWorkspaceContext => context.getEntityType?.() === UMB_MEDIA_TYPE_ENTITY_TYPE,
);
From 55ebdca0d1d2789bf918edda976f66a57a000405 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 22:49:20 +1300
Subject: [PATCH 11/25] fix imports
---
.../media-type-input.context.ts | 4 ++--
.../entity-actions/create/manifests.ts | 4 ++--
...media-type-create-options-modal.element.ts | 4 ++--
.../media-types/entity-actions/manifests.ts | 22 +++++++++----------
.../item/media-type-item.repository.ts | 2 +-
... => media-type-item.server.data-source.ts} | 0
6 files changed, 17 insertions(+), 19 deletions(-)
rename src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/{media-type-item.server.data.ts => media-type-item.server.data-source.ts} (100%)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/media-type-input/media-type-input.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/media-type-input/media-type-input.context.ts
index 2642d93198..473677c56a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/media-type-input/media-type-input.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/media-type-input/media-type-input.context.ts
@@ -1,4 +1,4 @@
-import { MEDIA_TYPE_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS } from '../../repository/index.js';
import { UmbPickerInputContext } from '@umbraco-cms/backoffice/picker-input';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UMB_MEDIA_TYPE_PICKER_MODAL } from '@umbraco-cms/backoffice/modal';
@@ -6,6 +6,6 @@ import { MediaTypeItemResponseModel } from '@umbraco-cms/backoffice/backend-api'
export class UmbMediaTypePickerContext extends UmbPickerInputContext {
constructor(host: UmbControllerHostElement) {
- super(host, MEDIA_TYPE_ITEM_REPOSITORY_ALIAS, UMB_MEDIA_TYPE_PICKER_MODAL);
+ super(host, UMB_MEDIA_TYPE_ITEM_REPOSITORY_ALIAS, UMB_MEDIA_TYPE_PICKER_MODAL);
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
index 133fee928d..e1195739df 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/manifests.ts
@@ -3,7 +3,7 @@ import {
UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE,
UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE,
} from '../../index.js';
-import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js';
+import { UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../repository/index.js';
import { UmbCreateMediaTypeEntityAction } from './create.action.js';
import { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry';
@@ -17,7 +17,7 @@ const entityActions: Array = [
meta: {
icon: 'icon-add',
label: 'Create...',
- repositoryAlias: MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ repositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE, UMB_MEDIA_TYPE_ROOT_ENTITY_TYPE, UMB_MEDIA_TYPE_FOLDER_ENTITY_TYPE],
},
},
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts
index b7bb4b9865..2f7a4cf080 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/create/modal/media-type-create-options-modal.element.ts
@@ -1,4 +1,4 @@
-import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../../repository/index.js';
+import { UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../../../repository/index.js';
import { UmbMediaTypeCreateOptionsModalData } from './index.js';
import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
@@ -30,7 +30,7 @@ export class UmbDataTypeCreateOptionsModalElement extends UmbLitElement {
#onClick(event: PointerEvent) {
event.stopPropagation();
const folderModalHandler = this.#modalContext?.open(UMB_FOLDER_MODAL, {
- repositoryAlias: MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ repositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
});
folderModalHandler?.onSubmit().then(() => this.modalContext?.submit());
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts
index f66e7b6d40..9916090b2e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/entity-actions/manifests.ts
@@ -1,12 +1,10 @@
-import { MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../index.js';
+import { UMB_MEDIA_TYPE_ENTITY_TYPE } from '../entity.js';
+import { UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS } from '../repository/index.js';
import { UmbCreateMediaTypeEntityAction } from './create/create.action.js';
import { manifests as createManifests } from './create/manifests.js';
import { UmbDeleteEntityAction, UmbMoveEntityAction, UmbCopyEntityAction } from '@umbraco-cms/backoffice/entity-action';
import type { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry';
-const entityType = 'media-type';
-const repositoryAlias = MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS;
-
const entityActions: Array = [
{
type: 'entityAction',
@@ -17,8 +15,8 @@ const entityActions: Array = [
meta: {
icon: 'icon-add',
label: 'Create',
- repositoryAlias,
- entityTypes: [entityType],
+ repositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE],
},
},
{
@@ -30,8 +28,8 @@ const entityActions: Array = [
meta: {
icon: 'icon-enter',
label: 'Move',
- repositoryAlias,
- entityTypes: [entityType],
+ repositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE],
},
},
{
@@ -43,8 +41,8 @@ const entityActions: Array = [
meta: {
icon: 'icon-documents',
label: 'Copy',
- repositoryAlias,
- entityTypes: [entityType],
+ repositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE],
},
},
{
@@ -56,8 +54,8 @@ const entityActions: Array = [
meta: {
icon: 'icon-trash',
label: 'Delete',
- repositoryAlias,
- entityTypes: [entityType],
+ repositoryAlias: UMB_MEDIA_TYPE_DETAIL_REPOSITORY_ALIAS,
+ entityTypes: [UMB_MEDIA_TYPE_ENTITY_TYPE],
},
},
];
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.repository.ts
index 06fe6fc814..8eec8ef031 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.repository.ts
@@ -1,5 +1,5 @@
import { UmbMediaTypeItemModel } from './types.js';
-import { UmbMediaTypeItemServerDataSource } from './media-type-item.server.data.js';
+import { UmbMediaTypeItemServerDataSource } from './media-type-item.server.data-source.js';
import { UMB_MEDIA_TYPE_ITEM_STORE_CONTEXT } from './media-type-item.store.js';
import { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
import { UmbItemRepositoryBase } from '@umbraco-cms/backoffice/repository';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.server.data.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.server.data-source.ts
similarity index 100%
rename from src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.server.data.ts
rename to src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/item/media-type-item.server.data-source.ts
From 695b2caeceba0710bc376083790ea7bcca900daa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 22:53:46 +1300
Subject: [PATCH 12/25] update detail store
---
.../repository/detail/media-type-detail.repository.ts | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
index 8ca70c649f..49ae8eb686 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
@@ -102,7 +102,10 @@ export class UmbMediaTypeDetailRepository
if (!error) {
this.#detailStore?.append(mediaType);
const treeItem = createTreeItem(mediaType);
- this.#treeStore?.appendItems([treeItem]);
+ this.#treeStore?.append(treeItem);
+
+ const notification = { data: { message: `Media Type created` } };
+ this.#notificationContext?.peek('positive', notification);
}
return { error };
@@ -120,9 +123,9 @@ export class UmbMediaTypeDetailRepository
// TODO: we currently don't use the detail store for anything.
// Consider to look up the data before fetching from the server
// Consider notify a workspace if a template is updated in the store while someone is editing it.
- this.#detailStore?.append(item);
+ this.#detailStore?.updateItem(id, item);
this.#treeStore?.updateItem(id, item);
- // TODO: would be nice to align the stores on methods/methodNames.
+ this.#itemStore?.updateItem(id, item);
const notification = { data: { message: `Media Type saved` } };
this.#notificationContext?.peek('positive', notification);
From d596da66eb950643cf39edd7b1f411a9a1badf9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jesper=20M=C3=B8ller=20Jensen?=
<26099018+JesmoDev@users.noreply.github.com>
Date: Mon, 20 Nov 2023 23:00:16 +1300
Subject: [PATCH 13/25] add notification
---
.../repository/detail/media-type-detail.repository.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
index 49ae8eb686..b01d10316f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/detail/media-type-detail.repository.ts
@@ -142,9 +142,6 @@ export class UmbMediaTypeDetailRepository
const { error } = await this.#detailDataSource.delete(id);
if (!error) {
- const notification = { data: { message: `Media Type deleted` } };
- this.#notificationContext?.peek('positive', notification);
-
// TODO: we currently don't use the detail store for anything.
// Consider to look up the data before fetching from the server.
// Consider notify a workspace if a template is deleted from the store while someone is editing it.
@@ -152,6 +149,9 @@ export class UmbMediaTypeDetailRepository
this.#detailStore?.removeItem(id);
this.#treeStore?.removeItem(id);
this.#itemStore?.removeItem(id);
+
+ const notification = { data: { message: `Media Type deleted` } };
+ this.#notificationContext?.peek('positive', notification);
}
return { error };
From 87960cdd5b4be71d6d3796897fb6305309a2b0f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 11:02:00 +0100
Subject: [PATCH 14/25] make a context alias and api alias
---
.../context-api/consume/context-consumer.ts | 23 ++++++++----
.../consume/context-request.event.ts | 8 ++---
.../context-api/provide/context-provider.ts | 13 ++++---
.../libs/context-api/token/context-token.ts | 35 +++++++++++++------
4 files changed, 53 insertions(+), 26 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts
index 777032acb1..4dff7b2a13 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.ts
@@ -22,29 +22,32 @@ export class UmbContextConsumer;
/**
* Creates an instance of UmbContextConsumer.
* @param {EventTarget} hostElement
- * @param {string} contextAlias
+ * @param {string} contextIdentifier
* @param {UmbContextCallback} callback
* @memberof UmbContextConsumer
*/
constructor(
protected hostElement: EventTarget,
- contextAlias: string | UmbContextToken,
+ contextIdentifier: string | UmbContextToken,
callback?: UmbContextCallback,
) {
- this.#contextAlias = contextAlias.toString();
+ const idSplit = contextIdentifier.toString().split('#');
+ this.#contextAlias = idSplit[0];
+ this.#apiAlias = idSplit[1] ?? 'default';
this.#callback = callback;
- this.#discriminator = (contextAlias as UmbContextToken).getDiscriminator?.();
+ this.#discriminator = (contextIdentifier as UmbContextToken).getDiscriminator?.();
}
protected _onResponse = (instance: BaseType): boolean => {
if (this.#instance === instance) {
- return false;
+ return true;
}
if (this.#discriminator) {
// Notice if discriminator returns false, we do not want to setInstance.
@@ -68,6 +71,11 @@ export class UmbContextConsumer = (instance: T) => void;
* @interface UmbContextRequestEvent
*/
export interface UmbContextRequestEvent extends Event {
- readonly contextAlias: string | UmbContextToken;
+ readonly contextAlias: string;
+ readonly apiAlias: string;
readonly callback: (context: ResultType) => boolean;
}
@@ -25,7 +24,8 @@ export class UmbContextRequestEventImplementation
implements UmbContextRequestEvent
{
public constructor(
- public readonly contextAlias: string | UmbContextToken,
+ public readonly contextAlias: string,
+ public readonly apiAlias: string,
public readonly callback: (context: ResultType) => boolean,
) {
super(UMB_CONTENT_REQUEST_EVENT_TYPE, { bubbles: true, composed: true, cancelable: true });
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts
index 74a9f62e5f..4cd04706de 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.ts
@@ -17,6 +17,7 @@ export class UmbContextProvider,
+ contextIdentifier: string | UmbContextToken,
instance: ResultType,
) {
this.hostElement = hostElement;
- this._contextAlias = contextAlias.toString();
+
+ const idSplit = contextIdentifier.toString().split('#');
+ this._contextAlias = idSplit[0];
+ this._apiAlias = idSplit[1] ?? 'default';
this.#instance = instance;
}
@@ -56,7 +60,8 @@ export class UmbContextProvider = (
+ instance: BaseType,
+) => instance is DiscriminatorResult;
-export type UmbContextDiscriminator = (instance: BaseType) => instance is DiscriminatorResult;
-
-export class UmbContextToken<
-BaseType = unknown,
-ResultType extends BaseType = BaseType> {
-
+/**
+ * @export
+ * @class UmbContextToken
+ * @template BaseType - A generic type of the API before decimated.
+ * @template ResultType - A concrete type of the API after decimation, use this when you apply a discriminator method. Note this is optional and defaults to the BaseType.
+ */
+export class UmbContextToken {
#discriminator: UmbContextDiscriminator | undefined;
/**
* Get the type of the token
@@ -18,12 +22,23 @@ ResultType extends BaseType = BaseType> {
readonly TYPE: ResultType = undefined as never;
/**
- * @param alias Unique identifier for the token
+ * @param contextAlias Unique identifier for the context
+ * @param apiAlias Unique identifier for the api
+ * @param discriminator A discriminator that will be used to discriminate the API — testing if the API lives up to a certain requirement. If the API does not meet the requirement then the consumer will not receive this API.
*/
- constructor(protected alias: string, discriminator?: UmbContextDiscriminator) {
+ constructor(
+ protected contextAlias: string,
+ protected apiAlias: string = 'default',
+ discriminator?: UmbContextDiscriminator,
+ ) {
this.#discriminator = discriminator;
}
+ /**
+ * Get the discriminator method for the token
+ *
+ * @returns the discriminator method
+ */
getDiscriminator(): UmbContextDiscriminator | undefined {
return this.#discriminator;
}
@@ -35,8 +50,6 @@ ResultType extends BaseType = BaseType> {
* @returns the unique alias of the token
*/
toString(): string {
- return this.alias;
+ return this.contextAlias + '#' + this.apiAlias;
}
-
-
}
From e7dd75978f6cfe019b5eb2cc66884ae4d21afb93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 11:02:04 +0100
Subject: [PATCH 15/25] implement
---
.../data-type-variant-context.token.ts | 14 +++++++++-----
.../workspace/data-type-workspace.context.ts | 1 +
.../nameable-variant-context.token.ts | 15 +++++++++------
.../variant-context/variant-context.token.ts | 6 +++---
.../variant-workspace-context.token.ts | 6 +++++-
.../workspace/dictionary-workspace.context.ts | 6 +++++-
.../workspace/document-type-workspace.context.ts | 1 +
.../document-variant-context.token.ts | 1 +
.../workspace/document-workspace.context.ts | 2 +-
.../workspace/media-type-workspace.context.ts | 6 +++++-
.../media/workspace/media-workspace.context.ts | 6 +++++-
.../workspace/member-group-workspace.context.ts | 1 +
.../workspace/member-type-workspace.context.ts | 13 ++++++++++---
.../members/workspace/member-workspace.context.ts | 1 +
.../language/language-workspace.context.ts | 14 ++++++++++----
.../workspace/relation-type-workspace.context.ts | 15 ++++++++++-----
.../workspace/partial-view-workspace.context.ts | 1 +
.../workspace/stylesheet-workspace.context.ts | 1 +
.../workspace/template-workspace.context.ts | 6 +++++-
.../workspace/user-group-workspace.context.ts | 6 +++++-
.../user/user/workspace/user-workspace.context.ts | 1 +
21 files changed, 90 insertions(+), 33 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts
index 2bd6edee08..b30be8a749 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts
@@ -1,8 +1,12 @@
-import type { UmbDataTypeVariantContext } from "./data-type-variant-context.js";
-import { UmbVariantContext } from "@umbraco-cms/backoffice/workspace";
-import { UmbContextToken } from "@umbraco-cms/backoffice/context-api";
+import type { UmbDataTypeVariantContext } from './data-type-variant-context.js';
+import { UmbVariantContext } from '@umbraco-cms/backoffice/workspace';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
-export const isDataTypeVariantContext = (context: UmbVariantContext): context is UmbDataTypeVariantContext => ('properties' in context && context.getType() === 'data-type');
+export const isDataTypeVariantContext = (context: UmbVariantContext): context is UmbDataTypeVariantContext =>
+ 'properties' in context && context.getType() === 'data-type';
export const UMB_DATA_TYPE_VARIANT_CONTEXT = new UmbContextToken(
- "UmbVariantContext", isDataTypeVariantContext);
+ 'UmbVariantContext',
+ 'default',
+ isDataTypeVariantContext,
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
index 7e249b245e..f71e75e0c0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
@@ -265,5 +265,6 @@ export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDataTypeWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts
index 307962082f..6fe922324b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts
@@ -1,9 +1,12 @@
-import { type UmbVariantContext } from "./variant-context.interface.js";
-import { UmbNameableVariantContext } from "./nameable-variant-context.interface.js";
-import { UmbContextToken } from "@umbraco-cms/backoffice/context-api";
+import { type UmbVariantContext } from './variant-context.interface.js';
+import { UmbNameableVariantContext } from './nameable-variant-context.interface.js';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
-export const isNameablePropertySetContext = (context: UmbVariantContext): context is UmbNameableVariantContext => 'setName' in context;
+export const isNameablePropertySetContext = (context: UmbVariantContext): context is UmbNameableVariantContext =>
+ 'setName' in context;
export const UMB_NAMEABLE_VARIANT_CONTEXT = new UmbContextToken(
- "UmbVariantContext",
- isNameablePropertySetContext);
+ 'UmbVariantContext',
+ 'default',
+ isNameablePropertySetContext,
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/variant-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/variant-context.token.ts
index 1827b68e81..bb33a6442a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/variant-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/variant-context.token.ts
@@ -1,4 +1,4 @@
-import { type UmbVariantContext } from "./variant-context.interface.js";
-import { UmbContextToken } from "@umbraco-cms/backoffice/context-api";
+import { type UmbVariantContext } from './variant-context.interface.js';
+import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
-export const UMB_VARIANT_CONTEXT = new UmbContextToken("UmbVariantContext");
+export const UMB_VARIANT_CONTEXT = new UmbContextToken('UmbVariantContext');
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/workspace-context/variant-workspace-context.token.ts
index 16ebe6b2cd..0e5012a346 100644
--- 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/workspace-context/variant-workspace-context.token.ts
@@ -6,4 +6,8 @@ import type { UmbEntityBase } from '@umbraco-cms/backoffice/models';
export const UMB_VARIANT_WORKSPACE_CONTEXT_TOKEN = new UmbContextToken<
UmbWorkspaceContextInterface,
UmbVariantableWorkspaceContextInterface
->('UmbWorkspaceContext', (context): context is UmbVariantableWorkspaceContextInterface => 'variants' in context);
+>(
+ 'UmbWorkspaceContext',
+ 'default',
+ (context): context is UmbVariantableWorkspaceContextInterface => 'variants' in context,
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
index 492b157e66..8d97b7d2ee 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
@@ -1,5 +1,8 @@
import { UmbDictionaryRepository } from '../repository/dictionary.repository.js';
-import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
+import {
+ UmbSaveableWorkspaceContextInterface,
+ UmbEditableWorkspaceContextBase,
+} from '@umbraco-cms/backoffice/workspace';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { DictionaryItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
@@ -97,5 +100,6 @@ export const UMB_DICTIONARY_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDictionaryWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbDictionaryWorkspaceContext => context.getEntityType?.() === 'dictionary-item',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts
index 82b49c3a00..b5b5b62a0e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts
@@ -176,5 +176,6 @@ export const UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDocumentTypeWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbDocumentTypeWorkspaceContext => context.getEntityType?.() === 'document-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts
index 2d97cee2b8..8cbefdcc82 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts
@@ -8,5 +8,6 @@ export const IsDocumentVariantContext = (context: UmbVariantContext): context is
export const UMB_DOCUMENT_VARIANT_CONTEXT = new UmbContextToken(
'UmbVariantContext',
+ 'default',
IsDocumentVariantContext,
);
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 ba169380b1..12cc53d2b0 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
@@ -235,6 +235,6 @@ export const UMB_DOCUMENT_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDocumentWorkspaceContext
>(
'UmbWorkspaceContext',
- // TODO: Refactor: make a better generic way to identify workspaces, maybe workspaceType or workspaceAlias?.
+ 'default',
(context): context is UmbDocumentWorkspaceContext => context.getEntityType?.() === UMB_DOCUMENT_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
index f5ababbdad..49519549f7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
@@ -1,5 +1,8 @@
import { UmbMediaTypeRepository } from '../repository/media-type.repository.js';
-import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
+import {
+ UmbSaveableWorkspaceContextInterface,
+ UmbEditableWorkspaceContextBase,
+} from '@umbraco-cms/backoffice/workspace';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
@@ -83,5 +86,6 @@ export const UMB_MEDIA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMediaTypeWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbMediaTypeWorkspaceContext => context.getEntityType?.() === 'media-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
index 64aab3cac8..e855ea90e5 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
@@ -89,4 +89,8 @@ export class UmbMediaWorkspaceContext
export const UMB_MEDIA_WORKSPACE_CONTEXT = new UmbContextToken<
UmbSaveableWorkspaceContextInterface,
UmbMediaWorkspaceContext
->('UmbWorkspaceContext', (context): context is UmbMediaWorkspaceContext => context.getEntityType?.() === 'media');
+>(
+ 'UmbWorkspaceContext',
+ 'default',
+ (context): context is UmbMediaWorkspaceContext => context.getEntityType?.() === 'media',
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
index 36a48e1b06..9a6436e6b9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
@@ -47,5 +47,6 @@ export const UMB_MEMBER_GROUP_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMemberGroupWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbMemberGroupWorkspaceContext => context.getEntityType?.() === UMB_MEMBER_GROUP_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
index 8063754df5..2fd8778f83 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
@@ -1,5 +1,8 @@
import { UmbMemberTypeRepository } from '../repository/member-type.repository.js';
-import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
+import {
+ UmbSaveableWorkspaceContextInterface,
+ UmbEditableWorkspaceContextBase,
+} from '@umbraco-cms/backoffice/workspace';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
@@ -75,7 +78,11 @@ export class UmbMemberTypeWorkspaceContext
}
}
-export const UMB_MEMBER_TYPE_WORKSPACE_CONTEXT = new UmbContextToken(
+export const UMB_MEMBER_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
+ UmbSaveableWorkspaceContextInterface,
+ UmbMemberTypeWorkspaceContext
+>(
'UmbWorkspaceContext',
- (context): context is UmbMemberTypeWorkspaceContext => context.getEntityType?.() === 'member-type'
+ 'default',
+ (context): context is UmbMemberTypeWorkspaceContext => context.getEntityType?.() === 'member-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
index 986f6adc3a..f1b88644d7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
@@ -47,5 +47,6 @@ export const UMB_MEMBER_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMemberWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbMemberWorkspaceContext => context.getEntityType?.() === UMB_MEMBER_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
index 9c6626a865..77fc85f1fd 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
@@ -1,5 +1,8 @@
import { UmbLanguageRepository } from '../../repository/language.repository.js';
-import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
+import {
+ UmbSaveableWorkspaceContextInterface,
+ UmbEditableWorkspaceContextBase,
+} from '@umbraco-cms/backoffice/workspace';
import { ApiError, LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
@@ -102,8 +105,11 @@ export class UmbLanguageWorkspaceContext
}
}
-
-export const UMB_LANGUAGE_WORKSPACE_CONTEXT = new UmbContextToken(
+export const UMB_LANGUAGE_WORKSPACE_CONTEXT = new UmbContextToken<
+ UmbSaveableWorkspaceContextInterface,
+ UmbLanguageWorkspaceContext
+>(
'UmbWorkspaceContext',
- (context): context is UmbLanguageWorkspaceContext => context.getEntityType?.() === 'language'
+ 'default',
+ (context): context is UmbLanguageWorkspaceContext => context.getEntityType?.() === 'language',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
index 237d6a83a5..85586bbb4e 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
@@ -1,5 +1,8 @@
import { UmbRelationTypeRepository } from '../repository/relation-type.repository.js';
-import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
+import {
+ UmbSaveableWorkspaceContextInterface,
+ UmbEditableWorkspaceContextBase,
+} from '@umbraco-cms/backoffice/workspace';
import type { RelationTypeBaseModel, RelationTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
@@ -77,9 +80,11 @@ export class UmbRelationTypeWorkspaceContext
}
}
-
-
-export const UMB_RELATION_TYPE_WORKSPACE_CONTEXT = new UmbContextToken(
+export const UMB_RELATION_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
+ UmbSaveableWorkspaceContextInterface,
+ UmbRelationTypeWorkspaceContext
+>(
'UmbWorkspaceContext',
- (context): context is UmbRelationTypeWorkspaceContext => context.getEntityType?.() === 'relation-type'
+ 'default',
+ (context): context is UmbRelationTypeWorkspaceContext => context.getEntityType?.() === 'relation-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
index 0b925b21c6..0fdc98c256 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
@@ -107,5 +107,6 @@ export const UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT = new UmbContextToken<
UmbPartialViewWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbPartialViewWorkspaceContext => context.getEntityType?.() === UMB_PARTIAL_VIEW_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
index 159cd65722..1e4c8a9aa3 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
@@ -189,5 +189,6 @@ export const UMB_STYLESHEET_WORKSPACE_CONTEXT = new UmbContextToken<
UmbStylesheetWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbStylesheetWorkspaceContext => context.getEntityType?.() === 'stylesheet',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts
index ae77ddbd4b..0d5b332168 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts
@@ -176,4 +176,8 @@ ${currentContent}`;
export const UMB_TEMPLATE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbSaveableWorkspaceContextInterface,
UmbTemplateWorkspaceContext
->('UmbWorkspaceContext', (context): context is UmbTemplateWorkspaceContext => context.getEntityType?.() === 'template');
+>(
+ 'UmbWorkspaceContext',
+ 'default',
+ (context): context is UmbTemplateWorkspaceContext => context.getEntityType?.() === 'template',
+);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts
index 07af16b3a1..388cb3edac 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts
@@ -1,6 +1,9 @@
import { UmbUserGroupRepository } from '../repository/user-group.repository.js';
import { UmbUserRepository } from '../../user/repository/user.repository.js';
-import { UmbSaveableWorkspaceContextInterface, UmbEditableWorkspaceContextBase } from '@umbraco-cms/backoffice/workspace';
+import {
+ UmbSaveableWorkspaceContextInterface,
+ UmbEditableWorkspaceContextBase,
+} from '@umbraco-cms/backoffice/workspace';
import type { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbArrayState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
@@ -153,5 +156,6 @@ export const UMB_USER_GROUP_WORKSPACE_CONTEXT = new UmbContextToken<
UmbUserGroupWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbUserGroupWorkspaceContext => context.getEntityType?.() === 'user-group',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts
index 9a3c410fa1..7469d3e1f2 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts
@@ -115,5 +115,6 @@ export const UMB_USER_WORKSPACE_CONTEXT = new UmbContextToken<
UmbUserWorkspaceContext
>(
'UmbWorkspaceContext',
+ 'default',
(context): context is UmbUserWorkspaceContext => context.getEntityType?.() === UMB_USER_ENTITY_TYPE,
);
From 7722da0d4f05ec4c336ccd80bfd3ea7f594aec8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 11:45:54 +0100
Subject: [PATCH 16/25] tests
---
.../consume/context-consumer.test.ts | 6 +-
.../consume/context-request.event.test.ts | 9 +-
.../provide/context-provider.test.ts | 5 +-
.../context-api/token/context-token.test.ts | 183 ++++++++++++++----
4 files changed, 158 insertions(+), 45 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
index edb6435a95..986a878cee 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
@@ -112,7 +112,7 @@ describe('UmbContextConsumer with discriminator test', () => {
it('discriminator determines the instance type', async () => {
const localConsumer = new UmbContextConsumer(
document.body,
- new UmbContextToken(testContextAlias, discriminator),
+ new UmbContextToken(testContextAlias, undefined, discriminator),
(instance: A) => {
console.log(instance);
},
@@ -136,7 +136,7 @@ describe('UmbContextConsumer with discriminator test', () => {
const localConsumer = new UmbContextConsumer(
element,
- new UmbContextToken(testContextAlias, discriminator),
+ new UmbContextToken(testContextAlias, undefined, discriminator),
(_instance) => {
expect(_instance.prop).to.eq('value from provider');
done();
@@ -156,7 +156,7 @@ describe('UmbContextConsumer with discriminator test', () => {
const localConsumer = new UmbContextConsumer(
element,
- new UmbContextToken(testContextAlias, badDiscriminator),
+ new UmbContextToken(testContextAlias, undefined, badDiscriminator),
(_instance) => {
expect(_instance.prop).to.eq('this must not happen!');
},
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.test.ts
index f6557a2a75..ee1cb0162e 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-request.event.test.ts
@@ -9,13 +9,18 @@ describe('UmbContextRequestEvent', () => {
const event: UmbContextRequestEvent = new UmbContextRequestEventImplementation(
'my-test-context-alias',
- contextRequestCallback
+ 'my-test-api-alias',
+ contextRequestCallback,
);
- it('has context', () => {
+ it('has context alias', () => {
expect(event.contextAlias).to.eq('my-test-context-alias');
});
+ it('has api alias', () => {
+ expect(event.apiAlias).to.eq('my-test-api-alias');
+ });
+
it('has a callback', () => {
expect(event.callback).to.eq(contextRequestCallback);
});
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts
index e8ff8bb119..5090598136 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/provide/context-provider.test.ts
@@ -42,11 +42,12 @@ describe('UmbContextProvider', () => {
it('handles context request events', (done) => {
const event = new UmbContextRequestEventImplementation(
'my-test-context',
+ 'default',
(_instance: UmbTestContextProviderClass) => {
expect(_instance.prop).to.eq('value from provider');
done();
return true;
- }
+ },
);
document.body.dispatchEvent(event);
@@ -63,7 +64,7 @@ describe('UmbContextProvider', () => {
expect(_instance?.prop).to.eq('value from provider');
done();
localConsumer.hostDisconnected();
- }
+ },
);
localConsumer.hostConnected();
});
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.test.ts
index 678534bec8..882442a1d9 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/token/context-token.test.ts
@@ -4,57 +4,164 @@ import { UmbContextProvider } from '../provide/context-provider.js';
import { UmbContextToken } from './context-token.js';
const testContextAlias = 'my-test-context';
+const testApiAlias = 'my-test-api';
class UmbTestContextTokenClass {
prop = 'value from provider';
}
describe('UmbContextToken', () => {
- const contextToken = new UmbContextToken(testContextAlias);
- const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
- typedProvider.hostConnected();
+ describe('Simple context token', () => {
+ const contextToken = new UmbContextToken(testContextAlias);
+ const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
+ typedProvider.hostConnected();
- after(() => {
- typedProvider.hostDisconnected();
+ after(() => {
+ typedProvider.hostDisconnected();
+ });
+
+ it('toString returns the alias', () => {
+ expect(contextToken.toString()).to.eq(testContextAlias + '#' + 'default');
+ });
+
+ it('can be used to consume a context API', (done) => {
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ contextToken,
+ (_instance: UmbTestContextTokenClass | undefined) => {
+ expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
+ expect(_instance?.prop).to.eq('value from provider');
+ done();
+ localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
+ },
+ );
+
+ localConsumer.hostConnected();
+ });
+
+ it('gives the same result when using the string alias', (done) => {
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ testContextAlias,
+ (_instance: UmbTestContextTokenClass | undefined) => {
+ expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
+ expect(_instance?.prop).to.eq('value from provider');
+ done();
+ localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
+ },
+ );
+
+ localConsumer.hostConnected();
+ });
});
- it('toString returns the alias', () => {
- expect(contextToken.toString()).to.eq(testContextAlias);
+ describe('Context Token with alternative api alias', () => {
+ const contextToken = new UmbContextToken(testContextAlias, testApiAlias);
+ const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
+ typedProvider.hostConnected();
+
+ after(() => {
+ typedProvider.hostDisconnected();
+ });
+
+ it('toString returns the alias', () => {
+ expect(contextToken.toString()).to.eq(testContextAlias + '#' + testApiAlias);
+ });
+
+ it('can be used to consume a context API', (done) => {
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ contextToken,
+ (_instance: UmbTestContextTokenClass | undefined) => {
+ expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
+ expect(_instance?.prop).to.eq('value from provider');
+ done();
+ localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
+ },
+ );
+
+ localConsumer.hostConnected();
+ });
+
+ it('gives the same result when using the string alias', (done) => {
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ testContextAlias,
+ (_instance: UmbTestContextTokenClass | undefined) => {
+ expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
+ expect(_instance?.prop).to.eq('value from provider');
+ done();
+ localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
+ },
+ );
+
+ localConsumer.hostConnected();
+ });
});
- it('can be used to consume a context API', (done) => {
- const element = document.createElement('div');
- document.body.appendChild(element);
-
- const localConsumer = new UmbContextConsumer(
- element,
- contextToken,
- (_instance: UmbTestContextTokenClass | undefined) => {
- expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
- expect(_instance?.prop).to.eq('value from provider');
- done();
- localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
- }
- );
-
- localConsumer.hostConnected();
- });
-
- it('gives the same result when using the string alias', (done) => {
- const element = document.createElement('div');
- document.body.appendChild(element);
-
- const localConsumer = new UmbContextConsumer(
- element,
+ describe('Context Token with discriminator method', () => {
+ const contextToken = new UmbContextToken(
testContextAlias,
- (_instance: UmbTestContextTokenClass | undefined) => {
- expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
- expect(_instance?.prop).to.eq('value from provider');
- done();
- localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
- }
+ undefined,
+ (instance): instance is UmbTestContextTokenClass => instance.prop === 'value from provider',
);
+ const typedProvider = new UmbContextProvider(document.body, contextToken, new UmbTestContextTokenClass());
+ typedProvider.hostConnected();
- localConsumer.hostConnected();
+ after(() => {
+ typedProvider.hostDisconnected();
+ });
+
+ it('toString returns the alias', () => {
+ expect(contextToken.toString()).to.eq(testContextAlias + '#' + 'default');
+ });
+
+ it('can be used to consume a context API', (done) => {
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ contextToken,
+ (_instance: UmbTestContextTokenClass | undefined) => {
+ expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
+ expect(_instance?.prop).to.eq('value from provider');
+ done();
+ localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
+ },
+ );
+
+ localConsumer.hostConnected();
+ });
+
+ it('gives the same result when using the string alias', (done) => {
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ testContextAlias,
+ (_instance: UmbTestContextTokenClass | undefined) => {
+ expect(_instance).to.be.instanceOf(UmbTestContextTokenClass);
+ expect(_instance?.prop).to.eq('value from provider');
+ done();
+ localConsumer.destroy(); // We do not want to react to when the provider is disconnected.
+ },
+ );
+
+ localConsumer.hostConnected();
+ });
});
});
From 692ff08250aee762638f5a2200d1f2b982a07b1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 12:51:58 +0100
Subject: [PATCH 17/25] use undefined to get default
---
.../variant-context/data-type-variant-context.token.ts | 2 +-
.../core/data-type/workspace/data-type-workspace.context.ts | 2 +-
.../workspace/variant-context/nameable-variant-context.token.ts | 2 +-
.../workspace-context/variant-workspace-context.token.ts | 2 +-
.../dictionary/workspace/dictionary-workspace.context.ts | 2 +-
.../document-types/workspace/document-type-workspace.context.ts | 2 +-
.../documents/variant-context/document-variant-context.token.ts | 2 +-
.../documents/documents/workspace/document-workspace.context.ts | 2 +-
.../media/media-types/workspace/media-type-workspace.context.ts | 2 +-
.../packages/media/media/workspace/media-workspace.context.ts | 2 +-
.../member-groups/workspace/member-group-workspace.context.ts | 2 +-
.../member-types/workspace/member-type-workspace.context.ts | 2 +-
.../members/members/workspace/member-workspace.context.ts | 2 +-
.../languages/workspace/language/language-workspace.context.ts | 2 +-
.../relation-types/workspace/relation-type-workspace.context.ts | 2 +-
.../partial-views/workspace/partial-view-workspace.context.ts | 2 +-
.../stylesheets/workspace/stylesheet-workspace.context.ts | 2 +-
.../templates/workspace/template-workspace.context.ts | 2 +-
.../user/user-group/workspace/user-group-workspace.context.ts | 2 +-
.../src/packages/user/user/workspace/user-workspace.context.ts | 2 +-
20 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts
index b30be8a749..465fdb7ec6 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/variant-context/data-type-variant-context.token.ts
@@ -7,6 +7,6 @@ export const isDataTypeVariantContext = (context: UmbVariantContext): context is
export const UMB_DATA_TYPE_VARIANT_CONTEXT = new UmbContextToken(
'UmbVariantContext',
- 'default',
+ undefined,
isDataTypeVariantContext,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
index f71e75e0c0..21a2f7af84 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
@@ -265,6 +265,6 @@ export const UMB_DATA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDataTypeWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbDataTypeWorkspaceContext => context.getEntityType?.() === 'data-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts
index 6fe922324b..c4386e9bfe 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/variant-context/nameable-variant-context.token.ts
@@ -7,6 +7,6 @@ export const isNameablePropertySetContext = (context: UmbVariantContext): contex
export const UMB_NAMEABLE_VARIANT_CONTEXT = new UmbContextToken(
'UmbVariantContext',
- 'default',
+ undefined,
isNameablePropertySetContext,
);
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/workspace-context/variant-workspace-context.token.ts
index 0e5012a346..e09238e6dc 100644
--- 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/workspace-context/variant-workspace-context.token.ts
@@ -8,6 +8,6 @@ export const UMB_VARIANT_WORKSPACE_CONTEXT_TOKEN = new UmbContextToken<
UmbVariantableWorkspaceContextInterface
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbVariantableWorkspaceContextInterface => 'variants' in context,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
index 8d97b7d2ee..997db59a7d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
@@ -100,6 +100,6 @@ export const UMB_DICTIONARY_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDictionaryWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbDictionaryWorkspaceContext => context.getEntityType?.() === 'dictionary-item',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts
index b5b5b62a0e..c39891181c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts
@@ -176,6 +176,6 @@ export const UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDocumentTypeWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbDocumentTypeWorkspaceContext => context.getEntityType?.() === 'document-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts
index 8cbefdcc82..e5ecd6f911 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/variant-context/document-variant-context.token.ts
@@ -8,6 +8,6 @@ export const IsDocumentVariantContext = (context: UmbVariantContext): context is
export const UMB_DOCUMENT_VARIANT_CONTEXT = new UmbContextToken(
'UmbVariantContext',
- 'default',
+ undefined,
IsDocumentVariantContext,
);
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 12cc53d2b0..0b2f8561fd 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
@@ -235,6 +235,6 @@ export const UMB_DOCUMENT_WORKSPACE_CONTEXT = new UmbContextToken<
UmbDocumentWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbDocumentWorkspaceContext => context.getEntityType?.() === UMB_DOCUMENT_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
index 49519549f7..e8ab17ba2c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
@@ -86,6 +86,6 @@ export const UMB_MEDIA_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMediaTypeWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbMediaTypeWorkspaceContext => context.getEntityType?.() === 'media-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
index e855ea90e5..65db834f3b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
@@ -91,6 +91,6 @@ export const UMB_MEDIA_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMediaWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbMediaWorkspaceContext => context.getEntityType?.() === 'media',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
index 9a6436e6b9..38da5949c0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
@@ -47,6 +47,6 @@ export const UMB_MEMBER_GROUP_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMemberGroupWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbMemberGroupWorkspaceContext => context.getEntityType?.() === UMB_MEMBER_GROUP_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
index 2fd8778f83..1ce66f3df7 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
@@ -83,6 +83,6 @@ export const UMB_MEMBER_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMemberTypeWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbMemberTypeWorkspaceContext => context.getEntityType?.() === 'member-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
index f1b88644d7..ad6c12f22c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
@@ -47,6 +47,6 @@ export const UMB_MEMBER_WORKSPACE_CONTEXT = new UmbContextToken<
UmbMemberWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbMemberWorkspaceContext => context.getEntityType?.() === UMB_MEMBER_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
index 77fc85f1fd..b0f89da15f 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
@@ -110,6 +110,6 @@ export const UMB_LANGUAGE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbLanguageWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbLanguageWorkspaceContext => context.getEntityType?.() === 'language',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
index 85586bbb4e..d4be3a51e0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
@@ -85,6 +85,6 @@ export const UMB_RELATION_TYPE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbRelationTypeWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbRelationTypeWorkspaceContext => context.getEntityType?.() === 'relation-type',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
index 0fdc98c256..6b818a1702 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
@@ -107,6 +107,6 @@ export const UMB_PARTIAL_VIEW_WORKSPACE_CONTEXT = new UmbContextToken<
UmbPartialViewWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbPartialViewWorkspaceContext => context.getEntityType?.() === UMB_PARTIAL_VIEW_ENTITY_TYPE,
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
index 1e4c8a9aa3..512d396a11 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
@@ -189,6 +189,6 @@ export const UMB_STYLESHEET_WORKSPACE_CONTEXT = new UmbContextToken<
UmbStylesheetWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbStylesheetWorkspaceContext => context.getEntityType?.() === 'stylesheet',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts
index 0d5b332168..c9f1f93c24 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.context.ts
@@ -178,6 +178,6 @@ export const UMB_TEMPLATE_WORKSPACE_CONTEXT = new UmbContextToken<
UmbTemplateWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbTemplateWorkspaceContext => context.getEntityType?.() === 'template',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts
index 388cb3edac..15384293e0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/workspace/user-group-workspace.context.ts
@@ -156,6 +156,6 @@ export const UMB_USER_GROUP_WORKSPACE_CONTEXT = new UmbContextToken<
UmbUserGroupWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbUserGroupWorkspaceContext => context.getEntityType?.() === 'user-group',
);
diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts
index 7469d3e1f2..11ab943a6c 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/workspace/user-workspace.context.ts
@@ -115,6 +115,6 @@ export const UMB_USER_WORKSPACE_CONTEXT = new UmbContextToken<
UmbUserWorkspaceContext
>(
'UmbWorkspaceContext',
- 'default',
+ undefined,
(context): context is UmbUserWorkspaceContext => context.getEntityType?.() === UMB_USER_ENTITY_TYPE,
);
From e2c3c99ffd463f22d4d671175fef45d5c38c4dad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 15:01:27 +0100
Subject: [PATCH 18/25] remove log and comment
---
.../workspace/document-workspace.element.ts | 22 ++++++-------------
1 file changed, 7 insertions(+), 15 deletions(-)
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
index c1d3c4e6e2..3c6d303203 100644
--- 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
@@ -1,5 +1,5 @@
import type { UmbDocumentWorkspaceContext } from './document-workspace.context.js';
-import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@@ -11,26 +11,18 @@ import { ManifestWorkspace, umbExtensionsRegistry } from '@umbraco-cms/backoffic
@customElement('umb-document-workspace')
export class UmbDocumentWorkspaceElement extends UmbLitElement {
-
-
#workspaceContext?: UmbDocumentWorkspaceContext;
-
@state()
_routes: UmbRoute[] = [];
public set manifest(manifest: ManifestWorkspace) {
-
- console.log("got manifest", manifest.alias)
- // TODO: Make context declaration.
-
- createExtensionApi(manifest, [this]).then( (context) => {
- if(context) {
+ createExtensionApi(manifest, [this]).then((context) => {
+ if (context) {
this.#gotWorkspaceContext(context);
}
- })
-
- };
+ });
+ }
#gotWorkspaceContext(context: UmbApi) {
this.#workspaceContext = context as UmbDocumentWorkspaceContext;
@@ -44,11 +36,11 @@ export class UmbDocumentWorkspaceElement extends UmbLitElement {
const parentId = info.match.params.parentId === 'null' ? null : info.match.params.parentId;
const documentTypeKey = info.match.params.documentTypeKey;
this.#workspaceContext!.create(documentTypeKey, parentId);
-
+
new UmbWorkspaceIsNewRedirectController(
this,
this.#workspaceContext!,
- this.shadowRoot!.querySelector('umb-router-slot')!
+ this.shadowRoot!.querySelector('umb-router-slot')!,
);
},
},
From 75f0ba87f464fe900babd31146e372d58b85d126 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 20:33:39 +0100
Subject: [PATCH 19/25] better tests
---
.../consume/context-consumer.test.ts | 282 +++++++++++-------
1 file changed, 167 insertions(+), 115 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
index 986a878cee..80b1df93b1 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
@@ -5,20 +5,22 @@ import { UmbContextConsumer } from './context-consumer.js';
import { UmbContextRequestEventImplementation, UMB_CONTENT_REQUEST_EVENT_TYPE } from './context-request.event.js';
const testContextAlias = 'my-test-context';
+const testContextAliasAndApiAlias = 'my-test-context#testApi';
+const testContextAliasAndNotExstingApiAlias = 'my-test-context#notExistingTestApi';
class UmbTestContextConsumerClass {
public prop: string = 'value from provider';
}
describe('UmbContextConsumer', () => {
- let consumer: UmbContextConsumer;
-
- beforeEach(() => {
- // eslint-disable-next-line @typescript-eslint/no-empty-function
- consumer = new UmbContextConsumer(document.body, testContextAlias, () => {});
- });
-
describe('Public API', () => {
+ let consumer: UmbContextConsumer;
+
+ beforeEach(() => {
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
+ consumer = new UmbContextConsumer(document.body, testContextAlias, () => {});
+ });
+
describe('properties', () => {
it('has a instance property', () => {
expect(consumer).to.have.property('instance').that.is.undefined;
@@ -45,128 +47,178 @@ describe('UmbContextConsumer', () => {
});
});
- it('works with UmbContextProvider', (done) => {
- const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
- provider.hostConnected();
+ describe('Simple implementation', () => {
+ it('works with UmbContextProvider', (done) => {
+ const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
+ provider.hostConnected();
- const element = document.createElement('div');
- document.body.appendChild(element);
+ const element = document.createElement('div');
+ document.body.appendChild(element);
- const localConsumer = new UmbContextConsumer(
- element,
- testContextAlias,
- (_instance: UmbTestContextConsumerClass | undefined) => {
+ const localConsumer = new UmbContextConsumer(
+ element,
+ testContextAlias,
+ (_instance: UmbTestContextConsumerClass | undefined) => {
+ if (_instance) {
+ expect(_instance.prop).to.eq('value from provider');
+ done();
+ localConsumer.hostDisconnected();
+ provider.hostDisconnected();
+ }
+ },
+ );
+ localConsumer.hostConnected();
+ });
+
+ /*
+ Unprovided feature is out commented currently. I'm not sure there is a use case. So lets leave the code around until we know for sure.
+ it('acts to Context API disconnected', (done) => {
+ const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
+ provider.hostConnected();
+
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ let callbackNum = 0;
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ testContextAlias,
+ (_instance: UmbTestContextConsumerClass | undefined) => {
+ callbackNum++;
+ if (callbackNum === 1) {
+ expect(_instance?.prop).to.eq('value from provider');
+ // unregister.
+ provider.hostDisconnected();
+ } else if (callbackNum === 2) {
+ expect(_instance?.prop).to.be.undefined;
+ done();
+ }
+ }
+ );
+ localConsumer.hostConnected();
+ });
+ */
+ });
+
+ describe('Implementation with Api Alias', () => {
+ it('responds when api alias matches', (done) => {
+ const provider = new UmbContextProvider(
+ document.body,
+ testContextAliasAndApiAlias,
+ new UmbTestContextConsumerClass(),
+ );
+ provider.hostConnected();
+
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(element, testContextAliasAndApiAlias, (_instance) => {
if (_instance) {
+ expect((_instance as UmbTestContextConsumerClass).prop).to.eq('value from provider');
+ localConsumer.hostDisconnected();
+ provider.hostDisconnected();
+ done();
+ }
+ });
+ localConsumer.hostConnected();
+ });
+
+ it('does not respond to a non existing api alias', (done) => {
+ const provider = new UmbContextProvider(
+ document.body,
+ testContextAliasAndApiAlias,
+ new UmbTestContextConsumerClass(),
+ );
+ provider.hostConnected();
+
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(element, testContextAliasAndNotExstingApiAlias, (_instance) => {
+ expect(false).to.be.true;
+ });
+ localConsumer.hostConnected();
+
+ // Delayed check to make sure the callback is not called.
+ Promise.resolve().then(() => {
+ localConsumer.hostDisconnected();
+ provider.hostDisconnected();
+ done();
+ });
+ });
+ });
+
+ describe('Implementation with discriminator method', () => {
+ type A = { prop: string };
+
+ function discriminator(instance: unknown): instance is A {
+ return typeof (instance as any).prop === 'string';
+ }
+
+ function badDiscriminator(instance: unknown): instance is A {
+ return typeof (instance as any).notExistingProp === 'string';
+ }
+
+ it('discriminator determines the instance type', async () => {
+ const localConsumer = new UmbContextConsumer(
+ document.body,
+ new UmbContextToken(testContextAlias, undefined, discriminator),
+ (instance: A) => {
+ console.log(instance);
+ },
+ );
+ localConsumer.hostConnected();
+
+ // This bit of code is not really a test but it serves as a TypeScript type test, making sure the given type is matches the one given from the Discriminator method.
+ type TestType = Exclude extends A ? true : never;
+ const test: TestType = true;
+ expect(test).to.be.true;
+
+ localConsumer.destroy();
+ });
+
+ it('approving discriminator still fires callback', (done) => {
+ const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
+ provider.hostConnected();
+
+ const element = document.createElement('div');
+ document.body.appendChild(element);
+
+ const localConsumer = new UmbContextConsumer(
+ element,
+ new UmbContextToken(testContextAlias, undefined, discriminator),
+ (_instance) => {
expect(_instance.prop).to.eq('value from provider');
done();
localConsumer.hostDisconnected();
provider.hostDisconnected();
- }
- },
- );
- localConsumer.hostConnected();
- });
+ },
+ );
+ localConsumer.hostConnected();
+ });
- /*
- Unprovided feature is out commented currently. I'm not sure there is a use case. So lets leave the code around until we know for sure.
- it('acts to Context API disconnected', (done) => {
- const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
- provider.hostConnected();
+ it('disapproving discriminator does not fire callback', (done) => {
+ const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
+ provider.hostConnected();
- const element = document.createElement('div');
- document.body.appendChild(element);
+ const element = document.createElement('div');
+ document.body.appendChild(element);
- let callbackNum = 0;
+ const localConsumer = new UmbContextConsumer(
+ element,
+ new UmbContextToken(testContextAlias, undefined, badDiscriminator),
+ (_instance) => {
+ expect(_instance.prop).to.eq('this must not happen!');
+ },
+ );
+ localConsumer.hostConnected();
- const localConsumer = new UmbContextConsumer(
- element,
- testContextAlias,
- (_instance: UmbTestContextConsumerClass | undefined) => {
- callbackNum++;
- if (callbackNum === 1) {
- expect(_instance?.prop).to.eq('value from provider');
- // unregister.
- provider.hostDisconnected();
- } else if (callbackNum === 2) {
- expect(_instance?.prop).to.be.undefined;
- done();
- }
- }
- );
- localConsumer.hostConnected();
- });
- */
-});
-
-describe('UmbContextConsumer with discriminator test', () => {
- type A = { prop: string };
-
- function discriminator(instance: unknown): instance is A {
- return typeof (instance as any).prop === 'string';
- }
-
- function badDiscriminator(instance: unknown): instance is A {
- return typeof (instance as any).notExistingProp === 'string';
- }
-
- it('discriminator determines the instance type', async () => {
- const localConsumer = new UmbContextConsumer(
- document.body,
- new UmbContextToken(testContextAlias, undefined, discriminator),
- (instance: A) => {
- console.log(instance);
- },
- );
- localConsumer.hostConnected();
-
- // This bit of code is not really a test but it serves as a TypeScript type test, making sure the given type is matches the one given from the Discriminator method.
- type TestType = Exclude extends A ? true : never;
- const test: TestType = true;
- expect(test).to.be.true;
-
- localConsumer.destroy();
- });
-
- it('approving discriminator still fires callback', (done) => {
- const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
- provider.hostConnected();
-
- const element = document.createElement('div');
- document.body.appendChild(element);
-
- const localConsumer = new UmbContextConsumer(
- element,
- new UmbContextToken(testContextAlias, undefined, discriminator),
- (_instance) => {
- expect(_instance.prop).to.eq('value from provider');
+ Promise.resolve().then(() => {
done();
localConsumer.hostDisconnected();
provider.hostDisconnected();
- },
- );
- localConsumer.hostConnected();
- });
-
- it('disapproving discriminator does not fire callback', (done) => {
- const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass());
- provider.hostConnected();
-
- const element = document.createElement('div');
- document.body.appendChild(element);
-
- const localConsumer = new UmbContextConsumer(
- element,
- new UmbContextToken(testContextAlias, undefined, badDiscriminator),
- (_instance) => {
- expect(_instance.prop).to.eq('this must not happen!');
- },
- );
- localConsumer.hostConnected();
-
- Promise.resolve().then(() => {
- done();
- localConsumer.hostDisconnected();
- provider.hostDisconnected();
+ });
});
});
});
From 58f4b18786132d0822576abd67dfdff674aa6704 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 20:58:37 +0100
Subject: [PATCH 20/25] update to use the right token
---
.../workspace/document-type-workspace-editor.element.ts | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts
index 592fdfee6e..79469d08b8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts
@@ -1,4 +1,4 @@
-import { UmbDocumentTypeWorkspaceContext } from './document-type-workspace.context.js';
+import { UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT } from './document-type-workspace.context.js';
import { UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui';
import { css, html, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
@@ -7,7 +7,6 @@ import {
UMB_MODAL_MANAGER_CONTEXT_TOKEN,
UMB_ICON_PICKER_MODAL,
} from '@umbraco-cms/backoffice/modal';
-import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace';
import { generateAlias } from '@umbraco-cms/backoffice/utils';
@customElement('umb-document-type-workspace-editor')
export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement {
@@ -27,15 +26,15 @@ export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement {
private _iconColorAlias?: string;
// TODO: Color should be using an alias, and look up in some dictionary/key/value) of project-colors.
- #workspaceContext?: UmbDocumentTypeWorkspaceContext;
+ #workspaceContext?: typeof UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT.TYPE;
private _modalContext?: UmbModalManagerContext;
constructor() {
super();
- this.consumeContext(UMB_WORKSPACE_CONTEXT, (instance) => {
- this.#workspaceContext = instance as UmbDocumentTypeWorkspaceContext;
+ this.consumeContext(UMB_DOCUMENT_TYPE_WORKSPACE_CONTEXT, (instance) => {
+ this.#workspaceContext = instance;
this.#observeDocumentType();
});
From 3470be65ee2cae824a74ee33c3715f60e33ecc9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 20:58:47 +0100
Subject: [PATCH 21/25] make sure we extend UmbApi
---
.../workspace-context/workspace-context.interface.ts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
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/workspace-context/workspace-context.interface.ts
index cdb9fa4b4e..e065c1adb0 100644
--- 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/workspace-context/workspace-context.interface.ts
@@ -1,4 +1,6 @@
-export interface UmbWorkspaceContextInterface {
+import type { UmbApi } from '@umbraco-cms/backoffice/extension-api';
+
+export interface UmbWorkspaceContextInterface extends UmbApi {
readonly workspaceAlias: string;
// TODO: should we consider another name than entity type. File system files are not entities but still have this type.
getEntityType(): string;
From 41f1e8f3c2cdf7f43d9fc5fbf9731c02a067470e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 20:59:02 +0100
Subject: [PATCH 22/25] media workspace get api through manifest
---
.../media/media/workspace/manifests.ts | 3 +-
.../workspace/media-workspace.context.ts | 4 +-
.../workspace/media-workspace.element.ts | 63 ++++++++++++++-----
3 files changed, 52 insertions(+), 18 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts
index e0c4ae4b7c..d36fa3c4dd 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts
@@ -11,7 +11,8 @@ const workspace: ManifestWorkspace = {
type: 'workspace',
alias: 'Umb.Workspace.Media',
name: 'Media Workspace',
- js: () => import('./media-workspace.element.js'),
+ element: () => import('./media-workspace.element.js'),
+ api: () => import('./media-workspace.context.js'),
meta: {
entityType: 'media',
},
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
index 65db834f3b..1b0575f358 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.context.ts
@@ -7,11 +7,12 @@ import {
import { appendToFrozenArray, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
+import { UmbApi } from '@umbraco-cms/backoffice/extension-api';
type EntityType = UmbMediaDetailModel;
export class UmbMediaWorkspaceContext
extends UmbEditableWorkspaceContextBase
- implements UmbSaveableWorkspaceContextInterface
+ implements UmbSaveableWorkspaceContextInterface, UmbApi
{
#data = new UmbObjectState(undefined);
data = this.#data.asObservable();
@@ -85,6 +86,7 @@ export class UmbMediaWorkspaceContext
this.#data.destroy();
}
}
+export const api = UmbMediaWorkspaceContext;
export const UMB_MEDIA_WORKSPACE_CONTEXT = new UmbContextToken<
UmbSaveableWorkspaceContextInterface,
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.element.ts
index aeeb6b3531..10c2fc5ecc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/media-workspace.element.ts
@@ -1,28 +1,59 @@
-import { UmbMediaWorkspaceContext } from './media-workspace.context.js';
-import { UmbMediaWorkspaceEditorElement } from './media-workspace-editor.element.js';
-import { UmbTextStyles } from "@umbraco-cms/backoffice/style";
+import { type UmbMediaWorkspaceContext } from './media-workspace.context.js';
+import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
+import { type UmbApi, createExtensionApi, UmbExtensionsApiInitializer } from '@umbraco-cms/backoffice/extension-api';
+import { umbExtensionsRegistry, type ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry';
+import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
@customElement('umb-media-workspace')
export class UmbMediaWorkspaceElement extends UmbLitElement {
- public readonly workspaceAlias = 'Umb.Workspace.Media';
-
- #workspaceContext = new UmbMediaWorkspaceContext(this);
- #element = new UmbMediaWorkspaceEditorElement();
+ #workspaceContext?: UmbMediaWorkspaceContext;
@state()
- _routes: UmbRoute[] = [
- {
- path: 'edit/:id',
- component: () => this.#element,
- setup: (_component, info) => {
- const id = info.match.params.id;
- this.#workspaceContext.load(id);
+ _routes: UmbRoute[] = [];
+
+ public set manifest(manifest: ManifestWorkspace) {
+ createExtensionApi(manifest, [this]).then((context) => {
+ if (context) {
+ this.#gotWorkspaceContext(context);
+ }
+ });
+ }
+
+ #gotWorkspaceContext(context: UmbApi) {
+ this.#workspaceContext = context as UmbMediaWorkspaceContext;
+
+ this._routes = [
+ {
+ path: 'create/:parentId', // /:mediaTypeKey
+ component: import('./media-workspace-editor.element.js'),
+ 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 parentId = info.match.params.parentId === 'null' ? null : info.match.params.parentId;
+ //const mediaTypeKey = info.match.params.mediaTypeKey;
+ this.#workspaceContext!.create(parentId /** , mediaTypeKey */);
+
+ new UmbWorkspaceIsNewRedirectController(
+ this,
+ this.#workspaceContext!,
+ this.shadowRoot!.querySelector('umb-router-slot')!,
+ );
+ },
},
- },
- ];
+ {
+ path: 'edit/:id',
+ component: import('./media-workspace-editor.element.js'),
+ setup: (_component, info) => {
+ const id = info.match.params.id;
+ this.#workspaceContext!.load(id);
+ },
+ },
+ ];
+
+ new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'workspaceContext', [this, this.#workspaceContext]);
+ }
render() {
return html``;
From 4f63dc5856efa8e8231c196a31e7ff7c1df9f3ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 21:01:54 +0100
Subject: [PATCH 23/25] clean up
---
.../templates/workspace/template-workspace.element.ts | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.element.ts
index c73caadf91..ca9068383a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/workspace/template-workspace.element.ts
@@ -1,6 +1,6 @@
import { UmbTemplateWorkspaceContext } from './template-workspace.context.js';
import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
-import type { IRoutingInfo, PageComponent, UmbRoute, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router';
+import type { IRoutingInfo, PageComponent, UmbRoute } from '@umbraco-cms/backoffice/router';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import '../../components/insert-menu/templating-insert-menu.element.js';
@@ -9,10 +9,6 @@ import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/wor
@customElement('umb-template-workspace')
export class UmbTemplateWorkspaceElement extends UmbLitElement {
- public load(entityId: string) {
- this.#templateWorkspaceContext.load(entityId);
- }
-
#templateWorkspaceContext = new UmbTemplateWorkspaceContext(this);
#element = document.createElement('umb-template-workspace-editor');
@@ -29,7 +25,7 @@ export class UmbTemplateWorkspaceElement extends UmbLitElement {
new UmbWorkspaceIsNewRedirectController(
this,
this.#templateWorkspaceContext,
- this.shadowRoot!.querySelector('umb-router-slot')!
+ this.shadowRoot!.querySelector('umb-router-slot')!,
);
},
},
From 57eec9f7f96df687929819c493873737ef5fe483 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 21:21:49 +0100
Subject: [PATCH 24/25] other minor corrections
---
.../workspace/data-type-workspace.context.ts | 18 ++++++++---------
.../workspace/dictionary-workspace.context.ts | 10 +++++-----
.../workspace/media-type-workspace.context.ts | 16 +++++++--------
.../member-group-workspace.context.ts | 4 ++--
.../member-type-workspace.context.ts | 4 ++--
.../workspace/member-workspace.context.ts | 2 +-
.../language/language-workspace.context.ts | 8 ++++----
.../relation-type-workspace.context.ts | 10 +++++-----
.../partial-view-workspace.context.ts | 16 +++++++--------
.../workspace/stylesheet-workspace.context.ts | 20 +++++++++----------
.../workspace/stylesheet-workspace.element.ts | 6 +++---
.../src/packages/templating/utils.ts | 10 ++--------
.../src/shared/utils/diff.type.ts | 4 ++--
.../src/shared/utils/index.ts | 4 +++-
.../src/shared/utils/path-decode.function.ts | 1 +
.../src/shared/utils/path-encode.function.ts | 1 +
.../src/shared/utils/umbraco-path.function.ts | 1 +
17 files changed, 67 insertions(+), 68 deletions(-)
create mode 100644 src/Umbraco.Web.UI.Client/src/shared/utils/path-decode.function.ts
create mode 100644 src/Umbraco.Web.UI.Client/src/shared/utils/path-encode.function.ts
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
index 21a2f7af84..d20a5bffa0 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/core/data-type/workspace/data-type-workspace.context.ts
@@ -28,17 +28,17 @@ export class UmbDataTypeWorkspaceContext
{
// TODO: revisit. temp solution because the create and response models are different.
#data = new UmbObjectState(undefined);
- data = this.#data.asObservable();
+ readonly data = this.#data.asObservable();
#getDataPromise?: Promise;
- name = this.#data.asObservablePart((data) => data?.name);
- id = this.#data.asObservablePart((data) => data?.id);
+ readonly name = this.#data.asObservablePart((data) => data?.name);
+ readonly id = this.#data.asObservablePart((data) => data?.id);
- propertyEditorUiAlias = this.#data.asObservablePart((data) => data?.propertyEditorUiAlias);
- propertyEditorSchemaAlias = this.#data.asObservablePart((data) => data?.propertyEditorAlias);
+ readonly propertyEditorUiAlias = this.#data.asObservablePart((data) => data?.propertyEditorUiAlias);
+ readonly propertyEditorSchemaAlias = this.#data.asObservablePart((data) => data?.propertyEditorAlias);
#properties = new UmbObjectState | undefined>(undefined);
- properties: Observable | undefined> = this.#properties.asObservable();
+ readonly properties: Observable | undefined> = this.#properties.asObservable();
private _propertyEditorSchemaConfigDefaultData: Array = [];
private _propertyEditorUISettingsDefaultData: Array = [];
@@ -53,13 +53,13 @@ export class UmbDataTypeWorkspaceContext
private _propertyEditorUISettingsSchemaAlias?: string;
#defaults = new UmbArrayState([], (entry) => entry.alias);
- defaults = this.#defaults.asObservable();
+ readonly defaults = this.#defaults.asObservable();
#propertyEditorUiIcon = new UmbStringState(null);
- propertyEditorUiIcon = this.#propertyEditorUiIcon.asObservable();
+ readonly propertyEditorUiIcon = this.#propertyEditorUiIcon.asObservable();
#propertyEditorUiName = new UmbStringState(null);
- propertyEditorUiName = this.#propertyEditorUiName.asObservable();
+ readonly propertyEditorUiName = this.#propertyEditorUiName.asObservable();
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.DataType', new UmbDataTypeDetailRepository(host));
diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
index 997db59a7d..b27f8bae0b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/dictionary/dictionary/workspace/dictionary-workspace.context.ts
@@ -1,9 +1,9 @@
import { UmbDictionaryRepository } from '../repository/dictionary.repository.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { DictionaryItemResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
@@ -13,10 +13,10 @@ export class UmbDictionaryWorkspaceContext
implements UmbSaveableWorkspaceContextInterface
{
#data = new UmbObjectState(undefined);
- data = this.#data.asObservable();
+ readonly data = this.#data.asObservable();
- name = this.#data.asObservablePart((data) => data?.name);
- dictionary = this.#data.asObservablePart((data) => data);
+ readonly name = this.#data.asObservablePart((data) => data?.name);
+ readonly dictionary = this.#data.asObservablePart((data) => data);
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.Dictionary', new UmbDictionaryRepository(host));
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
index e8ab17ba2c..1127403282 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/media-type-workspace.context.ts
@@ -1,9 +1,9 @@
import { UmbMediaTypeRepository } from '../repository/media-type.repository.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
import { MediaTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
@@ -14,14 +14,14 @@ export class UmbMediaTypeWorkspaceContext
implements UmbSaveableWorkspaceContextInterface
{
#data = new UmbObjectState(undefined);
- data = this.#data.asObservable();
+ readonly data = this.#data.asObservable();
#getDataPromise?: Promise;
- name = this.#data.asObservablePart((data) => data?.name);
- id = this.#data.asObservablePart((data) => data?.id);
- alias = this.#data.asObservablePart((data) => data?.alias);
- description = this.#data.asObservablePart((data) => data?.description);
- icon = this.#data.asObservablePart((data) => data?.icon);
+ readonly name = this.#data.asObservablePart((data) => data?.name);
+ readonly id = this.#data.asObservablePart((data) => data?.id);
+ readonly alias = this.#data.asObservablePart((data) => data?.alias);
+ readonly description = this.#data.asObservablePart((data) => data?.description);
+ readonly icon = this.#data.asObservablePart((data) => data?.icon);
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.MediaType', new UmbMediaTypeRepository(host));
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
index 38da5949c0..4af1a59466 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-groups/workspace/member-group-workspace.context.ts
@@ -3,10 +3,10 @@ import type { UmbMemberGroupDetailModel } from '../types.js';
import { UMB_MEMBER_GROUP_ENTITY_TYPE } from '../entity.js';
import { UMB_MEMBER_GROUP_WORKSPACE_ALIAS } from './manifests.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbMemberGroupWorkspaceContext
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
index 1ce66f3df7..ee32cbdaf9 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-types/workspace/member-type-workspace.context.ts
@@ -1,10 +1,10 @@
import { UmbMemberTypeRepository } from '../repository/member-type.repository.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
// TODO => use correct tpye
diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
index ad6c12f22c..55ecf02ee2 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/members/members/workspace/member-workspace.context.ts
@@ -3,7 +3,7 @@ import type { UmbMemberDetailModel } from '../types.js';
import { UMB_MEMBER_ENTITY_TYPE } from '../entity.js';
import { UMB_MEMBER_WORKSPACE_ALIAS } from './manifests.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
index b0f89da15f..e0fd57e2bc 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/language-workspace.context.ts
@@ -1,9 +1,9 @@
import { UmbLanguageRepository } from '../../repository/language.repository.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
-import { ApiError, LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
+import { ApiError, type LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
@@ -13,11 +13,11 @@ export class UmbLanguageWorkspaceContext
implements UmbSaveableWorkspaceContextInterface
{
#data = new UmbObjectState(undefined);
- data = this.#data.asObservable();
+ readonly data = this.#data.asObservable();
// TODO: this is a temp solution to bubble validation errors to the UI
#validationErrors = new UmbObjectState(undefined);
- validationErrors = this.#validationErrors.asObservable();
+ readonly validationErrors = this.#validationErrors.asObservable();
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.Language', new UmbLanguageRepository(host));
diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
index d4be3a51e0..b28d8568d8 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/settings/relation-types/workspace/relation-type-workspace.context.ts
@@ -1,11 +1,11 @@
import { UmbRelationTypeRepository } from '../repository/relation-type.repository.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
import type { RelationTypeBaseModel, RelationTypeResponseModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbRelationTypeWorkspaceContext
@@ -13,9 +13,9 @@ export class UmbRelationTypeWorkspaceContext
implements UmbSaveableWorkspaceContextInterface
{
#data = new UmbObjectState(undefined);
- data = this.#data.asObservable();
- name = this.#data.asObservablePart((data) => data?.name);
- id = this.#data.asObservablePart((data) => data?.id);
+ readonly data = this.#data.asObservable();
+ readonly name = this.#data.asObservablePart((data) => data?.name);
+ readonly id = this.#data.asObservablePart((data) => data?.id);
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.RelationType', new UmbRelationTypeRepository(host));
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
index 6b818a1702..7ea5a2601b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/partial-views/workspace/partial-view-workspace.context.ts
@@ -1,14 +1,14 @@
import { UmbPartialViewRepository } from '../repository/partial-view.repository.js';
-import { UmbPartialViewDetailModel } from '../types.js';
+import type { UmbPartialViewDetailModel } from '../types.js';
import { UMB_PARTIAL_VIEW_ENTITY_TYPE } from '../entity.js';
import { UmbBooleanState, UmbDeepState } from '@umbraco-cms/backoffice/observable-api';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import {
UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
-import { UpdatePartialViewRequestModel } from '@umbraco-cms/backoffice/backend-api';
+import type { UpdatePartialViewRequestModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export class UmbPartialViewWorkspaceContext
@@ -47,13 +47,13 @@ export class UmbPartialViewWorkspaceContext
}
#data = new UmbDeepState(undefined);
- data = this.#data.asObservable();
- name = this.#data.asObservablePart((data) => data?.name);
- content = this.#data.asObservablePart((data) => data?.content);
- path = this.#data.asObservablePart((data) => data?.path);
+ readonly data = this.#data.asObservable();
+ readonly name = this.#data.asObservablePart((data) => data?.name);
+ readonly content = this.#data.asObservablePart((data) => data?.content);
+ readonly path = this.#data.asObservablePart((data) => data?.path);
#isCodeEditorReady = new UmbBooleanState(false);
- isCodeEditorReady = this.#isCodeEditorReady.asObservable();
+ readonly isCodeEditorReady = this.#isCodeEditorReady.asObservable();
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.PartialView', new UmbPartialViewRepository(host));
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
index 512d396a11..5d0aed22ca 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.context.ts
@@ -1,13 +1,13 @@
import { UmbStylesheetRepository } from '../repository/stylesheet.repository.js';
-import { StylesheetDetails } from '../index.js';
+import type { StylesheetDetails } from '../index.js';
import {
- UmbSaveableWorkspaceContextInterface,
+ type UmbSaveableWorkspaceContextInterface,
UmbEditableWorkspaceContextBase,
} from '@umbraco-cms/backoffice/workspace';
-import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
+import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api';
import { UmbArrayState, UmbBooleanState, UmbObjectState } from '@umbraco-cms/backoffice/observable-api';
import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor';
-import { RichTextRuleModel, UpdateStylesheetRequestModel } from '@umbraco-cms/backoffice/backend-api';
+import type { RichTextRuleModel, UpdateStylesheetRequestModel } from '@umbraco-cms/backoffice/backend-api';
import { UmbContextToken } from '@umbraco-cms/backoffice/context-api';
export type RichTextRuleModelSortable = RichTextRuleModel & { sortOrder?: number };
@@ -18,14 +18,14 @@ export class UmbStylesheetWorkspaceContext
{
#data = new UmbObjectState(undefined);
#rules = new UmbArrayState([], (rule) => rule.name);
- data = this.#data.asObservable();
- rules = this.#rules.asObservable();
- name = this.#data.asObservablePart((data) => data?.name);
- content = this.#data.asObservablePart((data) => data?.content);
- path = this.#data.asObservablePart((data) => data?.path);
+ readonly data = this.#data.asObservable();
+ readonly rules = this.#rules.asObservable();
+ readonly name = this.#data.asObservablePart((data) => data?.name);
+ readonly content = this.#data.asObservablePart((data) => data?.content);
+ readonly path = this.#data.asObservablePart((data) => data?.path);
#isCodeEditorReady = new UmbBooleanState(false);
- isCodeEditorReady = this.#isCodeEditorReady.asObservable();
+ readonly isCodeEditorReady = this.#isCodeEditorReady.asObservable();
constructor(host: UmbControllerHostElement) {
super(host, 'Umb.Workspace.StyleSheet', new UmbStylesheetRepository(host));
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts
index c4f74d092e..1506091374 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/workspace/stylesheet-workspace.element.ts
@@ -1,10 +1,10 @@
-import { serverFilePathFromUrlFriendlyPath } from '../../utils.js';
import { UmbStylesheetWorkspaceContext } from './stylesheet-workspace.context.js';
import { UmbTextStyles } from '@umbraco-cms/backoffice/style';
import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit';
import type { UmbRoute } from '@umbraco-cms/backoffice/router';
import { UmbLitElement } from '@umbraco-cms/internal/lit-element';
import { UmbWorkspaceIsNewRedirectController } from '@umbraco-cms/backoffice/workspace';
+import { decodeFilePath } from '@umbraco-cms/backoffice/utils';
@customElement('umb-stylesheet-workspace')
export class UmbStylesheetWorkspaceElement extends UmbLitElement {
@@ -17,7 +17,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement {
component: import('./stylesheet-workspace-editor.element.js'),
setup: async (_component, info) => {
const path = info.match.params.path === 'null' ? null : info.match.params.path;
- const serverPath = path === null ? null : serverFilePathFromUrlFriendlyPath(path);
+ const serverPath = path === null ? null : decodeFilePath(path);
await this.#workspaceContext.create(serverPath);
await this.#workspaceContext.setRules([]);
@@ -34,7 +34,7 @@ export class UmbStylesheetWorkspaceElement extends UmbLitElement {
setup: (_component, info) => {
this.removeControllerByAlias('_observeIsNew');
const path = info.match.params.path;
- const serverPath = serverFilePathFromUrlFriendlyPath(path);
+ const serverPath = decodeFilePath(path);
this.#workspaceContext.load(serverPath);
},
},
diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/utils.ts
index cb7253772a..57c84ea4bf 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/templating/utils.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/templating/utils.ts
@@ -1,9 +1,3 @@
-// TODO: we can try and make pretty urls if we want to
-export const urlFriendlyPathFromServerFilePath = (path: string) => encodeURIComponent(path).replace('.', '-');
-
-// TODO: we can try and make pretty urls if we want to
-export const serverFilePathFromUrlFriendlyPath = (unique: string) => decodeURIComponent(unique.replace('-', '.'));
-
//Below are a copy of
export const getInsertDictionarySnippet = (nodeName: string) => {
return `@Umbraco.GetDictionaryValue("${nodeName}")`;
@@ -31,10 +25,10 @@ export const getRenderBodySnippet = () => '@RenderBody()';
export const getRenderSectionSnippet = (sectionName: string, isMandatory: boolean) =>
`@RenderSection("${sectionName}", ${isMandatory})`;
-export const getAddSectionSnippet = (sectionName: string) => `@section ${sectionName}
+export const getAddSectionSnippet = (sectionName: string) => `@section ${sectionName}
{
-
+
}`;
diff --git a/src/Umbraco.Web.UI.Client/src/shared/utils/diff.type.ts b/src/Umbraco.Web.UI.Client/src/shared/utils/diff.type.ts
index cbce25da17..699ea2524f 100644
--- a/src/Umbraco.Web.UI.Client/src/shared/utils/diff.type.ts
+++ b/src/Umbraco.Web.UI.Client/src/shared/utils/diff.type.ts
@@ -1,5 +1,5 @@
-type FilterKeys = {
+type _FilterKeys = {
[K in keyof T]: K extends keyof U ? never : K;
};
-export type Diff = Pick[keyof T]>;
+export type Diff = Pick[keyof T]>;
diff --git a/src/Umbraco.Web.UI.Client/src/shared/utils/index.ts b/src/Umbraco.Web.UI.Client/src/shared/utils/index.ts
index c5d439c2e2..7b605bb5de 100644
--- a/src/Umbraco.Web.UI.Client/src/shared/utils/index.ts
+++ b/src/Umbraco.Web.UI.Client/src/shared/utils/index.ts
@@ -4,11 +4,13 @@ export * from './ensure-path-ends-with-slash.function.js';
export * from './generate-umbraco-alias.function.js';
export * from './increment-string.function.js';
export * from './media-helper.service.js';
+export * from './pagination-manager/pagination.manager.js';
+export * from './path-decode.function.js';
+export * from './path-encode.function.js';
export * from './path-folder-name.function.js';
export * from './selection-manager.js';
export * from './udi-service.js';
export * from './umbraco-path.function.js';
-export * from './pagination-manager/pagination.manager.js';
declare global {
interface Window {
diff --git a/src/Umbraco.Web.UI.Client/src/shared/utils/path-decode.function.ts b/src/Umbraco.Web.UI.Client/src/shared/utils/path-decode.function.ts
new file mode 100644
index 0000000000..4858a64a5d
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/shared/utils/path-decode.function.ts
@@ -0,0 +1 @@
+export const decodeFilePath = (unique: string) => decodeURIComponent(unique.replace('-', '.'));
diff --git a/src/Umbraco.Web.UI.Client/src/shared/utils/path-encode.function.ts b/src/Umbraco.Web.UI.Client/src/shared/utils/path-encode.function.ts
new file mode 100644
index 0000000000..ef3e8b0a2b
--- /dev/null
+++ b/src/Umbraco.Web.UI.Client/src/shared/utils/path-encode.function.ts
@@ -0,0 +1 @@
+export const encodeFilePath = (path: string) => encodeURIComponent(path).replace('.', '-');
diff --git a/src/Umbraco.Web.UI.Client/src/shared/utils/umbraco-path.function.ts b/src/Umbraco.Web.UI.Client/src/shared/utils/umbraco-path.function.ts
index b536ed8a2e..9c54a56c4e 100644
--- a/src/Umbraco.Web.UI.Client/src/shared/utils/umbraco-path.function.ts
+++ b/src/Umbraco.Web.UI.Client/src/shared/utils/umbraco-path.function.ts
@@ -1,3 +1,4 @@
+// TODO: Rename to something more obvious, naming wise this can mean anything. I suggest: umbracoManagementApiPath()
export function umbracoPath(path: string) {
return `/umbraco/management/api/v1${path}`;
}
From 0492287ecac47142232b7c45101d4f36c353fcfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20Lyngs=C3=B8?=
Date: Tue, 21 Nov 2023 21:28:18 +0100
Subject: [PATCH 25/25] remove _instance
---
.../src/libs/context-api/consume/context-consumer.test.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
index 80b1df93b1..aee8547152 100644
--- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
+++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts
@@ -135,7 +135,7 @@ describe('UmbContextConsumer', () => {
const element = document.createElement('div');
document.body.appendChild(element);
- const localConsumer = new UmbContextConsumer(element, testContextAliasAndNotExstingApiAlias, (_instance) => {
+ const localConsumer = new UmbContextConsumer(element, testContextAliasAndNotExstingApiAlias, () => {
expect(false).to.be.true;
});
localConsumer.hostConnected();