From 32cb68e4c7360430995b0895bc650bc3071d36b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 30 Aug 2024 23:13:06 +0200 Subject: [PATCH 01/67] declare global UmbManifestTypes --- src/packages/core/extension-registry/models/index.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index adc53de04c..de089cb774 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -218,3 +218,12 @@ export type ManifestTypes = | ManifestWorkspaces | ManifestWorkspaceViews | ManifestBase; + +type UnionOfProperties = T extends object ? T[keyof T] : never; + +declare global { + interface UmbManifestType { + CORE: ManifestTypes; + } + type UmbManifestTypes = UnionOfProperties; +} From 140d7337503d5f411070749e98573a5ac478dad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 30 Aug 2024 23:13:31 +0200 Subject: [PATCH 02/67] move block editor custom view into its own module --- .../block-custom-view/block-custom-view.ts | 2 +- examples/block-custom-view/index.ts | 4 +- .../block-grid-block-inline.element.ts | 2 +- .../block-grid-block.element.ts | 3 +- .../block-grid-entry.element.ts | 12 ++-- .../block-list-entry.element.ts | 7 +-- .../property-editor-ui-block-list.element.ts | 3 +- ...i-block-list-type-configuration.element.ts | 4 +- src/packages/block/block-list/types.ts | 2 +- .../block-rte-entry.element.ts | 6 +- .../tiny-mce-block-picker.plugin.ts | 2 +- src/packages/block/block-rte/types.ts | 2 +- .../block-type-custom-view-guide.element.ts | 5 +- .../input-block-type.element.ts | 2 +- src/packages/block/block-type/types.ts | 15 ++++- .../workspace/block-type-workspace.context.ts | 4 +- .../block}/block-editor-custom-view.model.ts | 8 ++- .../context/block-entries.context-token.ts | 2 +- .../block/context/block-entries.context.ts | 2 +- .../context/block-entry.context-token.ts | 2 +- .../block/context/block-entry.context.ts | 2 +- .../block/context/block-manager.context.ts | 2 +- src/packages/block/block/index.ts | 2 +- .../block-catalogue-modal.token.ts | 3 +- src/packages/block/block/types.ts | 49 +++++++++++++++- .../block/custom-view/custom-view.element.ts | 2 +- src/packages/block/custom-view/manifest.ts | 4 +- ...ck-editor-custom-view-element.interface.ts | 57 ------------------- .../extension-registry/interfaces/index.ts | 1 - .../core/extension-registry/models/index.ts | 3 - ...ui-block-rte-type-configuration.element.ts | 4 +- 31 files changed, 104 insertions(+), 114 deletions(-) rename src/packages/{core/extension-registry/models => block/block}/block-editor-custom-view.model.ts (84%) delete mode 100644 src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts diff --git a/examples/block-custom-view/block-custom-view.ts b/examples/block-custom-view/block-custom-view.ts index e564f537a6..61f207d30c 100644 --- a/examples/block-custom-view/block-custom-view.ts +++ b/examples/block-custom-view/block-custom-view.ts @@ -1,7 +1,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { html, customElement, LitElement, property, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; // eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name @customElement('example-block-custom-view') diff --git a/examples/block-custom-view/index.ts b/examples/block-custom-view/index.ts index da81e169ac..25c1f19d2a 100644 --- a/examples/block-custom-view/index.ts +++ b/examples/block-custom-view/index.ts @@ -1,6 +1,4 @@ -import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifests: Array = [ +export const manifests: Array = [ { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', diff --git a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 08948600e1..7aac7408c7 100644 --- a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -3,9 +3,9 @@ import { UmbBlockGridInlinePropertyDatasetContext } from './block-grid-inline-pr import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/extension-registry'; import '../block-grid-areas-container/index.js'; import '../ref-grid-block/index.js'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; /** * @element umb-block-grid-block-inline diff --git a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts index 67cd1c81e7..325db2f6d9 100644 --- a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -1,8 +1,7 @@ import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/extension-registry'; -import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType, UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; import '@umbraco-cms/backoffice/ufm'; import '../block-grid-areas-container/index.js'; diff --git a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 291e9f269d..b8e9ccf1e9 100644 --- a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -2,11 +2,7 @@ import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; -import type { - ManifestBlockEditorCustomView, - UmbBlockEditorCustomViewProperties, - UmbPropertyEditorUiElement, -} from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UMB_BLOCK_GRID, type UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; @@ -14,7 +10,11 @@ import '../block-grid-block-inline/index.js'; import '../block-grid-block/index.js'; import '../block-scale-handler/index.js'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; -import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; +import { + type ManifestBlockEditorCustomView, + UmbDataPathBlockElementDataQuery, + type UmbBlockEditorCustomViewProperties, +} from '@umbraco-cms/backoffice/block'; import { UUIBlinkAnimationValue, UUIBlinkKeyframes } from '@umbraco-cms/backoffice/external/uui'; import type { UmbExtensionElementInitializer } from '@umbraco-cms/backoffice/extension-api'; /** diff --git a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 4beee2607a..8cd7361a1e 100644 --- a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -2,16 +2,13 @@ import { UmbBlockListEntryContext } from '../../context/block-list-entry.context import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; -import type { - ManifestBlockEditorCustomView, - UmbBlockEditorCustomViewProperties, - UmbPropertyEditorUiElement, -} from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import '../ref-list-block/index.js'; import '../inline-list-block/index.js'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; +import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; /** * @element umb-block-list-entry diff --git a/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index 2d60a0d689..dc71f8ebf7 100644 --- a/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -6,7 +6,7 @@ import { UMB_BLOCK_LIST_PROPERTY_EDITOR_ALIAS } from './manifests.js'; import { UmbLitElement, umbDestroyOnDisconnect } from '@umbraco-cms/backoffice/lit-element'; import { html, customElement, property, state, repeat, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbPropertyEditorUiElement, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbPropertyValueChangeEvent, type UmbPropertyEditorConfigCollection, @@ -19,6 +19,7 @@ import { UmbBlockElementDataValidationPathTranslator, type UmbBlockLayoutBaseModel, } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import '../../components/block-list-entry/index.js'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; diff --git a/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts b/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts index 639175c2fb..53154a5743 100644 --- a/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts +++ b/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts @@ -1,7 +1,7 @@ import '../../../block-type/components/input-block-type/index.js'; -import type { UmbInputBlockTypeElement } from '../../../block-type/index.js'; import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; -import type { UmbBlockTypeBaseModel, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, diff --git a/src/packages/block/block-list/types.ts b/src/packages/block/block-list/types.ts index 31c8dd7a55..94ff232c27 100644 --- a/src/packages/block/block-list/types.ts +++ b/src/packages/block/block-list/types.ts @@ -1,5 +1,5 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; export const UMB_BLOCK_LIST = 'block-list'; diff --git a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 3ca6afa49d..8c52ee27a9 100644 --- a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -2,11 +2,9 @@ import type { UmbBlockRteLayoutModel } from '../../types.js'; import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; -import type { - UmbBlockEditorCustomViewProperties, - UmbPropertyEditorUiElement, -} from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import type { UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; import '../ref-rte-block/index.js'; diff --git a/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts b/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts index 66fbd90b8c..8c01d6d7e6 100644 --- a/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts +++ b/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts @@ -2,7 +2,7 @@ import { UMB_BLOCK_RTE_MANAGER_CONTEXT } from '../context/block-rte-manager.cont import { UMB_BLOCK_RTE_ENTRIES_CONTEXT } from '../context/block-rte-entries.context-token.js'; import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '@umbraco-cms/backoffice/tiny-mce'; import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase { #localize = new UmbLocalizationController(this._host); diff --git a/src/packages/block/block-rte/types.ts b/src/packages/block/block-rte/types.ts index ea18ec9bad..c97075ec68 100644 --- a/src/packages/block/block-rte/types.ts +++ b/src/packages/block/block-rte/types.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; export const UMB_BLOCK_RTE_TYPE = 'block-rte-type'; diff --git a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts index ef5347f3d5..7dbbe77f25 100644 --- a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts +++ b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts @@ -2,11 +2,12 @@ import { UMB_MANIFEST_VIEWER_MODAL } from '../../../modals/manifest-viewer/index import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, customElement, state, property, css } from '@umbraco-cms/backoffice/external/lit'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -import { umbExtensionsRegistry, type ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; +import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/block'; @customElement('umb-block-type-custom-view-guide') export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { @@ -88,7 +89,7 @@ export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { async #generateManifest() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const manifest = { + const manifest: UmbManifestTypes = { type: 'blockEditorCustomView', alias: 'Local.blockEditorCustomView.' + this.#contentTypeAlias, name: 'Block Editor Custom View for ' + this.#contentTypeName, diff --git a/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index cade6212d8..2c6380be9f 100644 --- a/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -12,7 +12,7 @@ import { UMB_DOCUMENT_TYPE_PICKER_MODAL, } from '@umbraco-cms/backoffice/document-type'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import '../block-type-card/index.js'; diff --git a/src/packages/block/block-type/types.ts b/src/packages/block/block-type/types.ts index 4bb332af04..ece8e83203 100644 --- a/src/packages/block/block-type/types.ts +++ b/src/packages/block/block-type/types.ts @@ -1,6 +1,15 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; -export type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; - +import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; +// Shared with the Property Editor +export interface UmbBlockTypeBaseModel { + contentElementTypeKey: string; + settingsElementTypeKey?: string; + label?: string; + thumbnail?: string; + iconColor?: string; + backgroundColor?: string; + editorSize?: UUIModalSidebarSize; + forceHideContentEditorInOverlay: boolean; +} export interface UmbBlockTypeGroup { name?: string; key: string; diff --git a/src/packages/block/block-type/workspace/block-type-workspace.context.ts b/src/packages/block/block-type/workspace/block-type-workspace.context.ts index c50aad7dbb..61b2adb6a3 100644 --- a/src/packages/block/block-type/workspace/block-type-workspace.context.ts +++ b/src/packages/block/block-type/workspace/block-type-workspace.context.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeWithGroupKey } from '../types.js'; +import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../types.js'; import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-editor.element.js'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; @@ -13,7 +13,7 @@ import { } from '@umbraco-cms/backoffice/workspace'; import { UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { ManifestWorkspace, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry'; export class UmbBlockTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase diff --git a/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts b/src/packages/block/block/block-editor-custom-view.model.ts similarity index 84% rename from src/packages/core/extension-registry/models/block-editor-custom-view.model.ts rename to src/packages/block/block/block-editor-custom-view.model.ts index 55a8208789..9bbb3cd298 100644 --- a/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts +++ b/src/packages/block/block/block-editor-custom-view.model.ts @@ -1,4 +1,4 @@ -import type { UmbBlockEditorCustomViewElement } from '../interfaces/index.js'; +import type { UmbBlockEditorCustomViewElement } from './types.js'; import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestBlockEditorCustomView extends ManifestElement { @@ -18,3 +18,9 @@ export interface ManifestBlockEditorCustomView extends ManifestElement; } + +declare global { + interface UmbManifestType { + blockEditorCustomView: ManifestBlockEditorCustomView; + } +} diff --git a/src/packages/block/block/context/block-entries.context-token.ts b/src/packages/block/block/context/block-entries.context-token.ts index 75b2db18d9..e98e9607a0 100644 --- a/src/packages/block/block/context/block-entries.context-token.ts +++ b/src/packages/block/block/context/block-entries.context-token.ts @@ -3,7 +3,7 @@ import type { UmbBlockWorkspaceOriginData } from '../workspace/block-workspace.m import type { UmbBlockEntriesContext } from './block-entries.context.js'; import type { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export const UMB_BLOCK_ENTRIES_CONTEXT = new UmbContextToken< UmbBlockEntriesContext< diff --git a/src/packages/block/block/context/block-entries.context.ts b/src/packages/block/block/context/block-entries.context.ts index 234c942397..e5cb10d0b0 100644 --- a/src/packages/block/block/context/block-entries.context.ts +++ b/src/packages/block/block/context/block-entries.context.ts @@ -4,10 +4,10 @@ import type { UmbBlockDataObjectModel, UmbBlockManagerContext } from './block-ma import { UMB_BLOCK_ENTRIES_CONTEXT } from './block-entries.context-token.js'; import { type Observable, UmbArrayState, UmbBasicState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export abstract class UmbBlockEntriesContext< BlockManagerContextTokenType extends UmbContextToken, diff --git a/src/packages/block/block/context/block-entry.context-token.ts b/src/packages/block/block/context/block-entry.context-token.ts index 93b66d9b29..f913bec728 100644 --- a/src/packages/block/block/context/block-entry.context-token.ts +++ b/src/packages/block/block/context/block-entry.context-token.ts @@ -4,7 +4,7 @@ import type { UMB_BLOCK_ENTRIES_CONTEXT } from './block-entries.context-token.js import type { UmbBlockEntriesContext } from './block-entries.context.js'; import type { UmbBlockEntryContext } from './block-entry.context.js'; import type { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export const UMB_BLOCK_ENTRY_CONTEXT = new UmbContextToken< diff --git a/src/packages/block/block/context/block-entry.context.ts b/src/packages/block/block/context/block-entry.context.ts index c338636571..e8fddb2ec3 100644 --- a/src/packages/block/block/context/block-entry.context.ts +++ b/src/packages/block/block/context/block-entry.context.ts @@ -15,7 +15,7 @@ import { encodeFilePath } from '@umbraco-cms/backoffice/utils'; import { umbConfirmModal } from '@umbraco-cms/backoffice/modal'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export abstract class UmbBlockEntryContext< BlockManagerContextTokenType extends UmbContextToken, diff --git a/src/packages/block/block/context/block-manager.context.ts b/src/packages/block/block/context/block-manager.context.ts index df113d9b81..942ef5efe0 100644 --- a/src/packages/block/block/context/block-manager.context.ts +++ b/src/packages/block/block/context/block-manager.context.ts @@ -5,12 +5,12 @@ import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, UmbBooleanState, UmbClassState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; /** * diff --git a/src/packages/block/block/index.ts b/src/packages/block/block/index.ts index 0e7cb3f0dc..316fbaa517 100644 --- a/src/packages/block/block/index.ts +++ b/src/packages/block/block/index.ts @@ -1,5 +1,5 @@ export * from './context/index.js'; export * from './modals/index.js'; -export * from './types.js'; +export type * from './types.js'; export * from './validation/index.js'; export * from './workspace/index.js'; diff --git a/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts b/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts index d4fbc36096..743d522379 100644 --- a/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts +++ b/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts @@ -1,7 +1,6 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbBlockTypeGroup } from '@umbraco-cms/backoffice/block-type'; +import type { UmbBlockTypeGroup, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; export interface UmbBlockCatalogueModalData { blocks: Array; diff --git a/src/packages/block/block/types.ts b/src/packages/block/block/types.ts index 7c11cec0ac..55a2123751 100644 --- a/src/packages/block/block/types.ts +++ b/src/packages/block/block/types.ts @@ -1,5 +1,50 @@ -import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/extension-registry'; -export type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; +export type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; + +// Shared with the Property Editor +export interface UmbBlockLayoutBaseModel { + contentUdi: string; + settingsUdi?: string | null; +} + +// Shared with the Property Editor +export interface UmbBlockDataType { + udi: string; + contentTypeKey: string; + [key: string]: unknown; +} + +export interface UmbBlockEditorCustomViewConfiguration { + editContentPath?: string; + editSettingsPath?: string; + showContentEdit: boolean; + showSettingsEdit: boolean; +} + +export interface UmbBlockEditorCustomViewProperties< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> { + manifest?: ManifestBlockEditorCustomView; + config?: Partial; + blockType?: BlockType; + contentUdi?: string; + label?: string; + icon?: string; + index?: number; + layout?: LayoutType; + content?: UmbBlockDataType; + settings?: UmbBlockDataType; + contentInvalid?: boolean; + settingsInvalid?: boolean; +} + +export interface UmbBlockEditorCustomViewElement< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> extends UmbBlockEditorCustomViewProperties, + HTMLElement {} export interface UmbBlockValueType { layout: { [key: string]: Array | undefined }; diff --git a/src/packages/block/custom-view/custom-view.element.ts b/src/packages/block/custom-view/custom-view.element.ts index 9ac9fff679..3160976674 100644 --- a/src/packages/block/custom-view/custom-view.element.ts +++ b/src/packages/block/custom-view/custom-view.element.ts @@ -1,4 +1,4 @@ -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/block/custom-view/manifest.ts b/src/packages/block/custom-view/manifest.ts index 71839f5ac4..f99b3893f1 100644 --- a/src/packages/block/custom-view/manifest.ts +++ b/src/packages/block/custom-view/manifest.ts @@ -1,6 +1,4 @@ -import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; - -export const manifest: ManifestBlockEditorCustomView = { +export const manifest: UmbManifestTypes = { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', name: 'Block Editor Custom View Test', diff --git a/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts b/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts deleted file mode 100644 index 35ed551b97..0000000000 --- a/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts +++ /dev/null @@ -1,57 +0,0 @@ -import type { ManifestBlockEditorCustomView } from '../index.js'; -import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; -// Shared with the Property Editor -export interface UmbBlockTypeBaseModel { - contentElementTypeKey: string; - settingsElementTypeKey?: string; - label?: string; - thumbnail?: string; - iconColor?: string; - backgroundColor?: string; - editorSize?: UUIModalSidebarSize; - forceHideContentEditorInOverlay: boolean; -} - -// Shared with the Property Editor -export interface UmbBlockLayoutBaseModel { - contentUdi: string; - settingsUdi?: string | null; -} - -// Shared with the Property Editor -export interface UmbBlockDataType { - udi: string; - contentTypeKey: string; - [key: string]: unknown; -} - -export interface UmbBlockEditorCustomViewConfiguration { - editContentPath?: string; - editSettingsPath?: string; - showContentEdit: boolean; - showSettingsEdit: boolean; -} - -export interface UmbBlockEditorCustomViewProperties< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> { - manifest?: ManifestBlockEditorCustomView; - config?: Partial; - blockType?: BlockType; - contentUdi?: string; - label?: string; - icon?: string; - index?: number; - layout?: LayoutType; - content?: UmbBlockDataType; - settings?: UmbBlockDataType; - contentInvalid?: boolean; - settingsInvalid?: boolean; -} - -export interface UmbBlockEditorCustomViewElement< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> extends UmbBlockEditorCustomViewProperties, - HTMLElement {} diff --git a/src/packages/core/extension-registry/interfaces/index.ts b/src/packages/core/extension-registry/interfaces/index.ts index 7585b5001b..1721b7dfec 100644 --- a/src/packages/core/extension-registry/interfaces/index.ts +++ b/src/packages/core/extension-registry/interfaces/index.ts @@ -1,4 +1,3 @@ -export * from './block-editor-custom-view-element.interface.js'; export * from './dashboard-element.interface.js'; export * from './external-login-provider-element.interface.js'; export * from './menu-item-element.interface.js'; diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index de089cb774..c3386877ae 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -1,5 +1,4 @@ import type { ManifestAuthProvider } from './auth-provider.model.js'; -import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; import type { ManifestCollection } from './collection.models.js'; import type { ManifestCollectionView } from './collection-view.model.js'; import type { ManifestCurrentUserAction, ManifestCurrentUserActionDefaultKind } from './current-user-action.model.js'; @@ -77,7 +76,6 @@ import type { ManifestBase, ManifestBundle, ManifestCondition } from '@umbraco-c export type * from './app-entry-point.model.js'; export type * from './auth-provider.model.js'; export type * from './backoffice-entry-point.model.js'; -export type * from './block-editor-custom-view.model.js'; export type * from './collection-action.model.js'; export type * from './collection-view.model.js'; export type * from './collection.models.js'; @@ -158,7 +156,6 @@ export type ManifestTypes = | ManifestAppEntryPoint | ManifestAuthProvider | ManifestBackofficeEntryPoint - | ManifestBlockEditorCustomView | ManifestBundle | ManifestCollection | ManifestCollectionAction diff --git a/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts b/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts index 2b59427770..264dab15ba 100644 --- a/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts +++ b/src/packages/tiny-mce/property-editors/block/property-editor-ui-block-rte-type-configuration.element.ts @@ -1,6 +1,6 @@ -import { UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; +import { type UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; import { UMB_BLOCK_RTE_TYPE } from '@umbraco-cms/backoffice/block-rte'; -import type { UmbBlockTypeBaseModel, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, From bd571359be333ace6cd2522e9f18f84ba550ee79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 30 Aug 2024 23:25:14 +0200 Subject: [PATCH 03/67] JS Docs --- .../core/extension-registry/models/index.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index c3386877ae..d2efd62c42 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -219,8 +219,24 @@ export type ManifestTypes = type UnionOfProperties = T extends object ? T[keyof T] : never; declare global { + /** + * This global type allows to declare manifests types from its own module. + * @example + * ```js + declare global { + interface UmbManifestType { + My_UNIQUE_MANIFEST_NAME: ManifestTypes; + } + } + * ``` + */ interface UmbManifestType { - CORE: ManifestTypes; + UMB_CORE: ManifestTypes; } + + /** + * This global type provides a union of all declared manifest types. + * If this is a local package that declares additional Manifest Types, then these will also be included in this union. + */ type UmbManifestTypes = UnionOfProperties; } From d0d3cb356451fc654eb7521b16582bf1e5567ce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 19:36:23 +0200 Subject: [PATCH 04/67] JSON Schema corrections --- src/packages/core/extension-registry/umbraco-package.ts | 4 ++-- src/packages/core/json-schema/umbraco-package.ts | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 src/packages/core/json-schema/umbraco-package.ts diff --git a/src/packages/core/extension-registry/umbraco-package.ts b/src/packages/core/extension-registry/umbraco-package.ts index 3a05a2d7f0..19edb76a7f 100644 --- a/src/packages/core/extension-registry/umbraco-package.ts +++ b/src/packages/core/extension-registry/umbraco-package.ts @@ -1,4 +1,4 @@ -import type { ManifestTypes } from './models/index.js'; +import './models/index.js'; /** * Umbraco package manifest JSON @@ -37,7 +37,7 @@ export interface UmbracoPackage { * @title An array of Umbraco package manifest types that will be installed * @required */ - extensions: ManifestTypes[]; + extensions: UmbManifestTypes[]; /** * @title The importmap for the package diff --git a/src/packages/core/json-schema/umbraco-package.ts b/src/packages/core/json-schema/umbraco-package.ts new file mode 100644 index 0000000000..5be7369f5a --- /dev/null +++ b/src/packages/core/json-schema/umbraco-package.ts @@ -0,0 +1 @@ +export * from '@umbraco-cms/backoffice/extension-registry'; From 3c4de3d0d83f0a3835b312106d6e66a95b31bf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 19:50:00 +0200 Subject: [PATCH 05/67] use UmbManifestTypes in extension registry --- src/packages/core/extension-registry/registry.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/packages/core/extension-registry/registry.ts b/src/packages/core/extension-registry/registry.ts index 09294be440..b29da72ae5 100644 --- a/src/packages/core/extension-registry/registry.ts +++ b/src/packages/core/extension-registry/registry.ts @@ -1,8 +1,7 @@ -import type { ManifestTypes } from './models/index.js'; import type { ManifestKind } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionRegistry } from '@umbraco-cms/backoffice/extension-api'; -export type UmbBackofficeManifestKind = ManifestKind; -export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; +export type UmbBackofficeManifestKind = ManifestKind; +export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; -export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; +export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; From 3a7c850dd4d01c2604f2d92f24fd46480891fa82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 19:55:24 +0200 Subject: [PATCH 06/67] JSDocs --- .../registry/extension.registry.ts | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 2680d599e9..a97c4f4d9c 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,9 @@ import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbrac /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionArrayMemoization>( previousValue: Array, @@ -26,8 +27,9 @@ function extensionArrayMemoization>( /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionAndKindMatchArrayMemoization< T extends Pick & { __isMatchedWithKind?: boolean }, @@ -57,8 +59,9 @@ function extensionAndKindMatchArrayMemoization< /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionSingleMemoization>( previousValue: T | undefined, @@ -72,8 +75,9 @@ function extensionSingleMemoization>( /** * - * @param previousValue - * @param currentValue + * @param previousValue {Array} - previous value + * @param currentValue {Array} - current value + * @returns {boolean} - true if value is assumed to be the same as previous value. */ function extensionAndKindMatchSingleMemoization< T extends Pick & { __isMatchedWithKind?: boolean }, From 8cc14525a9c86d321f9dd386b6340770ae734603 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 22 Aug 2024 16:50:16 +0000 Subject: [PATCH 07/67] Adds new method to extensionRegistry for appendCondition --- .../registry/extension.registry.test.ts | 83 ++++++++++++++++++- .../registry/extension.registry.ts | 29 ++++++- 2 files changed, 110 insertions(+), 2 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 83ee09d37b..0ad82590b7 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,4 +1,5 @@ -import type { ManifestElementWithElementName, ManifestKind, ManifestBase } from '../types/index.js'; +import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; +import type { ManifestElementWithElementName, ManifestKind, ManifestBase, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; import { UmbExtensionRegistry } from './extension.registry.js'; import { expect } from '@open-wc/testing'; @@ -453,3 +454,83 @@ describe('UmbExtensionRegistry with exclusions', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.Late')).to.be.false; }); }); + +describe('Append Conditions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array< + ManifestWithDynamicConditions + >; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ + { + alias: "Umb.Test.Condition.Valid" + } + ] + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200 + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid' + }); + }); + + + it('allows an extension condition to be updated', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid' + }); + + // Add the new condition to the extension + const conditionToAdd:UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid' + }; + extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + + // Add a condition with a specific config to Section2 + const workspaceCondition:WorkspaceAliasConditionConfig = { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + + }; + extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + + const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; + expect(updatedWorkspaceExt.conditions?.length).to.equal(1); + }); +}); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index a97c4f4d9c..cb47923bc2 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -1,4 +1,4 @@ -import type { ManifestBase, ManifestKind } from '../types/index.js'; +import type { ManifestBase, ManifestKind, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; @@ -434,4 +434,31 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } + + /** + * Appends a new condition to an existing extension + * Useful to add a condition for example the Save And Publish workspace action shipped by core + * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code + * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it + * @param alias {string} - The alias of the extension to get. + * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. + */ + appendCondition(alias: string, newCondition: UmbConditionConfigBase) { + const allExtensions = this._extensions.getValue(); + const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + + if(extensionToUpdate === undefined) { + console.error(`Extension with alias ${alias} not found`); + } + + // Append the condition to the extensions conditions array + if (extensionToUpdate.conditions){ + extensionToUpdate.conditions.push(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } + + // Update the extensions observable + this._extensions.setValue(allExtensions); + } } From 64e80ce3f520c0c99dc24a0451ac44c6ce2ca75f Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 23 Aug 2024 09:57:11 +0000 Subject: [PATCH 08/67] Adds appendConditions to allow adding multiple in one go --- .../registry/extension.registry.test.ts | 20 +++++++++++++++++++ .../registry/extension.registry.ts | 11 +++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 0ad82590b7..f6add8c5c2 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -533,4 +533,24 @@ describe('Append Conditions', () => { const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); }); + + it('allows an extension to update with multiple conditions', () => { + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + const conditions:Array = [ + { + alias: 'Umb.Test.Condition.Valid' + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + } as WorkspaceAliasConditionConfig + ] + + extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(3); + }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index cb47923bc2..e776d131f2 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -440,7 +440,7 @@ export class UmbExtensionRegistry< * Useful to add a condition for example the Save And Publish workspace action shipped by core * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it - * @param alias {string} - The alias of the extension to get. + * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ appendCondition(alias: string, newCondition: UmbConditionConfigBase) { @@ -461,4 +461,13 @@ export class UmbExtensionRegistry< // Update the extensions observable this._extensions.setValue(allExtensions); } + + /** + * Appends a collection of conditions to an exsiting extension + * @param alias {string} - The alias of the extension to append the condition to + * @param newConditions {Array} - A collection of conditions to append to an extension. + */ + appendConditions(alias: string, newConditions: Array){ + newConditions.forEach((condition) => this.appendCondition(alias, condition)); + } } From b6db37359359ec7d3a8adedddb46762b0e9d9fab Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 29 Aug 2024 11:10:48 +0000 Subject: [PATCH 09/67] Adds prependCondition and prependConditions so you can make sure your condition loads first, as order of conditions are important --- .../registry/extension.registry.test.ts | 89 +++++++++++++++++++ .../registry/extension.registry.ts | 48 ++++++++-- 2 files changed, 132 insertions(+), 5 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index f6add8c5c2..9add871f65 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -554,3 +554,92 @@ describe('Append Conditions', () => { expect(ext.conditions?.length).to.equal(3); }); }); + +describe('Prepend Conditions', () => { + let extensionRegistry: UmbExtensionRegistry; + let manifests: Array; + + beforeEach(() => { + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ + { + alias: "Umb.Test.Condition.Valid" + } + ] + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200 + }, + ]; + + manifests.forEach((manifest) => extensionRegistry.register(manifest)); + + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid' + }); + }); + + it('allows an extension condition to be prepended', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid' + }); + + // Prepend the new condition to the extension + const conditionToPrepend: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid' + }; + extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions and the new condition is prepended + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); + + it('allows an extension to update with multiple prepended conditions', () => { + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Valid' + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document' + } as WorkspaceAliasConditionConfig + ]; + + extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); +}); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index e776d131f2..ed142671ac 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -1,4 +1,9 @@ -import type { ManifestBase, ManifestKind, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; +import type { + ManifestBase, + ManifestKind, + ManifestWithDynamicConditions, + UmbConditionConfigBase, +} from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; @@ -434,7 +439,7 @@ export class UmbExtensionRegistry< distinctUntilChanged(extensionAndKindMatchArrayMemoization), ) as Observable>; } - + /** * Appends a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core @@ -447,12 +452,12 @@ export class UmbExtensionRegistry< const allExtensions = this._extensions.getValue(); const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; - if(extensionToUpdate === undefined) { + if (extensionToUpdate === undefined) { console.error(`Extension with alias ${alias} not found`); } // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions){ + if (extensionToUpdate.conditions) { extensionToUpdate.conditions.push(newCondition); } else { extensionToUpdate.conditions = [newCondition]; @@ -467,7 +472,40 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - appendConditions(alias: string, newConditions: Array){ + appendConditions(alias: string, newConditions: Array) { newConditions.forEach((condition) => this.appendCondition(alias, condition)); } + + /** + * Prepends a new condition to an existing extension + * @param alias {string} - The alias of the extension to prepend the condition to + * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. + */ + prependCondition(alias: string, newCondition: UmbConditionConfigBase) { + const allExtensions = this._extensions.getValue(); + const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + + if (extensionToUpdate === undefined) { + console.error(`Extension with alias ${alias} not found`); + } + + // Prepend the condition to the extensions conditions array + if (extensionToUpdate.conditions) { + extensionToUpdate.conditions.unshift(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } + + // Update the extensions observable + this._extensions.setValue(allExtensions); + } + + /** + * Prepends a collection of conditions to an existing extension + * @param alias {string} - The alias of the extension to prepend the conditions to + * @param newConditions {Array} - A collection of conditions to prepend to an extension. + */ + prependConditions(alias: string, newConditions: Array) { + newConditions.forEach((condition) => this.prependCondition(alias, condition)); + } } From 2c0896335fae77fe97ddcede41d6e7bcc4da77b2 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Thu, 29 Aug 2024 16:14:06 +0000 Subject: [PATCH 10/67] Adds _whenExtensionAliasIsRegistered as a promise so that we basically wait until the manifest is registered so late extensions will work as well Seems to work with my hack in an entrypoint and the console logs the extension with the updated condition but its the tests I am struggling to get to work. As this code is heavily worked from me trying to Google, read RXJS docs and talking with Copilot I am not fully in confident in this approach --- .../registry/extension.registry.test.ts | 19 +-- .../registry/extension.registry.ts | 114 +++++++++++++----- src/packages/property-editors/entry-point.ts | 31 +++++ 3 files changed, 123 insertions(+), 41 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 9add871f65..94c5fccbf5 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -493,7 +493,7 @@ describe('Append Conditions', () => { }); - it('allows an extension condition to be updated', () => { + it('allows an extension condition to be updated', async () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; @@ -513,7 +513,7 @@ describe('Append Conditions', () => { const conditionToAdd:UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid' }; - extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -528,13 +528,13 @@ describe('Append Conditions', () => { match: 'Umb.Workspace.Document' }; - extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); }); - it('allows an extension to update with multiple conditions', () => { + it('allows an extension to update with multiple conditions', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -548,7 +548,7 @@ describe('Append Conditions', () => { } as WorkspaceAliasConditionConfig ] - extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(3); @@ -590,7 +590,7 @@ describe('Prepend Conditions', () => { }); }); - it('allows an extension condition to be prepended', () => { + it('allows an extension condition to be prepended', async () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; @@ -610,7 +610,8 @@ describe('Prepend Conditions', () => { const conditionToPrepend: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid' }; - extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -621,7 +622,7 @@ describe('Prepend Conditions', () => { expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); }); - it('allows an extension to update with multiple prepended conditions', () => { + it('allows an extension to update with multiple prepended conditions', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -635,7 +636,7 @@ describe('Prepend Conditions', () => { } as WorkspaceAliasConditionConfig ]; - extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index ed142671ac..19c9701a0a 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,8 @@ import type { } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbraco-cms/backoffice/external/rxjs'; +import type { Observable, Subscription } from '@umbraco-cms/backoffice/external/rxjs'; +import { map, distinctUntilChanged, combineLatest, of, switchMap, filter } from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -440,6 +440,37 @@ export class UmbExtensionRegistry< ) as Observable>; } + + /** + * Returns a promise that resolves when the extension with the specified alias is found. + * @param alias {string} - The alias of the extension to wait for. + * @returns {Promise} - A promise that resolves with the extension. + */ + private _whenExtensionAliasIsRegistered(alias: string): Promise { + return new Promise((resolve, reject) => { + const subscription: Subscription = this.extensions + .pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))) + .subscribe({ + next: (allExtensions) => { + console.log('I AM IN NEXT', allExtensions); + const extension = allExtensions.find((ext) => ext.alias === alias); + if (extension) { + subscription.unsubscribe(); + resolve(extension as ManifestBase); + } + }, + error: (error) => { + console.error('I AM IN ERROR', error); + reject(error); + }, + complete: () => { + console.log('I AM IN COMPLETE'); + reject(new Error(`Extension with alias ${alias} not found`)); + }, + }); + }); + } + /** * Appends a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core @@ -448,23 +479,39 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ - appendCondition(alias: string, newCondition: UmbConditionConfigBase) { - const allExtensions = this._extensions.getValue(); - const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + try { - if (extensionToUpdate === undefined) { - console.error(`Extension with alias ${alias} not found`); - } + // Wait for the extension to be registered (as it could be registered late) + const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.push(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } + // Got it... now carry on & mutate it + console.log('got the extension to update/mutate', extensionToWaitFor); + + // Append the condition to the extensions conditions array + if (extensionToWaitFor.conditions) { + extensionToWaitFor.conditions.push(newCondition); + } else { + extensionToWaitFor.conditions = [newCondition]; + } - // Update the extensions observable - this._extensions.setValue(allExtensions); + const allExtensions = this._extensions.getValue(); + const extensionToUpdateIndex = allExtensions.findIndex((ext) => ext.alias === alias); + if (extensionToUpdateIndex !== -1) { + // Replace the existing extension with the updated one + allExtensions[extensionToUpdateIndex] = extensionToWaitFor as ManifestTypes; + + // Update the main extensions collection/observable + this._extensions.setValue(allExtensions); + + // Log the updated extensions for debugging + console.log('UPDATED extensions:', this._extensions.getValue()); + console.table(this._extensions.getValue()); + } + } catch (error) { + // TODO: [WB] Will this ever catch an error? + console.error(`Extension with alias ${alias} was never found and threw ${error}`); + } } /** @@ -472,7 +519,7 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - appendConditions(alias: string, newConditions: Array) { + async appendConditions(alias: string, newConditions: Array): Promise { newConditions.forEach((condition) => this.appendCondition(alias, condition)); } @@ -481,23 +528,26 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to prepend the condition to * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. */ - prependCondition(alias: string, newCondition: UmbConditionConfigBase) { - const allExtensions = this._extensions.getValue(); - const extensionToUpdate = allExtensions.find((ext) => ext.alias === alias) as ManifestWithDynamicConditions; + async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + try { - if (extensionToUpdate === undefined) { - console.error(`Extension with alias ${alias} not found`); - } + // Wait for the extension to be registered (as it could be registered late) + const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Prepend the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.unshift(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } + // Got it... now carry on & mutate it + console.log('got the extension to update/mutate', extensionToUpdate); + + // Append the condition to the extensions conditions array + if (extensionToUpdate.conditions) { + extensionToUpdate.conditions.unshift(newCondition); + } else { + extensionToUpdate.conditions = [newCondition]; + } - // Update the extensions observable - this._extensions.setValue(allExtensions); + } catch (error) { + // TODO: [WB] Will this ever catch an error? + console.error(`Extension with alias ${alias} was never found and threw ${error}`); + } } /** @@ -505,7 +555,7 @@ export class UmbExtensionRegistry< * @param alias {string} - The alias of the extension to prepend the conditions to * @param newConditions {Array} - A collection of conditions to prepend to an extension. */ - prependConditions(alias: string, newConditions: Array) { + async prependConditions(alias: string, newConditions: Array): Promise { newConditions.forEach((condition) => this.prependCondition(alias, condition)); } } diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index 9745b0d139..baafe2af43 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,2 +1,33 @@ +import type { ManifestWithDynamicConditions, UmbConditionConfigBase, UmbEntryPointOnInit } from '@umbraco-cms/backoffice/extension-api'; +import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; + import './checkbox-list/components/index.js'; import './content-picker/components/index.js'; + +export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { + + console.log('HELLO AGAIN'); + + const condition: UmbConditionConfigBase = { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.WARRENYO', + } as WorkspaceAliasConditionConfig; + + _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); + + const ext:ManifestWithDynamicConditions = { + alias: 'Umb.Dashboard.UmbracoNewsLATE', + type: 'dashboard', + name: 'WARREN Package', + weight: 100, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.LATE-COMER-EXISTING', + } as WorkspaceAliasConditionConfig, + ], + }; + + _extensionRegistry.register(ext); + +}; From e2153992a7f2fdc1fa375ff046ef2142a8fad622 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 10:19:27 +0200 Subject: [PATCH 11/67] simplify _whenExtensionAliasIsRegistered --- .../registry/extension.registry.ts | 43 ++++++------------- 1 file changed, 14 insertions(+), 29 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 19c9701a0a..7e482d9d71 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -6,8 +6,16 @@ import type { } from '../types/index.js'; import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; -import type { Observable, Subscription } from '@umbraco-cms/backoffice/external/rxjs'; -import { map, distinctUntilChanged, combineLatest, of, switchMap, filter } from '@umbraco-cms/backoffice/external/rxjs'; +import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import { + map, + distinctUntilChanged, + combineLatest, + of, + switchMap, + filter, + firstValueFrom, +} from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -440,35 +448,15 @@ export class UmbExtensionRegistry< ) as Observable>; } - /** * Returns a promise that resolves when the extension with the specified alias is found. * @param alias {string} - The alias of the extension to wait for. * @returns {Promise} - A promise that resolves with the extension. */ - private _whenExtensionAliasIsRegistered(alias: string): Promise { - return new Promise((resolve, reject) => { - const subscription: Subscription = this.extensions - .pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))) - .subscribe({ - next: (allExtensions) => { - console.log('I AM IN NEXT', allExtensions); - const extension = allExtensions.find((ext) => ext.alias === alias); - if (extension) { - subscription.unsubscribe(); - resolve(extension as ManifestBase); - } - }, - error: (error) => { - console.error('I AM IN ERROR', error); - reject(error); - }, - complete: () => { - console.log('I AM IN COMPLETE'); - reject(new Error(`Extension with alias ${alias} not found`)); - }, - }); - }); + private async _whenExtensionAliasIsRegistered(alias: string): Promise { + const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); + const value = await firstValueFrom(source); + return value[0]; } /** @@ -481,7 +469,6 @@ export class UmbExtensionRegistry< */ async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { - // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -530,7 +517,6 @@ export class UmbExtensionRegistry< */ async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { - // Wait for the extension to be registered (as it could be registered late) const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -543,7 +529,6 @@ export class UmbExtensionRegistry< } else { extensionToUpdate.conditions = [newCondition]; } - } catch (error) { // TODO: [WB] Will this ever catch an error? console.error(`Extension with alias ${alias} was never found and threw ${error}`); From 8c40133392f5f5666288e9c39c2dd1315c5d02b8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 30 Aug 2024 10:22:24 +0200 Subject: [PATCH 12/67] split some tests --- .../registry/extension.registry.test.ts | 188 +++++++++--------- 1 file changed, 97 insertions(+), 91 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 94c5fccbf5..dd1e8612f9 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,5 +1,11 @@ import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; -import type { ManifestElementWithElementName, ManifestKind, ManifestBase, ManifestWithDynamicConditions, UmbConditionConfigBase } from '../types/index.js'; +import type { + ManifestElementWithElementName, + ManifestKind, + ManifestBase, + ManifestWithDynamicConditions, + UmbConditionConfigBase, +} from '../types/index.js'; import { UmbExtensionRegistry } from './extension.registry.js'; import { expect } from '@open-wc/testing'; @@ -457,9 +463,7 @@ describe('UmbExtensionRegistry with exclusions', () => { describe('Append Conditions', () => { let extensionRegistry: UmbExtensionRegistry; - let manifests: Array< - ManifestWithDynamicConditions - >; + let manifests: Array; beforeEach(() => { extensionRegistry = new UmbExtensionRegistry(); @@ -471,15 +475,15 @@ describe('Append Conditions', () => { weight: 1, conditions: [ { - alias: "Umb.Test.Condition.Valid" - } - ] + alias: 'Umb.Test.Condition.Valid', + }, + ], }, { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200 + weight: 200, }, ]; @@ -488,17 +492,18 @@ describe('Append Conditions', () => { extensionRegistry.register({ type: 'condition', name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid' + alias: 'Umb.Test.Condition.Invalid', }); }); - - it('allows an extension condition to be updated', async () => { + it('should have the extensions registered', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; + }); + it('allows an extension condition to be updated', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); @@ -506,12 +511,12 @@ describe('Append Conditions', () => { extensionRegistry.register({ type: 'condition', name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid' + alias: 'Umb.Test.Condition.Valid', }); // Add the new condition to the extension - const conditionToAdd:UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid' + const conditionToAdd: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid', }; await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); @@ -523,10 +528,9 @@ describe('Append Conditions', () => { expect(updatedExt.conditions?.length).to.equal(2); // Add a condition with a specific config to Section2 - const workspaceCondition:WorkspaceAliasConditionConfig = { + const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - + match: 'Umb.Workspace.Document', }; await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); @@ -538,15 +542,15 @@ describe('Append Conditions', () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); - const conditions:Array = [ + const conditions: Array = [ { - alias: 'Umb.Test.Condition.Valid' + alias: 'Umb.Test.Condition.Valid', }, { alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - } as WorkspaceAliasConditionConfig - ] + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); @@ -560,87 +564,89 @@ describe('Prepend Conditions', () => { let manifests: Array; beforeEach(() => { - extensionRegistry = new UmbExtensionRegistry(); - manifests = [ - { - type: 'section', - name: 'test-section-1', - alias: 'Umb.Test.Section.1', - weight: 1, - conditions: [ - { - alias: "Umb.Test.Condition.Valid" - } - ] - }, + extensionRegistry = new UmbExtensionRegistry(); + manifests = [ + { + type: 'section', + name: 'test-section-1', + alias: 'Umb.Test.Section.1', + weight: 1, + conditions: [ { - type: 'section', - name: 'test-section-2', - alias: 'Umb.Test.Section.2', - weight: 200 + alias: 'Umb.Test.Condition.Valid', }, - ]; + ], + }, + { + type: 'section', + name: 'test-section-2', + alias: 'Umb.Test.Section.2', + weight: 200, + }, + ]; - manifests.forEach((manifest) => extensionRegistry.register(manifest)); + manifests.forEach((manifest) => extensionRegistry.register(manifest)); - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid' - }); + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid', + }); + }); + + it('should have the extensions registered', () => { + expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; }); it('allows an extension condition to be prepended', async () => { - expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; - - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - - // Register new condition as if I was in my own entrypoint - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid' - }); - - // Prepend the new condition to the extension - const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid' - }; - - await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); - - // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; - - // Verify the extension now has two conditions and the new condition is prepended - const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); + + // Register new condition as if I was in my own entrypoint + extensionRegistry.register({ + type: 'condition', + name: 'test-condition-valid', + alias: 'Umb.Test.Condition.Valid', + }); + + // Prepend the new condition to the extension + const conditionToPrepend: UmbConditionConfigBase = { + alias: 'Umb.Test.Condition.Valid', + }; + + await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); + + // Check new condition is registered + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + + // Verify the extension now has two conditions and the new condition is prepended + const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); }); it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); + const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(ext.conditions?.length).to.equal(1); - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Valid' - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document' - } as WorkspaceAliasConditionConfig - ]; + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Valid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; - await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); }); }); From 3ee3cab0a380aacb9f2972a2c8a2ddb05f789e77 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 30 Aug 2024 11:43:31 +0100 Subject: [PATCH 13/67] Rework of tests to pass and minor fix to _whenExtensionAliasIsRegistered to get the ext alias that matches --- .../registry/extension.registry.test.ts | 56 +++++++++++-------- .../registry/extension.registry.ts | 21 +++---- 2 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index dd1e8612f9..e089f1bd17 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -475,7 +475,7 @@ describe('Append Conditions', () => { weight: 1, conditions: [ { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }, ], }, @@ -483,7 +483,7 @@ describe('Append Conditions', () => { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200, + weight: 200 }, ]; @@ -523,19 +523,23 @@ describe('Append Conditions', () => { // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; - // Verify the extension now has two conditions + // Verify the extension now has two conditions and in correct order with aliases const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(updatedExt.conditions?.length).to.equal(2); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); // Add a condition with a specific config to Section2 const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', match: 'Umb.Workspace.Document', }; + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); + expect(updatedWorkspaceExt.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); it('allows an extension to update with multiple conditions', async () => { @@ -555,7 +559,10 @@ describe('Append Conditions', () => { await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); }); @@ -582,59 +589,60 @@ describe('Prepend Conditions', () => { name: 'test-section-2', alias: 'Umb.Test.Section.2', weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], }, ]; manifests.forEach((manifest) => extensionRegistry.register(manifest)); - - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid', - }); }); it('should have the extensions registered', () => { expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.false; expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; }); it('allows an extension condition to be prepended', async () => { const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); + expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - // Register new condition as if I was in my own entrypoint extensionRegistry.register({ type: 'condition', - name: 'test-condition-valid', - alias: 'Umb.Test.Condition.Valid', + name: 'test-condition-invalid', + alias: 'Umb.Test.Condition.Invalid', }); // Prepend the new condition to the extension const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }; await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; + expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; // Verify the extension now has two conditions and the new condition is prepended const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); // Our new one prepended + expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); }); it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + const ext = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(ext.conditions?.length).to.equal(1); + expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); const conditions: Array = [ { - alias: 'Umb.Test.Condition.Valid', + alias: 'Umb.Test.Condition.Invalid', }, { alias: 'Umb.Condition.WorkspaceAlias', @@ -642,11 +650,15 @@ describe('Prepend Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.prependConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.prependConditions('Umb.Test.Section.2', conditions); - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; + const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); + + // The thing to note here our two new conditions is that are prepended in reverse order they are passed in + // as each one is prepended to the front of the array expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 7e482d9d71..91c06e1543 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -456,7 +456,8 @@ export class UmbExtensionRegistry< private async _whenExtensionAliasIsRegistered(alias: string): Promise { const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); const value = await firstValueFrom(source); - return value[0]; + const ext = value.find((ext) => ext.alias === alias) as ManifestBase; + return ext; } /** @@ -472,9 +473,6 @@ export class UmbExtensionRegistry< // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Got it... now carry on & mutate it - console.log('got the extension to update/mutate', extensionToWaitFor); - // Append the condition to the extensions conditions array if (extensionToWaitFor.conditions) { extensionToWaitFor.conditions.push(newCondition); @@ -490,10 +488,6 @@ export class UmbExtensionRegistry< // Update the main extensions collection/observable this._extensions.setValue(allExtensions); - - // Log the updated extensions for debugging - console.log('UPDATED extensions:', this._extensions.getValue()); - console.table(this._extensions.getValue()); } } catch (error) { // TODO: [WB] Will this ever catch an error? @@ -507,7 +501,9 @@ export class UmbExtensionRegistry< * @param newConditions {Array} - A collection of conditions to append to an extension. */ async appendConditions(alias: string, newConditions: Array): Promise { - newConditions.forEach((condition) => this.appendCondition(alias, condition)); + for (const condition of newConditions) { + await this.appendCondition(alias, condition); + } } /** @@ -520,9 +516,6 @@ export class UmbExtensionRegistry< // Wait for the extension to be registered (as it could be registered late) const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - // Got it... now carry on & mutate it - console.log('got the extension to update/mutate', extensionToUpdate); - // Append the condition to the extensions conditions array if (extensionToUpdate.conditions) { extensionToUpdate.conditions.unshift(newCondition); @@ -541,6 +534,8 @@ export class UmbExtensionRegistry< * @param newConditions {Array} - A collection of conditions to prepend to an extension. */ async prependConditions(alias: string, newConditions: Array): Promise { - newConditions.forEach((condition) => this.prependCondition(alias, condition)); + for (const condition of newConditions) { + await this.prependCondition(alias, condition); + } } } From ac415ca296c0654f0ef8ffbad934fd2f4922e940 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Fri, 30 Aug 2024 13:27:48 +0100 Subject: [PATCH 14/67] Trying to add a test to show that a late registered extension works - but test says otherwise compared to using it in entrypoint --- .../registry/extension.registry.test.ts | 46 ++++++++++++++++++- src/packages/property-editors/entry-point.ts | 20 +++++++- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index e089f1bd17..b38fdac8b2 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -483,7 +483,7 @@ describe('Append Conditions', () => { type: 'section', name: 'test-section-2', alias: 'Umb.Test.Section.2', - weight: 200 + weight: 200, }, ]; @@ -661,4 +661,48 @@ describe('Prepend Conditions', () => { expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); }); + + it('allows conditions to be prepended when an extension is loaded later on', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + console.log('About to go KABOOM..'); + + // Prepend the conditions + // [WB] HELP: Why is this fine when using in in an entrypoint + // /src/packages/property-editors/entry-point.ts + // But this TEST implodes if it can't find the extension that is not yet registered + await extensionRegistry.prependConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); }); diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index baafe2af43..64d64bc9c4 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,4 +1,8 @@ -import type { ManifestWithDynamicConditions, UmbConditionConfigBase, UmbEntryPointOnInit } from '@umbraco-cms/backoffice/extension-api'; +import type { + ManifestWithDynamicConditions, + UmbConditionConfigBase, + UmbEntryPointOnInit, +} from '@umbraco-cms/backoffice/extension-api'; import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; import './checkbox-list/components/index.js'; @@ -13,9 +17,16 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { match: 'Umb.Workspace.WARRENYO', } as WorkspaceAliasConditionConfig; + console.log( + 'Should not be false and not registered', + _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), + ); + _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - const ext:ManifestWithDynamicConditions = { + console.log('I HAZ APPENED CONDITIONS'); + + const ext: ManifestWithDynamicConditions = { alias: 'Umb.Dashboard.UmbracoNewsLATE', type: 'dashboard', name: 'WARREN Package', @@ -30,4 +41,9 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { _extensionRegistry.register(ext); + const amIRegistered = _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'); + console.log('Should be true and registered', amIRegistered); + + const getTheThing = _extensionRegistry.getByAlias('Umb.Dashboard.UmbracoNewsLATE'); + console.log('Should be the extension', getTheThing); }; From d3f7e28bc00aeedf63c605c2947a0dae38f266b7 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Sep 2024 17:18:21 +0100 Subject: [PATCH 15/67] Remove the prepend conditions and rename append to addCondition and addCondtions As the order of conditions is not important, as all conditions set on an extensions must be true/valid --- .../registry/extension.registry.ts | 43 +++---------------- 1 file changed, 5 insertions(+), 38 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index 91c06e1543..d4f984b4a8 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -461,14 +461,14 @@ export class UmbExtensionRegistry< } /** - * Appends a new condition to an existing extension + * Add a new condition to an existing extension * Useful to add a condition for example the Save And Publish workspace action shipped by core * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it * @param alias {string} - The alias of the extension to append the condition to * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. */ - async appendCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { + async addCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { try { // Wait for the extension to be registered (as it could be registered late) const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; @@ -496,46 +496,13 @@ export class UmbExtensionRegistry< } /** - * Appends a collection of conditions to an exsiting extension + * Adds a collection of conditions to an exsiting extension * @param alias {string} - The alias of the extension to append the condition to * @param newConditions {Array} - A collection of conditions to append to an extension. */ - async appendConditions(alias: string, newConditions: Array): Promise { + async addConditions(alias: string, newConditions: Array): Promise { for (const condition of newConditions) { - await this.appendCondition(alias, condition); - } - } - - /** - * Prepends a new condition to an existing extension - * @param alias {string} - The alias of the extension to prepend the condition to - * @param newCondition {UmbConditionConfigBase} - The condition to prepend to the extension. - */ - async prependCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { - try { - // Wait for the extension to be registered (as it could be registered late) - const extensionToUpdate = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - - // Append the condition to the extensions conditions array - if (extensionToUpdate.conditions) { - extensionToUpdate.conditions.unshift(newCondition); - } else { - extensionToUpdate.conditions = [newCondition]; - } - } catch (error) { - // TODO: [WB] Will this ever catch an error? - console.error(`Extension with alias ${alias} was never found and threw ${error}`); - } - } - - /** - * Prepends a collection of conditions to an existing extension - * @param alias {string} - The alias of the extension to prepend the conditions to - * @param newConditions {Array} - A collection of conditions to prepend to an extension. - */ - async prependConditions(alias: string, newConditions: Array): Promise { - for (const condition of newConditions) { - await this.prependCondition(alias, condition); + await this.addCondition(alias, condition); } } } From 18ce99a2061b9c25282b43d83ba8b3ba7e68d99e Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Mon, 2 Sep 2024 20:03:34 +0100 Subject: [PATCH 16/67] Update tests Still need to uncomment & reinvestigate the late loading test --- .../registry/extension.registry.test.ts | 191 +++++------------- 1 file changed, 47 insertions(+), 144 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index b38fdac8b2..feb27191c8 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -461,7 +461,7 @@ describe('UmbExtensionRegistry with exclusions', () => { }); }); -describe('Append Conditions', () => { +describe('Add Conditions', () => { let extensionRegistry: UmbExtensionRegistry; let manifests: Array; @@ -518,7 +518,7 @@ describe('Append Conditions', () => { const conditionToAdd: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid', }; - await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.addCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -535,7 +535,7 @@ describe('Append Conditions', () => { match: 'Umb.Workspace.Document', }; - await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.addCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); @@ -556,7 +556,7 @@ describe('Append Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.addConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); @@ -564,145 +564,48 @@ describe('Append Conditions', () => { expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); -}); - -describe('Prepend Conditions', () => { - let extensionRegistry: UmbExtensionRegistry; - let manifests: Array; - - beforeEach(() => { - extensionRegistry = new UmbExtensionRegistry(); - manifests = [ - { - type: 'section', - name: 'test-section-1', - alias: 'Umb.Test.Section.1', - weight: 1, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }, - { - type: 'section', - name: 'test-section-2', - alias: 'Umb.Test.Section.2', - weight: 200, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }, - ]; - - manifests.forEach((manifest) => extensionRegistry.register(manifest)); - }); - - it('should have the extensions registered', () => { - expect(extensionRegistry.isRegistered('Umb.Test.Section.1')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Section.2')).to.be.true; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.false; - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.false; - }); - - it('allows an extension condition to be prepended', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - - extensionRegistry.register({ - type: 'condition', - name: 'test-condition-invalid', - alias: 'Umb.Test.Condition.Invalid', - }); - - // Prepend the new condition to the extension - const conditionToPrepend: UmbConditionConfigBase = { - alias: 'Umb.Test.Condition.Invalid', - }; - - await extensionRegistry.prependCondition('Umb.Test.Section.1', conditionToPrepend); - - // Check new condition is registered - expect(extensionRegistry.isRegistered('Umb.Test.Condition.Invalid')).to.be.true; - - // Verify the extension now has two conditions and the new condition is prepended - const updatedExt = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; - expect(updatedExt.conditions?.length).to.equal(2); - expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); // Our new one prepended - expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); - - it('allows an extension to update with multiple prepended conditions', async () => { - const ext = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; - expect(ext.conditions?.length).to.equal(1); - expect(ext.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); - - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Invalid', - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document', - } as WorkspaceAliasConditionConfig, - ]; - - await extensionRegistry.prependConditions('Umb.Test.Section.2', conditions); - - const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - - // The thing to note here our two new conditions is that are prepended in reverse order they are passed in - // as each one is prepended to the front of the array - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); - - it('allows conditions to be prepended when an extension is loaded later on', async () => { - const conditions: Array = [ - { - alias: 'Umb.Test.Condition.Invalid', - }, - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.Document', - } as WorkspaceAliasConditionConfig, - ]; - console.log('About to go KABOOM..'); - - // Prepend the conditions - // [WB] HELP: Why is this fine when using in in an entrypoint - // /src/packages/property-editors/entry-point.ts - // But this TEST implodes if it can't find the extension that is not yet registered - await extensionRegistry.prependConditions('Late.Extension.To.Be.Loaded', conditions); - - // Make sure the extension is not registered YET - expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; - - // Register the extension LATE/after the conditions have been added - extensionRegistry.register({ - type: 'section', - name: 'Late Section Extension with one condition', - alias: 'Late.Extension.To.Be.Loaded', - weight: 200, - conditions: [ - { - alias: 'Umb.Test.Condition.Valid', - }, - ], - }); - - expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; - - const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; - expect(extUpdated.conditions?.length).to.equal(3); - expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - }); + // it('allows conditions to be prepended when an extension is loaded later on', async () => { + // const conditions: Array = [ + // { + // alias: 'Umb.Test.Condition.Invalid', + // }, + // { + // alias: 'Umb.Condition.WorkspaceAlias', + // match: 'Umb.Workspace.Document', + // } as WorkspaceAliasConditionConfig, + // ]; + + // console.log('About to go KABOOM..'); + + // // Prepend the conditions + // // [WB] HELP: Why is this fine when using in in an entrypoint + // // /src/packages/property-editors/entry-point.ts + // // But this TEST implodes if it can't find the extension that is not yet registered + // await extensionRegistry.addConditions('Late.Extension.To.Be.Loaded', conditions); + + // // Make sure the extension is not registered YET + // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // // Register the extension LATE/after the conditions have been added + // extensionRegistry.register({ + // type: 'section', + // name: 'Late Section Extension with one condition', + // alias: 'Late.Extension.To.Be.Loaded', + // weight: 200, + // conditions: [ + // { + // alias: 'Umb.Test.Condition.Valid', + // }, + // ], + // }); + + // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + // const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + // expect(extUpdated.conditions?.length).to.equal(3); + // expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + // expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + // expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); + // }); }); From a6faa5971115191c74055c2622a161e8eb91ef37 Mon Sep 17 00:00:00 2001 From: Warren Buckley Date: Tue, 3 Sep 2024 19:38:45 +0100 Subject: [PATCH 17/67] Fix up code so test passes & my rough entrypoint demo of usage works --- src/packages/property-editors/entry-point.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index 64d64bc9c4..f83895ac9b 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -22,9 +22,9 @@ export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), ); - _extensionRegistry.appendCondition('Umb.Dashboard.UmbracoNewsLATE', condition); + _extensionRegistry.addCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - console.log('I HAZ APPENED CONDITIONS'); + console.log('I HAZ ADDED CONDITION'); const ext: ManifestWithDynamicConditions = { alias: 'Umb.Dashboard.UmbracoNewsLATE', From eb197722317904423eeebe81e27d3a3f5550135f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 20:38:05 +0200 Subject: [PATCH 18/67] import type --- src/libs/extension-api/registry/extension.registry.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index feb27191c8..7f1d48752a 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -1,4 +1,4 @@ -import { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; +import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; import type { ManifestElementWithElementName, ManifestKind, From 8fd2cd03d375d682f3f137889b909d589fad3e79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 22:01:34 +0200 Subject: [PATCH 19/67] remove test code --- src/packages/property-editors/entry-point.ts | 47 -------------------- 1 file changed, 47 deletions(-) diff --git a/src/packages/property-editors/entry-point.ts b/src/packages/property-editors/entry-point.ts index f83895ac9b..9745b0d139 100644 --- a/src/packages/property-editors/entry-point.ts +++ b/src/packages/property-editors/entry-point.ts @@ -1,49 +1,2 @@ -import type { - ManifestWithDynamicConditions, - UmbConditionConfigBase, - UmbEntryPointOnInit, -} from '@umbraco-cms/backoffice/extension-api'; -import type { WorkspaceAliasConditionConfig } from '@umbraco-cms/backoffice/workspace'; - import './checkbox-list/components/index.js'; import './content-picker/components/index.js'; - -export const onInit: UmbEntryPointOnInit = (_host, _extensionRegistry) => { - - console.log('HELLO AGAIN'); - - const condition: UmbConditionConfigBase = { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.WARRENYO', - } as WorkspaceAliasConditionConfig; - - console.log( - 'Should not be false and not registered', - _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'), - ); - - _extensionRegistry.addCondition('Umb.Dashboard.UmbracoNewsLATE', condition); - - console.log('I HAZ ADDED CONDITION'); - - const ext: ManifestWithDynamicConditions = { - alias: 'Umb.Dashboard.UmbracoNewsLATE', - type: 'dashboard', - name: 'WARREN Package', - weight: 100, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: 'Umb.Workspace.LATE-COMER-EXISTING', - } as WorkspaceAliasConditionConfig, - ], - }; - - _extensionRegistry.register(ext); - - const amIRegistered = _extensionRegistry.isRegistered('Umb.Dashboard.UmbracoNewsLATE'); - console.log('Should be true and registered', amIRegistered); - - const getTheThing = _extensionRegistry.getByAlias('Umb.Dashboard.UmbracoNewsLATE'); - console.log('Should be the extension', getTheThing); -}; From 95031c913f0d2ee55a541774ee5eb31b82c8ac0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 12 Sep 2024 22:01:45 +0200 Subject: [PATCH 20/67] refactor for a more direct appending implementation --- .../registry/extension.registry.test.ts | 164 +++++++++++++----- .../registry/extension.registry.ts | 120 ++++++------- 2 files changed, 178 insertions(+), 106 deletions(-) diff --git a/src/libs/extension-api/registry/extension.registry.test.ts b/src/libs/extension-api/registry/extension.registry.test.ts index 7f1d48752a..caed039f60 100644 --- a/src/libs/extension-api/registry/extension.registry.test.ts +++ b/src/libs/extension-api/registry/extension.registry.test.ts @@ -518,7 +518,7 @@ describe('Add Conditions', () => { const conditionToAdd: UmbConditionConfigBase = { alias: 'Umb.Test.Condition.Valid', }; - await extensionRegistry.addCondition('Umb.Test.Section.1', conditionToAdd); + await extensionRegistry.appendCondition('Umb.Test.Section.1', conditionToAdd); // Check new condition is registered expect(extensionRegistry.isRegistered('Umb.Test.Condition.Valid')).to.be.true; @@ -529,13 +529,17 @@ describe('Add Conditions', () => { expect(updatedExt.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Invalid'); expect(updatedExt.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Valid'); + // Verify the other extension was not updated: + const otherExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; + expect(otherExt.conditions).to.be.undefined; + // Add a condition with a specific config to Section2 const workspaceCondition: WorkspaceAliasConditionConfig = { alias: 'Umb.Condition.WorkspaceAlias', match: 'Umb.Workspace.Document', }; - await extensionRegistry.addCondition('Umb.Test.Section.2', workspaceCondition); + await extensionRegistry.appendCondition('Umb.Test.Section.2', workspaceCondition); const updatedWorkspaceExt = extensionRegistry.getByAlias('Umb.Test.Section.2') as ManifestWithDynamicConditions; expect(updatedWorkspaceExt.conditions?.length).to.equal(1); @@ -556,7 +560,7 @@ describe('Add Conditions', () => { } as WorkspaceAliasConditionConfig, ]; - await extensionRegistry.addConditions('Umb.Test.Section.1', conditions); + await extensionRegistry.appendConditions('Umb.Test.Section.1', conditions); const extUpdated = extensionRegistry.getByAlias('Umb.Test.Section.1') as ManifestWithDynamicConditions; expect(extUpdated.conditions?.length).to.equal(3); @@ -565,47 +569,115 @@ describe('Add Conditions', () => { expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); }); - // it('allows conditions to be prepended when an extension is loaded later on', async () => { - // const conditions: Array = [ - // { - // alias: 'Umb.Test.Condition.Invalid', - // }, - // { - // alias: 'Umb.Condition.WorkspaceAlias', - // match: 'Umb.Workspace.Document', - // } as WorkspaceAliasConditionConfig, - // ]; - - // console.log('About to go KABOOM..'); - - // // Prepend the conditions - // // [WB] HELP: Why is this fine when using in in an entrypoint - // // /src/packages/property-editors/entry-point.ts - // // But this TEST implodes if it can't find the extension that is not yet registered - // await extensionRegistry.addConditions('Late.Extension.To.Be.Loaded', conditions); - - // // Make sure the extension is not registered YET - // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; - - // // Register the extension LATE/after the conditions have been added - // extensionRegistry.register({ - // type: 'section', - // name: 'Late Section Extension with one condition', - // alias: 'Late.Extension.To.Be.Loaded', - // weight: 200, - // conditions: [ - // { - // alias: 'Umb.Test.Condition.Valid', - // }, - // ], - // }); - - // expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; - - // const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; - // expect(extUpdated.conditions?.length).to.equal(3); - // expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); - // expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); - // expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Test.Condition.Valid'); - // }); + it('allows conditions to be prepended when an extension is loaded later on', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + // Prepend the conditions, but do not await this. + extensionRegistry.appendConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdated = extensionRegistry.getByAlias('Late.Extension.To.Be.Loaded') as ManifestWithDynamicConditions; + + expect(extUpdated.conditions?.length).to.equal(3); + expect(extUpdated.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + expect(extUpdated.conditions?.[1]?.alias).to.equal('Umb.Test.Condition.Invalid'); + expect(extUpdated.conditions?.[2]?.alias).to.equal('Umb.Condition.WorkspaceAlias'); + }); + + /** + * As of current state, it is by design without further reasons to why, but it is made so additional conditions are only added to a current or next time registered manifest. + * Meaning if it happens to be unregistered and re-registered it does not happen again. + * Unless the exact same appending of conditions happens again. [NL] + * + * This makes sense if extensions gets offloaded and re-registered, but the extension that registered additional conditions didn't get loaded/registered second time. Therefor they need to be re-registered for such to work. [NL] + */ + it('only append conditions to the next time the extension is registered', async () => { + const conditions: Array = [ + { + alias: 'Umb.Test.Condition.Invalid', + }, + { + alias: 'Umb.Condition.WorkspaceAlias', + match: 'Umb.Workspace.Document', + } as WorkspaceAliasConditionConfig, + ]; + + // Prepend the conditions, but do not await this. + extensionRegistry.appendConditions('Late.Extension.To.Be.Loaded', conditions); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdateFirstTime = extensionRegistry.getByAlias( + 'Late.Extension.To.Be.Loaded', + ) as ManifestWithDynamicConditions; + expect(extUpdateFirstTime.conditions?.length).to.equal(3); + + extensionRegistry.unregister('Late.Extension.To.Be.Loaded'); + + // Make sure the extension is not registered YET + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.false; + + // Register the extension LATE/after the conditions have been added + extensionRegistry.register({ + type: 'section', + name: 'Late Section Extension with one condition', + alias: 'Late.Extension.To.Be.Loaded', + weight: 200, + conditions: [ + { + alias: 'Umb.Test.Condition.Valid', + }, + ], + }); + + expect(extensionRegistry.isRegistered('Late.Extension.To.Be.Loaded')).to.be.true; + + const extUpdateSecondTime = extensionRegistry.getByAlias( + 'Late.Extension.To.Be.Loaded', + ) as ManifestWithDynamicConditions; + + expect(extUpdateSecondTime.conditions?.length).to.equal(1); + expect(extUpdateSecondTime.conditions?.[0]?.alias).to.equal('Umb.Test.Condition.Valid'); + }); }); diff --git a/src/libs/extension-api/registry/extension.registry.ts b/src/libs/extension-api/registry/extension.registry.ts index d4f984b4a8..6ff5762ca7 100644 --- a/src/libs/extension-api/registry/extension.registry.ts +++ b/src/libs/extension-api/registry/extension.registry.ts @@ -7,15 +7,7 @@ import type { import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; import { UmbBasicState } from '@umbraco-cms/backoffice/observable-api'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; -import { - map, - distinctUntilChanged, - combineLatest, - of, - switchMap, - filter, - firstValueFrom, -} from '@umbraco-cms/backoffice/external/rxjs'; +import { map, distinctUntilChanged, combineLatest, of, switchMap } from '@umbraco-cms/backoffice/external/rxjs'; /** * @@ -117,8 +109,26 @@ export class UmbExtensionRegistry< private _kinds = new UmbBasicState>>([]); public readonly kinds = this._kinds.asObservable(); + #exclusions: Array = []; + #additionalConditions: Map> = new Map(); + #appendAdditionalConditions(manifest: ManifestTypes) { + const newConditions = this.#additionalConditions.get(manifest.alias); + if (newConditions) { + // Append the condition to the extensions conditions array + if ((manifest as ManifestWithDynamicConditions).conditions) { + for (const condition of newConditions) { + (manifest as ManifestWithDynamicConditions).conditions!.push(condition); + } + } else { + (manifest as ManifestWithDynamicConditions).conditions = newConditions; + } + this.#additionalConditions.delete(manifest.alias); + } + return manifest; + } + defineKind(kind: ManifestKind): void { const extensionsValues = this._extensions.getValue(); const extension = extensionsValues.find( @@ -153,12 +163,25 @@ export class UmbExtensionRegistry< }; register(manifest: ManifestTypes | ManifestKind): void { - const isValid = this.#checkExtension(manifest); + const isValid = this.#validateExtension(manifest); if (!isValid) { return; } - this._extensions.setValue([...this._extensions.getValue(), manifest as ManifestTypes]); + if (manifest.type === 'kind') { + this.defineKind(manifest as ManifestKind); + return; + } + + const isApproved = this.#isExtensionApproved(manifest); + if (!isApproved) { + return; + } + + this._extensions.setValue([ + ...this._extensions.getValue(), + this.#appendAdditionalConditions(manifest as ManifestTypes), + ]); } getAllExtensions(): Array { @@ -194,7 +217,7 @@ export class UmbExtensionRegistry< return false; } - #checkExtension(manifest: ManifestTypes | ManifestKind): boolean { + #validateExtension(manifest: ManifestTypes | ManifestKind): boolean { if (!manifest.type) { console.error(`Extension is missing type`, manifest); return false; @@ -205,11 +228,9 @@ export class UmbExtensionRegistry< return false; } - if (manifest.type === 'kind') { - this.defineKind(manifest as ManifestKind); - return false; - } - + return true; + } + #isExtensionApproved(manifest: ManifestTypes | ManifestKind): boolean { if (!this.#acceptExtension(manifest as ManifestTypes)) { return false; } @@ -449,60 +470,39 @@ export class UmbExtensionRegistry< } /** - * Returns a promise that resolves when the extension with the specified alias is found. - * @param alias {string} - The alias of the extension to wait for. - * @returns {Promise} - A promise that resolves with the extension. + * Append a new condition to an existing extension + * Useful to add a condition for example the Save And Publish workspace action shipped by core. + * @param {string} alias - The alias of the extension to append the condition to. + * @param {UmbConditionConfigBase} newCondition - The condition to append to the extension. */ - private async _whenExtensionAliasIsRegistered(alias: string): Promise { - const source = this.extensions.pipe(filter((allExtensions) => allExtensions.some((ext) => ext.alias === alias))); - const value = await firstValueFrom(source); - const ext = value.find((ext) => ext.alias === alias) as ManifestBase; - return ext; + appendCondition(alias: string, newCondition: UmbConditionConfigBase) { + this.appendConditions(alias, [newCondition]); } /** - * Add a new condition to an existing extension - * Useful to add a condition for example the Save And Publish workspace action shipped by core - * As overwriting the whole extension to simply add an extra condition is not ideal as it causes a lot of duplicated code - * and could easily get out of sync from the CMS core implementation if a 3rd party dev was to try and overwrite it - * @param alias {string} - The alias of the extension to append the condition to - * @param newCondition {UmbConditionConfigBase} - The condition to append to the extension. + * Appends an array of conditions to an existing extension + * @param {string} alias - The alias of the extension to append the condition to + * @param {Array} newConditions - An array of conditions to be appended to an extension manifest. */ - async addCondition(alias: string, newCondition: UmbConditionConfigBase): Promise { - try { - // Wait for the extension to be registered (as it could be registered late) - const extensionToWaitFor = (await this._whenExtensionAliasIsRegistered(alias)) as ManifestWithDynamicConditions; - - // Append the condition to the extensions conditions array - if (extensionToWaitFor.conditions) { - extensionToWaitFor.conditions.push(newCondition); - } else { - extensionToWaitFor.conditions = [newCondition]; - } + appendConditions(alias: string, newConditions: Array) { + const existingConditionsToBeAdded = this.#additionalConditions.get(alias); + this.#additionalConditions.set( + alias, + existingConditionsToBeAdded ? [...existingConditionsToBeAdded, ...newConditions] : newConditions, + ); - const allExtensions = this._extensions.getValue(); - const extensionToUpdateIndex = allExtensions.findIndex((ext) => ext.alias === alias); - if (extensionToUpdateIndex !== -1) { + const allExtensions = this._extensions.getValue(); + for (const extension of allExtensions) { + if (extension.alias === alias) { // Replace the existing extension with the updated one - allExtensions[extensionToUpdateIndex] = extensionToWaitFor as ManifestTypes; + allExtensions[allExtensions.indexOf(extension)] = this.#appendAdditionalConditions(extension as ManifestTypes); // Update the main extensions collection/observable this._extensions.setValue(allExtensions); - } - } catch (error) { - // TODO: [WB] Will this ever catch an error? - console.error(`Extension with alias ${alias} was never found and threw ${error}`); - } - } - /** - * Adds a collection of conditions to an exsiting extension - * @param alias {string} - The alias of the extension to append the condition to - * @param newConditions {Array} - A collection of conditions to append to an extension. - */ - async addConditions(alias: string, newConditions: Array): Promise { - for (const condition of newConditions) { - await this.addCondition(alias, condition); + //Stop the search: + break; + } } } } From 8946912450f155acc3acf4757636c7b42fa9cfea Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 21:43:54 +0200 Subject: [PATCH 21/67] register user sidebar menu --- src/packages/settings/advanced/manifests.ts | 6 ++-- src/packages/user/manifests.ts | 2 +- .../{user-section => section}/constants.ts | 0 .../user/{user-section => section}/index.ts | 0 src/packages/user/section/manifests.ts | 31 +++++++++++++++++++ src/packages/user/section/menu/constants.ts | 1 + src/packages/user/section/menu/index.ts | 1 + src/packages/user/section/menu/manifests.ts | 9 ++++++ .../user/{user-section => section}/paths.ts | 0 .../user/section/sidebar-app/index.ts | 1 + .../user/section/sidebar-app/manifests.ts | 23 ++++++++++++++ .../user/user-group/section-view/manifests.ts | 2 +- src/packages/user/user-section/manifests.ts | 21 ------------- .../user/user/section-view/manifests.ts | 2 +- 14 files changed, 72 insertions(+), 27 deletions(-) rename src/packages/user/{user-section => section}/constants.ts (100%) rename src/packages/user/{user-section => section}/index.ts (100%) create mode 100644 src/packages/user/section/manifests.ts create mode 100644 src/packages/user/section/menu/constants.ts create mode 100644 src/packages/user/section/menu/index.ts create mode 100644 src/packages/user/section/menu/manifests.ts rename src/packages/user/{user-section => section}/paths.ts (100%) create mode 100644 src/packages/user/section/sidebar-app/index.ts create mode 100644 src/packages/user/section/sidebar-app/manifests.ts delete mode 100644 src/packages/user/user-section/manifests.ts diff --git a/src/packages/settings/advanced/manifests.ts b/src/packages/settings/advanced/manifests.ts index 5a452d9e3d..3931a9edb9 100644 --- a/src/packages/settings/advanced/manifests.ts +++ b/src/packages/settings/advanced/manifests.ts @@ -10,11 +10,11 @@ export const manifests = [ { type: 'sectionSidebarApp', kind: 'menu', - alias: 'Umb.SectionSidebarMenu.AdvancedSettings', - name: 'Advanced Settings Sidebar Menu', + alias: 'Umb.SectionSidebarApp.Menu.Users', + name: 'Users Section Sidebar Menu', weight: 100, meta: { - label: '#treeHeaders_advancedGroup', + label: 'Users', menu: UMB_ADVANCED_SETTINGS_MENU_ALIAS, }, conditions: [ diff --git a/src/packages/user/manifests.ts b/src/packages/user/manifests.ts index 96353d28f7..d649d8f06f 100644 --- a/src/packages/user/manifests.ts +++ b/src/packages/user/manifests.ts @@ -1,6 +1,6 @@ import { manifests as userGroupManifests } from './user-group/manifests.js'; import { manifests as userManifests } from './user/manifests.js'; -import { manifests as userSectionManifests } from './user-section/manifests.js'; +import { manifests as userSectionManifests } from './section/manifests.js'; import { manifests as currentUserManifests } from './current-user/manifests.js'; import { manifests as userPermissionManifests } from './user-permission/manifests.js'; import { manifests as changePasswordManifests } from './change-password/manifests.js'; diff --git a/src/packages/user/user-section/constants.ts b/src/packages/user/section/constants.ts similarity index 100% rename from src/packages/user/user-section/constants.ts rename to src/packages/user/section/constants.ts diff --git a/src/packages/user/user-section/index.ts b/src/packages/user/section/index.ts similarity index 100% rename from src/packages/user/user-section/index.ts rename to src/packages/user/section/index.ts diff --git a/src/packages/user/section/manifests.ts b/src/packages/user/section/manifests.ts new file mode 100644 index 0000000000..bb49da5322 --- /dev/null +++ b/src/packages/user/section/manifests.ts @@ -0,0 +1,31 @@ +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from './constants.js'; +import { manifests as sectionSidebarAppManifests } from './sidebar-app/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; +import type { + ManifestSection, + ManifestTypes, + UmbBackofficeManifestKind, +} from '@umbraco-cms/backoffice/extension-registry'; + +const section: ManifestSection = { + type: 'section', + alias: UMB_USER_MANAGEMENT_SECTION_ALIAS, + name: 'User Management Section', + weight: 600, + meta: { + label: '#sections_users', + pathname: 'user-management', + }, + conditions: [ + { + alias: 'Umb.Condition.SectionUserPermission', + match: UMB_USER_MANAGEMENT_SECTION_ALIAS, + }, + ], +}; + +export const manifests: Array = [ + section, + ...sectionSidebarAppManifests, + ...menuManifests, +]; diff --git a/src/packages/user/section/menu/constants.ts b/src/packages/user/section/menu/constants.ts new file mode 100644 index 0000000000..7bf050d53c --- /dev/null +++ b/src/packages/user/section/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_MANAGEMENT_MENU_ALIAS = 'Umb.Menu.UserManagement'; diff --git a/src/packages/user/section/menu/index.ts b/src/packages/user/section/menu/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/section/menu/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/section/menu/manifests.ts b/src/packages/user/section/menu/manifests.ts new file mode 100644 index 0000000000..f5852aa534 --- /dev/null +++ b/src/packages/user/section/menu/manifests.ts @@ -0,0 +1,9 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from './constants.js'; + +export const manifests = [ + { + type: 'menu', + alias: UMB_USER_MANAGEMENT_MENU_ALIAS, + name: 'User Management Menu', + }, +]; diff --git a/src/packages/user/user-section/paths.ts b/src/packages/user/section/paths.ts similarity index 100% rename from src/packages/user/user-section/paths.ts rename to src/packages/user/section/paths.ts diff --git a/src/packages/user/section/sidebar-app/index.ts b/src/packages/user/section/sidebar-app/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/section/sidebar-app/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/section/sidebar-app/manifests.ts b/src/packages/user/section/sidebar-app/manifests.ts new file mode 100644 index 0000000000..f21d698bc2 --- /dev/null +++ b/src/packages/user/section/sidebar-app/manifests.ts @@ -0,0 +1,23 @@ +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../constants.js'; +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../menu/index.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'sectionSidebarApp', + kind: 'menu', + alias: 'Umb.SectionSidebarApp.Menu.UserManagement', + name: 'User Management Menu Sidebar App', + weight: 100, + meta: { + label: '#treeHeaders_users', + menu: UMB_USER_MANAGEMENT_MENU_ALIAS, + }, + conditions: [ + { + alias: 'Umb.Condition.SectionAlias', + match: UMB_USER_MANAGEMENT_SECTION_ALIAS, + }, + ], + }, +]; diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/section-view/manifests.ts index 3780224244..f4549d458f 100644 --- a/src/packages/user/user-group/section-view/manifests.ts +++ b/src/packages/user/user-group/section-view/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../user-section/index.js'; +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const sectionsViews: Array = [ diff --git a/src/packages/user/user-section/manifests.ts b/src/packages/user/user-section/manifests.ts deleted file mode 100644 index 74bb597e28..0000000000 --- a/src/packages/user/user-section/manifests.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from './constants.js'; -import type { ManifestSection, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; - -const section: ManifestSection = { - type: 'section', - alias: UMB_USER_MANAGEMENT_SECTION_ALIAS, - name: 'User Management Section', - weight: 600, - meta: { - label: '#sections_users', - pathname: 'user-management', - }, - conditions: [ - { - alias: 'Umb.Condition.SectionUserPermission', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], -}; - -export const manifests: Array = [section]; diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index a9dbcd430b..8af99c6b24 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../user-section/index.js'; +import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; const sectionsViews: Array = [ From 26666fdb56fcddc908b3778566c69ccf76759ca7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 21:56:10 +0200 Subject: [PATCH 22/67] register root workspace --- src/packages/user/user/manifests.ts | 6 +- src/packages/user/user/menu-item/manifests.ts | 18 +++++ .../user/user/section-view/manifests.ts | 27 +++----- .../user-root-workspace-view.element.ts | 21 ++++++ .../users-section-view.element.ts | 67 ------------------- 5 files changed, 51 insertions(+), 88 deletions(-) create mode 100644 src/packages/user/user/menu-item/manifests.ts create mode 100644 src/packages/user/user/section-view/user-root-workspace-view.element.ts delete mode 100644 src/packages/user/user/section-view/users-section-view.element.ts diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index 3eae6c756b..d842d25b03 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -9,9 +9,10 @@ import { manifests as propertyEditorManifests } from './property-editor/manifest import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; +import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...clientCredentialManifests, ...collectionManifests, ...conditionsManifests, @@ -23,4 +24,5 @@ export const manifests: Array = [ ...repositoryManifests, ...sectionViewManifests, ...workspaceManifests, + ...menuItemManifests, ]; diff --git a/src/packages/user/user/menu-item/manifests.ts b/src/packages/user/user/menu-item/manifests.ts new file mode 100644 index 0000000000..2239c2fe0f --- /dev/null +++ b/src/packages/user/user/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.Users', + name: 'Users Menu Item', + weight: 100, + meta: { + label: '#treeHeaders_users', + icon: 'icon-user', + entityType: UMB_USER_ROOT_ENTITY_TYPE, + menus: [UMB_USER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index 8af99c6b24..aef4c6370e 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -1,25 +1,14 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const sectionsViews: Array = [ +export const manifests: Array = [ { - type: 'sectionView', - alias: 'Umb.SectionView.Users', - name: 'Users Section View', - js: () => import('./users-section-view.element.js'), - weight: 200, + type: 'workspace', + alias: 'Umb.Workspace.UserRoot', + name: 'User Root Workspace View', + element: () => import('./user-root-workspace-view.element.js'), meta: { - label: '#general_users', - pathname: 'users', - icon: 'icon-user', + entityType: UMB_USER_ROOT_ENTITY_TYPE, }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], }, ]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/user/user/section-view/user-root-workspace-view.element.ts b/src/packages/user/user/section-view/user-root-workspace-view.element.ts new file mode 100644 index 0000000000..6e286dada3 --- /dev/null +++ b/src/packages/user/user/section-view/user-root-workspace-view.element.ts @@ -0,0 +1,21 @@ +import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-user-root-workspace'; +@customElement(elementName) +export class UmbUserRootWorkspaceElement extends UmbLitElement { + override render() { + return html` + ; + `; + } +} + +export { UmbUserRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserRootWorkspaceElement; + } +} diff --git a/src/packages/user/user/section-view/users-section-view.element.ts b/src/packages/user/user/section-view/users-section-view.element.ts deleted file mode 100644 index 22f9d5069d..0000000000 --- a/src/packages/user/user/section-view/users-section-view.element.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; -import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; -import { UmbWorkspaceElement } from '@umbraco-cms/backoffice/workspace'; -import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; - -@customElement('umb-section-view-users') -export class UmbSectionViewUsersElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = new UmbCollectionElement(); - const entityContext = new UmbEntityContext(element); - entityContext.setEntityType(UMB_USER_ROOT_ENTITY_TYPE); - entityContext.setUnique(null); - element.setAttribute('alias', UMB_USER_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'user', - component: () => { - const element = new UmbWorkspaceElement(); - element.setAttribute('entity-type', UMB_USER_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html` `; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbSectionViewUsersElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-section-view-users': UmbSectionViewUsersElement; - } -} From 52385eef3ea615536a9a989c5e92a70f02140da0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 08:53:01 +0200 Subject: [PATCH 23/67] register user group menu item --- src/packages/user/user-group/entity.ts | 2 + src/packages/user/user-group/manifests.ts | 19 +++--- .../user/user-group/menu-item/manifests.ts | 18 ++++++ .../user/user-group/section-view/manifests.ts | 27 +++----- .../user-group-root-workspace.element.ts | 21 +++++++ .../user-group-section-view.element.ts | 63 ------------------- src/packages/user/user/menu-item/manifests.ts | 2 +- .../user/user/section-view/manifests.ts | 2 +- ...ment.ts => user-root-workspace.element.ts} | 0 9 files changed, 62 insertions(+), 92 deletions(-) create mode 100644 src/packages/user/user-group/menu-item/manifests.ts create mode 100644 src/packages/user/user-group/section-view/user-group-root-workspace.element.ts delete mode 100644 src/packages/user/user-group/section-view/user-group-section-view.element.ts rename src/packages/user/user/section-view/{user-root-workspace-view.element.ts => user-root-workspace.element.ts} (100%) diff --git a/src/packages/user/user-group/entity.ts b/src/packages/user/user-group/entity.ts index 40fc592fed..3978bfa6a5 100644 --- a/src/packages/user/user-group/entity.ts +++ b/src/packages/user/user-group/entity.ts @@ -1,3 +1,5 @@ export const UMB_USER_GROUP_ENTITY_TYPE = 'user-group'; +export const UMB_USER_GROUP_ROOT_ENTITY_TYPE = 'user-group-root'; export type UmbUserGroupEntityType = typeof UMB_USER_GROUP_ENTITY_TYPE; +export type UmbUserGroupRootEntityType = typeof UMB_USER_GROUP_ROOT_ENTITY_TYPE; diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index 4a03fbb339..1ac88d4e75 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -1,18 +1,21 @@ import { manifests as collectionManifests } from './collection/manifests.js'; -import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as workspaceManifests } from './workspace/manifests.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as entityActionManifests } from './entity-actions/manifests.js'; import { manifests as entityBulkActionManifests } from './entity-bulk-actions/manifests.js'; +import { manifests as menuItemManifests } from './menu-item/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; +import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as sectionViewManifests } from './section-view/manifests.js'; +import { manifests as workspaceManifests } from './workspace/manifests.js'; + import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ ...collectionManifests, - ...repositoryManifests, - ...workspaceManifests, - ...modalManifests, - ...sectionViewManifests, ...entityActionManifests, ...entityBulkActionManifests, + ...menuItemManifests, + ...modalManifests, + ...repositoryManifests, + ...sectionViewManifests, + ...workspaceManifests, ]; diff --git a/src/packages/user/user-group/menu-item/manifests.ts b/src/packages/user/user-group/menu-item/manifests.ts new file mode 100644 index 0000000000..1c770acdae --- /dev/null +++ b/src/packages/user/user-group/menu-item/manifests.ts @@ -0,0 +1,18 @@ +import { UMB_USER_MANAGEMENT_MENU_ALIAS } from '../../section/menu/constants.js'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menuItem', + alias: 'Umb.MenuItem.UserGroups', + name: 'User Groups Menu Item', + weight: 100, + meta: { + label: '#user_usergroups', + icon: 'icon-users', + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, + menus: [UMB_USER_MANAGEMENT_MENU_ALIAS], + }, + }, +]; diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/section-view/manifests.ts index f4549d458f..ade0536011 100644 --- a/src/packages/user/user-group/section-view/manifests.ts +++ b/src/packages/user/user-group/section-view/manifests.ts @@ -1,25 +1,14 @@ -import { UMB_USER_MANAGEMENT_SECTION_ALIAS } from '../../section/index.js'; -import type { ManifestSectionView, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const sectionsViews: Array = [ +export const manifests: Array = [ { - type: 'sectionView', - alias: 'Umb.SectionView.UserGroup', - name: 'User Group Section View', - js: () => import('./user-group-section-view.element.js'), - weight: 100, + type: 'workspace', + alias: 'Umb.Workspace.UserGroupRoot', + name: 'User Group Root Workspace View', + element: () => import('./user-group-root-workspace.element.js'), meta: { - label: '#user_usergroups', - pathname: 'user-groups', - icon: 'icon-users', + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, }, - conditions: [ - { - alias: 'Umb.Condition.SectionAlias', - match: UMB_USER_MANAGEMENT_SECTION_ALIAS, - }, - ], }, ]; - -export const manifests: Array = [...sectionsViews]; diff --git a/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts b/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts new file mode 100644 index 0000000000..f02687d62d --- /dev/null +++ b/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts @@ -0,0 +1,21 @@ +import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; +import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; + +const elementName = 'umb-user-group-root-workspace'; +@customElement(elementName) +export class UmbUserGroupRootWorkspaceElement extends UmbLitElement { + override render() { + return html` + ; + `; + } +} + +export { UmbUserGroupRootWorkspaceElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserGroupRootWorkspaceElement; + } +} diff --git a/src/packages/user/user-group/section-view/user-group-section-view.element.ts b/src/packages/user/user-group/section-view/user-group-section-view.element.ts deleted file mode 100644 index 4611f0962d..0000000000 --- a/src/packages/user/user-group/section-view/user-group-section-view.element.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from '../entity.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbRoute } from '@umbraco-cms/backoffice/router'; -import { UmbCollectionElement } from '@umbraco-cms/backoffice/collection'; -import { UmbWorkspaceElement } from '@umbraco-cms/backoffice/workspace'; - -@customElement('umb-user-group-section-view') -export class UmbUserGroupSectionViewElement extends UmbLitElement { - #routes: UmbRoute[] = [ - { - path: 'collection', - component: () => { - const element = new UmbCollectionElement(); - element.setAttribute('alias', UMB_USER_GROUP_COLLECTION_ALIAS); - return element; - }, - }, - { - path: 'user-group', - component: () => { - const element = new UmbWorkspaceElement(); - element.setAttribute('entity-type', UMB_USER_GROUP_ENTITY_TYPE); - return element; - }, - }, - { - path: '', - redirectTo: 'collection', - }, - { - path: `**`, - component: async () => (await import('@umbraco-cms/backoffice/router')).UmbRouteNotFoundElement, - }, - ]; - - override render() { - return html``; - } - - static override styles = [ - UmbTextStyles, - css` - :host { - height: 100%; - } - - #router-slot { - height: calc(100% - var(--umb-header-layout-height)); - } - `, - ]; -} - -export default UmbUserGroupSectionViewElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-user-group-section-view': UmbUserGroupSectionViewElement; - } -} diff --git a/src/packages/user/user/menu-item/manifests.ts b/src/packages/user/user/menu-item/manifests.ts index 2239c2fe0f..c1980c58ef 100644 --- a/src/packages/user/user/menu-item/manifests.ts +++ b/src/packages/user/user/menu-item/manifests.ts @@ -7,7 +7,7 @@ export const manifests: Array = [ type: 'menuItem', alias: 'Umb.MenuItem.Users', name: 'Users Menu Item', - weight: 100, + weight: 200, meta: { label: '#treeHeaders_users', icon: 'icon-user', diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/section-view/manifests.ts index aef4c6370e..96eea28eda 100644 --- a/src/packages/user/user/section-view/manifests.ts +++ b/src/packages/user/user/section-view/manifests.ts @@ -6,7 +6,7 @@ export const manifests: Array = [ type: 'workspace', alias: 'Umb.Workspace.UserRoot', name: 'User Root Workspace View', - element: () => import('./user-root-workspace-view.element.js'), + element: () => import('./user-root-workspace.element.js'), meta: { entityType: UMB_USER_ROOT_ENTITY_TYPE, }, diff --git a/src/packages/user/user/section-view/user-root-workspace-view.element.ts b/src/packages/user/user/section-view/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/section-view/user-root-workspace-view.element.ts rename to src/packages/user/user/section-view/user-root-workspace.element.ts From d86e4e76231ecbf88a66ce43085867b2d2ab1a9b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 12:55:06 +0200 Subject: [PATCH 24/67] update import path --- src/packages/user/user-group/paths.ts | 2 +- src/packages/user/user/paths.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user-group/paths.ts b/src/packages/user/user-group/paths.ts index 6fc1f8cc7e..bcd681d6dc 100644 --- a/src/packages/user/user-group/paths.ts +++ b/src/packages/user/user-group/paths.ts @@ -1,4 +1,4 @@ -import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/paths.ts b/src/packages/user/user/paths.ts index e9040e7270..eb80086f08 100644 --- a/src/packages/user/user/paths.ts +++ b/src/packages/user/user/paths.ts @@ -1,4 +1,4 @@ -import { UMB_USER_SECTION_PATHNAME } from '../user-section/paths.js'; +import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; import { UMB_USER_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; From dc0cd54ece0508bc6039001c397d93ca7a34fc24 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 18:53:49 +0200 Subject: [PATCH 25/67] pass entity type from manifest --- .../menu/components/menu-item/menu-item-default.element.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/core/menu/components/menu-item/menu-item-default.element.ts b/src/packages/core/menu/components/menu-item/menu-item-default.element.ts index 75fbc48075..916598bc99 100644 --- a/src/packages/core/menu/components/menu-item/menu-item-default.element.ts +++ b/src/packages/core/menu/components/menu-item/menu-item-default.element.ts @@ -45,7 +45,8 @@ export class UmbMenuItemDefaultElement extends UmbLitElement implements UmbMenuI + .label=${this.localize.string(this.manifest.meta.label ?? this.manifest.name)} + .entityType=${this.manifest.meta.entityType}> `; } From 4a09c9f0e430312b7a8e351c75bb0d592beba836 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:13:01 +0200 Subject: [PATCH 26/67] add path helper to root --- src/packages/user/user/paths.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/paths.ts b/src/packages/user/user/paths.ts index eb80086f08..210af851fd 100644 --- a/src/packages/user/user/paths.ts +++ b/src/packages/user/user/paths.ts @@ -1,8 +1,13 @@ import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; -import { UMB_USER_ENTITY_TYPE } from './entity.js'; +import { UMB_USER_ENTITY_TYPE, UMB_USER_ROOT_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; export const UMB_USER_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ sectionName: UMB_USER_SECTION_PATHNAME, entityType: UMB_USER_ENTITY_TYPE, }); + +export const UMB_USER_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_ROOT_ENTITY_TYPE, +}); From a8da784dc6faddc47c92881c7b9a4d144e6ec76f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:13:12 +0200 Subject: [PATCH 27/67] back button to root --- .../user/user/workspace/user-workspace-editor.element.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user-workspace-editor.element.ts index c4e11d2175..3a1d79c7ef 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user-workspace-editor.element.ts @@ -13,6 +13,8 @@ import './components/user-workspace-access/user-workspace-access.element.js'; import './components/user-workspace-info/user-workspace-info.element.js'; import './components/user-workspace-avatar/user-workspace-avatar.element.js'; import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; +import { UMB_USER_ROOT_WORKSPACE_PATH } from '../paths.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { @@ -50,7 +52,10 @@ export class UmbUserWorkspaceEditorElement extends UmbLitElement { if (!this._user) return html`User not found`; return html` - + ${this.#renderHeader()}
${this.#renderLeftColumn()}
From 1aab5dfb7bca2a2e06367d518500a9b4d29a502d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 21:39:06 +0200 Subject: [PATCH 28/67] wip create + invite entity actions --- .../create/create-user-entity-action.ts | 21 ++++ .../user/entity-actions/create/manifests.ts | 22 ++++ .../user/entity-actions/create/modal/index.ts | 8 ++ .../entity-actions/create/modal/manifests.ts | 10 ++ .../user-create-options-modal.element.ts | 108 ++++++++++++++++++ .../invite/invite-user-entity-action.ts | 11 ++ .../user/entity-actions/invite/manifests.ts | 19 +++ .../user/user/entity-actions/manifests.ts | 12 +- 8 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 src/packages/user/user/entity-actions/create/create-user-entity-action.ts create mode 100644 src/packages/user/user/entity-actions/create/manifests.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/index.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/manifests.ts create mode 100644 src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts create mode 100644 src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts create mode 100644 src/packages/user/user/entity-actions/invite/manifests.ts diff --git a/src/packages/user/user/entity-actions/create/create-user-entity-action.ts b/src/packages/user/user/entity-actions/create/create-user-entity-action.ts new file mode 100644 index 0000000000..a6da26da4f --- /dev/null +++ b/src/packages/user/user/entity-actions/create/create-user-entity-action.ts @@ -0,0 +1,21 @@ +import { UMB_USER_CREATE_OPTIONS_MODAL } from './modal/index.js'; +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateUserEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const modalContext = modalManager.open(this, UMB_USER_CREATE_OPTIONS_MODAL, { + data: { + parent: { + unique: this.args.unique, + entityType: this.args.entityType, + }, + }, + }); + + await modalContext.onSubmit(); + } +} + +export { UmbCreateUserEntityAction as api }; diff --git a/src/packages/user/user/entity-actions/create/manifests.ts b/src/packages/user/user/entity-actions/create/manifests.ts new file mode 100644 index 0000000000..7915152337 --- /dev/null +++ b/src/packages/user/user/entity-actions/create/manifests.ts @@ -0,0 +1,22 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; + +import { manifests as modalManifests } from './modal/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.Create', + name: 'Create User Entity Action', + weight: 1200, + api: () => import('./create-user-entity-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-add', + label: '#actions_create', + }, + }, + ...modalManifests, +]; diff --git a/src/packages/user/user/entity-actions/create/modal/index.ts b/src/packages/user/user/entity-actions/create/modal/index.ts new file mode 100644 index 0000000000..778a1fe38d --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/index.ts @@ -0,0 +1,8 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export const UMB_USER_CREATE_OPTIONS_MODAL = new UmbModalToken('Umb.Modal.User.CreateOptions', { + modal: { + type: 'sidebar', + size: 'small', + }, +}); diff --git a/src/packages/user/user/entity-actions/create/modal/manifests.ts b/src/packages/user/user/entity-actions/create/modal/manifests.ts new file mode 100644 index 0000000000..2c736c75fd --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/manifests.ts @@ -0,0 +1,10 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'modal', + alias: 'Umb.Modal.User.CreateOptions', + name: 'User Create Options Modal', + element: () => import('./user-create-options-modal.element.js'), + }, +]; diff --git a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts new file mode 100644 index 0000000000..29932ea273 --- /dev/null +++ b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -0,0 +1,108 @@ +import { UMB_CREATE_USER_MODAL } from '../../../modals/create/create-user-modal.token.js'; +import { UmbUserKind, type UmbUserKindType } from '../../../utils/index.js'; +import { html, customElement, map } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_MODAL_MANAGER_CONTEXT, UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UmbEntityModel } from '@umbraco-cms/backoffice/entity'; +import { UMB_ENTITY_CONTEXT } from '@umbraco-cms/backoffice/entity'; +import { UMB_ACTION_EVENT_CONTEXT } from '@umbraco-cms/backoffice/action'; +import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/entity-action'; + +interface UmbUserCreateOptionModel { + label: string; + description: string; + icon: string; + kind: UmbUserKindType; +} + +const elementName = 'umb-user-create-options-modal'; +@customElement(elementName) +export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { + #options: Array = [ + { + label: this.localize.term('user_userKindDefault'), + description: 'Donec augue nunc, ullamcorper non turpis ut, maximus facilisis lorem. Nunc id sagittis magna.', + icon: 'icon-user', + kind: UmbUserKind.DEFAULT, + }, + { + label: this.localize.term('user_userKindApi'), + description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + icon: 'icon-unplug', + kind: UmbUserKind.API, + }, + ]; + + async #onClick(event: Event, kind: UmbUserKindType) { + event.stopPropagation(); + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + const entityContext = await this.getContext(UMB_ENTITY_CONTEXT); + + const unique = entityContext.getUnique(); + const entityType = entityContext.getEntityType(); + + if (unique === undefined) throw new Error('Missing unique'); + if (!entityType) throw new Error('Missing entityType'); + + const modalContext = modalManager.open(this, UMB_CREATE_USER_MODAL, { + data: { + user: { + kind, + }, + }, + }); + + modalContext + ?.onSubmit() + .then(() => { + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }) + .catch(async () => { + // modal is closed after creation instead of navigating to the new user. + // We therefore need to reload the children of the entity + this.#requestReloadChildrenOfEntity({ entityType, unique }); + }); + } + + async #requestReloadChildrenOfEntity({ entityType, unique }: UmbEntityModel) { + const eventContext = await this.getContext(UMB_ACTION_EVENT_CONTEXT); + const event = new UmbRequestReloadChildrenOfEntityEvent({ + entityType, + unique, + }); + + eventContext.dispatchEvent(event); + } + + override render() { + return html` + + + + ${map( + this.#options, + (item) => html` + this.#onClick(event, item.kind)}> + `, + )} + + + + + `; + } +} + +export { UmbUserCreateOptionsModalElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbUserCreateOptionsModalElement; + } +} diff --git a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts b/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts new file mode 100644 index 0000000000..4ac61a28d5 --- /dev/null +++ b/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts @@ -0,0 +1,11 @@ +import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; +import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; + +export class UmbCreateUserEntityAction extends UmbEntityActionBase { + override async execute() { + const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); + debugger; + } +} + +export { UmbCreateUserEntityAction as api }; diff --git a/src/packages/user/user/entity-actions/invite/manifests.ts b/src/packages/user/user/entity-actions/invite/manifests.ts new file mode 100644 index 0000000000..0fc1e67e74 --- /dev/null +++ b/src/packages/user/user/entity-actions/invite/manifests.ts @@ -0,0 +1,19 @@ +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.Invite', + name: 'Invite User Entity Action', + weight: 1000, + api: () => import('./invite-user-entity-action.js'), + forEntityTypes: [UMB_USER_ROOT_ENTITY_TYPE], + meta: { + icon: 'icon-paper-plane', + label: '#user_invite', + }, + }, +]; diff --git a/src/packages/user/user/entity-actions/manifests.ts b/src/packages/user/user/entity-actions/manifests.ts index b67955449e..493f108ff1 100644 --- a/src/packages/user/user/entity-actions/manifests.ts +++ b/src/packages/user/user/entity-actions/manifests.ts @@ -1,6 +1,10 @@ import { UMB_USER_DETAIL_REPOSITORY_ALIAS, UMB_USER_ITEM_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +import { manifests as createManifests } from './create/manifests.js'; +import { manifests as inviteManifests } from './invite/manifests.js'; + +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; const entityActions: Array = [ { @@ -93,4 +97,8 @@ const entityActions: Array = [ }, ]; -export const manifests: Array = [...entityActions]; +export const manifests: Array = [ + ...entityActions, + ...createManifests, + ...inviteManifests, +]; From fdb51a33db56570a36e35cc21ec964b6108c933d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 22:01:12 +0200 Subject: [PATCH 29/67] update back path --- src/packages/user/user-group/paths.ts | 7 ++++++- src/packages/user/user-group/workspace/constants.ts | 1 + .../workspace/user-group-workspace-editor.element.ts | 6 ++++-- 3 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/packages/user/user-group/workspace/constants.ts diff --git a/src/packages/user/user-group/paths.ts b/src/packages/user/user-group/paths.ts index bcd681d6dc..51aa649211 100644 --- a/src/packages/user/user-group/paths.ts +++ b/src/packages/user/user-group/paths.ts @@ -1,8 +1,13 @@ import { UMB_USER_SECTION_PATHNAME } from '../section/paths.js'; -import { UMB_USER_GROUP_ENTITY_TYPE } from './entity.js'; +import { UMB_USER_GROUP_ENTITY_TYPE, UMB_USER_GROUP_ROOT_ENTITY_TYPE } from './entity.js'; import { UMB_WORKSPACE_PATH_PATTERN } from '@umbraco-cms/backoffice/workspace'; export const UMB_USER_GROUP_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ sectionName: UMB_USER_SECTION_PATHNAME, entityType: UMB_USER_GROUP_ENTITY_TYPE, }); + +export const UMB_USER_GROUP_ROOT_WORKSPACE_PATH = UMB_WORKSPACE_PATH_PATTERN.generateAbsolute({ + sectionName: UMB_USER_SECTION_PATHNAME, + entityType: UMB_USER_GROUP_ROOT_ENTITY_TYPE, +}); diff --git a/src/packages/user/user-group/workspace/constants.ts b/src/packages/user/user-group/workspace/constants.ts new file mode 100644 index 0000000000..6972100cb8 --- /dev/null +++ b/src/packages/user/user-group/workspace/constants.ts @@ -0,0 +1 @@ +export const UMB_USER_GROUP_WORKSPACE_ALIAS = 'Umb.Workspace.UserGroup'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts index 9374872d2a..a4d129dd04 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts @@ -1,5 +1,7 @@ import type { UmbUserGroupDetailModel } from '../index.js'; +import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../paths.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; +import { UMB_USER_GROUP_WORKSPACE_ALIAS } from './constants.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; @@ -170,9 +172,9 @@ export class UmbUserGroupWorkspaceEditorElement extends UmbLitElement { return html` + back-path=${UMB_USER_GROUP_ROOT_WORKSPACE_PATH}> ${this.#renderHeader()} ${this.#renderMain()} `; From 85bfc1eff01710a82e67e5879fbccf041145a8d6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:37:27 +0200 Subject: [PATCH 30/67] add to folder --- .../user/section/sidebar-app/index.ts | 2 +- src/packages/user/user-group/manifests.ts | 4 +- ...orkspace-action-user-group-save.element.ts | 2 +- .../user-allow-action-base.condition.ts | 2 +- src/packages/user/user/workspace/manifests.ts | 44 ++----------------- .../user-workspace-action-save.element.ts | 0 .../user-workspace-access.element.ts | 2 +- .../user-workspace-assign-access.element.ts | 2 +- .../user-workspace-avatar.element.ts | 2 +- ...er-workspace-client-credentials.element.ts | 8 ++-- .../user-workspace-info.element.ts | 8 ++-- ...user-workspace-profile-settings.element.ts | 4 +- .../user/workspace/{ => user}/constants.ts | 0 .../user/user/workspace/user/manifests.ts | 42 ++++++++++++++++++ .../user-workspace-editor.element.ts | 6 +-- .../user-workspace.context-token.ts | 2 +- .../{ => user}/user-workspace.context.ts | 10 ++--- .../{ => user}/user-workspace.test.ts | 0 18 files changed, 72 insertions(+), 68 deletions(-) rename src/packages/user/user/workspace/{ => user}/actions/user-workspace-action-save.element.ts (100%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-access/user-workspace-access.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-assign-access/user-workspace-assign-access.element.ts (99%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-avatar/user-workspace-avatar.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts (93%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-info/user-workspace-info.element.ts (95%) rename src/packages/user/user/workspace/{ => user}/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/constants.ts (100%) create mode 100644 src/packages/user/user/workspace/user/manifests.ts rename src/packages/user/user/workspace/{ => user}/user-workspace-editor.element.ts (97%) rename src/packages/user/user/workspace/{ => user}/user-workspace.context-token.ts (89%) rename src/packages/user/user/workspace/{ => user}/user-workspace.context.ts (94%) rename src/packages/user/user/workspace/{ => user}/user-workspace.test.ts (100%) diff --git a/src/packages/user/section/sidebar-app/index.ts b/src/packages/user/section/sidebar-app/index.ts index 4f07201dcf..42f853e5be 100644 --- a/src/packages/user/section/sidebar-app/index.ts +++ b/src/packages/user/section/sidebar-app/index.ts @@ -1 +1 @@ -export * from './constants.js'; +export * from '../constants.js'; diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index 1ac88d4e75..a68693f9c3 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -7,9 +7,9 @@ import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...collectionManifests, ...entityActionManifests, ...entityBulkActionManifests, diff --git a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts index 1c86ca5b08..530c72b616 100644 --- a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts +++ b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user/user-workspace.context-token.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/user/user/conditions/user-allow-action-base.condition.ts b/src/packages/user/user/conditions/user-allow-action-base.condition.ts index bdae21f4af..7dffc20550 100644 --- a/src/packages/user/user/conditions/user-allow-action-base.condition.ts +++ b/src/packages/user/user/conditions/user-allow-action-base.condition.ts @@ -1,5 +1,5 @@ import type { UmbUserStateEnum } from '../types.js'; -import { UMB_USER_WORKSPACE_CONTEXT } from '../workspace/user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_CONTEXT } from '../workspace/user/user-workspace.context-token.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { isCurrentUser } from '@umbraco-cms/backoffice/current-user'; import type { diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index d2c5c90ec4..a8bafd21d8 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,42 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; -import type { - ManifestWorkspaces, - ManifestWorkspaceActions, - ManifestTypes, -} from '@umbraco-cms/backoffice/extension-registry'; +import { manifests as userManifests } from './user/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -const workspace: ManifestWorkspaces = { - type: 'workspace', - kind: 'routable', - alias: UMB_USER_WORKSPACE_ALIAS, - name: 'User Workspace', - api: () => import('./user-workspace.context.js'), - meta: { - entityType: UMB_USER_ENTITY_TYPE, - }, -}; - -const workspaceActions: Array = [ - { - type: 'workspaceAction', - kind: 'default', - alias: 'Umb.WorkspaceAction.User.Save', - name: 'Save User Workspace Action', - api: UmbSubmitWorkspaceAction, - meta: { - label: '#buttons_save', - look: 'primary', - color: 'positive', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: workspace.alias, - }, - ], - }, -]; - -export const manifests: Array = [workspace, ...workspaceActions]; +export const manifests: Array = [...userManifests]; diff --git a/src/packages/user/user/workspace/actions/user-workspace-action-save.element.ts b/src/packages/user/user/workspace/user/actions/user-workspace-action-save.element.ts similarity index 100% rename from src/packages/user/user/workspace/actions/user-workspace-action-save.element.ts rename to src/packages/user/user/workspace/user/actions/user-workspace-action-save.element.ts diff --git a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts index 7177e91909..86197319e5 100644 --- a/src/packages/user/user/workspace/components/user-workspace-access/user-workspace-access.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-access/user-workspace-access.element.ts @@ -1,5 +1,5 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserStartNodesModel } from '../../../types.js'; +import type { UmbUserStartNodesModel } from '../../../../types.js'; import { html, customElement, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts similarity index 99% rename from src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts index 6a7a881039..d32bb6e0fd 100644 --- a/src/packages/user/user/workspace/components/user-workspace-assign-access/user-workspace-assign-access.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-assign-access/user-workspace-assign-access.element.ts @@ -1,5 +1,5 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; import { html, customElement, state, nothing, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts index b3c7317d12..9400230d7a 100644 --- a/src/packages/user/user/workspace/components/user-workspace-avatar/user-workspace-avatar.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-avatar/user-workspace-avatar.element.ts @@ -1,4 +1,4 @@ -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; import { css, html, customElement, query, nothing, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts similarity index 93% rename from src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts index 512d97f2d6..7d77417056 100644 --- a/src/packages/user/user/workspace/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-client-credentials/user-workspace-client-credentials.element.ts @@ -2,10 +2,10 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.j import type { UmbDeleteUserClientCredentialRequestArgs, UmbUserClientCredentialModel, -} from '../../../client-credential/index.js'; -import { UmbUserClientCredentialRepository } from '../../../client-credential/index.js'; -import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; -import { UmbUserKind } from '../../../utils/index.js'; +} from '../../../../client-credential/index.js'; +import { UmbUserClientCredentialRepository } from '../../../../client-credential/index.js'; +import { UMB_CREATE_USER_CLIENT_CREDENTIAL_MODAL } from '../../../../client-credential/create/modal/create-user-client-credential-modal.token.js'; +import { UmbUserKind } from '../../../../utils/index.js'; import { html, customElement, state, css, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts similarity index 95% rename from src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts index 898bea5823..8f5d2437b0 100644 --- a/src/packages/user/user/workspace/components/user-workspace-info/user-workspace-info.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-info/user-workspace-info.element.ts @@ -1,8 +1,8 @@ -import type { UmbUserDisplayStatus } from '../../../utils.js'; -import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../utils.js'; +import type { UmbUserDisplayStatus } from '../../../../utils.js'; +import { TimeFormatOptions, getDisplayStateFromUserStatus } from '../../../../utils.js'; import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; -import { UmbUserKind } from '../../../utils/index.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; +import { UmbUserKind } from '../../../../utils/index.js'; import { html, customElement, state, css, repeat, ifDefined, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; diff --git a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts b/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts similarity index 97% rename from src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts rename to src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts index fd4e67c615..0d313eb130 100644 --- a/src/packages/user/user/workspace/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts +++ b/src/packages/user/user/workspace/user/components/user-workspace-profile-settings/user-workspace-profile-settings.element.ts @@ -1,11 +1,11 @@ import { UMB_USER_WORKSPACE_CONTEXT } from '../../user-workspace.context-token.js'; -import type { UmbUserDetailModel } from '../../../types.js'; +import type { UmbUserDetailModel } from '../../../../types.js'; +import { UmbUserKind } from '../../../../utils/index.js'; import { html, customElement, state, ifDefined, css, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbUiCultureInputElement } from '@umbraco-cms/backoffice/localization'; -import { UmbUserKind } from '../../../utils/index.js'; @customElement('umb-user-workspace-profile-settings') export class UmbUserWorkspaceProfileSettingsElement extends UmbLitElement { diff --git a/src/packages/user/user/workspace/constants.ts b/src/packages/user/user/workspace/user/constants.ts similarity index 100% rename from src/packages/user/user/workspace/constants.ts rename to src/packages/user/user/workspace/user/constants.ts diff --git a/src/packages/user/user/workspace/user/manifests.ts b/src/packages/user/user/workspace/user/manifests.ts new file mode 100644 index 0000000000..3f4203dd88 --- /dev/null +++ b/src/packages/user/user/workspace/user/manifests.ts @@ -0,0 +1,42 @@ +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import type { + ManifestWorkspaces, + ManifestWorkspaceActions, + ManifestTypes, +} from '@umbraco-cms/backoffice/extension-registry'; + +const workspace: ManifestWorkspaces = { + type: 'workspace', + kind: 'routable', + alias: UMB_USER_WORKSPACE_ALIAS, + name: 'User Workspace', + api: () => import('./user-workspace.context.js'), + meta: { + entityType: UMB_USER_ENTITY_TYPE, + }, +}; + +const workspaceActions: Array = [ + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.User.Save', + name: 'Save User Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#buttons_save', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: workspace.alias, + }, + ], + }, +]; + +export const manifests: Array = [workspace, ...workspaceActions]; diff --git a/src/packages/user/user/workspace/user-workspace-editor.element.ts b/src/packages/user/user/workspace/user/user-workspace-editor.element.ts similarity index 97% rename from src/packages/user/user/workspace/user-workspace-editor.element.ts rename to src/packages/user/user/workspace/user/user-workspace-editor.element.ts index 3a1d79c7ef..b65ebebf63 100644 --- a/src/packages/user/user/workspace/user-workspace-editor.element.ts +++ b/src/packages/user/user/workspace/user/user-workspace-editor.element.ts @@ -1,6 +1,8 @@ -import type { UmbUserDetailModel } from '../index.js'; +import type { UmbUserDetailModel } from '../../index.js'; +import { UMB_USER_ROOT_WORKSPACE_PATH } from '../../paths.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UMB_USER_WORKSPACE_CONTEXT } from './user-workspace.context-token.js'; +import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; @@ -13,8 +15,6 @@ import './components/user-workspace-access/user-workspace-access.element.js'; import './components/user-workspace-info/user-workspace-info.element.js'; import './components/user-workspace-avatar/user-workspace-avatar.element.js'; import './components/user-workspace-client-credentials/user-workspace-client-credentials.element.js'; -import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; -import { UMB_USER_ROOT_WORKSPACE_PATH } from '../paths.js'; @customElement('umb-user-workspace-editor') export class UmbUserWorkspaceEditorElement extends UmbLitElement { diff --git a/src/packages/user/user/workspace/user-workspace.context-token.ts b/src/packages/user/user/workspace/user/user-workspace.context-token.ts similarity index 89% rename from src/packages/user/user/workspace/user-workspace.context-token.ts rename to src/packages/user/user/workspace/user/user-workspace.context-token.ts index ac99021cc5..bac31a226c 100644 --- a/src/packages/user/user/workspace/user-workspace.context-token.ts +++ b/src/packages/user/user/workspace/user/user-workspace.context-token.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; import type { UmbUserWorkspaceContext } from './user-workspace.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/workspace/user-workspace.context.ts b/src/packages/user/user/workspace/user/user-workspace.context.ts similarity index 94% rename from src/packages/user/user/workspace/user-workspace.context.ts rename to src/packages/user/user/workspace/user/user-workspace.context.ts index 69587e191d..18963318ec 100644 --- a/src/packages/user/user/workspace/user-workspace.context.ts +++ b/src/packages/user/user/workspace/user/user-workspace.context.ts @@ -1,8 +1,8 @@ -import type { UmbUserDetailModel, UmbUserStartNodesModel, UmbUserStateEnum } from '../types.js'; -import { UMB_USER_ENTITY_TYPE } from '../entity.js'; -import { UmbUserDetailRepository } from '../repository/index.js'; -import { UmbUserAvatarRepository } from '../repository/avatar/index.js'; -import { UmbUserConfigRepository } from '../repository/config/index.js'; +import type { UmbUserDetailModel, UmbUserStartNodesModel, UmbUserStateEnum } from '../../types.js'; +import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { UmbUserDetailRepository } from '../../repository/index.js'; +import { UmbUserAvatarRepository } from '../../repository/avatar/index.js'; +import { UmbUserConfigRepository } from '../../repository/config/index.js'; import { UMB_USER_WORKSPACE_ALIAS } from './constants.js'; import { UmbUserWorkspaceEditorElement } from './user-workspace-editor.element.js'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user/workspace/user-workspace.test.ts b/src/packages/user/user/workspace/user/user-workspace.test.ts similarity index 100% rename from src/packages/user/user/workspace/user-workspace.test.ts rename to src/packages/user/user/workspace/user/user-workspace.test.ts From 4a31f36f743bd6af0a0b05c21268f3e6b9ddd283 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:38:05 +0200 Subject: [PATCH 31/67] rename folder --- src/packages/user/user/{section-view => user-root}/manifests.ts | 0 .../{section-view => user-root}/user-root-workspace.element.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/packages/user/user/{section-view => user-root}/manifests.ts (100%) rename src/packages/user/user/{section-view => user-root}/user-root-workspace.element.ts (100%) diff --git a/src/packages/user/user/section-view/manifests.ts b/src/packages/user/user/user-root/manifests.ts similarity index 100% rename from src/packages/user/user/section-view/manifests.ts rename to src/packages/user/user/user-root/manifests.ts diff --git a/src/packages/user/user/section-view/user-root-workspace.element.ts b/src/packages/user/user/user-root/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/section-view/user-root-workspace.element.ts rename to src/packages/user/user/user-root/user-root-workspace.element.ts From 025bc5bd56ce83e2107e0885b4fc28b0dfcf14f9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:38:59 +0200 Subject: [PATCH 32/67] move into workspace folder --- src/packages/user/user/manifests.ts | 2 -- src/packages/user/user/workspace/manifests.ts | 3 ++- src/packages/user/user/{ => workspace}/user-root/manifests.ts | 2 +- .../{ => workspace}/user-root/user-root-workspace.element.ts | 0 4 files changed, 3 insertions(+), 4 deletions(-) rename src/packages/user/user/{ => workspace}/user-root/manifests.ts (86%) rename src/packages/user/user/{ => workspace}/user-root/user-root-workspace.element.ts (100%) diff --git a/src/packages/user/user/manifests.ts b/src/packages/user/user/manifests.ts index d842d25b03..8d11c2dc37 100644 --- a/src/packages/user/user/manifests.ts +++ b/src/packages/user/user/manifests.ts @@ -7,7 +7,6 @@ import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as propertyEditorManifests } from './property-editor/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import { manifests as menuItemManifests } from './menu-item/manifests.js'; import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -22,7 +21,6 @@ export const manifests: Array = [ ...modalManifests, ...propertyEditorManifests, ...repositoryManifests, - ...sectionViewManifests, ...workspaceManifests, ...menuItemManifests, ]; diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index a8bafd21d8..09e4d463e9 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,4 +1,5 @@ import { manifests as userManifests } from './user/manifests.js'; +import { manifests as userRootManifests } from './user-root/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...userManifests]; +export const manifests: Array = [...userManifests, ...userRootManifests]; diff --git a/src/packages/user/user/user-root/manifests.ts b/src/packages/user/user/workspace/user-root/manifests.ts similarity index 86% rename from src/packages/user/user/user-root/manifests.ts rename to src/packages/user/user/workspace/user-root/manifests.ts index 96eea28eda..9cb07892d3 100644 --- a/src/packages/user/user/user-root/manifests.ts +++ b/src/packages/user/user/workspace/user-root/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ diff --git a/src/packages/user/user/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts similarity index 100% rename from src/packages/user/user/user-root/user-root-workspace.element.ts rename to src/packages/user/user/workspace/user-root/user-root-workspace.element.ts From b40d0cf6d304599be66877698a940150089aac73 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:40:31 +0200 Subject: [PATCH 33/67] add missing type --- src/packages/user/user/workspace/manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/user/user/workspace/manifests.ts b/src/packages/user/user/workspace/manifests.ts index 09e4d463e9..2208cee94d 100644 --- a/src/packages/user/user/workspace/manifests.ts +++ b/src/packages/user/user/workspace/manifests.ts @@ -1,5 +1,5 @@ import { manifests as userManifests } from './user/manifests.js'; import { manifests as userRootManifests } from './user-root/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...userManifests, ...userRootManifests]; +export const manifests: Array = [...userManifests, ...userRootManifests]; From 5f843ca620d6f969ebd1b00d50cbf3496b854723 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:40:37 +0200 Subject: [PATCH 34/67] fix path --- .../user/workspace/user-root/user-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 6e286dada3..65ec9cd88c 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_USER_COLLECTION_ALIAS } from '../../collection/index.js'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; From db4ec145d339d14bc2b3ba43a1019f5c66eec70e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 15:43:55 +0200 Subject: [PATCH 35/67] delete unused code --- ...orkspace-action-user-group-save.element.ts | 52 ------------------- 1 file changed, 52 deletions(-) delete mode 100644 src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts diff --git a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts b/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts deleted file mode 100644 index 530c72b616..0000000000 --- a/src/packages/user/user-group/workspace/actions/workspace-action-user-group-save.element.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { UMB_USER_WORKSPACE_CONTEXT } from '../../../user/workspace/user/user-workspace.context-token.js'; -import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -// TODO: Revisit this component, it can be made via a kind with api instead. [NL] -// TODO: This seems like legacy code [NL] -@customElement('umb-workspace-action-user-group-save') -export class UmbWorkspaceActionUserGroupSaveElement extends UmbLitElement { - @state() - private _saveButtonState?: UUIButtonState; - - private _workspaceContext?: typeof UMB_USER_WORKSPACE_CONTEXT.TYPE; - - constructor() { - super(); - - this.consumeContext(UMB_USER_WORKSPACE_CONTEXT, (instance) => { - this._workspaceContext = instance; - }); - } - - private async _handleSave() { - if (!this._workspaceContext) return; - - this._saveButtonState = 'waiting'; - await this._workspaceContext - .requestSubmit() - .then(() => { - this._saveButtonState = 'success'; - }) - .catch(() => { - this._saveButtonState = 'failed'; - }); - } - - override render() { - return html``; - } -} - -export default UmbWorkspaceActionUserGroupSaveElement; - -declare global { - interface HTMLElementTagNameMap { - 'umb-workspace-action-user-group-save': UmbWorkspaceActionUserGroupSaveElement; - } -} From a75f84eca778b0ae5f4191a82a71d524fa183b31 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:04:02 +0200 Subject: [PATCH 36/67] set up entity context --- .../workspace/user-root/user-root-workspace.element.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 65ec9cd88c..2411336b55 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -1,10 +1,20 @@ import { UMB_USER_COLLECTION_ALIAS } from '../../collection/index.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UmbEntityContext } from '@umbraco-cms/backoffice/entity'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; const elementName = 'umb-user-root-workspace'; @customElement(elementName) export class UmbUserRootWorkspaceElement extends UmbLitElement { + constructor() { + super(); + // TODO: this.should happen automatically + const entityContext = new UmbEntityContext(this); + entityContext.setEntityType(UMB_USER_ROOT_ENTITY_TYPE); + entityContext.setUnique(null); + } + override render() { return html` ; From f4d34209f417e27c631c3c9a7d31c6bd11749bb3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:09:03 +0200 Subject: [PATCH 37/67] add invite entity action + clean up --- .../user/user/entity-actions/manifests.ts | 7 +---- .../invite/invite-user-entity-action.ts | 4 ++- .../entity-action}/invite/manifests.ts | 2 +- .../user/invite/entity-action/manifests.ts | 28 ++++--------------- .../entity-action/resend-invite/manifests.ts | 19 +++++++++++++ src/packages/user/user/invite/manifests.ts | 4 +-- 6 files changed, 31 insertions(+), 33 deletions(-) rename src/packages/user/user/{entity-actions => invite/entity-action}/invite/invite-user-entity-action.ts (70%) rename src/packages/user/user/{entity-actions => invite/entity-action}/invite/manifests.ts (88%) diff --git a/src/packages/user/user/entity-actions/manifests.ts b/src/packages/user/user/entity-actions/manifests.ts index 493f108ff1..f59da30aeb 100644 --- a/src/packages/user/user/entity-actions/manifests.ts +++ b/src/packages/user/user/entity-actions/manifests.ts @@ -2,7 +2,6 @@ import { UMB_USER_DETAIL_REPOSITORY_ALIAS, UMB_USER_ITEM_REPOSITORY_ALIAS } from import { UMB_USER_ENTITY_TYPE } from '../entity.js'; import { manifests as createManifests } from './create/manifests.js'; -import { manifests as inviteManifests } from './invite/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; @@ -97,8 +96,4 @@ const entityActions: Array = [ }, ]; -export const manifests: Array = [ - ...entityActions, - ...createManifests, - ...inviteManifests, -]; +export const manifests: Array = [...entityActions, ...createManifests]; diff --git a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts b/src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts similarity index 70% rename from src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts rename to src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts index 4ac61a28d5..7d7f86ec79 100644 --- a/src/packages/user/user/entity-actions/invite/invite-user-entity-action.ts +++ b/src/packages/user/user/invite/entity-action/invite/invite-user-entity-action.ts @@ -1,10 +1,12 @@ +import { UMB_INVITE_USER_MODAL } from '../../index.js'; import { UmbEntityActionBase } from '@umbraco-cms/backoffice/entity-action'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; export class UmbCreateUserEntityAction extends UmbEntityActionBase { override async execute() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - debugger; + const modalContext = modalManager.open(this, UMB_INVITE_USER_MODAL); + await modalContext?.onSubmit(); } } diff --git a/src/packages/user/user/entity-actions/invite/manifests.ts b/src/packages/user/user/invite/entity-action/invite/manifests.ts similarity index 88% rename from src/packages/user/user/entity-actions/invite/manifests.ts rename to src/packages/user/user/invite/entity-action/invite/manifests.ts index 0fc1e67e74..64ca8e8772 100644 --- a/src/packages/user/user/entity-actions/invite/manifests.ts +++ b/src/packages/user/user/invite/entity-action/invite/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_ROOT_ENTITY_TYPE } from '../../entity.js'; +import { UMB_USER_ROOT_ENTITY_TYPE } from '../../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/user/user/invite/entity-action/manifests.ts b/src/packages/user/user/invite/entity-action/manifests.ts index af09b5ff79..0958868a9f 100644 --- a/src/packages/user/user/invite/entity-action/manifests.ts +++ b/src/packages/user/user/invite/entity-action/manifests.ts @@ -1,27 +1,9 @@ -import { UMB_USER_ENTITY_TYPE } from '../../entity.js'; +import { manifests as inviteManifests } from './invite/manifests.js'; import { manifests as resendInviteManifests } from './resend-invite/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -const entityActions: Array = [ - { - type: 'entityAction', - kind: 'default', - alias: 'Umb.EntityAction.User.ResendInvite', - name: 'Resend Invite User Entity Action', - weight: 500, - api: () => import('./resend-invite/resend-invite.action.js'), - forEntityTypes: [UMB_USER_ENTITY_TYPE], - meta: { - icon: 'icon-message', - label: '#actions_resendInvite', - }, - conditions: [ - { - alias: 'Umb.Condition.User.AllowResendInviteAction', - }, - ], - }, +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + ...inviteManifests, ...resendInviteManifests, ]; - -export const manifests: Array = [...entityActions]; diff --git a/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts b/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts index 87dac3af79..1525273137 100644 --- a/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts +++ b/src/packages/user/user/invite/entity-action/resend-invite/manifests.ts @@ -1,6 +1,25 @@ +import { UMB_USER_ENTITY_TYPE } from '../../../entity.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ + { + type: 'entityAction', + kind: 'default', + alias: 'Umb.EntityAction.User.ResendInvite', + name: 'Resend Invite User Entity Action', + weight: 500, + api: () => import('./resend-invite.action.js'), + forEntityTypes: [UMB_USER_ENTITY_TYPE], + meta: { + icon: 'icon-message', + label: '#actions_resendInvite', + }, + conditions: [ + { + alias: 'Umb.Condition.User.AllowResendInviteAction', + }, + ], + }, { type: 'condition', name: 'User Allow Resend Invite Action Condition', diff --git a/src/packages/user/user/invite/manifests.ts b/src/packages/user/user/invite/manifests.ts index 63b76f1ec9..3d56168a11 100644 --- a/src/packages/user/user/invite/manifests.ts +++ b/src/packages/user/user/invite/manifests.ts @@ -2,9 +2,9 @@ import { manifests as collectionActionManifests } from './collection-action/mani import { manifests as modalManifests } from './modal/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; import { manifests as entityActionManifests } from './entity-action/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ +export const manifests: Array = [ ...collectionActionManifests, ...modalManifests, ...repositoryManifests, From 63ff3ef3e79c447657e44c522ff3a20af4d66f3c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 16:23:51 +0200 Subject: [PATCH 38/67] update user group create path --- src/packages/user/user-group/collection/action/manifests.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/packages/user/user-group/collection/action/manifests.ts b/src/packages/user/user-group/collection/action/manifests.ts index 1168e303e3..3f67cc84e1 100644 --- a/src/packages/user/user-group/collection/action/manifests.ts +++ b/src/packages/user/user-group/collection/action/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_USER_GROUP_WORKSPACE_PATH } from '../../paths.js'; import { UMB_COLLECTION_ALIAS_CONDITION } from '@umbraco-cms/backoffice/collection'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; @@ -9,7 +10,7 @@ export const createManifest: ManifestTypes = { weight: 200, meta: { label: '#general_create', - href: 'section/user-management/view/user-groups/user-group/create', + href: `${UMB_USER_GROUP_WORKSPACE_PATH}/create`, }, conditions: [ { From 1799a95fd1042dd9a8f8b6e32e37cccdad7522cb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 21:58:23 +0200 Subject: [PATCH 39/67] revert merge mistake --- src/packages/settings/advanced/manifests.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/packages/settings/advanced/manifests.ts b/src/packages/settings/advanced/manifests.ts index 3931a9edb9..5a452d9e3d 100644 --- a/src/packages/settings/advanced/manifests.ts +++ b/src/packages/settings/advanced/manifests.ts @@ -10,11 +10,11 @@ export const manifests = [ { type: 'sectionSidebarApp', kind: 'menu', - alias: 'Umb.SectionSidebarApp.Menu.Users', - name: 'Users Section Sidebar Menu', + alias: 'Umb.SectionSidebarMenu.AdvancedSettings', + name: 'Advanced Settings Sidebar Menu', weight: 100, meta: { - label: 'Users', + label: '#treeHeaders_advancedGroup', menu: UMB_ADVANCED_SETTINGS_MENU_ALIAS, }, conditions: [ From befea8161eb14147835724839d61de1631b41aa4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:48:41 +0200 Subject: [PATCH 40/67] move into folder --- .../user/user-group/workspace/manifests.ts | 44 ++----------------- ...oup-entity-user-permission-list.element.ts | 0 ...-group-granular-permission-list.element.ts | 0 .../workspace/{ => user-group}/constants.ts | 0 .../workspace/user-group/manifests.ts | 42 ++++++++++++++++++ .../user-group-workspace-editor.element.ts | 4 +- .../user-group-workspace.context-token.ts | 2 +- .../user-group-workspace.context.ts | 4 +- 8 files changed, 50 insertions(+), 46 deletions(-) rename src/packages/user/user-group/workspace/{ => user-group}/components/user-group-entity-user-permission-list.element.ts (100%) rename src/packages/user/user-group/workspace/{ => user-group}/components/user-group-granular-permission-list.element.ts (100%) rename src/packages/user/user-group/workspace/{ => user-group}/constants.ts (100%) create mode 100644 src/packages/user/user-group/workspace/user-group/manifests.ts rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace-editor.element.ts (98%) rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace.context-token.ts (89%) rename src/packages/user/user-group/workspace/{ => user-group}/user-group-workspace.context.ts (97%) diff --git a/src/packages/user/user-group/workspace/manifests.ts b/src/packages/user/user-group/workspace/manifests.ts index 4a593776bc..806ce0f556 100644 --- a/src/packages/user/user-group/workspace/manifests.ts +++ b/src/packages/user/user-group/workspace/manifests.ts @@ -1,42 +1,4 @@ -import type { - ManifestWorkspaces, - ManifestWorkspaceActions, - ManifestWorkspaceView, - ManifestTypes, -} from '@umbraco-cms/backoffice/extension-registry'; -import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import { manifests as userGroupManifests } from './user-group/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -const workspace: ManifestWorkspaces = { - type: 'workspace', - kind: 'routable', - alias: 'Umb.Workspace.UserGroup', - name: 'User Group Workspace', - api: () => import('./user-group-workspace.context.js'), - meta: { - entityType: 'user-group', - }, -}; - -const workspaceViews: Array = []; -const workspaceActions: Array = [ - { - type: 'workspaceAction', - kind: 'default', - alias: 'Umb.WorkspaceAction.UserGroup.Save', - name: 'Save User Group Workspace Action', - api: UmbSubmitWorkspaceAction, - meta: { - label: '#buttons_save', - look: 'primary', - color: 'positive', - }, - conditions: [ - { - alias: 'Umb.Condition.WorkspaceAlias', - match: workspace.alias, - }, - ], - }, -]; - -export const manifests: Array = [workspace, ...workspaceViews, ...workspaceActions]; +export const manifests: Array = [...userGroupManifests]; diff --git a/src/packages/user/user-group/workspace/components/user-group-entity-user-permission-list.element.ts b/src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts similarity index 100% rename from src/packages/user/user-group/workspace/components/user-group-entity-user-permission-list.element.ts rename to src/packages/user/user-group/workspace/user-group/components/user-group-entity-user-permission-list.element.ts diff --git a/src/packages/user/user-group/workspace/components/user-group-granular-permission-list.element.ts b/src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts similarity index 100% rename from src/packages/user/user-group/workspace/components/user-group-granular-permission-list.element.ts rename to src/packages/user/user-group/workspace/user-group/components/user-group-granular-permission-list.element.ts diff --git a/src/packages/user/user-group/workspace/constants.ts b/src/packages/user/user-group/workspace/user-group/constants.ts similarity index 100% rename from src/packages/user/user-group/workspace/constants.ts rename to src/packages/user/user-group/workspace/user-group/constants.ts diff --git a/src/packages/user/user-group/workspace/user-group/manifests.ts b/src/packages/user/user-group/workspace/user-group/manifests.ts new file mode 100644 index 0000000000..4a593776bc --- /dev/null +++ b/src/packages/user/user-group/workspace/user-group/manifests.ts @@ -0,0 +1,42 @@ +import type { + ManifestWorkspaces, + ManifestWorkspaceActions, + ManifestWorkspaceView, + ManifestTypes, +} from '@umbraco-cms/backoffice/extension-registry'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; + +const workspace: ManifestWorkspaces = { + type: 'workspace', + kind: 'routable', + alias: 'Umb.Workspace.UserGroup', + name: 'User Group Workspace', + api: () => import('./user-group-workspace.context.js'), + meta: { + entityType: 'user-group', + }, +}; + +const workspaceViews: Array = []; +const workspaceActions: Array = [ + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.UserGroup.Save', + name: 'Save User Group Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#buttons_save', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: workspace.alias, + }, + ], + }, +]; + +export const manifests: Array = [workspace, ...workspaceViews, ...workspaceActions]; diff --git a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts similarity index 98% rename from src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts index a4d129dd04..01835e7c2a 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace-editor.element.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace-editor.element.ts @@ -1,5 +1,5 @@ -import type { UmbUserGroupDetailModel } from '../index.js'; -import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../paths.js'; +import type { UmbUserGroupDetailModel } from '../../index.js'; +import { UMB_USER_GROUP_ROOT_WORKSPACE_PATH } from '../../paths.js'; import { UMB_USER_GROUP_WORKSPACE_CONTEXT } from './user-group-workspace.context-token.js'; import { UMB_USER_GROUP_WORKSPACE_ALIAS } from './constants.js'; import type { UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace.context-token.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts similarity index 89% rename from src/packages/user/user-group/workspace/user-group-workspace.context-token.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts index a09ae6a716..3a11176569 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace.context-token.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context-token.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_ENTITY_TYPE } from '../index.js'; +import { UMB_USER_GROUP_ENTITY_TYPE } from '../../index.js'; import type { UmbUserGroupWorkspaceContext } from './user-group-workspace.context.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; diff --git a/src/packages/user/user-group/workspace/user-group-workspace.context.ts b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts similarity index 97% rename from src/packages/user/user-group/workspace/user-group-workspace.context.ts rename to src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts index c360e2057f..6f81961747 100644 --- a/src/packages/user/user-group/workspace/user-group-workspace.context.ts +++ b/src/packages/user/user-group/workspace/user-group/user-group-workspace.context.ts @@ -1,5 +1,5 @@ -import { UmbUserGroupDetailRepository } from '../repository/detail/index.js'; -import type { UmbUserGroupDetailModel } from '../types.js'; +import { UmbUserGroupDetailRepository } from '../../repository/detail/index.js'; +import type { UmbUserGroupDetailModel } from '../../types.js'; import { UmbUserGroupWorkspaceEditorElement } from './user-group-workspace-editor.element.js'; import type { UmbUserPermissionModel } from '@umbraco-cms/backoffice/user-permission'; import type { UmbRoutableWorkspaceContext, UmbSubmittableWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; From 7b54c75d128886c821b5ddf437cb5fd7c9ebb2de Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:49:09 +0200 Subject: [PATCH 41/67] rename folder --- .../user-group/{section-view => user-group-root}/manifests.ts | 0 .../user-group-root-workspace.element.ts | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/packages/user/user-group/{section-view => user-group-root}/manifests.ts (100%) rename src/packages/user/user-group/{section-view => user-group-root}/user-group-root-workspace.element.ts (100%) diff --git a/src/packages/user/user-group/section-view/manifests.ts b/src/packages/user/user-group/user-group-root/manifests.ts similarity index 100% rename from src/packages/user/user-group/section-view/manifests.ts rename to src/packages/user/user-group/user-group-root/manifests.ts diff --git a/src/packages/user/user-group/section-view/user-group-root-workspace.element.ts b/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts similarity index 100% rename from src/packages/user/user-group/section-view/user-group-root-workspace.element.ts rename to src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts From cf470a9dfaf6f4b3c8b3ead05d8c4e2ed3209ee4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:49:35 +0200 Subject: [PATCH 42/67] move folder into workspace --- src/packages/user/user-group/manifests.ts | 2 +- .../user-group/{ => workspace}/user-group-root/manifests.ts | 2 +- .../user-group-root/user-group-root-workspace.element.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/packages/user/user-group/{ => workspace}/user-group-root/manifests.ts (86%) rename src/packages/user/user-group/{ => workspace}/user-group-root/user-group-root-workspace.element.ts (89%) diff --git a/src/packages/user/user-group/manifests.ts b/src/packages/user/user-group/manifests.ts index a68693f9c3..7db75cbebf 100644 --- a/src/packages/user/user-group/manifests.ts +++ b/src/packages/user/user-group/manifests.ts @@ -4,7 +4,7 @@ import { manifests as entityBulkActionManifests } from './entity-bulk-actions/ma import { manifests as menuItemManifests } from './menu-item/manifests.js'; import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; -import { manifests as sectionViewManifests } from './section-view/manifests.js'; +import { manifests as sectionViewManifests } from './workspace/user-group-root/manifests.js'; import { manifests as workspaceManifests } from './workspace/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/packages/user/user-group/user-group-root/manifests.ts b/src/packages/user/user-group/workspace/user-group-root/manifests.ts similarity index 86% rename from src/packages/user/user-group/user-group-root/manifests.ts rename to src/packages/user/user-group/workspace/user-group-root/manifests.ts index ade0536011..ac7b088e93 100644 --- a/src/packages/user/user-group/user-group-root/manifests.ts +++ b/src/packages/user/user-group/workspace/user-group-root/manifests.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../entity.js'; +import { UMB_USER_GROUP_ROOT_ENTITY_TYPE } from '../../entity.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ diff --git a/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts similarity index 89% rename from src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts rename to src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts index f02687d62d..0a77413d07 100644 --- a/src/packages/user/user-group/user-group-root/user-group-root-workspace.element.ts +++ b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts @@ -1,4 +1,4 @@ -import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../collection/index.js'; +import { UMB_USER_GROUP_COLLECTION_ALIAS } from '../../collection/index.js'; import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; From e287af848c30d7fb1b5babfc259c5085828f1337 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:50:58 +0200 Subject: [PATCH 43/67] localize headline --- .../user-group-root/user-group-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts index 0a77413d07..0900cee472 100644 --- a/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts +++ b/src/packages/user/user-group/workspace/user-group-root/user-group-root-workspace.element.ts @@ -6,7 +6,7 @@ const elementName = 'umb-user-group-root-workspace'; @customElement(elementName) export class UmbUserGroupRootWorkspaceElement extends UmbLitElement { override render() { - return html` + return html` ; `; } From ea60185456e7b0a80fcb9897aeb4e31dc76e1095 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 22:56:11 +0200 Subject: [PATCH 44/67] localize header --- .../user/workspace/user-root/user-root-workspace.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts index 2411336b55..335f7b9590 100644 --- a/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts +++ b/src/packages/user/user/workspace/user-root/user-root-workspace.element.ts @@ -16,7 +16,7 @@ export class UmbUserRootWorkspaceElement extends UmbLitElement { } override render() { - return html` + return html` ; `; } From 05f3f6f968a6dc69fd44ad96451b325e5ba53364 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 12 Sep 2024 23:12:53 +0200 Subject: [PATCH 45/67] remove lorem ipsum --- .../create/modal/user-create-options-modal.element.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts index 29932ea273..74e8646990 100644 --- a/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts +++ b/src/packages/user/user/entity-actions/create/modal/user-create-options-modal.element.ts @@ -9,7 +9,7 @@ import { UmbRequestReloadChildrenOfEntityEvent } from '@umbraco-cms/backoffice/e interface UmbUserCreateOptionModel { label: string; - description: string; + description?: string; icon: string; kind: UmbUserKindType; } @@ -20,13 +20,11 @@ export class UmbUserCreateOptionsModalElement extends UmbModalBaseElement { #options: Array = [ { label: this.localize.term('user_userKindDefault'), - description: 'Donec augue nunc, ullamcorper non turpis ut, maximus facilisis lorem. Nunc id sagittis magna.', icon: 'icon-user', kind: UmbUserKind.DEFAULT, }, { label: this.localize.term('user_userKindApi'), - description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', icon: 'icon-unplug', kind: UmbUserKind.API, }, From bbacb93206659f51c90779114d5e105cfa7aa0ad Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 17:59:20 +0200 Subject: [PATCH 46/67] scaffold help package + header app --- src/apps/backoffice/backoffice.element.ts | 1 + src/packages/help/help-header-app.element.ts | 21 ++++++++++++++++++++ src/packages/help/manifests.ts | 16 +++++++++++++++ src/packages/help/umbraco-package.ts | 9 +++++++++ src/packages/help/vite.config.ts | 12 +++++++++++ 5 files changed, 59 insertions(+) create mode 100644 src/packages/help/help-header-app.element.ts create mode 100644 src/packages/help/manifests.ts create mode 100644 src/packages/help/umbraco-package.ts create mode 100644 src/packages/help/vite.config.ts diff --git a/src/apps/backoffice/backoffice.element.ts b/src/apps/backoffice/backoffice.element.ts index 144e8eda69..d54b7fc79e 100644 --- a/src/apps/backoffice/backoffice.element.ts +++ b/src/apps/backoffice/backoffice.element.ts @@ -18,6 +18,7 @@ const CORE_PACKAGES = [ import('../../packages/dictionary/umbraco-package.js'), import('../../packages/documents/umbraco-package.js'), import('../../packages/health-check/umbraco-package.js'), + import('../../packages/help/umbraco-package.js'), import('../../packages/language/umbraco-package.js'), import('../../packages/log-viewer/umbraco-package.js'), import('../../packages/markdown-editor/umbraco-package.js'), diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts new file mode 100644 index 0000000000..e34b0d906b --- /dev/null +++ b/src/packages/help/help-header-app.element.ts @@ -0,0 +1,21 @@ +import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; + +const elementName = 'umb-help-header-app'; +@customElement(elementName) +export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { + override render() { + return html`
My Header App
`; + } + + static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; +} + +export { UmbHelpHeaderAppElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbHelpHeaderAppElement; + } +} diff --git a/src/packages/help/manifests.ts b/src/packages/help/manifests.ts new file mode 100644 index 0000000000..9504557d0d --- /dev/null +++ b/src/packages/help/manifests.ts @@ -0,0 +1,16 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'headerApp', + alias: 'Umb.HeaderApp.Help', + name: 'Help Header App', + element: () => import('./help-header-app.element.js'), + weight: 0, + meta: { + label: 'TODO: how should we enable this to not be set.', + icon: 'TODO: how should we enable this to not be set.', + pathname: 'help', + }, + }, +]; diff --git a/src/packages/help/umbraco-package.ts b/src/packages/help/umbraco-package.ts new file mode 100644 index 0000000000..bbf3a996b9 --- /dev/null +++ b/src/packages/help/umbraco-package.ts @@ -0,0 +1,9 @@ +export const name = 'Umbraco.Core.Help'; +export const extensions = [ + { + name: 'Help Bundle', + alias: 'Umb.Bundle.Help', + type: 'bundle', + js: () => import('./manifests.js'), + }, +]; diff --git a/src/packages/help/vite.config.ts b/src/packages/help/vite.config.ts new file mode 100644 index 0000000000..a320e9a053 --- /dev/null +++ b/src/packages/help/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite'; +import { rmSync } from 'fs'; +import { getDefaultConfig } from '../../vite-config-base'; + +const dist = '../../../dist-cms/packages/help'; + +// delete the unbundled dist folder +rmSync(dist, { recursive: true, force: true }); + +export default defineConfig({ + ...getDefaultConfig({ dist, entry: ['manifests.ts', 'umbraco-package.ts'] }), +}); From 7779ec468169816094f445cd6aa4f3acaf51b4b4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 18:04:44 +0200 Subject: [PATCH 47/67] render button with icon --- src/packages/help/help-header-app.element.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts index e34b0d906b..bafddc24b0 100644 --- a/src/packages/help/help-header-app.element.ts +++ b/src/packages/help/help-header-app.element.ts @@ -6,7 +6,11 @@ const elementName = 'umb-help-header-app'; @customElement(elementName) export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { override render() { - return html`
My Header App
`; + return html` + + + + `; } static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; From f935bf3d19016af0385aa497414219a149958500 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Sep 2024 19:07:43 +0200 Subject: [PATCH 48/67] split into header app and menu + register two menu items --- .../header-app/help-header-app.element.ts | 48 +++++++++++++++++++ src/packages/help/header-app/manifests.ts | 11 +++++ src/packages/help/help-header-app.element.ts | 25 ---------- src/packages/help/manifests.ts | 17 ++----- src/packages/help/menu/constants.ts | 1 + src/packages/help/menu/index.ts | 1 + src/packages/help/menu/manifests.ts | 32 +++++++++++++ 7 files changed, 96 insertions(+), 39 deletions(-) create mode 100644 src/packages/help/header-app/help-header-app.element.ts create mode 100644 src/packages/help/header-app/manifests.ts delete mode 100644 src/packages/help/help-header-app.element.ts create mode 100644 src/packages/help/menu/constants.ts create mode 100644 src/packages/help/menu/index.ts create mode 100644 src/packages/help/menu/manifests.ts diff --git a/src/packages/help/header-app/help-header-app.element.ts b/src/packages/help/header-app/help-header-app.element.ts new file mode 100644 index 0000000000..7b0b767d13 --- /dev/null +++ b/src/packages/help/header-app/help-header-app.element.ts @@ -0,0 +1,48 @@ +import { UMB_HELP_MENU_ALIAS } from '../menu/index.js'; +import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; +import type { ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; + +const elementName = 'umb-help-header-app'; +@customElement(elementName) +export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { + @state() + private _popoverOpen = false; + + #onPopoverToggle(event: ToggleEvent) { + // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this._popoverOpen = event.newState === 'open'; + } + + override render() { + return html` + + + + + + + + + + + + `; + } + + static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; +} + +export { UmbHelpHeaderAppElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbHelpHeaderAppElement; + } +} diff --git a/src/packages/help/header-app/manifests.ts b/src/packages/help/header-app/manifests.ts new file mode 100644 index 0000000000..46bb441c2c --- /dev/null +++ b/src/packages/help/header-app/manifests.ts @@ -0,0 +1,11 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'headerApp', + alias: 'Umb.HeaderApp.Help', + name: 'Help Header App', + element: () => import('./help-header-app.element.js'), + weight: 500, + }, +]; diff --git a/src/packages/help/help-header-app.element.ts b/src/packages/help/help-header-app.element.ts deleted file mode 100644 index bafddc24b0..0000000000 --- a/src/packages/help/help-header-app.element.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; - -const elementName = 'umb-help-header-app'; -@customElement(elementName) -export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { - override render() { - return html` - - - - `; - } - - static override styles: CSSResultGroup = [UmbHeaderAppButtonElement.styles, css``]; -} - -export { UmbHelpHeaderAppElement as element }; - -declare global { - interface HTMLElementTagNameMap { - [elementName]: UmbHelpHeaderAppElement; - } -} diff --git a/src/packages/help/manifests.ts b/src/packages/help/manifests.ts index 9504557d0d..223544e6db 100644 --- a/src/packages/help/manifests.ts +++ b/src/packages/help/manifests.ts @@ -1,16 +1,5 @@ +import { manifests as headerAppManifests } from './header-app/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [ - { - type: 'headerApp', - alias: 'Umb.HeaderApp.Help', - name: 'Help Header App', - element: () => import('./help-header-app.element.js'), - weight: 0, - meta: { - label: 'TODO: how should we enable this to not be set.', - icon: 'TODO: how should we enable this to not be set.', - pathname: 'help', - }, - }, -]; +export const manifests: Array = [...menuManifests, ...headerAppManifests]; diff --git a/src/packages/help/menu/constants.ts b/src/packages/help/menu/constants.ts new file mode 100644 index 0000000000..cae4c017c3 --- /dev/null +++ b/src/packages/help/menu/constants.ts @@ -0,0 +1 @@ +export const UMB_HELP_MENU_ALIAS = 'Umb.Menu.Help'; diff --git a/src/packages/help/menu/index.ts b/src/packages/help/menu/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/help/menu/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts new file mode 100644 index 0000000000..06cab3d506 --- /dev/null +++ b/src/packages/help/menu/manifests.ts @@ -0,0 +1,32 @@ +import { UMB_HELP_MENU_ALIAS } from './constants.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'menu', + alias: UMB_HELP_MENU_ALIAS, + name: 'Help Menu', + }, + { + type: 'menuItem', + alias: 'Umb.MenuItem.Help.LearningBase', + name: 'Learning Base Help Menu Item', + weight: 200, + meta: { + label: 'Umbraco Learning Base', + icon: 'icon-movie-alt', + menus: [UMB_HELP_MENU_ALIAS], + }, + }, + { + type: 'menuItem', + alias: 'Umb.MenuItem.Help.CommunityWebsite', + name: 'Community Website Help Menu Item', + weight: 100, + meta: { + label: 'Community Website', + icon: 'icon-hearts', + menus: [UMB_HELP_MENU_ALIAS], + }, + }, +]; From 02b990e84445b313fdfc8d9cf601cb03b0e832fb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 08:53:36 +0200 Subject: [PATCH 49/67] add link menu item kind --- .../core/extension-registry/models/index.ts | 3 +- .../models/menu-item.model.ts | 10 +++++++ src/packages/core/manifests.ts | 2 ++ .../menu-item-layout.element.ts | 11 +++++++- .../menu-item/link/link-menu-item.element.ts | 28 +++++++++++++++++++ .../components/menu-item/link/manifests.ts | 14 ++++++++++ .../menu/components/menu-item/manifests.ts | 4 +++ src/packages/core/menu/manifests.ts | 4 +++ src/packages/help/menu/manifests.ts | 8 ++++-- 9 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/packages/core/menu/components/menu-item/link/link-menu-item.element.ts create mode 100644 src/packages/core/menu/components/menu-item/link/manifests.ts create mode 100644 src/packages/core/menu/components/menu-item/manifests.ts create mode 100644 src/packages/core/menu/manifests.ts diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index 97ef8fd968..8a297a6ac8 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -29,7 +29,7 @@ import type { ManifestHealthCheck } from './health-check.model.js'; import type { ManifestIcons } from './icons.model.js'; import type { ManifestLocalization } from './localization.model.js'; import type { ManifestMenu } from './menu.model.js'; -import type { ManifestMenuItem, ManifestMenuItemTreeKind } from './menu-item.model.js'; +import type { ManifestMenuItem, ManifestMenuItemLinkKind, ManifestMenuItemTreeKind } from './menu-item.model.js'; import type { ManifestModal } from './modal.model.js'; import type { ManifestPackageView } from './package-view.model.js'; import type { ManifestPreviewAppProvider } from './preview-app.model.js'; @@ -185,6 +185,7 @@ export type ManifestTypes = | ManifestMenu | ManifestMenuItem | ManifestMenuItemTreeKind + | ManifestMenuItemLinkKind | ManifestMfaLoginProvider | ManifestModal | ManifestMonacoMarkdownEditorAction diff --git a/src/packages/core/extension-registry/models/menu-item.model.ts b/src/packages/core/extension-registry/models/menu-item.model.ts index 05eeb81b78..68f7d2f354 100644 --- a/src/packages/core/extension-registry/models/menu-item.model.ts +++ b/src/packages/core/extension-registry/models/menu-item.model.ts @@ -26,3 +26,13 @@ export interface MetaMenuItemTreeKind extends MetaMenuItem { treeAlias: string; hideTreeRoot?: boolean; } + +export interface ManifestMenuItemLinkKind extends ManifestMenuItem { + type: 'menuItem'; + kind: 'link'; + meta: MetaMenuItemLinkKind; +} + +export interface MetaMenuItemLinkKind extends MetaMenuItem { + href: string; +} diff --git a/src/packages/core/manifests.ts b/src/packages/core/manifests.ts index 893b161f1f..5fc8f5c5a8 100644 --- a/src/packages/core/manifests.ts +++ b/src/packages/core/manifests.ts @@ -9,6 +9,7 @@ import { manifests as entityBulkActionManifests } from './entity-bulk-action/man import { manifests as extensionManifests } from './extension-registry/manifests.js'; import { manifests as iconRegistryManifests } from './icon-registry/manifests.js'; import { manifests as localizationManifests } from './localization/manifests.js'; +import { manifests as menuManifests } from './menu/manifests.js'; import { manifests as modalManifests } from './modal/common/manifests.js'; import { manifests as pickerManifests } from './picker/manifests.js'; import { manifests as propertyActionManifests } from './property-action/manifests.js'; @@ -35,6 +36,7 @@ export const manifests: Array = [ ...extensionManifests, ...iconRegistryManifests, ...localizationManifests, + ...menuManifests, ...modalManifests, ...pickerManifests, ...propertyActionManifests, diff --git a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts index e9d7291e34..af64f06949 100644 --- a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts +++ b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts @@ -47,6 +47,14 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { #debouncedCheckIsActive = debounce(() => this.#checkIsActive(), 100); + #getTarget() { + if (this.href && this.href.startsWith('http')) { + return '_blank'; + } + + return '_self'; + } + #checkIsActive() { if (!this.href) { this._isActive = false; @@ -63,7 +71,8 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { label=${this.label} .caretLabel=${this.localize.term('visuallyHiddenTexts_expandChildItems') + ' ' + this.label} ?active=${this._isActive} - ?has-children=${this.hasChildren}> + ?has-children=${this.hasChildren} + target=${this.#getTarget()}> ${this.entityType ? html` + + `; + } +} + +export { UmbLinkMenuItemElement as element }; + +declare global { + interface HTMLElementTagNameMap { + [elementName]: UmbLinkMenuItemElement; + } +} diff --git a/src/packages/core/menu/components/menu-item/link/manifests.ts b/src/packages/core/menu/components/menu-item/link/manifests.ts new file mode 100644 index 0000000000..1645bd2edc --- /dev/null +++ b/src/packages/core/menu/components/menu-item/link/manifests.ts @@ -0,0 +1,14 @@ +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'kind', + alias: 'Umb.Kind.MenuItem.Link', + matchKind: 'link', + matchType: 'menuItem', + manifest: { + type: 'menuItem', + element: () => import('./link-menu-item.element.js'), + }, + }, +]; diff --git a/src/packages/core/menu/components/menu-item/manifests.ts b/src/packages/core/menu/components/menu-item/manifests.ts new file mode 100644 index 0000000000..08daa5be16 --- /dev/null +++ b/src/packages/core/menu/components/menu-item/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as linkManifests } from './link/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...linkManifests]; diff --git a/src/packages/core/menu/manifests.ts b/src/packages/core/menu/manifests.ts new file mode 100644 index 0000000000..88cfb7bd3d --- /dev/null +++ b/src/packages/core/menu/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as menuItemManifests } from './components/menu-item/manifests.js'; +import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...menuItemManifests]; diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index 06cab3d506..4d9985a5b5 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -9,24 +9,28 @@ export const manifests: Array = [ }, { type: 'menuItem', + kind: 'link', alias: 'Umb.MenuItem.Help.LearningBase', name: 'Learning Base Help Menu Item', weight: 200, meta: { + menus: [UMB_HELP_MENU_ALIAS], label: 'Umbraco Learning Base', icon: 'icon-movie-alt', - menus: [UMB_HELP_MENU_ALIAS], + href: 'https://learn.umbraco.com', }, }, { type: 'menuItem', + kind: 'link', alias: 'Umb.MenuItem.Help.CommunityWebsite', name: 'Community Website Help Menu Item', weight: 100, meta: { + menus: [UMB_HELP_MENU_ALIAS], label: 'Community Website', icon: 'icon-hearts', - menus: [UMB_HELP_MENU_ALIAS], + href: 'https://our.umbraco.com', }, }, ]; From 14347779c8660e67fe5e4a42ea61b53333c8af2e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:36:00 +0200 Subject: [PATCH 50/67] move target logic to link element --- .../menu-item-layout.element.ts | 19 ++++++++++--------- .../menu-item/link/link-menu-item.element.ts | 11 +++++++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts index af64f06949..b6471e064d 100644 --- a/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts +++ b/src/packages/core/menu/components/menu-item-layout/menu-item-layout.element.ts @@ -37,6 +37,15 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { @property({ type: String }) public href?: string; + /** + * Set an anchor tag target, only used when using href. + * @type {string} + * @attr + * @default undefined + */ + @property({ type: String }) + public target?: '_blank' | '_parent' | '_self' | '_top'; + @state() private _isActive = false; @@ -47,14 +56,6 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { #debouncedCheckIsActive = debounce(() => this.#checkIsActive(), 100); - #getTarget() { - if (this.href && this.href.startsWith('http')) { - return '_blank'; - } - - return '_self'; - } - #checkIsActive() { if (!this.href) { this._isActive = false; @@ -72,7 +73,7 @@ export class UmbMenuItemLayoutElement extends UmbLitElement { .caretLabel=${this.localize.term('visuallyHiddenTexts_expandChildItems') + ' ' + this.label} ?active=${this._isActive} ?has-children=${this.hasChildren} - target=${this.#getTarget()}> + target=${ifDefined(this.href && this.target ? this.target : undefined)}> ${this.entityType ? html` From b72cf681f9d51edd81eb0c0a96a1dc1fcd4bb085 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 14:59:31 +0200 Subject: [PATCH 51/67] add condition to check if the current user is admin --- .../conditions/is-admin/constants.ts | 1 + .../current-user/conditions/is-admin/index.ts | 1 + .../is-admin/is-admin.condition.manifest.ts | 9 +++++++++ .../conditions/is-admin/is-admin.condition.ts | 20 +++++++++++++++++++ .../user/current-user/conditions/manifests.ts | 3 +++ src/packages/user/current-user/manifests.ts | 16 +++++++-------- 6 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 src/packages/user/current-user/conditions/is-admin/constants.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/index.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts create mode 100644 src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts create mode 100644 src/packages/user/current-user/conditions/manifests.ts diff --git a/src/packages/user/current-user/conditions/is-admin/constants.ts b/src/packages/user/current-user/conditions/is-admin/constants.ts new file mode 100644 index 0000000000..2d3a8d78da --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/constants.ts @@ -0,0 +1 @@ +export const UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS = 'Umb.Condition.CurrentUser.IsAdmin'; diff --git a/src/packages/user/current-user/conditions/is-admin/index.ts b/src/packages/user/current-user/conditions/is-admin/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; diff --git a/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts new file mode 100644 index 0000000000..b9c81293e0 --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.manifest.ts @@ -0,0 +1,9 @@ +import { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from './constants.js'; +import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; + +export const manifest: ManifestCondition = { + type: 'condition', + name: 'Current user is admin Condition', + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + api: () => import('./is-admin.condition.js'), +}; diff --git a/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts new file mode 100644 index 0000000000..438258d6f4 --- /dev/null +++ b/src/packages/user/current-user/conditions/is-admin/is-admin.condition.ts @@ -0,0 +1,20 @@ +import { isCurrentUserAnAdmin } from '../../utils/is-current-user.function.js'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; + +export class UmbContentHasPropertiesWorkspaceCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + isCurrentUserAnAdmin(host).then((isAdmin) => (this.permitted = isAdmin)); + } +} + +export { UmbContentHasPropertiesWorkspaceCondition as api }; diff --git a/src/packages/user/current-user/conditions/manifests.ts b/src/packages/user/current-user/conditions/manifests.ts new file mode 100644 index 0000000000..63918c839e --- /dev/null +++ b/src/packages/user/current-user/conditions/manifests.ts @@ -0,0 +1,3 @@ +import { manifest as isAdminManifests } from './is-admin/is-admin.condition.manifest.js'; + +export const manifests = [isAdminManifests]; diff --git a/src/packages/user/current-user/manifests.ts b/src/packages/user/current-user/manifests.ts index dce911901e..32ebb91d36 100644 --- a/src/packages/user/current-user/manifests.ts +++ b/src/packages/user/current-user/manifests.ts @@ -1,11 +1,13 @@ import { manifest as actionDefaultKindManifest } from './action/default.kind.js'; -import { manifests as modalManifests } from './modals/manifests.js'; -import { manifests as historyManifests } from './history/manifests.js'; +import { manifests as conditionManifests } from './conditions/manifests.js'; import { manifests as externalLoginProviderManifests } from './external-login/manifests.js'; +import { manifests as historyManifests } from './history/manifests.js'; import { manifests as mfaLoginProviderManifests } from './mfa-login/manifests.js'; +import { manifests as modalManifests } from './modals/manifests.js'; import { manifests as profileManifests } from './profile/manifests.js'; -import { manifests as themeManifests } from './theme/manifests.js'; import { manifests as repositoryManifests } from './repository/manifests.js'; +import { manifests as themeManifests } from './theme/manifests.js'; + import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const headerApps: Array = [ @@ -21,19 +23,15 @@ export const headerApps: Array = [ name: 'Current User', element: () => import('./current-user-header-app.element.js'), weight: 0, - meta: { - label: 'TODO: how should we enable this to not be set.', - icon: 'TODO: how should we enable this to not be set.', - pathname: 'user', - }, }, ]; export const manifests = [ actionDefaultKindManifest, + ...conditionManifests, + ...externalLoginProviderManifests, ...headerApps, ...historyManifests, - ...externalLoginProviderManifests, ...mfaLoginProviderManifests, ...modalManifests, ...profileManifests, From 9e306d30a3180f4f6cbdd359eaf18fd507098002 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:01:55 +0200 Subject: [PATCH 52/67] export condition alias --- src/packages/user/current-user/conditions/index.ts | 1 + src/packages/user/current-user/index.ts | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) create mode 100644 src/packages/user/current-user/conditions/index.ts diff --git a/src/packages/user/current-user/conditions/index.ts b/src/packages/user/current-user/conditions/index.ts new file mode 100644 index 0000000000..8e80a3f329 --- /dev/null +++ b/src/packages/user/current-user/conditions/index.ts @@ -0,0 +1 @@ +export * from './is-admin/index.js'; diff --git a/src/packages/user/current-user/index.ts b/src/packages/user/current-user/index.ts index 343c0ed765..606a128e69 100644 --- a/src/packages/user/current-user/index.ts +++ b/src/packages/user/current-user/index.ts @@ -1,9 +1,10 @@ export * from './action/index.js'; export * from './components/index.js'; -export * from './history/current-user-history.store.js'; -export * from './utils/index.js'; -export * from './repository/index.js'; +export * from './conditions/index.js'; export * from './current-user.context.js'; export * from './current-user.context.token.js'; +export * from './history/current-user-history.store.js'; +export * from './repository/index.js'; +export * from './utils/index.js'; export type * from './types.js'; From 83da6765515adac029fc7dca50faa6c7c533a917 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:02:09 +0200 Subject: [PATCH 53/67] add conditions to links --- src/packages/help/menu/manifests.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index 4d9985a5b5..aa4b9d68c9 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -1,4 +1,5 @@ import { UMB_HELP_MENU_ALIAS } from './constants.js'; +import { UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS } from '@umbraco-cms/backoffice/current-user'; import type { ManifestTypes, UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; export const manifests: Array = [ @@ -19,6 +20,11 @@ export const manifests: Array = [ icon: 'icon-movie-alt', href: 'https://learn.umbraco.com', }, + conditions: [ + { + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + }, + ], }, { type: 'menuItem', @@ -32,5 +38,10 @@ export const manifests: Array = [ icon: 'icon-hearts', href: 'https://our.umbraco.com', }, + conditions: [ + { + alias: UMB_CURRENT_USER_IS_ADMIN_CONDITION_ALIAS, + }, + ], }, ]; From 1a79437df9f89b7b2731cb1f23c1a2d8bae15b5f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 10 Sep 2024 15:54:25 +0200 Subject: [PATCH 54/67] update links --- src/packages/help/menu/manifests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/packages/help/menu/manifests.ts b/src/packages/help/menu/manifests.ts index aa4b9d68c9..ee466c9a80 100644 --- a/src/packages/help/menu/manifests.ts +++ b/src/packages/help/menu/manifests.ts @@ -18,7 +18,7 @@ export const manifests: Array = [ menus: [UMB_HELP_MENU_ALIAS], label: 'Umbraco Learning Base', icon: 'icon-movie-alt', - href: 'https://learn.umbraco.com', + href: 'https://umbra.co/ulb', }, conditions: [ { @@ -36,7 +36,7 @@ export const manifests: Array = [ menus: [UMB_HELP_MENU_ALIAS], label: 'Community Website', icon: 'icon-hearts', - href: 'https://our.umbraco.com', + href: 'https://our.umbraco.com?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=our', }, conditions: [ { From d50ea877bf8cc08f36d62ee60d35910664dbb4d0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:20 +0200 Subject: [PATCH 55/67] add help module --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index bb90de7a06..cefbbb4419 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", + "./help": "./dist-cms/packages/core/help/index.js", "./icon": "./dist-cms/packages/core/icon-registry/index.js", "./id": "./dist-cms/packages/core/id/index.js", "./imaging": "./dist-cms/packages/media/imaging/index.js", From 4641854b4584ab0c6e1f30519431e764e95aea84 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:29 +0200 Subject: [PATCH 56/67] export alias --- src/packages/help/index.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/packages/help/index.ts diff --git a/src/packages/help/index.ts b/src/packages/help/index.ts new file mode 100644 index 0000000000..f15384a062 --- /dev/null +++ b/src/packages/help/index.ts @@ -0,0 +1 @@ +export * from './menu/index.js'; From 724cb03d7c1a234b6dde2e3141342bb4b84b8ff2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 10:34:45 +0200 Subject: [PATCH 57/67] Update tsconfig.json --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index cce8eece25..ee2325c332 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -69,6 +69,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/entity": ["./src/packages/core/entity/index.ts"], "@umbraco-cms/backoffice/event": ["./src/packages/core/event/index.ts"], "@umbraco-cms/backoffice/extension-registry": ["./src/packages/core/extension-registry/index.ts"], + "@umbraco-cms/backoffice/help": ["./src/packages/core/help/index.ts"], "@umbraco-cms/backoffice/icon": ["./src/packages/core/icon-registry/index.ts"], "@umbraco-cms/backoffice/id": ["./src/packages/core/id/index.ts"], "@umbraco-cms/backoffice/imaging": ["./src/packages/media/imaging/index.ts"], From 462b2f14ab0394df1b3d5749aba8956bb2e067a0 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:11:12 +0200 Subject: [PATCH 58/67] only render header app if menu has items --- .../header-app/help-header-app.element.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/packages/help/header-app/help-header-app.element.ts b/src/packages/help/header-app/help-header-app.element.ts index 7b0b767d13..0c8ff69b84 100644 --- a/src/packages/help/header-app/help-header-app.element.ts +++ b/src/packages/help/header-app/help-header-app.element.ts @@ -1,8 +1,9 @@ import { UMB_HELP_MENU_ALIAS } from '../menu/index.js'; import type { CSSResultGroup } from '@umbraco-cms/backoffice/external/lit'; -import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbHeaderAppButtonElement } from '@umbraco-cms/backoffice/components'; -import type { ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; +import { umbExtensionsRegistry, type ManifestMenu } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; const elementName = 'umb-help-header-app'; @customElement(elementName) @@ -10,6 +11,24 @@ export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { @state() private _popoverOpen = false; + @state() + private _helpMenuHasMenuItems = false; + + constructor() { + super(); + + new UmbExtensionsManifestInitializer( + this, + umbExtensionsRegistry, + 'menuItem', + (manifest) => manifest.meta.menus.includes(UMB_HELP_MENU_ALIAS), + (menuItems) => { + const manifests = menuItems.map((menuItem) => menuItem.manifest); + this._helpMenuHasMenuItems = manifests.length > 0; + }, + ); + } + #onPopoverToggle(event: ToggleEvent) { // TODO: This ignorer is just neede for JSON SCHEMA TO WORK, As its not updated with latest TS jet. // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -18,11 +37,21 @@ export class UmbHelpHeaderAppElement extends UmbHeaderAppButtonElement { } override render() { + return html` ${this.#renderButton()} ${this.#renderPopover()} `; + } + + #renderButton() { + if (!this._helpMenuHasMenuItems) return nothing; + return html` + `; + } + #renderPopover() { + return html` From a63c5f3e189fbb7b87a282567c76b195c303c715 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:19:56 +0200 Subject: [PATCH 59/67] update package build --- package.json | 2 +- src/packages/help/package.json | 8 ++++++++ src/packages/help/vite.config.ts | 2 +- tsconfig.json | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/packages/help/package.json diff --git a/package.json b/package.json index cefbbb4419..a522d9d100 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", - "./help": "./dist-cms/packages/core/help/index.js", + "./help": "./dist-cms/packages/help/index.js", "./icon": "./dist-cms/packages/core/icon-registry/index.js", "./id": "./dist-cms/packages/core/id/index.js", "./imaging": "./dist-cms/packages/media/imaging/index.js", diff --git a/src/packages/help/package.json b/src/packages/help/package.json new file mode 100644 index 0000000000..3cae8e94ec --- /dev/null +++ b/src/packages/help/package.json @@ -0,0 +1,8 @@ +{ + "name": "@umbraco-backoffice/help", + "private": true, + "type": "module", + "scripts": { + "build": "vite build" + } +} \ No newline at end of file diff --git a/src/packages/help/vite.config.ts b/src/packages/help/vite.config.ts index a320e9a053..965d250b98 100644 --- a/src/packages/help/vite.config.ts +++ b/src/packages/help/vite.config.ts @@ -8,5 +8,5 @@ const dist = '../../../dist-cms/packages/help'; rmSync(dist, { recursive: true, force: true }); export default defineConfig({ - ...getDefaultConfig({ dist, entry: ['manifests.ts', 'umbraco-package.ts'] }), + ...getDefaultConfig({ dist }), }); diff --git a/tsconfig.json b/tsconfig.json index ee2325c332..bcfc0e0b33 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -69,7 +69,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/entity": ["./src/packages/core/entity/index.ts"], "@umbraco-cms/backoffice/event": ["./src/packages/core/event/index.ts"], "@umbraco-cms/backoffice/extension-registry": ["./src/packages/core/extension-registry/index.ts"], - "@umbraco-cms/backoffice/help": ["./src/packages/core/help/index.ts"], + "@umbraco-cms/backoffice/help": ["./src/packages/help/index.ts"], "@umbraco-cms/backoffice/icon": ["./src/packages/core/icon-registry/index.ts"], "@umbraco-cms/backoffice/id": ["./src/packages/core/id/index.ts"], "@umbraco-cms/backoffice/imaging": ["./src/packages/media/imaging/index.ts"], From 165ae6fd57fb039b1a10fffd5ab66326a3efdc76 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 12:38:12 +0200 Subject: [PATCH 60/67] Update package-lock.json --- package-lock.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/package-lock.json b/package-lock.json index 5f5ada3f20..1800a286b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7811,6 +7811,10 @@ "resolved": "src/packages/health-check", "link": true }, + "node_modules/@umbraco-backoffice/help": { + "resolved": "src/packages/help", + "link": true + }, "node_modules/@umbraco-backoffice/language": { "resolved": "src/packages/language", "link": true @@ -23078,6 +23082,7 @@ "src/packages/health-check": { "name": "@umbraco-backoffice/health-check" }, + "src/packages/help": {}, "src/packages/language": { "name": "@umbraco-backoffice/language" }, From 6379bdd077a3f0f1a597903ece9d674da9ff4c3b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Sep 2024 14:57:08 +0200 Subject: [PATCH 61/67] add pattern validation --- ...ate-user-client-credential-modal.element.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts index dc48873e55..c18ac77d4b 100644 --- a/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts +++ b/src/packages/user/user/client-credential/create/modal/create-user-client-credential-modal.element.ts @@ -7,6 +7,7 @@ import type { import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, query } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; +import type { UUIInputElement } from '@umbraco-cms/backoffice/external/uui'; const elementName = 'umb-create-user-client-credential-modal'; @customElement(elementName) @@ -17,10 +18,27 @@ export class UmbCreateUserModalElement extends UmbModalBaseElement< @query('#CreateUserClientCredentialForm') _form?: HTMLFormElement; + @query('#unique') + _inputUniqueElement?: UUIInputElement; + #userClientCredentialRepository = new UmbUserClientCredentialRepository(this); #uniquePrefix = 'umbraco-back-office-'; + protected override firstUpdated(): void { + // For some reason the pattern attribute is not working with this specific regex. It complains about the regex is invalid. + // TODO: investigate why this is happening. + this._inputUniqueElement?.addValidator( + 'patternMismatch', + () => 'Only alphanumeric characters and hyphens are allowed', + () => { + const value = (this._inputUniqueElement?.value as string) || ''; + // eslint-disable-next-line no-useless-escape + return !new RegExp(/^[a-zA-Z0-9\-]+$/).test(value); + }, + ); + } + async #onSubmit(e: SubmitEvent) { e.preventDefault(); From 706410dd996641dfced101f52fcc75603082cb0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 10:56:38 +0200 Subject: [PATCH 62/67] extension api interface --- src/libs/extension-api/models/extension-api.interface.ts | 9 +++++++++ src/libs/extension-api/models/index.ts | 1 + 2 files changed, 10 insertions(+) create mode 100644 src/libs/extension-api/models/extension-api.interface.ts diff --git a/src/libs/extension-api/models/extension-api.interface.ts b/src/libs/extension-api/models/extension-api.interface.ts new file mode 100644 index 0000000000..0183b99fe1 --- /dev/null +++ b/src/libs/extension-api/models/extension-api.interface.ts @@ -0,0 +1,9 @@ +import type { ManifestBase } from '../types/index.js'; +import type { UmbApi } from './api.interface.js'; + +/** + * Interface for APIs of a Extension. + */ +export interface UmbExtensionApi extends UmbApi { + manifest?: ManifestType; +} diff --git a/src/libs/extension-api/models/index.ts b/src/libs/extension-api/models/index.ts index bb52c4681d..45548d385c 100644 --- a/src/libs/extension-api/models/index.ts +++ b/src/libs/extension-api/models/index.ts @@ -1,2 +1,3 @@ export * from './entry-point.interface.js'; export * from './api.interface.js'; +export * from './extension-api.interface.js'; From 6b19f2ae826de1dd5357008c3c500cda0599491a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:14:33 +0200 Subject: [PATCH 63/67] refactor block packages --- package.json | 1 + .../block-editor-custom-view.extension.ts} | 4 +-- src/packages/block/block-custom-view/index.ts | 1 + src/packages/block/block-custom-view/types.ts | 36 +++++++++++++++++++ src/packages/block/block-type/types.ts | 1 + src/packages/block/block/types.ts | 35 ------------------ src/packages/block/vite.config.ts | 1 + 7 files changed, 42 insertions(+), 37 deletions(-) rename src/packages/block/{block/block-editor-custom-view.model.ts => block-custom-view/block-editor-custom-view.extension.ts} (77%) create mode 100644 src/packages/block/block-custom-view/index.ts create mode 100644 src/packages/block/block-custom-view/types.ts diff --git a/package.json b/package.json index a522d9d100..40890bb7e1 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "./action": "./dist-cms/packages/core/action/index.js", "./audit-log": "./dist-cms/packages/core/audit-log/index.js", "./auth": "./dist-cms/packages/core/auth/index.js", + "./block-custom-view": "./dist-cms/packages/block/block-custom-view/index.js", "./block-grid": "./dist-cms/packages/block/block-grid/index.js", "./block-list": "./dist-cms/packages/block/block-list/index.js", "./block-rte": "./dist-cms/packages/block/block-rte/index.js", diff --git a/src/packages/block/block/block-editor-custom-view.model.ts b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts similarity index 77% rename from src/packages/block/block/block-editor-custom-view.model.ts rename to src/packages/block/block-custom-view/block-editor-custom-view.extension.ts index 9bbb3cd298..b82d46ec03 100644 --- a/src/packages/block/block/block-editor-custom-view.model.ts +++ b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts @@ -4,14 +4,14 @@ import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; export interface ManifestBlockEditorCustomView extends ManifestElement { type: 'blockEditorCustomView'; /** - * @property {string | Array } - Declare if this Custom View only must appear at specific Content Types by Alias. + * @property {string | Array } forContentTypeAlias - Declare if this Custom View only must appear at specific Content Types by Alias. * @description Optional condition if you like this custom view to only appear at for one or more specific Content Types. * @example 'my-element-type-alias' * @example ['my-element-type-alias-A', 'my-element-type-alias-B'] */ forContentTypeAlias?: string | Array; /** - * @property {string | Array } - Declare if this Custom View only must appear at specific Block Editors. + * @property {string | Array } forBlockEditor - Declare if this Custom View only must appear at specific Block Editors. * @description Optional condition if you like this custom view to only appear at a specific type of Block Editor. * @example 'block-list' * @example ['block-list', 'block-grid'] diff --git a/src/packages/block/block-custom-view/index.ts b/src/packages/block/block-custom-view/index.ts new file mode 100644 index 0000000000..06c33f562f --- /dev/null +++ b/src/packages/block/block-custom-view/index.ts @@ -0,0 +1 @@ +export type * from './types.js'; diff --git a/src/packages/block/block-custom-view/types.ts b/src/packages/block/block-custom-view/types.ts new file mode 100644 index 0000000000..63c13123f3 --- /dev/null +++ b/src/packages/block/block-custom-view/types.ts @@ -0,0 +1,36 @@ +import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.extension.js'; +import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; + +export type * from './block-editor-custom-view.extension.js'; + +export interface UmbBlockEditorCustomViewConfiguration { + editContentPath?: string; + editSettingsPath?: string; + showContentEdit: boolean; + showSettingsEdit: boolean; +} + +export interface UmbBlockEditorCustomViewProperties< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> { + manifest?: ManifestBlockEditorCustomView; + config?: Partial; + blockType?: BlockType; + contentUdi?: string; + label?: string; + icon?: string; + index?: number; + layout?: LayoutType; + content?: UmbBlockDataType; + settings?: UmbBlockDataType; + contentInvalid?: boolean; + settingsInvalid?: boolean; +} + +export interface UmbBlockEditorCustomViewElement< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> extends UmbBlockEditorCustomViewProperties, + HTMLElement {} diff --git a/src/packages/block/block-type/types.ts b/src/packages/block/block-type/types.ts index ece8e83203..58b67597e8 100644 --- a/src/packages/block/block-type/types.ts +++ b/src/packages/block/block-type/types.ts @@ -1,4 +1,5 @@ import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; + // Shared with the Property Editor export interface UmbBlockTypeBaseModel { contentElementTypeKey: string; diff --git a/src/packages/block/block/types.ts b/src/packages/block/block/types.ts index 55a2123751..0df9c79277 100644 --- a/src/packages/block/block/types.ts +++ b/src/packages/block/block/types.ts @@ -1,7 +1,3 @@ -import type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; -export type { ManifestBlockEditorCustomView } from './block-editor-custom-view.model.js'; - // Shared with the Property Editor export interface UmbBlockLayoutBaseModel { contentUdi: string; @@ -15,37 +11,6 @@ export interface UmbBlockDataType { [key: string]: unknown; } -export interface UmbBlockEditorCustomViewConfiguration { - editContentPath?: string; - editSettingsPath?: string; - showContentEdit: boolean; - showSettingsEdit: boolean; -} - -export interface UmbBlockEditorCustomViewProperties< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> { - manifest?: ManifestBlockEditorCustomView; - config?: Partial; - blockType?: BlockType; - contentUdi?: string; - label?: string; - icon?: string; - index?: number; - layout?: LayoutType; - content?: UmbBlockDataType; - settings?: UmbBlockDataType; - contentInvalid?: boolean; - settingsInvalid?: boolean; -} - -export interface UmbBlockEditorCustomViewElement< - LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, - BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, -> extends UmbBlockEditorCustomViewProperties, - HTMLElement {} - export interface UmbBlockValueType { layout: { [key: string]: Array | undefined }; contentData: Array; diff --git a/src/packages/block/vite.config.ts b/src/packages/block/vite.config.ts index a8a9c55143..47b4244ed0 100644 --- a/src/packages/block/vite.config.ts +++ b/src/packages/block/vite.config.ts @@ -12,6 +12,7 @@ export default defineConfig({ dist, entry: { 'block/index': 'block/index.ts', + 'block-custom-view/index': 'block-custom-view/index.ts', 'block-grid/index': 'block-grid/index.ts', 'block-list/index': 'block-list/index.ts', 'block-rte/index': 'block-rte/index.ts', From 3bf04f6add71ff40e81d66b581a7aba77af6ac25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:23:37 +0200 Subject: [PATCH 64/67] tsc corrections --- examples/block-custom-view/block-custom-view.ts | 3 ++- .../block-grid-block-inline.element.ts | 2 +- .../block-grid-block/block-grid-block.element.ts | 3 ++- .../block-grid-entry/block-grid-entry.element.ts | 10 +++++----- .../block-list-entry/block-list-entry.element.ts | 5 ++++- .../block-rte-entry/block-rte-entry.element.ts | 2 +- .../block-type-custom-view-guide.element.ts | 2 +- src/packages/block/custom-view/custom-view.element.ts | 3 ++- tsconfig.json | 1 + 9 files changed, 19 insertions(+), 12 deletions(-) diff --git a/examples/block-custom-view/block-custom-view.ts b/examples/block-custom-view/block-custom-view.ts index 61f207d30c..78de43087d 100644 --- a/examples/block-custom-view/block-custom-view.ts +++ b/examples/block-custom-view/block-custom-view.ts @@ -1,7 +1,8 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { html, customElement, LitElement, property, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view'; // eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name @customElement('example-block-custom-view') diff --git a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 7aac7408c7..076752e03a 100644 --- a/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -5,7 +5,7 @@ import { css, customElement, html, property, state } from '@umbraco-cms/backoffi import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; import '../block-grid-areas-container/index.js'; import '../ref-grid-block/index.js'; -import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; /** * @element umb-block-grid-block-inline diff --git a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts index 325db2f6d9..1e16df8024 100644 --- a/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts +++ b/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -1,7 +1,8 @@ import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbBlockDataType, UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/block-custom-view'; import '@umbraco-cms/backoffice/ufm'; import '../block-grid-areas-container/index.js'; diff --git a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index b8e9ccf1e9..a2091a3c91 100644 --- a/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -10,11 +10,11 @@ import '../block-grid-block-inline/index.js'; import '../block-grid-block/index.js'; import '../block-scale-handler/index.js'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; -import { - type ManifestBlockEditorCustomView, - UmbDataPathBlockElementDataQuery, - type UmbBlockEditorCustomViewProperties, -} from '@umbraco-cms/backoffice/block'; +import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; +import type { + ManifestBlockEditorCustomView, + UmbBlockEditorCustomViewProperties, +} from '@umbraco-cms/backoffice/block-custom-view'; import { UUIBlinkAnimationValue, UUIBlinkKeyframes } from '@umbraco-cms/backoffice/external/uui'; import type { UmbExtensionElementInitializer } from '@umbraco-cms/backoffice/extension-api'; /** diff --git a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 22b5780558..e378af99d2 100644 --- a/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -8,7 +8,10 @@ import '../inline-list-block/index.js'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbObserveValidationStateController } from '@umbraco-cms/backoffice/validation'; import { UmbDataPathBlockElementDataQuery } from '@umbraco-cms/backoffice/block'; -import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; +import type { + ManifestBlockEditorCustomView, + UmbBlockEditorCustomViewProperties, +} from '@umbraco-cms/backoffice/block-custom-view'; /** * @element umb-block-list-entry diff --git a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 8c52ee27a9..54a59940f8 100644 --- a/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -4,7 +4,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewProperties } from '@umbraco-cms/backoffice/block-custom-view'; import '../ref-rte-block/index.js'; diff --git a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts index 7dbbe77f25..b2fce3bef7 100644 --- a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts +++ b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts @@ -7,7 +7,7 @@ import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbExtensionsManifestInitializer } from '@umbraco-cms/backoffice/extension-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; import { UMB_MODAL_MANAGER_CONTEXT } from '@umbraco-cms/backoffice/modal'; -import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/block'; +import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/block-custom-view'; @customElement('umb-block-type-custom-view-guide') export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { diff --git a/src/packages/block/custom-view/custom-view.element.ts b/src/packages/block/custom-view/custom-view.element.ts index 3160976674..f06fb85444 100644 --- a/src/packages/block/custom-view/custom-view.element.ts +++ b/src/packages/block/custom-view/custom-view.element.ts @@ -1,4 +1,5 @@ -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/block-custom-view'; import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/tsconfig.json b/tsconfig.json index bcfc0e0b33..d6914be56f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -45,6 +45,7 @@ DON'T EDIT THIS FILE DIRECTLY. It is generated by /devops/tsconfig/index.js "@umbraco-cms/backoffice/action": ["./src/packages/core/action/index.ts"], "@umbraco-cms/backoffice/audit-log": ["./src/packages/core/audit-log/index.ts"], "@umbraco-cms/backoffice/auth": ["./src/packages/core/auth/index.ts"], + "@umbraco-cms/backoffice/block-custom-view": ["./src/packages/block/block-custom-view/index.ts"], "@umbraco-cms/backoffice/block-grid": ["./src/packages/block/block-grid/index.ts"], "@umbraco-cms/backoffice/block-list": ["./src/packages/block/block-list/index.ts"], "@umbraco-cms/backoffice/block-rte": ["./src/packages/block/block-rte/index.ts"], From 9b0c8b174e627832d435761a05e1252c206b6cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:25:10 +0200 Subject: [PATCH 65/67] rename test umbraco package --- .../json-schema/{test-package.json => test-umbraco-package.json} | 1 + 1 file changed, 1 insertion(+) rename utils/json-schema/{test-package.json => test-umbraco-package.json} (99%) diff --git a/utils/json-schema/test-package.json b/utils/json-schema/test-umbraco-package.json similarity index 99% rename from utils/json-schema/test-package.json rename to utils/json-schema/test-umbraco-package.json index 26812fa8b7..11b6cf37e8 100644 --- a/utils/json-schema/test-package.json +++ b/utils/json-schema/test-umbraco-package.json @@ -8,6 +8,7 @@ "name": "My Dashboard", "alias": "myDashboard", + "weight": -10, "elementName": "my-dashboard", "js": "js/my-dashboard.js", From 820fafad9a4084088df79fb59df71b82efbfce33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:28:06 +0200 Subject: [PATCH 66/67] rename global manifest type --- examples/block-custom-view/index.ts | 2 +- src/libs/extension-api/types/manifest-bundle.interface.ts | 4 ++-- .../block-type-custom-view-guide.element.ts | 2 +- src/packages/block/custom-view/manifest.ts | 2 +- src/packages/core/extension-registry/models/index.ts | 2 +- src/packages/core/extension-registry/registry.ts | 6 +++--- src/packages/core/extension-registry/umbraco-package.ts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/block-custom-view/index.ts b/examples/block-custom-view/index.ts index 25c1f19d2a..9bf95dc267 100644 --- a/examples/block-custom-view/index.ts +++ b/examples/block-custom-view/index.ts @@ -1,4 +1,4 @@ -export const manifests: Array = [ +export const manifests: Array = [ { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', diff --git a/src/libs/extension-api/types/manifest-bundle.interface.ts b/src/libs/extension-api/types/manifest-bundle.interface.ts index f0e62ede1b..9531fb9396 100644 --- a/src/libs/extension-api/types/manifest-bundle.interface.ts +++ b/src/libs/extension-api/types/manifest-bundle.interface.ts @@ -4,7 +4,7 @@ import type { ManifestBase } from './manifest-base.interface.js'; /** * This type of extension takes a JS module and registers all exported manifests from the pointed JS file. */ -export interface ManifestBundle - extends ManifestPlainJs<{ [key: string]: Array }> { +export interface ManifestBundle + extends ManifestPlainJs<{ [key: string]: Array }> { type: 'bundle'; } diff --git a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts index b2fce3bef7..923339fc71 100644 --- a/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts +++ b/src/packages/block/block-type/components/block-type-custom-view-guide/block-type-custom-view-guide.element.ts @@ -89,7 +89,7 @@ export class UmbBlockTypeCustomViewGuideElement extends UmbLitElement { async #generateManifest() { const modalManager = await this.getContext(UMB_MODAL_MANAGER_CONTEXT); - const manifest: UmbManifestTypes = { + const manifest: UmbExtensionManifest = { type: 'blockEditorCustomView', alias: 'Local.blockEditorCustomView.' + this.#contentTypeAlias, name: 'Block Editor Custom View for ' + this.#contentTypeName, diff --git a/src/packages/block/custom-view/manifest.ts b/src/packages/block/custom-view/manifest.ts index f99b3893f1..46e74f3b3a 100644 --- a/src/packages/block/custom-view/manifest.ts +++ b/src/packages/block/custom-view/manifest.ts @@ -1,4 +1,4 @@ -export const manifest: UmbManifestTypes = { +export const manifest: UmbExtensionManifest = { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', name: 'Block Editor Custom View Test', diff --git a/src/packages/core/extension-registry/models/index.ts b/src/packages/core/extension-registry/models/index.ts index 8a297a6ac8..819ea6af8d 100644 --- a/src/packages/core/extension-registry/models/index.ts +++ b/src/packages/core/extension-registry/models/index.ts @@ -242,5 +242,5 @@ declare global { * This global type provides a union of all declared manifest types. * If this is a local package that declares additional Manifest Types, then these will also be included in this union. */ - type UmbManifestTypes = UnionOfProperties; + type UmbExtensionManifest = UnionOfProperties; } diff --git a/src/packages/core/extension-registry/registry.ts b/src/packages/core/extension-registry/registry.ts index b29da72ae5..649d77294a 100644 --- a/src/packages/core/extension-registry/registry.ts +++ b/src/packages/core/extension-registry/registry.ts @@ -1,7 +1,7 @@ import type { ManifestKind } from '@umbraco-cms/backoffice/extension-api'; import { UmbExtensionRegistry } from '@umbraco-cms/backoffice/extension-api'; -export type UmbBackofficeManifestKind = ManifestKind; -export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; +export type UmbBackofficeManifestKind = ManifestKind; +export type UmbBackofficeExtensionRegistry = UmbExtensionRegistry; -export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; +export const umbExtensionsRegistry = new UmbExtensionRegistry() as UmbBackofficeExtensionRegistry; diff --git a/src/packages/core/extension-registry/umbraco-package.ts b/src/packages/core/extension-registry/umbraco-package.ts index 19edb76a7f..7e11d17764 100644 --- a/src/packages/core/extension-registry/umbraco-package.ts +++ b/src/packages/core/extension-registry/umbraco-package.ts @@ -37,7 +37,7 @@ export interface UmbracoPackage { * @title An array of Umbraco package manifest types that will be installed * @required */ - extensions: UmbManifestTypes[]; + extensions: UmbExtensionManifest[]; /** * @title The importmap for the package From 7c62d8a3dafa6ffc964dd3f7f8050b4d3b3eafd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 13 Sep 2024 11:36:30 +0200 Subject: [PATCH 67/67] rename map --- .../block-editor-custom-view.extension.ts | 2 +- .../core/extension-registry/models/index.ts | 24 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts index b82d46ec03..2212ae53c1 100644 --- a/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts +++ b/src/packages/block/block-custom-view/block-editor-custom-view.extension.ts @@ -20,7 +20,7 @@ export interface ManifestBlockEditorCustomView extends ManifestElement; + type UmbExtensionManifest = UnionOfProperties; }