From c0656ae8cbeaef0127791518e15767f5c83136e6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 20 Sep 2023 15:18:29 +0200 Subject: [PATCH 01/22] move event files from shared into core --- .../collection-selection-actions.element.ts | 30 ++++++++++++------- .../common/template/template-modal.element.ts | 2 +- .../core/picker-input/picker-input.context.ts | 2 +- .../input-multiple-text-string.element.ts | 8 ++--- .../core}/umb-events/change.event.ts | 0 .../core}/umb-events/delete.event.ts | 0 .../core}/umb-events/executed.event.ts | 0 .../core}/umb-events/index.ts | 0 .../core}/umb-events/input.event.ts | 0 .../workspace-action-menu.element.ts | 2 +- .../workspace-action.element.ts | 6 ++-- ...language-details-workspace-view.element.ts | 2 +- .../code-editor/code-editor.controller.ts | 4 +-- .../components/alias-input/alias-input.ts | 6 ++-- src/Umbraco.Web.UI.Client/tsconfig.json | 2 +- 15 files changed, 36 insertions(+), 28 deletions(-) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/umb-events/change.event.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/umb-events/delete.event.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/umb-events/executed.event.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/umb-events/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/umb-events/input.event.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts index ae694f4fe4..a7363e8b92 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts @@ -49,14 +49,22 @@ export class UmbCollectionSelectionActionsElement extends UmbLitElement { if (!this._collectionContext) return; // TODO: Make sure it only updates on length change. - this.observe(this._collectionContext.items, (mediaItems) => { - this._nodesLength = mediaItems.length; - }, 'observeItem'); + this.observe( + this._collectionContext.items, + (mediaItems) => { + this._nodesLength = mediaItems.length; + }, + 'observeItem', + ); - this.observe(this._collectionContext.selection, (selection) => { - this._selectionLength = selection.length; - this._selection = selection; - }, 'observeSelection'); + this.observe( + this._collectionContext.selection, + (selection) => { + this._selectionLength = selection.length; + this._selection = selection; + }, + 'observeSelection', + ); } private _renderSelectionCount() { @@ -69,12 +77,12 @@ export class UmbCollectionSelectionActionsElement extends UmbLitElement { umbExtensionsRegistry.extensionsOfType('entityBulkAction').pipe( map((extensions) => { return extensions.filter((extension) => extension.conditions.entityType === this.#entityType); - }) + }), ), (bulkActions) => { this._entityBulkActions = bulkActions; - } - , 'observeEntityBulkActions' + }, + 'observeEntityBulkActions', ); } @@ -103,7 +111,7 @@ export class UmbCollectionSelectionActionsElement extends UmbLitElement { html`` + .manifest=${manifest}>`, )} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts index 0020d86e6f..6c3fc6cd7d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts @@ -41,7 +41,7 @@ export class UmbTemplateModalElement extends UmbModalBaseElement host: UmbControllerHostElement, repositoryAlias: string, modalAlias: string | UmbModalToken, - getUniqueMethod?: (entry: ItemType) => string | undefined + getUniqueMethod?: (entry: ItemType) => string | undefined, ) { this.host = host; this.modalAlias = modalAlias; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts index cad33d5410..3c9cf85e24 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts @@ -86,12 +86,12 @@ export class UmbInputMultipleTextStringElement extends FormControlMixin(UmbLitEl this.addValidator( 'rangeUnderflow', () => this.minMessage, - () => !!this.min && this._items.length < this.min + () => !!this.min && this._items.length < this.min, ); this.addValidator( 'rangeOverflow', () => this.maxMessage, - () => !!this.max && this._items.length > this.max + () => !!this.max && this._items.length > this.max, ); } @@ -138,7 +138,7 @@ export class UmbInputMultipleTextStringElement extends FormControlMixin(UmbLitEl async #focusNewItem() { await this.updateComplete; const items = this.shadowRoot?.querySelectorAll( - 'umb-input-multiple-text-string-item' + 'umb-input-multiple-text-string-item', ) as NodeListOf; const newItem = items[items.length - 1]; newItem.focus(); @@ -173,7 +173,7 @@ export class UmbInputMultipleTextStringElement extends FormControlMixin(UmbLitEl ?disabled=${this.disabled} ?readonly=${this.readonly} required - required-message="Item ${index + 1} is missing a value">` + required-message="Item ${index + 1} is missing a value">`, )} `; } diff --git a/src/Umbraco.Web.UI.Client/src/shared/umb-events/change.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/change.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/umb-events/change.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/umb-events/change.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/umb-events/delete.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/delete.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/umb-events/delete.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/umb-events/delete.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/umb-events/executed.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/executed.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/umb-events/executed.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/umb-events/executed.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/umb-events/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/umb-events/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/umb-events/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/umb-events/input.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/input.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/umb-events/input.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/umb-events/input.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts index 3f78226d8a..14404cfb9e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts @@ -1,4 +1,4 @@ -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts index 1b21bf25bc..80421bd17c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts @@ -1,7 +1,7 @@ import { UmbWorkspaceAction } from './index.js'; -import { css, html, customElement, property, state, query } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; -import type { UUIButtonElement, UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; +import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { ManifestWorkspaceAction } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts index 1b521cae1c..d408ed2f68 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts @@ -1,6 +1,6 @@ -import type { UmbInputCultureSelectElement } from '@umbraco-cms/backoffice/culture'; import { UMB_LANGUAGE_WORKSPACE_CONTEXT } from '../../language-workspace.context.js'; import type { UmbInputLanguagePickerElement } from '../../../../components/input-language-picker/input-language-picker.element.js'; +import type { UmbInputCultureSelectElement } from '@umbraco-cms/backoffice/culture'; import { UUIBooleanInputEvent, UUIToggleElement } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts index 9aeb5e2a10..889ad97f9b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts @@ -222,7 +222,7 @@ export class UmbCodeEditorController { if (selections?.length > 0) { this.#editor.executeEdits( null, - selections.map((selection) => ({ range: selection, text })) + selections.map((selection) => ({ range: selection, text })), ); } } @@ -236,7 +236,7 @@ export class UmbCodeEditorController { */ find( searchString: string, - searchOptions: CodeEditorSearchOptions = {} + searchOptions: CodeEditorSearchOptions = {}, ): UmbCodeEditorRange[] { if (!this.#editor) throw new Error('Editor object not found'); const defaultOptions = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts index 5d17a74e02..76a4461367 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts @@ -1,4 +1,4 @@ -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; @@ -11,8 +11,8 @@ export class UmbTemplateAliasInputElement extends UmbLitElement { + this.#setValue + }> `; } diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index d4de6fd9d6..e40d094367 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -43,7 +43,7 @@ // SHARED "@umbraco-cms/backoffice/auth": ["src/shared/auth"], - "@umbraco-cms/backoffice/events": ["src/shared/umb-events"], + "@umbraco-cms/backoffice/events": ["src/packages/core/umb-events"], "@umbraco-cms/backoffice/icon": ["src/shared/icon-registry"], "@umbraco-cms/backoffice/models": ["src/shared/models"], "@umbraco-cms/backoffice/repository": ["src/shared/repository"], From 959b7df675c4474636eaabe08d20f8014589a7c1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 20 Sep 2023 15:40:12 +0200 Subject: [PATCH 02/22] update web test runner config --- src/Umbraco.Web.UI.Client/web-test-runner.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs b/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs index 397aed2b1b..47c5b195e6 100644 --- a/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs +++ b/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs @@ -42,7 +42,6 @@ export default { '@umbraco-cms/backoffice/observable-api': './src/libs/observable-api/index.ts', '@umbraco-cms/backoffice/auth': './src/shared/auth/index.ts', - '@umbraco-cms/backoffice/events': './src/shared/umb-events/index.ts', '@umbraco-cms/backoffice/icon': './src/shared/icon-registry/index.ts', '@umbraco-cms/backoffice/models': './src/shared/models/index.ts', '@umbraco-cms/backoffice/repository': './src/shared/repository/index.ts', @@ -79,6 +78,7 @@ export default { '@umbraco-cms/backoffice/variant': './src/packages/core/variant/index.ts', '@umbraco-cms/backoffice/workspace': './src/packages/core/workspace/index.ts', '@umbraco-cms/backoffice/culture': './src/packages/core/culture/index.ts', + '@umbraco-cms/backoffice/events': './src/packages/core/umb-events/index.ts', '@umbraco-cms/backoffice/dictionary': './src/packages/dictionary/dictionary/index.ts', From 793ccfd2d3dc04ce404f9786f35c3ca65d06806a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 21 Sep 2023 10:52:55 +0200 Subject: [PATCH 03/22] Update package.json --- src/Umbraco.Web.UI.Client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 03d64b8394..2cb0650ff4 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -14,7 +14,6 @@ "./localization-api": "./dist-cms/libs/localization-api/index.js", "./observable-api": "./dist-cms/libs/observable-api/index.js", "./auth": "./dist-cms/shared/auth/index.js", - "./events": "./dist-cms/shared/umb-events/index.js", "./icon": "./dist-cms/shared/icon/index.js", "./models": "./dist-cms/shared/models/index.js", "./repository": "./dist-cms/shared/repository/index.js", @@ -47,6 +46,7 @@ "./tree": "./dist-cms/packages/core/tree/index.js", "./variant": "./dist-cms/packages/core/variant/index.js", "./workspace": "./dist-cms/packages/core/workspace/index.js", + "./events": "./dist-cms/packages/core/umb-events/index.js", "./dictionary": "./dist-cms/packages/dictionary/dictionary/index.js", "./document": "./dist-cms/packages/documents/documents/index.js", "./document-blueprint": "./dist-cms/packages/documents/document-blueprints/index.js", From 9037ff05b34121b39641d84860ab495bb75017b7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 20 Sep 2023 15:37:42 +0200 Subject: [PATCH 04/22] move repository files into core folder --- .../core}/repository/collection-repository.interface.ts | 0 .../core}/repository/copy-repository.interface.ts | 0 .../data-source/collection-data-source.interface.ts | 0 .../repository/data-source/copy-data-source.interface.ts | 2 +- .../data-source/data-source-response.interface.ts | 0 .../core}/repository/data-source/data-source.interface.ts | 6 +++--- .../extend-data-source-paged-response-data.function.ts | 0 .../extend-data-source-paged-response-data.test.ts | 0 .../extend-data-source-response-data.function.ts | 0 .../data-source/extend-data-source-response-data.test.ts | 0 .../repository/data-source/folder-data-source.interface.ts | 0 .../core}/repository/data-source/index.ts | 0 .../repository/data-source/item-data-source.interface.ts | 2 +- .../repository/data-source/move-data-source.interface.ts | 2 +- .../repository/data-source/tree-data-source.interface.ts | 0 .../core}/repository/detail-repository.interface.ts | 0 .../core}/repository/folder-repository.interface.ts | 0 .../src/{shared => packages/core}/repository/index.ts | 0 .../core}/repository/item-repository.interface.ts | 0 .../core}/repository/move-repository.interface.ts | 0 .../core}/repository/repository-items.manager.ts | 2 +- .../core}/repository/tree-repository.interface.ts | 0 src/Umbraco.Web.UI.Client/tsconfig.json | 2 +- 23 files changed, 8 insertions(+), 8 deletions(-) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/collection-repository.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/copy-repository.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/collection-data-source.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/copy-data-source.interface.ts (62%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/data-source-response.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/data-source.interface.ts (80%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/extend-data-source-paged-response-data.function.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/extend-data-source-paged-response-data.test.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/extend-data-source-response-data.function.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/extend-data-source-response-data.test.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/folder-data-source.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/item-data-source.interface.ts (62%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/move-data-source.interface.ts (60%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/data-source/tree-data-source.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/detail-repository.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/folder-repository.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/item-repository.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/move-repository.interface.ts (100%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/repository-items.manager.ts (97%) rename src/Umbraco.Web.UI.Client/src/{shared => packages/core}/repository/tree-repository.interface.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/collection-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/collection-repository.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/collection-repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/collection-repository.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/copy-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/copy-repository.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/copy-repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/copy-repository.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/collection-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/collection-data-source.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/collection-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/collection-data-source.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/copy-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/copy-data-source.interface.ts similarity index 62% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/copy-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/copy-data-source.interface.ts index f2477be161..50c4ff2501 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/copy-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/copy-data-source.interface.ts @@ -1,4 +1,4 @@ -import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import type { DataSourceResponse } from 'src/packages/core/repository'; export interface UmbCopyDataSource { copy(unique: string, targetUnique: string | null): Promise>; diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/data-source-response.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source-response.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/data-source-response.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source-response.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source.interface.ts similarity index 80% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/data-source.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source.interface.ts index 23689c83d9..3699d7bc1e 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source.interface.ts @@ -1,15 +1,15 @@ -import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import type { DataSourceResponse } from 'src/packages/core/repository'; export interface UmbDataSource< CreateRequestType, CreateResponseType, UpdateRequestType, ResponseType, - CreateScaffoldPresetType = Partial + CreateScaffoldPresetType = Partial, > { createScaffold( parentId: string | null, - preset?: Partial | CreateScaffoldPresetType + preset?: Partial | CreateScaffoldPresetType, ): Promise>; get(unique: string): Promise>; insert(data: CreateRequestType): Promise>; diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-paged-response-data.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-paged-response-data.function.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-paged-response-data.function.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-paged-response-data.function.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-paged-response-data.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-paged-response-data.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-paged-response-data.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-paged-response-data.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-response-data.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-response-data.function.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-response-data.function.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-response-data.function.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-response-data.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-response-data.test.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/extend-data-source-response-data.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/extend-data-source-response-data.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/folder-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/folder-data-source.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/folder-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/folder-data-source.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/item-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/item-data-source.interface.ts similarity index 62% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/item-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/item-data-source.interface.ts index 88fb741ee3..ef09afc89d 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/item-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/item-data-source.interface.ts @@ -1,4 +1,4 @@ -import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; +import type { DataSourceResponse } from 'src/packages/core/repository'; export interface UmbItemDataSource { getItems(unique: Array): Promise>>; diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/move-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/move-data-source.interface.ts similarity index 60% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/move-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/move-data-source.interface.ts index e0ac7ce1d7..7621e2fe4e 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/move-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/move-data-source.interface.ts @@ -1,4 +1,4 @@ -import type { UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository'; +import type { UmbDataSourceErrorResponse } from 'src/packages/core/repository'; export interface UmbMoveDataSource { move(unique: string, targetUnique: string | null): Promise; diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/data-source/tree-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/tree-data-source.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/data-source/tree-data-source.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/tree-data-source.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/detail-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/detail-repository.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/detail-repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/detail-repository.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/folder-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/folder-repository.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/folder-repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/folder-repository.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/item-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/item-repository.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/item-repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/item-repository.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/move-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/move-repository.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/move-repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/move-repository.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/repository-items.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts similarity index 97% rename from src/Umbraco.Web.UI.Client/src/shared/repository/repository-items.manager.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts index 991d1aa290..b4f3a1cfb5 100644 --- a/src/Umbraco.Web.UI.Client/src/shared/repository/repository-items.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts @@ -1,4 +1,4 @@ -import { UmbItemRepository } from '@umbraco-cms/backoffice/repository'; +import { UmbItemRepository } from 'src/packages/core/repository'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; import { UmbExtensionClassInitializer } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/shared/repository/tree-repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/tree-repository.interface.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/shared/repository/tree-repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/tree-repository.interface.ts diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index d4de6fd9d6..7c949e5c74 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -46,7 +46,7 @@ "@umbraco-cms/backoffice/events": ["src/shared/umb-events"], "@umbraco-cms/backoffice/icon": ["src/shared/icon-registry"], "@umbraco-cms/backoffice/models": ["src/shared/models"], - "@umbraco-cms/backoffice/repository": ["src/shared/repository"], + "@umbraco-cms/backoffice/repository": ["src/packages/core/repository"], "@umbraco-cms/backoffice/resources": ["src/shared/resources"], "@umbraco-cms/backoffice/router": ["src/shared/router"], "@umbraco-cms/backoffice/style": ["src/shared/style"], From 4af3b577fc265b0afad5ccd7c92de6e5eed9f172 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 20 Sep 2023 15:39:03 +0200 Subject: [PATCH 05/22] update web test runner importmap --- src/Umbraco.Web.UI.Client/web-test-runner.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs b/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs index 397aed2b1b..c24e8c5ce9 100644 --- a/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs +++ b/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs @@ -45,7 +45,6 @@ export default { '@umbraco-cms/backoffice/events': './src/shared/umb-events/index.ts', '@umbraco-cms/backoffice/icon': './src/shared/icon-registry/index.ts', '@umbraco-cms/backoffice/models': './src/shared/models/index.ts', - '@umbraco-cms/backoffice/repository': './src/shared/repository/index.ts', '@umbraco-cms/backoffice/resources': './src/shared/resources/index.ts', '@umbraco-cms/backoffice/router': './src/shared/router/index.ts', '@umbraco-cms/backoffice/style': './src/shared/style/index.ts', @@ -79,6 +78,7 @@ export default { '@umbraco-cms/backoffice/variant': './src/packages/core/variant/index.ts', '@umbraco-cms/backoffice/workspace': './src/packages/core/workspace/index.ts', '@umbraco-cms/backoffice/culture': './src/packages/core/culture/index.ts', + '@umbraco-cms/backoffice/repository': './src/packages/core/repository/index.ts', '@umbraco-cms/backoffice/dictionary': './src/packages/dictionary/dictionary/index.ts', From e506795888e6a1f06821af7cf84f92f384117951 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 21 Sep 2023 10:54:11 +0200 Subject: [PATCH 06/22] Update package.json --- src/Umbraco.Web.UI.Client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 114c08d952..213a1916e3 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -17,7 +17,6 @@ "./events": "./dist-cms/shared/umb-events/index.js", "./icon": "./dist-cms/shared/icon/index.js", "./models": "./dist-cms/shared/models/index.js", - "./repository": "./dist-cms/shared/repository/index.js", "./resources": "./dist-cms/shared/resources/index.js", "./router": "./dist-cms/shared/router/index.js", "./style": "./dist-cms/shared/style/index.js", @@ -47,6 +46,7 @@ "./tree": "./dist-cms/packages/core/tree/index.js", "./variant": "./dist-cms/packages/core/variant/index.js", "./workspace": "./dist-cms/packages/core/workspace/index.js", + "./repository": "./dist-cms/packages/core/repository/index.js", "./dictionary": "./dist-cms/packages/dictionary/dictionary/index.js", "./document": "./dist-cms/packages/documents/documents/index.js", "./document-blueprint": "./dist-cms/packages/documents/document-blueprints/index.js", From d46b1ea0e73939378940a5a4edfddbec0f0c8166 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 21 Sep 2023 11:00:19 +0200 Subject: [PATCH 07/22] update imports --- .../core/repository/data-source/copy-data-source.interface.ts | 2 +- .../core/repository/data-source/data-source.interface.ts | 2 +- .../core/repository/data-source/item-data-source.interface.ts | 2 +- .../core/repository/data-source/move-data-source.interface.ts | 2 +- .../src/packages/core/repository/repository-items.manager.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/copy-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/copy-data-source.interface.ts index 50c4ff2501..f2477be161 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/copy-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/copy-data-source.interface.ts @@ -1,4 +1,4 @@ -import type { DataSourceResponse } from 'src/packages/core/repository'; +import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; export interface UmbCopyDataSource { copy(unique: string, targetUnique: string | null): Promise>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source.interface.ts index 3699d7bc1e..c029560648 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/data-source.interface.ts @@ -1,4 +1,4 @@ -import type { DataSourceResponse } from 'src/packages/core/repository'; +import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; export interface UmbDataSource< CreateRequestType, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/item-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/item-data-source.interface.ts index ef09afc89d..88fb741ee3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/item-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/item-data-source.interface.ts @@ -1,4 +1,4 @@ -import type { DataSourceResponse } from 'src/packages/core/repository'; +import type { DataSourceResponse } from '@umbraco-cms/backoffice/repository'; export interface UmbItemDataSource { getItems(unique: Array): Promise>>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/move-data-source.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/move-data-source.interface.ts index 7621e2fe4e..e0ac7ce1d7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/move-data-source.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/data-source/move-data-source.interface.ts @@ -1,4 +1,4 @@ -import type { UmbDataSourceErrorResponse } from 'src/packages/core/repository'; +import type { UmbDataSourceErrorResponse } from '@umbraco-cms/backoffice/repository'; export interface UmbMoveDataSource { move(unique: string, targetUnique: string | null): Promise; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts index b4f3a1cfb5..991d1aa290 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository-items.manager.ts @@ -1,4 +1,4 @@ -import { UmbItemRepository } from 'src/packages/core/repository'; +import { UmbItemRepository } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; import { UmbExtensionClassInitializer } from '@umbraco-cms/backoffice/extension-registry'; From 84bf0f86f8cf90276c96e971d82e184c107100f0 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:07:11 +0200 Subject: [PATCH 08/22] basic actions --- .../input-markdown.element.ts | 368 +++++++++++++++++- 1 file changed, 361 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts index e9202df63b..0753b304d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts @@ -1,4 +1,6 @@ -import { UmbCodeEditorElement, loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; +import { KeyCode, KeyMod } from 'monaco-editor'; +import { UmbMediaPickerContext } from '../../../media/media/components/input-media/input-media.context.js'; +import { UmbCodeEditorController, UmbCodeEditorElement, loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; import { css, html, customElement, query, property } from '@umbraco-cms/backoffice/external/lit'; import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; @@ -12,18 +14,20 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @customElement('umb-input-markdown') export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { protected getFormElement() { - return undefined; + return this._codeEditor; } @property({ type: Boolean }) preview?: boolean; #isCodeEditorReady = new UmbBooleanState(false); - isCodeEditorReady = this.#isCodeEditorReady.asObservable(); + #editor?: UmbCodeEditorController; @query('umb-code-editor') _codeEditor?: UmbCodeEditorElement; + #mediaPicker = new UmbMediaPickerContext(this); + constructor() { super(); this.#loadCodeEditor(); @@ -32,20 +36,356 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { async #loadCodeEditor() { try { await loadCodeEditor(); - this._codeEditor?.editor?.updateOptions({ + this.#isCodeEditorReady.next(true); + + this.#editor = this._codeEditor?.editor; + + this.#editor?.updateOptions({ lineNumbers: false, minimap: false, folding: false, }); - this.#isCodeEditorReady.next(true); + this.#loadActions(); } catch (error) { console.error(error); } } + async #loadActions() { + // Going to base the keybindings of a Markdown Shortcut plugin https://marketplace.visualstudio.com/items?itemName=robole.markdown-shortcuts#shortcuts + // TODO: Find a way to have "double" keybindings (ctrl+m+ctrl+c for `code`, rather than simple ctrl+c as its taken by OS to copy things) + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H1', + id: 'h1', + keybindings: [KeyMod.CtrlCmd | KeyCode.Digit1], + run: () => this._insertAtCurrentLine('#'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H2', + id: 'h2', + keybindings: [KeyMod.CtrlCmd | KeyCode.Digit2], + run: () => this._insertAtCurrentLine('##'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H3', + id: 'h3', + keybindings: [KeyMod.CtrlCmd | KeyCode.Digit3], + run: () => this._insertAtCurrentLine('###'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H4', + id: 'h4', + keybindings: [KeyMod.CtrlCmd | KeyCode.Digit4], + run: () => this._insertAtCurrentLine('####'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H5', + id: 'h5', + keybindings: [KeyMod.CtrlCmd | KeyCode.Digit5], + run: () => this._insertAtCurrentLine('#####'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H6', + id: 'h6', + keybindings: [KeyMod.CtrlCmd | KeyCode.Digit6], + run: () => this._insertAtCurrentLine('######'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Bold Text', + id: 'b', + keybindings: [KeyMod.CtrlCmd | KeyCode.KeyB], + run: () => this._insertBetweenSelection('**', '**', 'Your Bold Text'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Italic Text', + id: 'i', + keybindings: [KeyMod.CtrlCmd | KeyCode.KeyI], + run: () => this._insertBetweenSelection('*', '*', 'Your Italic Text'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Quote', + id: 'q', + keybindings: [KeyMod.CtrlCmd | KeyCode.KeyQ], + run: () => this._insertAtCurrentLine('> '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Ordered List', + id: 'ol', + keybindings: [KeyMod.CtrlCmd | KeyCode.KeyO], + run: () => this._insertAtCurrentLine('1. '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Unordered List', + id: 'ul', + keybindings: [KeyMod.CtrlCmd | KeyCode.KeyU], + run: () => this._insertAtCurrentLine('- '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Code', + id: 'code', + //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC], + run: () => this._insertBetweenSelection('`', '`', 'Code'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Fenced Code', + id: 'fenced-code', + //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyF], + run: () => this._insertBetweenSelection('```', '```', 'Code'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Line', + id: 'line', + //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC], + run: () => this._insertAtCurrentLine('---\n'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Link', + id: 'link', + //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC], + run: () => this._insertBetweenSelection('[', '](https://example.com)', 'title'), + // TODO: Open in modal + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Image', + id: 'image', + //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC], + run: () => this._insertBetweenSelection('![', '](example.png)', 'alt text'), + // TODO: Open in modal + }); + } + + private _focusEditor(): void { + // If we press one of the action buttons manually (which is outside the editor), we need to focus the editor again. + this.#editor?.monacoEditor?.focus(); + } + + private _insertBetweenSelection(startValue: string, endValue: string, placeholder?: string) { + this._focusEditor(); + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + const selectedValue = this.#editor?.getValueInRange({ + startLineNumber: selection.startLineNumber, + endLineNumber: selection.endLineNumber, + startColumn: selection.startColumn - startValue.length, + endColumn: selection.endColumn + endValue.length, + }); + if (selectedValue?.startsWith(startValue) && selectedValue.endsWith(endValue)) { + //Cancel previous insert + this.#editor?.select({ ...selection, startColumn: selection.startColumn + startValue.length }); + this.#editor?.monacoEditor?.executeEdits('', [ + { + range: { + startColumn: selection.startColumn - startValue.length, + startLineNumber: selection.startLineNumber, + endColumn: selection.startColumn, + endLineNumber: selection.startLineNumber, + }, + text: '', + }, + { + range: { + startColumn: selection.endColumn + startValue.length, + startLineNumber: selection.startLineNumber, + endColumn: selection.endColumn, + endLineNumber: selection.startLineNumber, + }, + text: '', + }, + ]); + } else { + // Insert + this.#editor?.insertAtPosition(startValue, { + lineNumber: selection.startLineNumber, + column: selection.startColumn, + }); + this.#editor?.insertAtPosition(endValue, { + lineNumber: selection.endLineNumber, + column: selection.endColumn + startValue.length, + }); + } + + // if no text were selected when action fired + if (selection.startColumn === selection.endColumn && selection.startLineNumber === selection.endLineNumber) { + if (placeholder) { + this.#editor?.insertAtPosition(placeholder, { + lineNumber: selection.startLineNumber, + column: selection.startColumn + startValue.length, + }); + } + this.#editor?.select({ + startLineNumber: selection.startLineNumber, + endLineNumber: selection.endLineNumber, + startColumn: selection.startColumn + startValue.length, + endColumn: selection.startColumn + startValue.length + (placeholder?.length ?? 0), + }); + } + } + + private _insertAtCurrentLine(value: string) { + this._focusEditor(); + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + const previousLineValue = this.#editor?.getValueInRange({ + ...selection, + startLineNumber: selection.startLineNumber - 1, + }); + const lineValue = this.#editor?.getValueInRange({ ...selection, startColumn: 1 }); + + // Regex: check if the line starts with a positive number followed by dot and a space + if (lineValue?.startsWith(value) || lineValue?.match(/^[1-9]\d*\.\s.*/)) { + // Cancel previous insert + this.#editor?.monacoEditor?.executeEdits('', [ + { + range: { + startColumn: 1, + startLineNumber: selection.startLineNumber, + endColumn: 1 + value.length, + endLineNumber: selection.startLineNumber, + }, + text: '', + }, + ]); + } else if (value.match(/^[1-9]\d*\.\s.*/) && previousLineValue?.match(/^[1-9]\d*\.\s.*/)) { + // Check if the PREVIOUS line starts with a positive number followed by dot and a space. If yes, get that number. + const previousNumber = parseInt(previousLineValue, 10); + this.#editor?.insertAtPosition(`${previousNumber + 1}. `, { + lineNumber: selection.startLineNumber, + column: 1, + }); + } else { + // Insert + this.#editor?.insertAtPosition(value, { + lineNumber: selection.startLineNumber, + column: 1, + }); + } + } + + private _renderBasicActions() { + return html`
+ this.#editor?.monacoEditor?.getAction('h1')?.run()}> + H + + this.#editor?.monacoEditor?.getAction('b')?.run()}> + B + + this.#editor?.monacoEditor?.getAction('i')?.run()}> + I + +
+
+ this.#editor?.monacoEditor?.getAction('q')?.run()}> + + + this.#editor?.monacoEditor?.getAction('ol')?.run()}> + + + this.#editor?.monacoEditor?.getAction('ul')?.run()}> + + +
+
+ this.#editor?.monacoEditor?.getAction('fenced-code')?.run()}> + + + this.#editor?.monacoEditor?.getAction('line')?.run()}> + + + this.#editor?.monacoEditor?.getAction('link')?.run()}> + + + this.#editor?.monacoEditor?.getAction('image')?.run()}> + + +
+
+ { + this._focusEditor(); + this.#editor?.monacoEditor?.trigger('', 'editor.action.quickCommand', ''); + }}> + F1 + +
`; + } + + onKeyPress(e: KeyboardEvent) { + if (e.key !== 'Enter' && e.key !== 'Tab') return; + + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + const lineValue = this.#editor?.getValueInRange({ ...selection, startColumn: 1 }); + if (!lineValue) return; + + if (e.key === 'Enter') { + if (lineValue.startsWith('- ') && lineValue.length > 3) { + requestAnimationFrame(() => this.#editor?.insert('- ')); + } else if (lineValue.match(/^[1-9]\d*\.\s.*/) && lineValue.length) { + const previousNumber = parseInt(lineValue, 10); + requestAnimationFrame(() => this.#editor?.insert(`${previousNumber + 1}. `)); + } + } + } + render() { - return html`
- + return html`
${this._renderBasicActions()}
+ ${this.renderPreview()}`; } @@ -63,6 +403,16 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { #actions { background-color: var(--uui-color-background-alt); display: flex; + gap: var(--uui-size-6); + } + + #actions div { + display: flex; + gap: var(--uui-size-1); + } + + #actions div:last-child { + margin-left: auto; } umb-code-editor { @@ -70,6 +420,10 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { border-radius: var(--uui-border-radius); border: 1px solid var(--uui-color-divider-emphasis); } + + uui-button { + width: 50px; + } `, ]; } From d2f9be20661c103af44bd161b0ca7d84b4f90fac Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Oct 2023 13:58:49 +0200 Subject: [PATCH 09/22] rename folder and importmap to use singular form --- .../core/collection/collection-selection-actions.element.ts | 2 +- .../input-culture-select/input-culture-select.element.ts | 2 +- .../src/packages/core/entity-action/entity-action.element.ts | 2 +- .../core/entity-bulk-action/entity-bulk-action.element.ts | 2 +- .../src/packages/core/{umb-events => event}/change.event.ts | 0 .../src/packages/core/{umb-events => event}/delete.event.ts | 0 .../src/packages/core/{umb-events => event}/executed.event.ts | 0 .../src/packages/core/{umb-events => event}/index.ts | 0 .../src/packages/core/{umb-events => event}/input.event.ts | 0 .../src/packages/core/{umb-events => event}/selected.event.ts | 0 .../core/modal/common/template/template-modal.element.ts | 2 +- .../core/modal/common/tree-picker/tree-picker-modal.element.ts | 2 +- .../src/packages/core/picker-input/picker-input.context.ts | 2 +- .../input-multiple-text-string-item.element.ts | 2 +- .../input-multiple-text-string.element.ts | 2 +- .../property-editor-ui-multiple-text-string.element.ts | 2 +- .../src/packages/core/tree/tree.context.ts | 2 +- .../workspace-action-menu/workspace-action-menu.element.ts | 2 +- .../core/workspace/workspace-action/workspace-action.element.ts | 2 +- .../document-table-actions-column-layout.element.ts | 2 +- .../input-document-granular-permission.element.ts | 2 +- .../views/details/language-details-workspace-view.element.ts | 2 +- .../packages/templating/code-editor/code-editor.controller.ts | 2 +- .../templating/templates/components/alias-input/alias-input.ts | 2 +- .../components/user-group-default-permission-list.element.ts | 2 +- .../workspace/user-group-workspace-editor.element.ts | 2 +- .../user-permission-setting/user-permission-setting.element.ts | 2 +- src/Umbraco.Web.UI.Client/tsconfig.json | 2 +- src/Umbraco.Web.UI.Client/web-test-runner.config.mjs | 2 +- 29 files changed, 23 insertions(+), 23 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/core/{umb-events => event}/change.event.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{umb-events => event}/delete.event.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{umb-events => event}/executed.event.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{umb-events => event}/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{umb-events => event}/input.event.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{umb-events => event}/selected.event.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts index a7363e8b92..dd43060c0d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/collection/collection-selection-actions.element.ts @@ -1,10 +1,10 @@ +import { UmbExecutedEvent } from '@umbraco-cms/backoffice/event'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, nothing, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { map } from '@umbraco-cms/backoffice/external/rxjs'; import { UMB_COLLECTION_CONTEXT_TOKEN, UmbCollectionContext } from '@umbraco-cms/backoffice/collection'; import { ManifestEntityBulkAction, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; @customElement('umb-collection-selection-actions') export class UmbCollectionSelectionActionsElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.element.ts index 4e04199eb3..3c9f545096 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.element.ts @@ -1,7 +1,7 @@ +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbCultureRepository } from '../../repository/culture.repository.js'; import { html, repeat, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { FormControlMixin, UUIComboboxElement, UUIComboboxEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { CultureReponseModel } from '@umbraco-cms/backoffice/backend-api'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts index d03f19fe2e..cd901e0044 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action.element.ts @@ -1,6 +1,6 @@ +import { UmbExecutedEvent } from '@umbraco-cms/backoffice/event'; import { html, nothing, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UUIMenuItemEvent } from '@umbraco-cms/backoffice/external/uui'; -import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { ManifestEntityAction } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts index b83fd56941..95648818e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-bulk-action/entity-bulk-action.element.ts @@ -1,6 +1,6 @@ +import { UmbExecutedEvent } from '@umbraco-cms/backoffice/event'; import { UmbEntityBulkAction } from './entity-bulk-action.js'; import { html, ifDefined, customElement, property } from '@umbraco-cms/backoffice/external/lit'; -import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; import { ManifestEntityBulkAction } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/change.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/event/change.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/umb-events/change.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/event/change.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/delete.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/event/delete.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/umb-events/delete.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/event/delete.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/executed.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/event/executed.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/umb-events/executed.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/event/executed.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/event/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/umb-events/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/event/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/input.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/event/input.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/umb-events/input.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/event/input.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/umb-events/selected.event.ts b/src/Umbraco.Web.UI.Client/src/packages/core/event/selected.event.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/umb-events/selected.event.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/event/selected.event.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts index 6c3fc6cd7d..05435c7095 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/template/template-modal.element.ts @@ -1,8 +1,8 @@ +import { UmbInputEvent } from '@umbraco-cms/backoffice/event'; import type { UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; import { css, html, ifDefined, customElement, query, state } from '@umbraco-cms/backoffice/external/lit'; import { UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UmbTemplateModalData, UmbTemplateModalResult } from '@umbraco-cms/backoffice/modal'; -import { UmbInputEvent } from '@umbraco-cms/backoffice/events'; import { TemplateResource, TemplateResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/tree-picker/tree-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/tree-picker/tree-picker-modal.element.ts index 3ecae28a7d..3287abbb50 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/tree-picker/tree-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/tree-picker/tree-picker-modal.element.ts @@ -1,10 +1,10 @@ +import { UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; import type { UmbTreeElement } from '../../../tree/tree.element.js'; import { html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbTreePickerModalData, UmbPickerModalResult } from '@umbraco-cms/backoffice/modal'; import { UmbModalBaseElement } from '@umbraco-cms/internal/modal'; import { TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbSelectedEvent } from '@umbraco-cms/backoffice/events'; @customElement('umb-tree-picker-modal') export class UmbTreePickerModalElement extends UmbModalBaseElement< diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts index a77b907fee..bb0eac8fad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/picker-input/picker-input.context.ts @@ -1,3 +1,4 @@ +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbItemRepository, UmbRepositoryItemsManager } from '@umbraco-cms/backoffice/repository'; import { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; import { @@ -9,7 +10,6 @@ import { } from '@umbraco-cms/backoffice/modal'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import { ItemResponseModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; export class UmbPickerInputContext { host: UmbControllerHostElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string-item/input-multiple-text-string-item.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string-item/input-multiple-text-string-item.element.ts index b56c82b7bb..48a69ec19b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string-item/input-multiple-text-string-item.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string-item/input-multiple-text-string-item.element.ts @@ -5,7 +5,7 @@ import { UMB_MODAL_MANAGER_CONTEXT_TOKEN, UMB_CONFIRM_MODAL, } from '@umbraco-cms/backoffice/modal'; -import { UmbChangeEvent, UmbInputEvent, UmbDeleteEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent, UmbInputEvent, UmbDeleteEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts index 3c9cf85e24..e099a27904 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/input-multiple-text-string/input-multiple-text-string.element.ts @@ -1,7 +1,7 @@ import UmbInputMultipleTextStringItemElement from '../input-multiple-text-string-item/input-multiple-text-string-item.element.js'; import { css, html, nothing, repeat, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui'; -import { UmbInputEvent, UmbChangeEvent, UmbDeleteEvent } from '@umbraco-cms/backoffice/events'; +import { UmbInputEvent, UmbChangeEvent, UmbDeleteEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; export type MultipleTextStringValue = Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts index db71e5d040..db5a26480e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/multiple-text-string/property-editor-ui-multiple-text-string.element.ts @@ -1,3 +1,4 @@ +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbPropertyValueChangeEvent } from '../../index.js'; import { UmbInputMultipleTextStringElement, @@ -6,7 +7,6 @@ import { import { html, customElement, property, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbPropertyEditorExtensionElement } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts index 1e9c5fe3a6..da70add6b9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.context.ts @@ -6,7 +6,7 @@ import { UmbBaseController, UmbControllerHostElement } from '@umbraco-cms/backof import { createExtensionClass } from '@umbraco-cms/backoffice/extension-api'; import { ProblemDetails, TreeItemPresentationModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbSelectionManagerBase } from '@umbraco-cms/backoffice/utils'; -import { UmbSelectedEvent } from '@umbraco-cms/backoffice/events'; +import { UmbSelectedEvent } from '@umbraco-cms/backoffice/event'; // TODO: update interface export interface UmbTreeContext extends UmbBaseController { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts index 14404cfb9e..d4d7fd322c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action-menu/workspace-action-menu.element.ts @@ -1,6 +1,6 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; +import { UmbExecutedEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; @customElement('umb-workspace-action-menu') diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts index 80421bd17c..0e64bb260e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-action/workspace-action.element.ts @@ -2,7 +2,7 @@ import { UmbWorkspaceAction } from './index.js'; import { css, html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; -import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; +import { UmbExecutedEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { ManifestWorkspaceAction } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-actions-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-actions-column-layout.element.ts index 083ed5cb3e..fcf57577cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-actions-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/collection/views/table/column-layouts/document-table-actions-column-layout.element.ts @@ -9,7 +9,7 @@ import { state, } from '@umbraco-cms/backoffice/external/lit'; import type { UmbTableColumn, UmbTableItem } from '@umbraco-cms/backoffice/components'; -import { UmbExecutedEvent } from '@umbraco-cms/backoffice/events'; +import { UmbExecutedEvent } from '@umbraco-cms/backoffice/event'; // TODO: this could be done more generic, but for now we just need it for the document table @customElement('umb-document-table-actions-column-layout') diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document-granular-permission/input-document-granular-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document-granular-permission/input-document-granular-permission.element.ts index 1ab33f7290..a157f93c73 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document-granular-permission/input-document-granular-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document-granular-permission/input-document-granular-permission.element.ts @@ -9,7 +9,7 @@ import { import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { DocumentItemResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbDocumentRepository } from '@umbraco-cms/backoffice/document'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbObserverController } from '@umbraco-cms/backoffice/observable-api'; @customElement('umb-input-document-granular-permission') diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts index d408ed2f68..3faae4637a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/settings/languages/workspace/language/views/details/language-details-workspace-view.element.ts @@ -3,7 +3,7 @@ import type { UmbInputLanguagePickerElement } from '../../../../components/input import type { UmbInputCultureSelectElement } from '@umbraco-cms/backoffice/culture'; import { UUIBooleanInputEvent, UUIToggleElement } from '@umbraco-cms/backoffice/external/uui'; import { css, html, nothing, customElement, state, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { LanguageResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts index 889ad97f9b..3ce2e64817 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/code-editor/code-editor.controller.ts @@ -11,7 +11,7 @@ import { } from './code-editor.model.js'; import { themes } from './themes/index.js'; import { monaco } from '@umbraco-cms/backoffice/external/monaco-editor'; -import { UmbChangeEvent, UmbInputEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent, UmbInputEvent } from '@umbraco-cms/backoffice/event'; //TODO - consider firing change event on blur diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts index 76a4461367..10a09a53ca 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/components/alias-input/alias-input.ts @@ -1,7 +1,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @customElement('umb-template-alias-input') export class UmbTemplateAliasInputElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/components/user-group-default-permission-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/components/user-group-default-permission-list.element.ts index 84d7880f9e..8b87699017 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/components/user-group-default-permission-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/components/user-group-default-permission-list.element.ts @@ -4,7 +4,7 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UserGroupResponseModel } from '@umbraco-cms/backoffice/backend-api'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { ManifestUserPermission, umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { type UmbUserPermissionSettingElement } from '@umbraco-cms/backoffice/users'; import { groupBy } from '@umbraco-cms/backoffice/external/lodash'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/user-group-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/user-group-workspace-editor.element.ts index 7b7453b3b2..08243f8ad0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/user-group-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/users/user-groups/workspace/user-group-workspace-editor.element.ts @@ -8,7 +8,7 @@ import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbInputDocumentElement } from '@umbraco-cms/backoffice/document'; import { UmbInputSectionElement } from '@umbraco-cms/backoffice/components'; import { UmbUserInputElement } from '@umbraco-cms/backoffice/users'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbInputMediaElement } from '@umbraco-cms/backoffice/media'; import './components/user-group-default-permission-list.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/users/users/components/user-permission-setting/user-permission-setting.element.ts b/src/Umbraco.Web.UI.Client/src/packages/users/users/components/user-permission-setting/user-permission-setting.element.ts index 2231e11f10..ba504104d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/users/users/components/user-permission-setting/user-permission-setting.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/users/users/components/user-permission-setting/user-permission-setting.element.ts @@ -2,7 +2,7 @@ import { type UUIBooleanInputEvent } from '@umbraco-cms/backoffice/external/uui' import { css, html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/events'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @customElement('umb-user-permission-setting') export class UmbUserPermissionSettingElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/tsconfig.json b/src/Umbraco.Web.UI.Client/tsconfig.json index 67ec84f13e..05b86aeebc 100644 --- a/src/Umbraco.Web.UI.Client/tsconfig.json +++ b/src/Umbraco.Web.UI.Client/tsconfig.json @@ -43,7 +43,7 @@ // SHARED "@umbraco-cms/backoffice/auth": ["src/shared/auth"], - "@umbraco-cms/backoffice/events": ["src/packages/core/umb-events"], + "@umbraco-cms/backoffice/event": ["src/packages/core/event"], "@umbraco-cms/backoffice/icon": ["src/shared/icon-registry"], "@umbraco-cms/backoffice/models": ["src/shared/models"], "@umbraco-cms/backoffice/repository": ["src/packages/core/repository"], diff --git a/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs b/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs index 1af3c40ae8..f1230ade63 100644 --- a/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs +++ b/src/Umbraco.Web.UI.Client/web-test-runner.config.mjs @@ -77,7 +77,7 @@ export default { '@umbraco-cms/backoffice/variant': './src/packages/core/variant/index.ts', '@umbraco-cms/backoffice/workspace': './src/packages/core/workspace/index.ts', '@umbraco-cms/backoffice/culture': './src/packages/core/culture/index.ts', - '@umbraco-cms/backoffice/events': './src/packages/core/umb-events/index.ts', + '@umbraco-cms/backoffice/event': './src/packages/core/event/index.ts', '@umbraco-cms/backoffice/repository': './src/packages/core/repository/index.ts', '@umbraco-cms/backoffice/dictionary': './src/packages/dictionary/dictionary/index.ts', From d921a14087920c82f150260fbd905e128d190f16 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:59:31 +0200 Subject: [PATCH 10/22] link and media inserts --- .../input-markdown.element.ts | 183 ++++++++++++++++-- .../link-picker/link-picker-modal.element.ts | 2 + 2 files changed, 166 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts index 0753b304d6..98b97bf5f6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts @@ -1,10 +1,15 @@ import { KeyCode, KeyMod } from 'monaco-editor'; -import { UmbMediaPickerContext } from '../../../media/media/components/input-media/input-media.context.js'; import { UmbCodeEditorController, UmbCodeEditorElement, loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; -import { css, html, customElement, query, property } from '@umbraco-cms/backoffice/external/lit'; +import { css, html, customElement, query, property, state } from '@umbraco-cms/backoffice/external/lit'; import { FormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; +import { + UMB_LINK_PICKER_MODAL, + UMB_MEDIA_TREE_PICKER_MODAL, + UMB_MODAL_MANAGER_CONTEXT_TOKEN, + UmbModalManagerContext, +} from '@umbraco-cms/backoffice/modal'; /** * @element umb-input-markdown @@ -26,11 +31,17 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { @query('umb-code-editor') _codeEditor?: UmbCodeEditorElement; - #mediaPicker = new UmbMediaPickerContext(this); + private _modalContext?: UmbModalManagerContext; + + @state() + tabSize = 4; constructor() { super(); this.#loadCodeEditor(); + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT_TOKEN, (instance) => { + this._modalContext = instance; + }); } async #loadCodeEditor() { @@ -45,6 +56,7 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { minimap: false, folding: false, }); + this.tabSize = this.#editor?.monacoModel?.getOptions().tabSize ?? 4; this.#loadActions(); } catch (error) { console.error(error); @@ -52,8 +64,8 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { } async #loadActions() { - // Going to base the keybindings of a Markdown Shortcut plugin https://marketplace.visualstudio.com/items?itemName=robole.markdown-shortcuts#shortcuts // TODO: Find a way to have "double" keybindings (ctrl+m+ctrl+c for `code`, rather than simple ctrl+c as its taken by OS to copy things) + // Going with the keybindings of a Markdown Shortcut plugin https://marketplace.visualstudio.com/items?itemName=robole.markdown-shortcuts#shortcuts or perhaps there are keybindings that would make more sense. this.#editor?.monacoEditor?.addAction({ label: 'Add Heading H1', id: 'h1', @@ -106,7 +118,7 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { label: 'Add Quote', id: 'q', keybindings: [KeyMod.CtrlCmd | KeyCode.KeyQ], - run: () => this._insertAtCurrentLine('> '), + run: () => this._insertQuote(), }); this.#editor?.monacoEditor?.addAction({ label: 'Add Ordered List', @@ -136,20 +148,20 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { label: 'Add Line', id: 'line', //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC], - run: () => this._insertAtCurrentLine('---\n'), + run: () => this._insertLine(), }); this.#editor?.monacoEditor?.addAction({ label: 'Add Link', id: 'link', //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC], - run: () => this._insertBetweenSelection('[', '](https://example.com)', 'title'), + run: () => this._insertLink(), // TODO: Open in modal }); this.#editor?.monacoEditor?.addAction({ label: 'Add Image', id: 'image', //keybindings: [KeyMod.CtrlCmd | KeyCode.KeyM | KeyMod.CtrlCmd | KeyCode.KeyC], - run: () => this._insertBetweenSelection('![', '](example.png)', 'alt text'), + run: () => this._insertMedia(), // TODO: Open in modal }); } @@ -159,6 +171,100 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { this.#editor?.monacoEditor?.focus(); } + private _insertLink() { + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + const selectedValue = this.#editor?.getValueInRange(selection); + + this._focusEditor(); // Focus before opening modal + const modalContext = this._modalContext?.open(UMB_LINK_PICKER_MODAL, { + index: null, + link: { name: selectedValue }, + config: {}, + }); + + modalContext + ?.onSubmit() + .then((data) => { + const name = this.localize.term('general_name'); + const url = this.localize.term('general_url'); + + this.#editor?.monacoEditor?.executeEdits('', [ + { range: selection, text: `[${data.link.name || name}](${data.link.url || url})` }, + ]); + + if (!data.link.name) { + this.#editor?.select({ + startColumn: selection.startColumn + 1, + endColumn: selection.startColumn + 1 + name.length, + endLineNumber: selection.startLineNumber, + startLineNumber: selection.startLineNumber, + }); + } else if (!data.link.url) { + this.#editor?.select({ + startColumn: selection.startColumn + 3 + data.link.name.length, + endColumn: selection.startColumn + 3 + data.link.name.length + url.length, + endLineNumber: selection.startLineNumber, + startLineNumber: selection.startLineNumber, + }); + } + }) + .catch(() => undefined) + .finally(() => this._focusEditor()); + } + + private _insertMedia() { + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + const alt = this.#editor?.getValueInRange(selection); + + this._focusEditor(); // Focus before opening modal + const modalContext = this._modalContext?.open(UMB_MEDIA_TREE_PICKER_MODAL, {}); + + modalContext + ?.onSubmit() + .then((data) => { + const imgUrl = data.selection[0]; + this.#editor?.monacoEditor?.executeEdits('', [ + //TODO: media url + { range: selection, text: `[${alt || 'alt text'}](TODO: id-${imgUrl || this.localize.term('general_url')})` }, + ]); + + if (!alt?.length) { + this.#editor?.select({ + startColumn: selection.startColumn + 1, + endColumn: selection.startColumn + 9, + endLineNumber: selection.startLineNumber, + startLineNumber: selection.startLineNumber, + }); + } + }) + .catch(() => undefined) + .finally(() => this._focusEditor()); + } + + private _insertLine() { + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + const endColumn = this.#editor?.monacoModel?.getLineMaxColumn(selection.endLineNumber) ?? 1; + + if (endColumn === 1) { + this.#editor?.insertAtPosition('---\n', { + lineNumber: selection.endLineNumber, + column: 1, + }); + } else { + this.#editor?.insertAtPosition('\n---\n', { + lineNumber: selection.endLineNumber, + column: endColumn, + }); + } + this._focusEditor(); + } + private _insertBetweenSelection(startValue: string, endValue: string, placeholder?: string) { this._focusEditor(); const selection = this.#editor?.getSelections()[0]; @@ -170,7 +276,12 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { startColumn: selection.startColumn - startValue.length, endColumn: selection.endColumn + endValue.length, }); - if (selectedValue?.startsWith(startValue) && selectedValue.endsWith(endValue)) { + + if ( + selectedValue?.startsWith(startValue) && + selectedValue.endsWith(endValue) && + selectedValue.length > startValue.length + endValue.length + ) { //Cancel previous insert this.#editor?.select({ ...selection, startColumn: selection.startColumn + startValue.length }); this.#editor?.monacoEditor?.executeEdits('', [ @@ -203,6 +314,13 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { lineNumber: selection.endLineNumber, column: selection.endColumn + startValue.length, }); + + this.#editor?.select({ + startLineNumber: selection.startLineNumber, + endLineNumber: selection.endLineNumber, + startColumn: selection.startColumn + startValue.length, + endColumn: selection.endColumn + startValue.length, + }); } // if no text were selected when action fired @@ -213,6 +331,7 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { column: selection.startColumn + startValue.length, }); } + this.#editor?.select({ startLineNumber: selection.startLineNumber, endLineNumber: selection.endLineNumber, @@ -263,6 +382,28 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { } } + private _insertQuote() { + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + let index = selection.startLineNumber; + for (index; index <= selection.endLineNumber; index++) { + const line = this.#editor?.getValueInRange({ + startLineNumber: index, + endLineNumber: index, + startColumn: 1, + endColumn: 3, + }); + if (!line?.startsWith('> ')) { + this.#editor?.insertAtPosition('> ', { + lineNumber: index, + column: 1, + }); + } + } + this._focusEditor(); + } + private _renderBasicActions() { return html`
3) { - requestAnimationFrame(() => this.#editor?.insert('- ')); - } else if (lineValue.match(/^[1-9]\d*\.\s.*/) && lineValue.length) { - const previousNumber = parseInt(lineValue, 10); - requestAnimationFrame(() => this.#editor?.insert(`${previousNumber + 1}. `)); - } + if (lineValue.startsWith('- ') && lineValue.length > 2) { + requestAnimationFrame(() => this.#editor?.insert('- ')); + } else if (lineValue.match(/^[1-9]\d*\.\s.*/) && lineValue.length > 3) { + const previousNumber = parseInt(lineValue, 10); + requestAnimationFrame(() => this.#editor?.insert(`${previousNumber + 1}. `)); } } render() { + //TODO: Why is the theme dark in Backoffice, but light in Storybook? return html`
${this._renderBasicActions()}
- + ${this.renderPreview()}`; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts index aece02e1a1..df38f1f184 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/link-picker/link-picker-modal.element.ts @@ -153,6 +153,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElementLink to page this._handleSelectionChange(event, 'document')} .selection=${[this._selectedKey ?? '']} @@ -163,6 +164,7 @@ export class UmbLinkPickerModalElement extends UmbModalBaseElementLink to media this._handleSelectionChange(event, 'media')} .selection=${[this._selectedKey ?? '']} From 402d17d98daf4d0e1c735062a1e8dcbec19811fa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 9 Oct 2023 14:03:11 +0200 Subject: [PATCH 11/22] combine repository and repositories folder --- .../core/components/input-date/input-date.element.ts | 6 +++--- .../src/packages/core/repositories/index.ts | 1 - .../config/config.repository.ts | 0 .../src/packages/core/repository/index.ts | 1 + .../{repositories => repository}/repository.interface.ts | 2 -- 5 files changed, 4 insertions(+), 6 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/repositories/index.ts rename src/Umbraco.Web.UI.Client/src/packages/core/{repositories => repository}/config/config.repository.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/core/{repositories => repository}/repository.interface.ts (99%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts index 3df8c085a9..56fd3a4184 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.element.ts @@ -1,4 +1,4 @@ -import { UmbConfigRepository } from '../../repositories/config/config.repository.js'; +import { UmbConfigRepository } from '../../repository/config/config.repository.js'; import { css, html, ifDefined, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { FormControlMixin, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @@ -98,7 +98,7 @@ export class UmbInputDateElement extends FormControlMixin(UmbLitElement) { if (this.type === 'time') { const newDate = new Date(`${new Date().toJSON().slice(0, 10)} ${d}`); const dateOffset = new Date( - newDate.setTime(newDate.getTime() + (utc ? this._offsetValue * -1 : this._offsetValue) * 60 * 1000) + newDate.setTime(newDate.getTime() + (utc ? this._offsetValue * -1 : this._offsetValue) * 60 * 1000), ); const time = dateOffset .toLocaleTimeString(undefined, { @@ -109,7 +109,7 @@ export class UmbInputDateElement extends FormControlMixin(UmbLitElement) { } else { const newDate = new Date(d.replace('Z', '')); const dateOffset = new Date( - newDate.setTime(newDate.getTime() + (utc ? this._offsetValue * -1 : this._offsetValue) * 60 * 1000) + newDate.setTime(newDate.getTime() + (utc ? this._offsetValue * -1 : this._offsetValue) * 60 * 1000), ); return this.type === 'datetime-local' ? this.#dateToString(dateOffset) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repositories/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repositories/index.ts deleted file mode 100644 index a7d3719d54..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repositories/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './repository.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repositories/config/config.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/config/config.repository.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/core/repositories/config/config.repository.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/config/config.repository.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts index a11ca47da5..b63156a757 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/index.ts @@ -7,3 +7,4 @@ export * from './item-repository.interface.js'; export * from './move-repository.interface.js'; export * from './copy-repository.interface.js'; export * from './repository-items.manager.js'; +export * from './repository.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/repositories/repository.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository.interface.ts similarity index 99% rename from src/Umbraco.Web.UI.Client/src/packages/core/repositories/repository.interface.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/repository/repository.interface.ts index 1ea5957a38..9b2f588588 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/repositories/repository.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/repository/repository.interface.ts @@ -1,5 +1,4 @@ export interface UmbRepository { - /** * Get the type of the entity * @@ -8,5 +7,4 @@ export interface UmbRepository { * @returns undefined */ readonly ENTITY_TYPE: EntityType; - } From d89cd3ecd4f1a58ed6248f3735f491b4a6c360d0 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:17:57 +0200 Subject: [PATCH 12/22] remove tabsize --- .../input-markdown-editor/input-markdown.element.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts index 98b97bf5f6..23d31e1088 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-markdown-editor/input-markdown.element.ts @@ -33,9 +33,6 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { private _modalContext?: UmbModalManagerContext; - @state() - tabSize = 4; - constructor() { super(); this.#loadCodeEditor(); @@ -56,7 +53,6 @@ export class UmbInputMarkdownElement extends FormControlMixin(UmbLitElement) { minimap: false, folding: false, }); - this.tabSize = this.#editor?.monacoModel?.getOptions().tabSize ?? 4; this.#loadActions(); } catch (error) { console.error(error); From 7ccc543801168e7a91e7600f35f2aba407fea0d8 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 22 Sep 2023 09:33:00 +0200 Subject: [PATCH 13/22] sorting tabs --- ...t-type-container-structure-helper.class.ts | 15 +- .../content-type-structure-manager.class.ts | 12 + ...-workspace-view-edit-properties.element.ts | 15 +- ...pe-workspace-view-edit-property.element.ts | 10 +- ...cument-type-workspace-view-edit.element.ts | 340 ++++++++++++------ 5 files changed, 279 insertions(+), 113 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-container-structure-helper.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-container-structure-helper.class.ts index 230b5b4f80..d6fa9d50d9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-container-structure-helper.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-container-structure-helper.class.ts @@ -198,6 +198,16 @@ export class UmbContentTypeContainerStructureHelper { /** Manipulate methods: */ + async insertContainer(container: PropertyTypeContainerModelBaseModel, sortOrder = 0) { + await this.#init; + if (!this.#structure) return false; + + const newContainer = { ...container, sortOrder }; + + await this.#structure.insertContainer(null, newContainer); + return true; + } + async addContainer(parentContainerId?: string | null, sortOrder?: number) { if (!this.#structure) return; @@ -206,9 +216,10 @@ export class UmbContentTypeContainerStructureHelper { async removeContainer(groupId: string) { await this.#init; - if (!this.#structure) return; + if (!this.#structure) return false; - return await this.#structure.removeContainer(null, groupId); + await this.#structure.removeContainer(null, groupId); + return true; } async partialUpdateContainer(containerId: string, partialUpdate: Partial) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-structure-manager.class.ts index f0be7b3295..add77202a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/content-type-structure-manager.class.ts @@ -186,6 +186,18 @@ export class UmbContentTypePropertyStructureManager x.id === contentTypeId)?.containers ?? []; + + const containers = appendToFrozenArray(frozenContainers, container, (x) => x.id === container.id); + + console.log(frozenContainers, containers); + this.#contentTypes.updateOne(contentTypeId, { containers }); + } + makeContainerNameUniqueForOwnerContentType( newName: string, containerType: PropertyContainerTypes = 'Tab', diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts index 2d77e819c7..5685a84159 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts @@ -1,7 +1,7 @@ import { UmbDocumentTypeWorkspaceContext } from '../../document-type-workspace.context.js'; import './document-type-workspace-view-edit-property.element.js'; import { css, html, customElement, property, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbContentTypePropertyStructureHelper, PropertyContainerTypes } from '@umbraco-cms/backoffice/content-type'; import { UmbSorterController, UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; @@ -12,6 +12,7 @@ import { } from '@umbraco-cms/backoffice/backend-api'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { UMB_PROPERTY_SETTINGS_MODAL, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; + const SORTER_CONFIG: UmbSorterConfig = { compareElementToModel: (element: HTMLElement, model: DocumentTypePropertyTypeResponseModel) => { return element.getAttribute('data-umb-property-id') === model.id; @@ -19,11 +20,14 @@ const SORTER_CONFIG: UmbSorterConfig = { querySelectModelToElement: (container: HTMLElement, modelEntry: DocumentTypePropertyTypeResponseModel) => { return container.querySelector('data-umb-property-id[' + modelEntry.id + ']'); }, + placeholderClass: 'select', identifier: 'content-type-property-sorter', itemSelector: '[data-umb-property-id]', disabledItemSelector: '[inherited]', containerSelector: '#property-list', + resolveVerticalDirection: () => false, }; + @customElement('umb-document-type-workspace-view-edit-properties') export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitElement { #propertySorter = new UmbSorterController(this, { @@ -40,9 +44,11 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle 0) + 1; } } + console.log('perform insert', sortOrder, args.item.id); return this._propertyStructureHelper.insertProperty(args.item, sortOrder); }, performItemRemove: (args) => { + console.log('perform remove'); return this._propertyStructureHelper.removeProperty(args.item.id!); }, }); @@ -104,14 +110,13 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle new UmbModalRouteRegistrationController(this, UMB_PROPERTY_SETTINGS_MODAL) .addAdditionalPath('new-property') .onSetup(async () => { - const documentTypeId = this._ownerDocumentTypes?.find( (types) => types.containers?.find((containers) => containers.id === this.containerId), )?.id; - if(documentTypeId === undefined) return false; + if (documentTypeId === undefined) return false; const propertyData = await this._propertyStructureHelper.createPropertyScaffold(this._containerId); - if(propertyData === undefined) return false; - return {propertyData, documentTypeId}; + if (propertyData === undefined) return false; + return { propertyData, documentTypeId }; }) .onSubmit((result) => { this.#addProperty(result); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts index a980b612f7..da4a7d82ae 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts @@ -87,10 +87,10 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { .addUniquePaths(['propertyId']) .onSetup(() => { const documentTypeId = this.ownerDocumentTypeId; - if(documentTypeId === undefined) return false; + if (documentTypeId === undefined) return false; const propertyData = this.property; - if(propertyData === undefined) return false; - return {propertyData, documentTypeId}; + if (propertyData === undefined) return false; + return { propertyData, documentTypeId }; }) .onSubmit((result) => { this._partialUpdate(result); @@ -233,8 +233,8 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { ${this.renderPropertyTags()} - - ${this.localize.term('contentTypeEditor_inheritedFrom')} + ${this.localize.term('contentTypeEditor_inheritedFrom')} ${this.ownerDocumentTypeName ?? '??'} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts index 0c367870cd..cb680bba2a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts @@ -1,22 +1,60 @@ import { UmbDocumentTypeWorkspaceContext } from '../../document-type-workspace.context.js'; import type { UmbDocumentTypeWorkspaceViewEditTabElement } from './document-type-workspace-view-edit-tab.element.js'; -import { css, html, customElement, state, repeat, nothing, query } from '@umbraco-cms/backoffice/external/lit'; -import { UUIInputElement, UUIInputEvent, UUITabElement } from '@umbraco-cms/backoffice/external/uui'; +import { css, html, customElement, state, repeat, nothing, ifDefined } from '@umbraco-cms/backoffice/external/lit'; +import { UUIInputElement, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; import { UmbContentTypeContainerStructureHelper } from '@umbraco-cms/backoffice/content-type'; import { encodeFolderName, UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; -import { PropertyTypeContainerModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; +import { + DocumentTypePropertyTypeContainerResponseModel, + PropertyTypeContainerModelBaseModel, +} from '@umbraco-cms/backoffice/backend-api'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import type { UmbRoute } from '@umbraco-cms/backoffice/router'; import { UmbWorkspaceEditorViewExtensionElement } from '@umbraco-cms/backoffice/extension-registry'; import { UMB_CONFIRM_MODAL, UMB_MODAL_MANAGER_CONTEXT_TOKEN, UmbConfirmModalData } from '@umbraco-cms/backoffice/modal'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UmbSorterConfig, UmbSorterController } from '@umbraco-cms/backoffice/sorter'; + +const SORTER_CONFIG: UmbSorterConfig = { + compareElementToModel: (element: HTMLElement, model: DocumentTypePropertyTypeContainerResponseModel) => { + return element.getAttribute('data-umb-tabs-id') === model.id; + }, + querySelectModelToElement: (container: HTMLElement, modelEntry: PropertyTypeContainerModelBaseModel) => { + return container.querySelector('data-umb-tabs-id[' + modelEntry.id + ']'); + }, + identifier: 'content-type-tabs-sorter', + itemSelector: '[data-umb-tabs-id]', + containerSelector: '#tabs-group', + disabledItemSelector: '[inherited]', + resolveVerticalDirection: () => { + return false; + }, +}; @customElement('umb-document-type-workspace-view-edit') export class UmbDocumentTypeWorkspaceViewEditElement extends UmbLitElement implements UmbWorkspaceEditorViewExtensionElement { + public sorter?: UmbSorterController; + + config: UmbSorterConfig = { + ...SORTER_CONFIG, + performItemInsert: (args) => { + let sortOrder = 0; + if (this._tabs && this._tabs.length > 0) { + if (args.newIndex === 0) { + sortOrder = (this._tabs[0].sortOrder ?? 0) - 1; + } else { + sortOrder = ((this._tabs[Math.min(args.newIndex, this._tabs.length - 1)] as any).sortOrder ?? 0) + 1; + } + } + this._tabsStructureHelper.partialUpdateContainer(args.item.id!, { sortOrder }); + return true; + }, + }; + //private _hasRootProperties = false; private _hasRootGroups = false; @@ -32,6 +70,9 @@ export class UmbDocumentTypeWorkspaceViewEditElement @state() private _activePath = ''; + @state() + private sortModeActive = false; + @state() private _buttonDisabled: boolean = false; @@ -41,9 +82,6 @@ export class UmbDocumentTypeWorkspaceViewEditElement private _modalManagerContext?: typeof UMB_MODAL_MANAGER_CONTEXT_TOKEN.TYPE; - @query('uui-tab') - private _tabElements!: UUITabElement[]; - constructor() { super(); @@ -82,6 +120,13 @@ export class UmbDocumentTypeWorkspaceViewEditElement ); } + #changeMode() { + this.sortModeActive = !this.sortModeActive; + if (!this._tabs || !this.sortModeActive) return; + this.sorter = new UmbSorterController(this, this.config); + this.sorter.setModel(this._tabs); + } + private _createRoutes() { if (!this._workspaceContext || !this._tabs) return; const routes: UmbRoute[] = []; @@ -128,13 +173,13 @@ export class UmbDocumentTypeWorkspaceViewEditElement #requestRemoveTab(tab: PropertyTypeContainerModelBaseModel | undefined) { const Message: UmbConfirmModalData = { headline: 'Delete tab', - content: html`Are you sure you want to delete the tab ${tab?.name ?? tab?.id} + content: html` + Are you sure you want to delete the tab ${tab?.name ?? tab?.id} +
- This will delete all items that doesn't belong to a composition. + + This will delete all items that doesn't belong to a composition. +
`, confirmLabel: this.localize.term('actions_delete'), color: 'danger', @@ -207,93 +252,11 @@ export class UmbDocumentTypeWorkspaceViewEditElement window.history.replaceState(null, '', this._routerPath + '/tab/' + encodeFolderName(newName)); } - renderTabsNavigation() { - if (!this._tabs) return; - const rootTabPath = this._routerPath + '/root'; - const rootTabActive = rootTabPath === this._activePath; - return html` - - Content - - ${repeat( - this._tabs, - (tab) => tab.id! + tab.name, - (tab) => { - const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || ''); - const tabActive = path === this._activePath; - return html` -
- ${!this._tabsStructureHelper.isOwnerContainer(tab.id!) - ? html` ` - : nothing} - ${tabActive && this._tabsStructureHelper.isOwnerContainer(tab.id!) - ? html` this.#tabNameChanged(e, tab)} - @blur=${(e: InputEvent) => this.#tabNameChanged(e, tab)} - @input=${() => (this._buttonDisabled = true)} - @focus=${(e: UUIInputEvent) => (e.target.value ? nothing : (this._buttonDisabled = true))} - auto-width> - this.#requestRemoveTab(tab)} - compact> - - - ` - : html`
- ${tab.name!} - ${this._tabsStructureHelper.isOwnerContainer(tab.id!) - ? html` this.#requestRemoveTab(tab)} - compact> - - ` - : nothing} -
`} -
-
`; - }, - )} -
- - - Add tab - `; - } - - renderActions() { - return html`
- - - Compositions - - - - Reorder - -
`; - } - render() { return html` + + Add tab +
`; + } + + renderActions() { + const sortButtonText = this.sortModeActive + ? this.localize.term('general_reorderDone') + : this.localize.term('general_reorder'); + + return html`
+ ${this.renderHiddenActions()} + + + ${this.localize.term('contentTypeEditor_compositions')} + + + + ${sortButtonText} + +
`; + } + + renderHiddenActions() { + //TODO: If currently dragging a container of type "group", show this button + if (this.sortModeActive && this._activePath == 'dummy text to force false for now') { + return html` + ${this.localize.term('contentTypeEditor_convertToTab')} + `; + } + return; + } + + renderTabsNavigation() { + if (!this._tabs) return; + const rootTabPath = this._routerPath + '/root'; + const rootTabActive = rootTabPath === this._activePath; + + return html`
+ + + ${this.localize.term('general_content')} + + ${repeat( + this._tabs, + (tab) => tab.id! + tab.name, + (tab) => this.renderTab(tab), + )} + +
`; + } + + renderTab(tab: PropertyTypeContainerModelBaseModel) { + if (this.sortModeActive) { + return this.renderTabInSortMode(tab); + } else { + return this.renderTabInDefaultMode(tab); + } + } + + renderTabInDefaultMode(tab: PropertyTypeContainerModelBaseModel) { + const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || ''); + const tabActive = path === this._activePath; + const tabInherited = !this._tabsStructureHelper.isOwnerContainer(tab.id!); + + console.log(tabInherited, tab.name); + + return html` +
+ ${tabInherited ? html` ` : nothing} + ${tabActive && !tabInherited + ? html` this.#tabNameChanged(e, tab)} + @blur=${(e: InputEvent) => this.#tabNameChanged(e, tab)} + @input=${() => (this._buttonDisabled = true)} + @focus=${(e: UUIInputEvent) => (e.target.value ? nothing : (this._buttonDisabled = true))}> + ${this.renderDeleteFor(tab)} + ` + : html`
+ ${tab.name!} ${this._tabsStructureHelper.isOwnerContainer(tab.id!) ? this.renderDeleteFor(tab) : nothing} +
`} +
+
`; + } + + #changeOrder(tab: PropertyTypeContainerModelBaseModel, e: UUIInputEvent) { + if (!e.target.value || !tab.id) return; + const sortOrder = Number(e.target.value); + this._tabsStructureHelper.partialUpdateContainer(tab.id, { sortOrder }); + console.log('d'); + } + + renderTabInSortMode(tab: PropertyTypeContainerModelBaseModel) { + const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || ''); + const tabActive = path === this._activePath; + + return html` +
+ + ${!this._tabsStructureHelper.isOwnerContainer(tab.id!) + ? html`${tab.name!}` + : html`${tab.name!} + this.#changeOrder(tab, e)}>`} +
+
`; + } + + renderDeleteFor(tab: PropertyTypeContainerModelBaseModel) { + return html` this.#requestRemoveTab(tab)} + compact> + + `; + } + static styles = [ UmbTextStyles, css` + uui-tab .no-edit { + pointer-events: none; + } + + .no-edit uui-input { + pointer-events: auto; + } + + .--umb-sorter-placeholder::after { + content: ''; + position: absolute; + inset: 2px; + border: 1px dashed var(--uui-color-divider-emphasis); + } + + #buttons-wrapper { + flex: 1; + display: flex; + align-items: center; + justify-content: space-between; + align-items: stretch; + } + :host { position: relative; display: flex; @@ -333,6 +462,14 @@ export class UmbDocumentTypeWorkspaceViewEditElement display: flex; } + #tabs-group { + display: flex; + } + + uui-tab-group { + flex-wrap: nowrap; + } + .content-tab-is-empty { align-self: center; border-radius: 3px; @@ -341,7 +478,8 @@ export class UmbDocumentTypeWorkspaceViewEditElement } uui-tab { - border-left: 1px solid transparent; + position: relative; + border-left: 1px hidden transparent; border-right: 1px solid var(--uui-color-border); } @@ -350,11 +488,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement transition: opacity 120ms; } - .tab { - position: relative; - } - - .external { + .inherited { vertical-align: sub; } @@ -374,6 +508,10 @@ export class UmbDocumentTypeWorkspaceViewEditElement opacity: 1; transition: opacity 120ms; } + + .--umb-sorter-placeholder > * { + visibility: hidden; + } `, ]; } From 5457ab8d95fe93de40dc6ed1b5a3482248da30f8 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 25 Sep 2023 10:14:45 +0200 Subject: [PATCH 14/22] model query --- ...cument-type-workspace-view-edit.element.ts | 95 +++++++++++-------- 1 file changed, 56 insertions(+), 39 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts index cb680bba2a..0929c258c4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts @@ -21,7 +21,7 @@ const SORTER_CONFIG: UmbSorterConfig = { return element.getAttribute('data-umb-tabs-id') === model.id; }, querySelectModelToElement: (container: HTMLElement, modelEntry: PropertyTypeContainerModelBaseModel) => { - return container.querySelector('data-umb-tabs-id[' + modelEntry.id + ']'); + return container.querySelector(`[data-umb-tabs-id='` + modelEntry.id + `']`); }, identifier: 'content-type-tabs-sorter', itemSelector: '[data-umb-tabs-id]', @@ -41,16 +41,28 @@ export class UmbDocumentTypeWorkspaceViewEditElement config: UmbSorterConfig = { ...SORTER_CONFIG, - performItemInsert: (args) => { + performItemInsert: async (args) => { + if (!this._tabs) return false; + const oldIndex = this._tabs.findIndex((tab) => tab.id! === args.item.id); + if (args.newIndex === oldIndex) return true; + let sortOrder = 0; - if (this._tabs && this._tabs.length > 0) { + //TODO the sortOrder set is not correct + if (this._tabs.length > 0) { if (args.newIndex === 0) { sortOrder = (this._tabs[0].sortOrder ?? 0) - 1; } else { - sortOrder = ((this._tabs[Math.min(args.newIndex, this._tabs.length - 1)] as any).sortOrder ?? 0) + 1; + sortOrder = (this._tabs[Math.min(args.newIndex, this._tabs.length - 1)].sortOrder ?? 0) + 1; + } + + if (sortOrder !== args.item.sortOrder) { + await this._tabsStructureHelper.partialUpdateContainer(args.item.id!, { sortOrder }); } } - this._tabsStructureHelper.partialUpdateContainer(args.item.id!, { sortOrder }); + + return true; + }, + performItemRemove: () => { return true; }, }; @@ -256,7 +268,9 @@ export class UmbDocumentTypeWorkspaceViewEditElement return html` - - - ${this.localize.term('general_content')} - - ${repeat( - this._tabs, - (tab) => tab.id! + tab.name, - (tab) => this.renderTab(tab), - )} - -
`; + if (this.sortModeActive) { + return html`
+ + ${this.renderRootTab()} + ${repeat( + this._tabs, + (tab) => tab.id! + tab.name, + (tab) => this.renderTabInSortMode(tab), + )} + +
`; + } else { + return html`
+ + ${this.renderRootTab()} + ${repeat( + this._tabs, + (tab) => tab.id! + tab.name, + (tab) => this.renderTabInDefaultMode(tab), + )} + +
`; + } } - renderTab(tab: PropertyTypeContainerModelBaseModel) { - if (this.sortModeActive) { - return this.renderTabInSortMode(tab); - } else { - return this.renderTabInDefaultMode(tab); - } + renderRootTab() { + const rootTabPath = this._routerPath + '/root'; + const rootTabActive = rootTabPath === this._activePath; + return html` + ${this.localize.term('general_content')} + `; } renderTabInDefaultMode(tab: PropertyTypeContainerModelBaseModel) { @@ -344,8 +367,6 @@ export class UmbDocumentTypeWorkspaceViewEditElement const tabActive = path === this._activePath; const tabInherited = !this._tabsStructureHelper.isOwnerContainer(tab.id!); - console.log(tabInherited, tab.name); - return html`${tab.name!}` : html`${tab.name!} this.#changeOrder(tab, e)}>`} + @keypress=${(e: UUIInputEvent) => this.#changeOrder(tab, e)}>`} `; } @@ -458,14 +480,9 @@ export class UmbDocumentTypeWorkspaceViewEditElement flex-wrap: nowrap; } - #tabs-wrapper { + .flex { display: flex; } - - #tabs-group { - display: flex; - } - uui-tab-group { flex-wrap: nowrap; } From c16474fd146ada5e63ca1137a00d86e8e00f7faa Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:17:10 +0200 Subject: [PATCH 15/22] observable sorter --- .../workspace-context.interface.ts | 3 + .../workspace-context/workspace-context.ts | 14 ++++- .../document-type-workspace-editor.element.ts | 20 +++---- .../document-type-workspace-sorter.ts | 36 +++++++++++ .../document-type-workspace.context.ts | 2 + ...-workspace-view-edit-properties.element.ts | 7 +-- ...nt-type-workspace-view-edit-tab.element.ts | 6 +- ...cument-type-workspace-view-edit.element.ts | 59 ++++++++++--------- 8 files changed, 101 insertions(+), 46 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-sorter.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts index 4ff5c395bb..2ffb87ed1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts @@ -16,4 +16,7 @@ export interface UmbWorkspaceContextInterface { getIsNew(): boolean | undefined; setIsNew(value: boolean): void; + isSorting: Observable; + getIsSorting(): boolean | undefined; + setIsSorting(value: boolean): void; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts index 790f96c653..dffc605cd7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts @@ -24,8 +24,11 @@ export abstract class UmbWorkspaceContext; - } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts index 8314f0f48f..54841ad11f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-editor.element.ts @@ -11,15 +11,6 @@ import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; import { generateAlias } from '@umbraco-cms/backoffice/utils'; @customElement('umb-document-type-workspace-editor') export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement { - @state() - private _icon?: string; - - @state() - private _iconColorAlias?: string; - // TODO: Color should be using an alias, and look up in some dictionary/key/value) of project-colors. - - #workspaceContext?: UmbDocumentTypeWorkspaceContext; - @state() private _name?: string; @@ -29,6 +20,15 @@ export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement { @state() private _aliasLocked = true; + @state() + private _icon?: string; + + @state() + private _iconColorAlias?: string; + // TODO: Color should be using an alias, and look up in some dictionary/key/value) of project-colors. + + #workspaceContext?: UmbDocumentTypeWorkspaceContext; + private _modalContext?: UmbModalManagerContext; constructor() { @@ -59,7 +59,7 @@ export class UmbDocumentTypeWorkspaceEditorElement extends UmbLitElement { } this.removeControllerByAlias('_observeIsNew'); }, - '_observeIsNew' + '_observeIsNew', ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-sorter.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-sorter.ts new file mode 100644 index 0000000000..bb0ace3e49 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace-sorter.ts @@ -0,0 +1,36 @@ +import { + DocumentTypePropertyTypeContainerResponseModel, + PropertyTypeContainerModelBaseModel, +} from '@umbraco-cms/backoffice/backend-api'; +import { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; + +const SORTER_CONFIG_HORIZONTAL: UmbSorterConfig = { + compareElementToModel: (element: HTMLElement, model: DocumentTypePropertyTypeContainerResponseModel) => { + return element.getAttribute('data-umb-tabs-id') === model.id; + }, + querySelectModelToElement: (container: HTMLElement, modelEntry: PropertyTypeContainerModelBaseModel) => { + return container.querySelector(`[data-umb-tabs-id='` + modelEntry.id + `']`); + }, + identifier: 'content-type-tabs-sorter', + itemSelector: '[data-umb-tabs-id]', + containerSelector: '#tabs-group', + disabledItemSelector: '[inherited]', + resolveVerticalDirection: () => { + return false; + }, +}; + +const SORTER_CONFIG_VERTICAL: UmbSorterConfig = { + compareElementToModel: (element: HTMLElement, model: DocumentTypePropertyTypeContainerResponseModel) => { + return element.getAttribute('data-umb-property-id') === model.id; + }, + querySelectModelToElement: (container: HTMLElement, modelEntry: PropertyTypeContainerModelBaseModel) => { + return container.querySelector(`[data-umb-property-id='` + modelEntry.id + `']`); + }, + identifier: 'content-type-property-sorter', + itemSelector: '[data-umb-property-id]', + containerSelector: '#property-list', + disabledItemSelector: '[inherited]', +}; + +export { SORTER_CONFIG_VERTICAL, SORTER_CONFIG_HORIZONTAL }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts index 8abc8eb4f4..3bcddde693 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/document-type-workspace.context.ts @@ -120,6 +120,7 @@ export class UmbDocumentTypeWorkspaceContext if (!data) return undefined; this.setIsNew(true); + this.setIsSorting(false); //this.#draft.next(data); return { data } || undefined; // TODO: Is this wrong? should we return { data }?? @@ -130,6 +131,7 @@ export class UmbDocumentTypeWorkspaceContext if (!data) return undefined; this.setIsNew(false); + this.setIsSorting(false); //this.#draft.next(data); return { data } || undefined; // TODO: Is this wrong? should we return { data }?? diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts index 5685a84159..7cecdadd3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts @@ -18,14 +18,13 @@ const SORTER_CONFIG: UmbSorterConfig = { return element.getAttribute('data-umb-property-id') === model.id; }, querySelectModelToElement: (container: HTMLElement, modelEntry: DocumentTypePropertyTypeResponseModel) => { - return container.querySelector('data-umb-property-id[' + modelEntry.id + ']'); + return container.querySelector('data-umb-property-id=[' + modelEntry.id + ']'); }, placeholderClass: 'select', identifier: 'content-type-property-sorter', itemSelector: '[data-umb-property-id]', disabledItemSelector: '[inherited]', containerSelector: '#property-list', - resolveVerticalDirection: () => false, }; @customElement('umb-document-type-workspace-view-edit-properties') @@ -175,11 +174,11 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle )} - Add property + Add property `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts index 444cffcf24..93fabafc3f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts @@ -1,6 +1,6 @@ import { UmbDocumentTypeWorkspaceContext } from '../../document-type-workspace.context.js'; import { css, html, customElement, property, state, repeat, ifDefined } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from "@umbraco-cms/backoffice/style"; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbContentTypeContainerStructureHelper } from '@umbraco-cms/backoffice/content-type'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { PropertyTypeContainerModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; @@ -59,11 +59,15 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement { @state() _hasProperties = false; + @state() + _sortModeActive?: boolean; + constructor() { super(); this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => { this._groupStructureHelper.setStructureManager((context as UmbDocumentTypeWorkspaceContext).structure); + this.observe(context.isSorting, (isSorting) => (this._sortModeActive = isSorting)); }); this.observe(this._groupStructureHelper.containers, (groups) => { this._groups = groups; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts index 0929c258c4..84d2b4bf31 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts @@ -83,7 +83,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement private _activePath = ''; @state() - private sortModeActive = false; + private sortModeActive?: boolean; @state() private _buttonDisabled: boolean = false; @@ -130,11 +130,14 @@ export class UmbDocumentTypeWorkspaceViewEditElement }, '_observeGroups', ); + + this.observe(this._workspaceContext.isSorting, (isSorting) => (this.sortModeActive = isSorting)); } #changeMode() { - this.sortModeActive = !this.sortModeActive; - if (!this._tabs || !this.sortModeActive) return; + this._workspaceContext?.setIsSorting(!this.sortModeActive); + + if (!this._tabs) return; this.sorter = new UmbSorterController(this, this.config); this.sorter.setModel(this._tabs); } @@ -381,6 +384,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement placeholder="Unnamed" label=${tab.name!} value="${tab.name!}" + auto-width @change=${(e: InputEvent) => this.#tabNameChanged(e, tab)} @blur=${(e: InputEvent) => this.#tabNameChanged(e, tab)} @input=${() => (this._buttonDisabled = true)} @@ -440,21 +444,6 @@ export class UmbDocumentTypeWorkspaceViewEditElement static styles = [ UmbTextStyles, css` - uui-tab .no-edit { - pointer-events: none; - } - - .no-edit uui-input { - pointer-events: auto; - } - - .--umb-sorter-placeholder::after { - content: ''; - position: absolute; - inset: 2px; - border: 1px dashed var(--uui-color-divider-emphasis); - } - #buttons-wrapper { flex: 1; display: flex; @@ -500,20 +489,12 @@ export class UmbDocumentTypeWorkspaceViewEditElement border-right: 1px solid var(--uui-color-border); } - uui-tab:not(:hover, :focus) .trash { - opacity: 0; - transition: opacity 120ms; - } - - .inherited { - vertical-align: sub; - } - - uui-input:not(:focus, :hover) { - border: 1px solid transparent; + .no-edit uui-input { + pointer-events: auto; } .no-edit { + pointer-events: none; display: inline-flex; padding-left: var(--uui-size-space-3); border: 1px solid transparent; @@ -526,9 +507,29 @@ export class UmbDocumentTypeWorkspaceViewEditElement transition: opacity 120ms; } + uui-tab:not(:hover, :focus) .trash { + opacity: 0; + transition: opacity 120ms; + } + + uui-input:not(:focus, :hover) { + border: 1px solid transparent; + } + + .inherited { + vertical-align: sub; + } + .--umb-sorter-placeholder > * { visibility: hidden; } + + .--umb-sorter-placeholder::after { + content: ''; + position: absolute; + inset: 2px; + border: 1px dashed var(--uui-color-divider-emphasis); + } `, ]; } From 56b692d45a8a39ebcd59a113dee2ce5a47636b1f Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 29 Sep 2023 11:27:51 +0200 Subject: [PATCH 16/22] sort --- ...-workspace-view-edit-properties.element.ts | 14 +++ ...cument-type-workspace-view-edit.element.ts | 114 ++++++++---------- 2 files changed, 63 insertions(+), 65 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts index 7cecdadd3e..aa2c091c78 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts @@ -188,6 +188,20 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle #add { width: 100%; } + document-type-workspace-view-edit-property { + position: relative; + } + + .select { + visibility: hidden; + } + + .select { + position: absolute; + inset: 0; + content: ''; + border: 2px solid red; + } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts index 84d2b4bf31..96b3107510 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts @@ -328,29 +328,16 @@ export class UmbDocumentTypeWorkspaceViewEditElement renderTabsNavigation() { if (!this._tabs) return; - if (this.sortModeActive) { - return html`
- - ${this.renderRootTab()} - ${repeat( - this._tabs, - (tab) => tab.id! + tab.name, - (tab) => this.renderTabInSortMode(tab), - )} - -
`; - } else { - return html`
- - ${this.renderRootTab()} - ${repeat( - this._tabs, - (tab) => tab.id! + tab.name, - (tab) => this.renderTabInDefaultMode(tab), - )} - -
`; - } + return html`
+ + ${this.renderRootTab()} + ${repeat( + this._tabs, + (tab) => tab.id! + tab.name, + (tab) => this.renderTab(tab), + )} + +
`; } renderRootTab() { @@ -365,7 +352,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement `; } - renderTabInDefaultMode(tab: PropertyTypeContainerModelBaseModel) { + renderTab(tab: PropertyTypeContainerModelBaseModel) { const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || ''); const tabActive = path === this._activePath; const tabInherited = !this._tabsStructureHelper.isOwnerContainer(tab.id!); @@ -374,47 +361,14 @@ export class UmbDocumentTypeWorkspaceViewEditElement label=${tab.name ?? 'unnamed'} .active=${tabActive} href=${path} - ?data-umb-tabs-inherited=${tabInherited}> -
- ${tabInherited ? html` ` : nothing} - ${tabActive && !tabInherited - ? html` this.#tabNameChanged(e, tab)} - @blur=${(e: InputEvent) => this.#tabNameChanged(e, tab)} - @input=${() => (this._buttonDisabled = true)} - @focus=${(e: UUIInputEvent) => (e.target.value ? nothing : (this._buttonDisabled = true))}> - ${this.renderDeleteFor(tab)} - ` - : html`
- ${tab.name!} ${this._tabsStructureHelper.isOwnerContainer(tab.id!) ? this.renderDeleteFor(tab) : nothing} -
`} -
+ data-umb-tabs-id=${ifDefined(tab.id)}> + ${this.renderTabInner(tab, tabActive, tabInherited)} `; } - #changeOrder(tab: PropertyTypeContainerModelBaseModel, e: UUIInputEvent) { - if (!e.target.value || !tab.id) return; - const sortOrder = Number(e.target.value); - this._tabsStructureHelper.partialUpdateContainer(tab.id, { sortOrder }); - console.log('d'); - } - - renderTabInSortMode(tab: PropertyTypeContainerModelBaseModel) { - const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || ''); - const tabActive = path === this._activePath; - - return html` -
+ renderTabInner(tab: PropertyTypeContainerModelBaseModel, tabActive: boolean, tabInherited: boolean) { + if (this.sortModeActive) { + return html`
${!this._tabsStructureHelper.isOwnerContainer(tab.id!) ? html`${tab.name!}` @@ -424,9 +378,39 @@ export class UmbDocumentTypeWorkspaceViewEditElement type="number" value=${ifDefined(tab.sortOrder)} style="width:50px" - @keypress=${(e: UUIInputEvent) => this.#changeOrder(tab, e)}>`} -
- `; + @keypress=${(e: UUIInputEvent) => this.#changeOrderNumber(tab, e)}>`} +
`; + } + + if (tabActive && !tabInherited) { + return html`
+ this.#tabNameChanged(e, tab)} + @blur=${(e: InputEvent) => this.#tabNameChanged(e, tab)} + @input=${() => (this._buttonDisabled = true)} + @focus=${(e: UUIInputEvent) => (e.target.value ? nothing : (this._buttonDisabled = true))}> + ${this.renderDeleteFor(tab)} + +
`; + } + + if (tabInherited) { + return html`
${tab.name!}
`; + } else { + return html`
${tab.name!} ${this.renderDeleteFor(tab)}
`; + } + } + + #changeOrderNumber(tab: PropertyTypeContainerModelBaseModel, e: UUIInputEvent) { + if (!e.target.value || !tab.id) return; + const sortOrder = Number(e.target.value); + this._tabsStructureHelper.partialUpdateContainer(tab.id, { sortOrder }); } renderDeleteFor(tab: PropertyTypeContainerModelBaseModel) { From 44ad430db1ec4f1ebf2a934bb58e388ad7e08738 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Fri, 29 Sep 2023 16:05:55 +0200 Subject: [PATCH 17/22] sort on tab and properties --- ...-workspace-view-edit-properties.element.ts | 63 +++--- ...pe-workspace-view-edit-property.element.ts | 193 +++++++++++------- ...nt-type-workspace-view-edit-tab.element.ts | 166 ++++++++++++--- ...cument-type-workspace-view-edit.element.ts | 35 ++-- 4 files changed, 302 insertions(+), 155 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts index aa2c091c78..623c65fb5c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts @@ -20,7 +20,6 @@ const SORTER_CONFIG: UmbSorterConfig = { querySelectModelToElement: (container: HTMLElement, modelEntry: DocumentTypePropertyTypeResponseModel) => { return container.querySelector('data-umb-property-id=[' + modelEntry.id + ']'); }, - placeholderClass: 'select', identifier: 'content-type-property-sorter', itemSelector: '[data-umb-property-id]', disabledItemSelector: '[inherited]', @@ -35,19 +34,15 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle let sortOrder = 0; if (this._propertyStructure.length > 0) { if (args.newIndex === 0) { - // TODO: Remove 'as any' when sortOrder is added to the model: - sortOrder = ((this._propertyStructure[0] as any).sortOrder ?? 0) - 1; + sortOrder = (this._propertyStructure[0].sortOrder ?? 0) - 1; } else { sortOrder = - ((this._propertyStructure[Math.min(args.newIndex, this._propertyStructure.length - 1)] as any).sortOrder ?? - 0) + 1; + (this._propertyStructure[Math.min(args.newIndex, this._propertyStructure.length - 1)].sortOrder ?? 0) + 1; } } - console.log('perform insert', sortOrder, args.item.id); return this._propertyStructureHelper.insertProperty(args.item, sortOrder); }, performItemRemove: (args) => { - console.log('perform remove'); return this._propertyStructureHelper.removeProperty(args.item.id!); }, }); @@ -92,6 +87,9 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle @state() protected _modalRouteNewProperty?: string; + @state() + _sortModeActive?: boolean; + constructor() { super(); @@ -99,10 +97,17 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle this._propertyStructureHelper.setStructureManager( (workspaceContext as UmbDocumentTypeWorkspaceContext).structure, ); + this.observe( + workspaceContext.isSorting, + (isSorting) => { + this._sortModeActive = isSorting; + this.#setModel(isSorting); + }, + '_observeIsSorting', + ); }); this.observe(this._propertyStructureHelper.propertyStructure, (propertyStructure) => { this._propertyStructure = propertyStructure; - this.#propertySorter.setModel(this._propertyStructure); }); // Note: Route for adding a new property @@ -125,6 +130,14 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle }); } + #setModel(isSorting?: boolean) { + if (isSorting) { + this.#propertySorter.setModel(this._propertyStructure); + } else { + this.#propertySorter.setModel([]); + } + } + connectedCallback(): void { super.connectedCallback(); const doctypes = this._propertyStructureHelper.ownerDocumentTypes; @@ -149,7 +162,7 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle return html`
${repeat( this._propertyStructure, - (property) => property.id ?? '' + property.containerId ?? '' + (property as any).sortOrder ?? '', + (property) => property.id ?? '' + property.containerId ?? '' + property.sortOrder ?? '', (property) => { // Note: This piece might be moved into the property component const inheritedFromDocument = this._ownerDocumentTypes?.find( @@ -157,11 +170,11 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle ); return html` { this._propertyStructureHelper.partialUpdateProperty(property.id, event.detail); @@ -173,13 +186,15 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle }, )}
- - Add property - `; + ${!this._sortModeActive + ? html` + Add property + ` + : ''} `; } static styles = [ @@ -188,20 +203,6 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle #add { width: 100%; } - document-type-workspace-view-edit-property { - position: relative; - } - - .select { - visibility: hidden; - } - - .select { - position: absolute; - inset: 0; - content: ''; - border: 2px solid red; - } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts index da4a7d82ae..1ab110139f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-property.element.ts @@ -50,6 +50,9 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { @property({ type: Boolean }) public inherited?: boolean; + @property({ type: Boolean, reflect: true, attribute: 'sort-mode-active' }) + public sortModeActive = false; + #dataTypeRepository = new UmbDataTypeRepository(this); #modalRegistration; @@ -82,7 +85,6 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { constructor() { super(); - this.#modalRegistration = new UmbModalRouteRegistrationController(this, UMB_PROPERTY_SETTINGS_MODAL) .addUniquePaths(['propertyId']) .onSetup(() => { @@ -181,68 +183,91 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { } } + renderSortableProperty() { + if (!this.property) return; + return html` +
+ + ${this.property.name} (${this.property.alias}) +
+ + `; + } + renderEditableProperty() { - return this.property - ? html` - - - ${this.renderPropertyTags()} - - - - - - - ` - : ''; + if (!this.property) return; + + if (this.sortModeActive) { + return this.renderSortableProperty(); + } else { + return html` + + + ${this.renderPropertyTags()} + + + + + + + `; + } } renderInheritedProperty() { - return this.property - ? html` - -
- ${this.renderPropertyTags()} - - - ${this.localize.term('contentTypeEditor_inheritedFrom')} - - ${this.ownerDocumentTypeName ?? '??'} - - - -
- ` - : ''; + if (!this.property) return; + + if (this.sortModeActive) { + return this.renderSortableProperty(); + } else { + return html` + +
+ ${this.renderPropertyTags()} + + + ${this.localize.term('contentTypeEditor_inheritedFrom')} + + ${this.ownerDocumentTypeName ?? '??'} + + + +
+ `; + } } renderPropertyAlias() { @@ -292,7 +317,7 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { static styles = [ UmbTextStyles, css` - :host { + :host(:not([sort-mode-active])) { display: grid; grid-template-columns: 200px auto; column-gap: var(--uui-size-layout-2); @@ -311,32 +336,52 @@ export class UmbDocumentTypeWorkspacePropertyElement extends UmbLitElement { } } + :host(:first-of-type) { + padding-top: 0; + } :host(:last-of-type) { border-bottom: none; } - :host(:first-of-type) { - padding-top: 0; + :host([sort-mode-active]) { + position: relative; + display: flex; + padding: 0; + margin-bottom: var(--uui-size-3); } - :host([draggable='true']) { + + :host([sort-mode-active]:last-of-type) { + margin-bottom: 0; + } + + :host([sort-mode-active]:not([inherited])) { cursor: grab; } + :host([sort-mode-active]) .sortable { + flex: 1; + display: flex; + background-color: var(--uui-color-divider); + align-items: center; + padding: 0 var(--uui-size-3); + gap: var(--uui-size-3); + } + + :host([sort-mode-active]) uui-input { + max-width: 75px; + } + /* Placeholder style, used when property is being dragged.*/ - :host(.--umb-sorter-placeholder) { - height: 2px; - } - :host(.--umb-sorter-placeholder) > div, - :host(.--umb-sorter-placeholder) > uui-button { - display: none; + :host(.--umb-sorter-placeholder) > * { + visibility: hidden; } + :host(.--umb-sorter-placeholder)::after { content: ''; - grid-column: span 2; - width: 100%; - border-top: 2px solid blue; - border-radius: 1px; - /* TODO: Make use of same highlight color as UUI and the same Animation. Consider making this a component/(available style) in UUI? */ + inset: 0; + position: absolute; + border: 1px dashed var(--uui-color-divider-emphasis); + border-radius: var(--uui-border-radius); } p { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts index 93fabafc3f..57d995f690 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts @@ -5,11 +5,52 @@ import { UmbContentTypeContainerStructureHelper } from '@umbraco-cms/backoffice/ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { PropertyTypeContainerModelBaseModel } from '@umbraco-cms/backoffice/backend-api'; import { UMB_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/workspace'; +import { UmbSorterConfig, UmbSorterController } from '@umbraco-cms/backoffice/sorter'; import './document-type-workspace-view-edit-properties.element.js'; +const SORTER_CONFIG: UmbSorterConfig = { + compareElementToModel: (element: HTMLElement, model: PropertyTypeContainerModelBaseModel) => { + return element.getAttribute('data-umb-group-id') === model.id; + }, + querySelectModelToElement: (container: HTMLElement, modelEntry: PropertyTypeContainerModelBaseModel) => { + return container.querySelector('data-umb-group-id=[' + modelEntry.id + ']'); + }, + identifier: 'content-type-group-sorter', + itemSelector: '[data-umb-group-id]', + disabledItemSelector: '[inherited]', + containerSelector: '#group-list', +}; + @customElement('umb-document-type-workspace-view-edit-tab') export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement { + public sorter?: UmbSorterController; + + config: UmbSorterConfig = { + ...SORTER_CONFIG, + performItemInsert: async (args) => { + if (!this._groups) return false; + const oldIndex = this._groups.findIndex((group) => group.id! === args.item.id); + if (args.newIndex === oldIndex) return true; + + let sortOrder = 0; + //TODO the sortOrder set is not correct + if (this._groups.length > 0) { + if (args.newIndex === 0) { + sortOrder = (this._groups[0].sortOrder ?? 0) - 1; + } else { + sortOrder = (this._groups[Math.min(args.newIndex, this._groups.length - 1)].sortOrder ?? 0) + 1; + } + + if (sortOrder !== args.item.sortOrder) { + await this._groupStructureHelper.partialUpdateContainer(args.item.id!, { sortOrder }); + } + } + + return true; + }, + }; + private _ownerTabId?: string | null; // TODO: get rid of this: @@ -65,9 +106,22 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement { constructor() { super(); + this.sorter = new UmbSorterController(this, this.config); + this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => { this._groupStructureHelper.setStructureManager((context as UmbDocumentTypeWorkspaceContext).structure); - this.observe(context.isSorting, (isSorting) => (this._sortModeActive = isSorting)); + this.observe( + context.isSorting, + (isSorting) => { + this._sortModeActive = isSorting; + if (isSorting) { + this.sorter?.setModel(this._groups); + } else { + this.sorter?.setModel([]); + } + }, + '_observeIsSorting', + ); }); this.observe(this._groupStructureHelper.containers, (groups) => { this._groups = groups; @@ -96,42 +150,62 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement { ` : ''} - ${repeat( - this._groups, - (group) => group.id ?? '' + group.name, - (group) => html` +
+ ${repeat( + this._groups, + (group) => group.id ?? '' + group.name, + (group) => html` ${ this._groupStructureHelper.isOwnerChildContainer(group.id!) ? html`
- { - const newName = (e.target as HTMLInputElement).value; - this._groupStructureHelper.updateContainerName(group.id!, group.parentId ?? null, newName); - }}> - +
+ ${this._sortModeActive ? html`` : ''} + + { + const newName = (e.target as HTMLInputElement).value; + this._groupStructureHelper.updateContainerName(group.id!, group.parentId ?? null, newName); + }}> + +
+ ${this._sortModeActive + ? html`` + : ''}
` - : html`
${group.name ?? ''} (Inherited)
` + : html`
+
${group.name ?? ''} (Inherited)
+ ${!this._sortModeActive + ? html`` + : ''} +
` }
- `, - )} - - ${this.localize.term('contentTypeEditor_addGroup')} - + `, + )} + + ${!this._sortModeActive + ? html` + ${this.localize.term('contentTypeEditor_addGroup')} + ` + : ''} `; } @@ -142,12 +216,48 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement { width: 100%; } - #add:not(:first-child) { - width: 100%; + #add:first-child { margin-top: var(--uui-size-layout-1); } - uui-box:not(:first-child) { - margin-top: var(--uui-size-layout-1); + uui-box { + margin-bottom: var(--uui-size-layout-1); + } + + [data-umb-group-id] { + display: block; + position: relative; + } + + div[slot='header'] { + display: flex; + align-items: center; + justify-content: space-between; + } + + div[slot='header'] > div { + display: flex; + align-items: center; + gap: var(--uui-size-3); + } + + uui-input[type='number'] { + max-width: 75px; + } + + .sorting { + cursor: grab; + } + + .--umb-sorter-placeholder > uui-box { + visibility: hidden; + } + + .--umb-sorter-placeholder::after { + content: ''; + inset: 0; + position: absolute; + border-radius: var(--uui-border-radius); + border: 1px dashed var(--uui-color-divider-emphasis); } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts index 96b3107510..641e7f909e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit.element.ts @@ -62,9 +62,6 @@ export class UmbDocumentTypeWorkspaceViewEditElement return true; }, - performItemRemove: () => { - return true; - }, }; //private _hasRootProperties = false; @@ -96,6 +93,7 @@ export class UmbDocumentTypeWorkspaceViewEditElement constructor() { super(); + this.sorter = new UmbSorterController(this, this.config); //TODO: We need to differentiate between local and composition tabs (and hybrids) @@ -111,6 +109,11 @@ export class UmbDocumentTypeWorkspaceViewEditElement this.consumeContext(UMB_WORKSPACE_CONTEXT, (workspaceContext) => { this._workspaceContext = workspaceContext as UmbDocumentTypeWorkspaceContext; this._tabsStructureHelper.setStructureManager((workspaceContext as UmbDocumentTypeWorkspaceContext).structure); + this.observe( + this._workspaceContext.isSorting, + (isSorting) => (this.sortModeActive = isSorting), + '_observeIsSorting', + ); this._observeRootGroups(); }); @@ -130,16 +133,16 @@ export class UmbDocumentTypeWorkspaceViewEditElement }, '_observeGroups', ); - - this.observe(this._workspaceContext.isSorting, (isSorting) => (this.sortModeActive = isSorting)); } #changeMode() { this._workspaceContext?.setIsSorting(!this.sortModeActive); - if (!this._tabs) return; - this.sorter = new UmbSorterController(this, this.config); - this.sorter.setModel(this._tabs); + if (this.sortModeActive && this._tabs) { + this.sorter?.setModel(this._tabs); + } else { + this.sorter?.setModel([]); + } } private _createRoutes() { @@ -303,7 +306,6 @@ export class UmbDocumentTypeWorkspaceViewEditElement : this.localize.term('general_reorder'); return html`
- ${this.renderHiddenActions()} ${this.localize.term('contentTypeEditor_compositions')} @@ -315,16 +317,6 @@ export class UmbDocumentTypeWorkspaceViewEditElement
`; } - renderHiddenActions() { - //TODO: If currently dragging a container of type "group", show this button - if (this.sortModeActive && this._activePath == 'dummy text to force false for now') { - return html` - ${this.localize.term('contentTypeEditor_convertToTab')} - `; - } - return; - } - renderTabsNavigation() { if (!this._tabs) return; @@ -369,10 +361,9 @@ export class UmbDocumentTypeWorkspaceViewEditElement renderTabInner(tab: PropertyTypeContainerModelBaseModel, tabActive: boolean, tabInherited: boolean) { if (this.sortModeActive) { return html`
- - ${!this._tabsStructureHelper.isOwnerContainer(tab.id!) + ${tabInherited ? html`${tab.name!}` - : html`${tab.name!} + : html` ${tab.name!} Date: Mon, 9 Oct 2023 15:30:53 +0200 Subject: [PATCH 18/22] move from general workspace context to document type context --- .../workspace-context/workspace-context.interface.ts | 4 ---- .../workspace/workspace-context/workspace-context.ts | 11 ----------- .../workspace/document-type-workspace.context.ts | 12 ++++++++++++ 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts index 2ffb87ed1f..0846447441 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.interface.ts @@ -15,8 +15,4 @@ export interface UmbWorkspaceContextInterface { isNew: Observable; getIsNew(): boolean | undefined; setIsNew(value: boolean): void; - - isSorting: Observable; - getIsSorting(): boolean | undefined; - setIsSorting(value: boolean): void; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts index dffc605cd7..d9ec50b0ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/workspace-context/workspace-context.ts @@ -24,9 +24,6 @@ export abstract class UmbWorkspaceContext data?.defaultTemplateId); } + getIsSorting() { + return this.#isSorting.getValue(); + } + + setIsSorting(isSorting: boolean) { + this.#isSorting.next(isSorting); + } + getData() { return this.structure.getOwnerContentType() || {}; } From 5387ee766060b2257848daeb91c3c441cec0a54a Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:43:40 +0200 Subject: [PATCH 19/22] correct type --- .../document-type-workspace-view-edit-properties.element.ts | 2 +- .../design/document-type-workspace-view-edit-tab.element.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts index 623c65fb5c..97f890bfd1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-properties.element.ts @@ -98,7 +98,7 @@ export class UmbDocumentTypeWorkspaceViewEditPropertiesElement extends UmbLitEle (workspaceContext as UmbDocumentTypeWorkspaceContext).structure, ); this.observe( - workspaceContext.isSorting, + (workspaceContext as UmbDocumentTypeWorkspaceContext).isSorting, (isSorting) => { this._sortModeActive = isSorting; this.#setModel(isSorting); diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts index 57d995f690..db905f1869 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/workspace/views/design/document-type-workspace-view-edit-tab.element.ts @@ -111,7 +111,7 @@ export class UmbDocumentTypeWorkspaceViewEditTabElement extends UmbLitElement { this.consumeContext(UMB_WORKSPACE_CONTEXT, (context) => { this._groupStructureHelper.setStructureManager((context as UmbDocumentTypeWorkspaceContext).structure); this.observe( - context.isSorting, + (context as UmbDocumentTypeWorkspaceContext).isSorting, (isSorting) => { this._sortModeActive = isSorting; if (isSorting) { From 90c3e5c0f10254a2057c18cc57e43171ff8419db Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:48:20 +0200 Subject: [PATCH 20/22] property editor dropdown --- .../src/mocks/data/data-type.data.ts | 15 ++++- .../core/components/input-dropdown/index.ts | 1 + .../input-dropdown-list.element.ts | 54 +++++++++++++++++ .../input-dropdown-list.stories.ts | 50 ++++++++++++++++ .../input-dropdown-list.test.ts | 18 ++++++ .../property-editor-ui-dropdown.element.ts | 59 ++++++++++++++++--- 6 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.stories.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.test.ts diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts index 113799666c..8c1490effe 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type.data.ts @@ -299,7 +299,20 @@ export const data: Array = parentId: null, propertyEditorAlias: 'Umbraco.DropDown.Flexible', propertyEditorUiAlias: 'Umb.PropertyEditorUi.Dropdown', - values: [], + values: [ + { + alias: 'multiple', + value: false, + }, + { + alias: 'items', + value: { + 0: { sortOrder: 1, value: 'First Option' }, + 1: { sortOrder: 2, value: 'Second Option' }, + 2: { sortOrder: 3, value: 'I Am the third Option' }, + }, + }, + ], }, { type: 'data-type', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/index.ts new file mode 100644 index 0000000000..6ba9298f35 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/index.ts @@ -0,0 +1 @@ +export * from './input-dropdown-list.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.element.ts new file mode 100644 index 0000000000..c822ce0d85 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.element.ts @@ -0,0 +1,54 @@ +import { css, html, nothing, customElement, property, query, state } from '@umbraco-cms/backoffice/external/lit'; +import { FormControlMixin, UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; +import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; + +@customElement('umb-input-dropdown-list') +export class UmbInputDropdownListElement extends FormControlMixin(UmbLitElement) { + @property({ type: Array }) + public options?: Array