From 252366f7cff454ecd96ae396e83e117c311618bf Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Thu, 15 Feb 2024 00:33:53 +0100 Subject: [PATCH 001/325] Add code editor --- .../mocks/data/data-type/data-type.data.ts | 20 ++++++++++ .../uis/code-editor/manifests.ts | 30 ++++++++++++++ .../property-editor-ui-code-editor.element.ts | 40 +++++++++++++++++++ .../property-editor-ui-code-editor.stories.ts | 15 +++++++ .../core/property-editor/uis/manifests.ts | 2 + 5 files changed, 107 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts index 3087789c13..23ef24a31a 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts @@ -456,6 +456,26 @@ export const data: Array = [ }, ], }, + { + name: 'Code Editor', + id: 'dt-codeEditor', + parent: null, + editorAlias: 'Umbraco.CodeEditor', + editorUiAlias: 'Umb.PropertyEditorUi.CodeEditor', + hasChildren: false, + isFolder: false, + values: [ + { + alias: 'language', + value: { + 0: { sortOrder: 1, value: 'Razor' }, + 1: { sortOrder: 2, value: 'HTML' }, + 2: { sortOrder: 3, value: 'CSS' }, + 3: { sortOrder: 4, value: 'JavaScript' }, + }, + }, + ], + }, { name: 'Markdown Editor', id: 'dt-markdownEditor', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts new file mode 100644 index 0000000000..9c7efaac80 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts @@ -0,0 +1,30 @@ +import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifest: ManifestPropertyEditorUi = { + type: 'propertyEditorUi', + alias: 'Umb.PropertyEditorUi.CodeEditor', + name: 'Code Editor Property Editor UI', + element: () => import('./property-editor-ui-code-editor.element.js'), + meta: { + label: 'Code Editor', + propertyEditorSchemaAlias: 'Umbraco.CodeEditor', + icon: 'icon-code', + group: 'common', + settings: { + properties: [ + { + alias: 'language', + label: 'Language', + description: 'Select the programming language.', + propertyEditorUiAlias: 'Umb.PropertyEditorUi.Dropdown', + config: [ + { + alias: 'items', + value: ['Razor', 'HTML', 'CSS', 'JavaScript'], + }, + ], + }, + ], + }, + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts new file mode 100644 index 0000000000..be24db95e6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts @@ -0,0 +1,40 @@ +import { css, html, customElement, property, state, ifDefined, styleMap } from '@umbraco-cms/backoffice/external/lit'; +//import type { UUICodeEditorElement } from '@umbraco-cms/backoffice/external/uui'; +import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; + +@customElement('umb-property-editor-ui-code-editor') +export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implements UmbPropertyEditorUiElement { + @property() + value = ''; + + @state() + private _language?: string; + + @property({ attribute: false }) + public set config(config: UmbPropertyEditorConfigCollection | undefined) { + this._language = config?.getValueByAlias('language'); + } + + #onInput(event: Event) { + //this.value = (event.target as UmbCodeEditorElement).code as string; + this.dispatchEvent(new CustomEvent('property-value-change')); + } + + render() { + return html``; + } +} + +export default UmbPropertyEditorUICodeEditorElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-property-editor-ui-code-editor': UmbPropertyEditorUICodeEditorElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.stories.ts new file mode 100644 index 0000000000..0c211a4357 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.stories.ts @@ -0,0 +1,15 @@ +import type { Meta, Story } from '@storybook/web-components'; +import type { UmbPropertyEditorUICodeEditorElement } from './property-editor-ui-code-editor.element.js'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './property-editor-ui-code-editor.element.js'; + +export default { + title: 'Property Editor UIs/Code Editor', + component: 'umb-property-editor-ui-code-editor', + id: 'umb-property-editor-ui-code-editor', +} as Meta; + +export const AAAOverview: Story = () => + html` `; +AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/manifests.ts index b6fc6c9caf..689a9bc550 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/manifests.ts @@ -1,4 +1,5 @@ import { manifest as checkboxList } from './checkbox-list/manifests.js'; +import { manifest as codeEditor } from './code-editor/manifests.js'; import { manifest as colorEditor } from './color-swatches-editor/manifests.js'; import { manifest as colorPicker } from './color-picker/manifests.js'; import { manifest as datePicker } from './date-picker/manifests.js'; @@ -30,6 +31,7 @@ import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension export const manifests: Array = [ checkboxList, + codeEditor, colorEditor, colorPicker, datePicker, From c2d7bceb5d9537a3d1d40478e18142c9be539277 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Thu, 15 Feb 2024 01:05:08 +0100 Subject: [PATCH 002/325] Add dummy data --- .../src/mocks/data/document/document.data.ts | 32 +++++++++++++++++++ .../property-editor-ui-code-editor.element.ts | 11 +++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts index f0ae2b9b88..b0251d41d5 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts @@ -47,6 +47,38 @@ export const data: Array = [ `, }, }, + { + alias: 'codeEditor', + culture: null, + segment: null, + value: ` +

Lorem ipsum dolor sit amet consectetuer adipiscing elit

+
    +
  • Lorem ipsum dolor sit amet consectetuer.
  • +
  • Aenean commodo ligula eget dolor.
  • +
  • Aenean massa cum sociis natoque penatibus.
  • +
+

+ Lorem ipsum dolor sit amet, consectetuer adipiscing + elit. Aenean commodo ligula eget dolor. +

+

+

+ Lorem ipsum dolor sit amet, consectetuer + adipiscing elit. Aenean commodo ligula eget dolor. + Aenean massa strong. Cum sociis + natoque penatibus et magnis dis parturient montes, + nascetur ridiculus mus. Donec quam felis, ultricies + nec, pellentesque eu, pretium quis, sem. Nulla consequat + massa quis enim. Donec pede justo, fringilla vel, + aliquet nec, vulputate eget, arcu. In em + enim justo, rhoncus ut, imperdiet a, venenatis vitae, + justo. Nullam link + dictum felis eu pede mollis pretium. +
+

+ `, + }, { alias: 'email', culture: null, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts index be24db95e6..127b3c62ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts @@ -1,5 +1,6 @@ import { css, html, customElement, property, state, ifDefined, styleMap } from '@umbraco-cms/backoffice/external/lit'; -//import type { UUICodeEditorElement } from '@umbraco-cms/backoffice/external/uui'; +import { monaco } from '@umbraco-cms/backoffice/external/monaco-editor'; +import type { UmbCodeEditorController, UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; @@ -9,8 +10,11 @@ export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implemen @property() value = ''; + //@query('umb-code-editor') + _codeEditor?: UmbCodeEditorElement; + @state() - private _language?: string; + private _language?: string = 'HTML'; @property({ attribute: false }) public set config(config: UmbPropertyEditorConfigCollection | undefined) { @@ -18,7 +22,8 @@ export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implemen } #onInput(event: Event) { - //this.value = (event.target as UmbCodeEditorElement).code as string; + this.value = (event.target as UmbCodeEditorElement).code as string; + //this.value = this.#editor?.monacoEditor?.getValue() ?? ''; this.dispatchEvent(new CustomEvent('property-value-change')); } From 5adafc1d66a8a9e8c317dbd1667d6794fa5877c1 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Thu, 15 Feb 2024 08:24:57 +0100 Subject: [PATCH 003/325] Add input code editor --- .../components/input-code-editor/index.ts | 1 + .../input-code-editor.element.ts | 627 ++++++++++++++++++ .../input-code-editor.stories.ts | 16 + 3 files changed, 644 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/index.ts new file mode 100644 index 0000000000..70028de684 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/index.ts @@ -0,0 +1 @@ +export * from './input-code-editor.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts new file mode 100644 index 0000000000..00055d8f54 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts @@ -0,0 +1,627 @@ +import { DOMPurify } from '@umbraco-cms/backoffice/external/dompurify'; +import { marked } from '@umbraco-cms/backoffice/external/marked'; +import { monaco } from '@umbraco-cms/backoffice/external/monaco-editor'; +import type { UmbCodeEditorController, UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; +import { loadCodeEditor } from '@umbraco-cms/backoffice/code-editor'; +import { css, html, customElement, query, property, unsafeHTML, when } from '@umbraco-cms/backoffice/external/lit'; +import { FormControlMixin, type UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; +import { UmbBooleanState } from '@umbraco-cms/backoffice/observable-api'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbModalManagerContext } from '@umbraco-cms/backoffice/modal'; +import { + UMB_LINK_PICKER_MODAL, + UMB_MEDIA_TREE_PICKER_MODAL, + UMB_MODAL_MANAGER_CONTEXT, +} from '@umbraco-cms/backoffice/modal'; +import { UMB_APP_CONTEXT } from '@umbraco-cms/backoffice/app'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; + +/** + * @element umb-input-code-editor + * @fires change - when the value of the input changes + */ + +@customElement('umb-input-code-editor') +export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { + protected getFormElement() { + return this._codeEditor; + } + + // TODO: Make actions be able to handle multiple selection + + @property({ type: Boolean }) + preview: boolean = false; + + @property() + overlaySize?: UUIModalSidebarSize; + + #isCodeEditorReady = new UmbBooleanState(false); + #editor?: UmbCodeEditorController; + + @query('umb-code-editor') + _codeEditor?: UmbCodeEditorElement; + + private _modalContext?: UmbModalManagerContext; + + private serverUrl?: string; + + constructor() { + super(); + this.#loadCodeEditor(); + this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { + this._modalContext = instance; + }); + this.consumeContext(UMB_APP_CONTEXT, (instance) => { + this.serverUrl = instance.getServerUrl(); + }); + } + + async #loadCodeEditor() { + try { + await loadCodeEditor(); + + this.#editor = this._codeEditor?.editor; + + this.#editor?.updateOptions({ + lineNumbers: false, + minimap: false, + folding: false, + }); // Prefer to update options before showing the editor, to avoid seeing the changes in the UI. + + this.#isCodeEditorReady.setValue(true); + this.#loadActions(); + } catch (error) { + console.error(error); + } + } + + async #loadActions() { + //Note: UI Buttons have the keybindings hardcoded in its title. If you change the keybindings here, please update the render as well. + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H1', + id: 'h1', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit1], + run: () => this._insertAtCurrentLine('# '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H2', + id: 'h2', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit2], + run: () => this._insertAtCurrentLine('## '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H3', + id: 'h3', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit3], + run: () => this._insertAtCurrentLine('### '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H4', + id: 'h4', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit4], + run: () => this._insertAtCurrentLine('#### '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H5', + id: 'h5', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit5], + run: () => this._insertAtCurrentLine('##### '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Heading H6', + id: 'h6', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit6], + run: () => this._insertAtCurrentLine('###### '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Bold Text', + id: 'b', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB], + run: () => this._insertBetweenSelection('**', '**', 'Your Bold Text'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Italic Text', + id: 'i', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI], + run: () => this._insertBetweenSelection('*', '*', 'Your Italic Text'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Quote', + id: 'q', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Period], + run: () => this._insertQuote(), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Ordered List', + id: 'ol', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit7], + run: () => this._insertAtCurrentLine('1. '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Unordered List', + id: 'ul', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit8], + run: () => this._insertAtCurrentLine('- '), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Code', + id: 'code', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyE], + run: () => this._insertBetweenSelection('`', '`', 'Code'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Fenced Code', + id: 'fenced-code', + run: () => this._insertBetweenSelection('```', '```', 'Code'), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Line', + id: 'line', + run: () => this._insertLine(), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Link', + id: 'link', + keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK], + run: () => this._insertLink(), + }); + this.#editor?.monacoEditor?.addAction({ + label: 'Add Image', + id: 'image', + //keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyJ], // What keybinding would be good for image? + run: () => this._insertMedia(), + // TODO: Update when media picker is complete. + }); + } + + 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 _insertLink() { + const selection = this.#editor?.getSelections()[0]; + if (!selection || !this._modalContext) return; + + const selectedValue = this.#editor?.getValueInRange(selection); + + this._focusEditor(); // Focus before opening modal + const modalContext = this._modalContext.open(UMB_LINK_PICKER_MODAL, { + data: { + index: null, + config: { overlaySize: this.overlaySize }, + }, + value: { + link: { name: selectedValue }, + }, + }); + + modalContext + ?.onSubmit() + .then((value) => { + if (!value) return; + + const name = this.localize.term('general_name'); + const url = this.localize.term('general_url'); + + this.#editor?.monacoEditor?.executeEdits('', [ + { range: selection, text: `[${value.link.name || name}](${value.link.url || url})` }, + ]); + + if (!value.link.name) { + this.#editor?.select({ + startColumn: selection.startColumn + 1, + endColumn: selection.startColumn + 1 + name.length, + endLineNumber: selection.startLineNumber, + startLineNumber: selection.startLineNumber, + }); + } else if (!value.link.url) { + this.#editor?.select({ + startColumn: selection.startColumn + 3 + value.link.name.length, + endColumn: selection.startColumn + 3 + value.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) || 'alt text'; + + this._focusEditor(); // Focus before opening modal, otherwise cannot regain focus back after modal + const modalContext = this._modalContext?.open(UMB_MEDIA_TREE_PICKER_MODAL); + + modalContext + ?.onSubmit() + .then((value) => { + if (!value) return; + const imgUrl = value.selection[0]; + this.#editor?.monacoEditor?.executeEdits('', [ + //TODO: Get the correct media URL + { + range: selection, + text: `![${alt}](${imgUrl ? `${this.serverUrl}'/media/'${imgUrl}` : 'URL'})`, + }, + ]); + this.#editor?.select({ + startColumn: selection.startColumn + 2, + endColumn: selection.startColumn + alt.length + 2, // +2 because of ![ + 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---\n', { + lineNumber: selection.endLineNumber, + column: endColumn, + }); + } + this._focusEditor(); + } + + 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) && + selectedValue.length > startValue.length + endValue.length + ) { + //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, + }); + + 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 + 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 _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`
+ 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('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') return; + //TODO: Tab does not seem to trigger keyboard events. We need to make some logic for ordered and unordered lists when tab is being used. + + const selection = this.#editor?.getSelections()[0]; + if (!selection) return; + + const lineValue = this.#editor?.getValueInRange({ ...selection, startColumn: 1 }).trimStart(); + if (!lineValue) return; + + 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}. `)); + } + } + + #onInput(e: CustomEvent) { + e.stopPropagation(); + this.value = this.#editor?.monacoEditor?.getValue() ?? ''; + this.dispatchEvent(new CustomEvent('change')); + } + + render() { + return html`
${this._renderBasicActions()}
+ + ${when(this.preview && this.value, () => this.renderPreview(this.value as string))}`; + } + + renderPreview(markdown: string) { + const markdownAsHtml = marked.parse(markdown) as string; + const sanitizedHtml = markdownAsHtml ? DOMPurify.sanitize(markdownAsHtml) : ''; + return html` ${unsafeHTML(sanitizedHtml)} `; + } + + static styles = [ + UmbTextStyles, + css` + :host { + display: flex; + flex-direction: column; + } + #actions { + background-color: var(--uui-color-background-alt); + display: flex; + gap: var(--uui-size-6); + } + + #preview { + max-height: 400px; + } + + #actions div { + display: flex; + gap: var(--uui-size-1); + } + + #actions div:last-child { + margin-left: auto; + } + + umb-code-editor { + height: 200px; + border-radius: var(--uui-border-radius); + border: 1px solid var(--uui-color-divider-emphasis); + } + + uui-button { + width: 50px; + } + + blockquote { + border-left: 2px solid var(--uui-color-default-emphasis); + margin-inline: 0; + padding-inline: var(--uui-size-3); + } + + p > code, + pre { + border: 1px solid var(--uui-color-divider-emphasis); + border-radius: var(--uui-border-radius); + padding: 0 var(--uui-size-1); + background-color: var(--uui-color-background); + } + + hr { + border: none; + border-bottom: 1px solid var(--uui-palette-cocoa-black); + } + `, + ]; +} +export default UmbInputCodeEditorElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-input-code-editor': UmbInputCodeEditorElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts new file mode 100644 index 0000000000..73196554df --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from '@storybook/web-components'; +import './input-code-editor.element.js'; +import type { UmbInputCodeEditorElement } from './input-code-editor.element.js'; + +const meta: Meta = { + title: 'Components/Inputs/Code Editor', + component: 'umb-input-code-editor', + args: { + preview: false, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Overview: Story = {}; From a5684551a2c89f6e47543d0ec9dfb4a150c0ad30 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 16:18:29 +0100 Subject: [PATCH 004/325] Use umb-input-code-editor --- .../input-code-editor/input-code-editor.element.ts | 3 +++ .../code-editor/property-editor-ui-code-editor.element.ts | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts index 00055d8f54..c1552cc779 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts @@ -32,6 +32,9 @@ export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { @property({ type: Boolean }) preview: boolean = false; + @property({ type: String }) + language: string = ''; + @property() overlaySize?: UUIModalSidebarSize; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts index 127b3c62ad..2d94c6771b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts @@ -28,11 +28,11 @@ export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implemen } render() { - return html``; + .value=${this.value ?? ''} + @input=${this.#onInput}>`; } } From 7a1bd585856bc6322c2a5b798056aec8c13227dc Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 16:37:06 +0100 Subject: [PATCH 005/325] On change --- .../property-editor-ui-code-editor.element.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts index 2d94c6771b..0b6fa2ce1f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts @@ -10,9 +10,6 @@ export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implemen @property() value = ''; - //@query('umb-code-editor') - _codeEditor?: UmbCodeEditorElement; - @state() private _language?: string = 'HTML'; @@ -21,18 +18,16 @@ export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implemen this._language = config?.getValueByAlias('language'); } - #onInput(event: Event) { - this.value = (event.target as UmbCodeEditorElement).code as string; - //this.value = this.#editor?.monacoEditor?.getValue() ?? ''; + #onChange(e: Event) { + this.value = (e.target as UmbInputCodeEditorElement).value as string; this.dispatchEvent(new CustomEvent('property-value-change')); } render() { return html``; + @change=${this.#onChange}>`; } } From afd57463a39bd47335f5e16bb6df3b72c0973925 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 17:05:52 +0100 Subject: [PATCH 006/325] Import input code editor --- .../code-editor/property-editor-ui-code-editor.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts index 0b6fa2ce1f..e15e1082bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts @@ -1,6 +1,6 @@ -import { css, html, customElement, property, state, ifDefined, styleMap } from '@umbraco-cms/backoffice/external/lit'; -import { monaco } from '@umbraco-cms/backoffice/external/monaco-editor'; -import type { UmbCodeEditorController, UmbCodeEditorElement } from '@umbraco-cms/backoffice/code-editor'; +import type { UmbInputCodeEditorElement } from '../../../components/input-code-editor/index.js'; +import '../../../components/input-code-editor/index.js'; +import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; From abf617c5d43f1aa7579dec65d6da38e872b8483a Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 17:14:13 +0100 Subject: [PATCH 007/325] Add document type data --- .../data/document-type/document-type.data.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts index b6ee696086..7bf77f79c7 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document-type/document-type.data.ts @@ -660,6 +660,30 @@ export const data: Array = [ labelOnTop: false, }, }, + { + id: '34', + container: { + id: 'all-properties-group-key', + }, + alias: 'codeEditor', + name: 'Code Editor', + description: '', + dataType: { + id: 'dt-codeEditor', + }, + variesByCulture: false, + variesBySegment: false, + sortOrder: 0, + validation: { + mandatory: true, + mandatoryMessage: null, + regEx: null, + regExMessage: null, + }, + appearance: { + labelOnTop: false, + }, + }, ], containers: [ { From d933f5a33aaef60b87ecfaa167f4b645dae8f07d Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 17:21:53 +0100 Subject: [PATCH 008/325] Cleanup actions copied from markdown --- .../input-code-editor.element.ts | 487 +----------------- .../input-code-editor.stories.ts | 2 +- 2 files changed, 4 insertions(+), 485 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts index c1552cc779..18386f9e7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts @@ -27,13 +27,8 @@ export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { return this._codeEditor; } - // TODO: Make actions be able to handle multiple selection - - @property({ type: Boolean }) - preview: boolean = false; - @property({ type: String }) - language: string = ''; + language: string = 'HTML'; @property() overlaySize?: UUIModalSidebarSize; @@ -72,457 +67,16 @@ export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { }); // Prefer to update options before showing the editor, to avoid seeing the changes in the UI. this.#isCodeEditorReady.setValue(true); - this.#loadActions(); } catch (error) { console.error(error); } } - async #loadActions() { - //Note: UI Buttons have the keybindings hardcoded in its title. If you change the keybindings here, please update the render as well. - this.#editor?.monacoEditor?.addAction({ - label: 'Add Heading H1', - id: 'h1', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit1], - run: () => this._insertAtCurrentLine('# '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Heading H2', - id: 'h2', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit2], - run: () => this._insertAtCurrentLine('## '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Heading H3', - id: 'h3', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit3], - run: () => this._insertAtCurrentLine('### '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Heading H4', - id: 'h4', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit4], - run: () => this._insertAtCurrentLine('#### '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Heading H5', - id: 'h5', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit5], - run: () => this._insertAtCurrentLine('##### '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Heading H6', - id: 'h6', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit6], - run: () => this._insertAtCurrentLine('###### '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Bold Text', - id: 'b', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyB], - run: () => this._insertBetweenSelection('**', '**', 'Your Bold Text'), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Italic Text', - id: 'i', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyI], - run: () => this._insertBetweenSelection('*', '*', 'Your Italic Text'), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Quote', - id: 'q', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Period], - run: () => this._insertQuote(), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Ordered List', - id: 'ol', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit7], - run: () => this._insertAtCurrentLine('1. '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Unordered List', - id: 'ul', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.Digit8], - run: () => this._insertAtCurrentLine('- '), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Code', - id: 'code', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyE], - run: () => this._insertBetweenSelection('`', '`', 'Code'), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Fenced Code', - id: 'fenced-code', - run: () => this._insertBetweenSelection('```', '```', 'Code'), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Line', - id: 'line', - run: () => this._insertLine(), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Link', - id: 'link', - keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyK], - run: () => this._insertLink(), - }); - this.#editor?.monacoEditor?.addAction({ - label: 'Add Image', - id: 'image', - //keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyJ], // What keybinding would be good for image? - run: () => this._insertMedia(), - // TODO: Update when media picker is complete. - }); - } - 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 _insertLink() { - const selection = this.#editor?.getSelections()[0]; - if (!selection || !this._modalContext) return; - - const selectedValue = this.#editor?.getValueInRange(selection); - - this._focusEditor(); // Focus before opening modal - const modalContext = this._modalContext.open(UMB_LINK_PICKER_MODAL, { - data: { - index: null, - config: { overlaySize: this.overlaySize }, - }, - value: { - link: { name: selectedValue }, - }, - }); - - modalContext - ?.onSubmit() - .then((value) => { - if (!value) return; - - const name = this.localize.term('general_name'); - const url = this.localize.term('general_url'); - - this.#editor?.monacoEditor?.executeEdits('', [ - { range: selection, text: `[${value.link.name || name}](${value.link.url || url})` }, - ]); - - if (!value.link.name) { - this.#editor?.select({ - startColumn: selection.startColumn + 1, - endColumn: selection.startColumn + 1 + name.length, - endLineNumber: selection.startLineNumber, - startLineNumber: selection.startLineNumber, - }); - } else if (!value.link.url) { - this.#editor?.select({ - startColumn: selection.startColumn + 3 + value.link.name.length, - endColumn: selection.startColumn + 3 + value.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) || 'alt text'; - - this._focusEditor(); // Focus before opening modal, otherwise cannot regain focus back after modal - const modalContext = this._modalContext?.open(UMB_MEDIA_TREE_PICKER_MODAL); - - modalContext - ?.onSubmit() - .then((value) => { - if (!value) return; - const imgUrl = value.selection[0]; - this.#editor?.monacoEditor?.executeEdits('', [ - //TODO: Get the correct media URL - { - range: selection, - text: `![${alt}](${imgUrl ? `${this.serverUrl}'/media/'${imgUrl}` : 'URL'})`, - }, - ]); - this.#editor?.select({ - startColumn: selection.startColumn + 2, - endColumn: selection.startColumn + alt.length + 2, // +2 because of ![ - 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---\n', { - lineNumber: selection.endLineNumber, - column: endColumn, - }); - } - this._focusEditor(); - } - - 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) && - selectedValue.length > startValue.length + endValue.length - ) { - //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, - }); - - 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 - 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 _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`
- 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('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') return; //TODO: Tab does not seem to trigger keyboard events. We need to make some logic for ordered and unordered lists when tab is being used. @@ -548,20 +102,13 @@ export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { } render() { - return html`
${this._renderBasicActions()}
+ return html` - ${when(this.preview && this.value, () => this.renderPreview(this.value as string))}`; - } - - renderPreview(markdown: string) { - const markdownAsHtml = marked.parse(markdown) as string; - const sanitizedHtml = markdownAsHtml ? DOMPurify.sanitize(markdownAsHtml) : ''; - return html` ${unsafeHTML(sanitizedHtml)} `; + theme="umb-light">`; } static styles = [ @@ -571,24 +118,6 @@ export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { display: flex; flex-direction: column; } - #actions { - background-color: var(--uui-color-background-alt); - display: flex; - gap: var(--uui-size-6); - } - - #preview { - max-height: 400px; - } - - #actions div { - display: flex; - gap: var(--uui-size-1); - } - - #actions div:last-child { - margin-left: auto; - } umb-code-editor { height: 200px; @@ -596,16 +125,6 @@ export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { border: 1px solid var(--uui-color-divider-emphasis); } - uui-button { - width: 50px; - } - - blockquote { - border-left: 2px solid var(--uui-color-default-emphasis); - margin-inline: 0; - padding-inline: var(--uui-size-3); - } - p > code, pre { border: 1px solid var(--uui-color-divider-emphasis); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts index 73196554df..8cfc62d48d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.stories.ts @@ -6,7 +6,7 @@ const meta: Meta = { title: 'Components/Inputs/Code Editor', component: 'umb-input-code-editor', args: { - preview: false, + language: 'HTML', }, }; From 33ef79042429d03466bb94a4b98baf62e4e9d583 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 18:42:35 +0100 Subject: [PATCH 009/325] Language need to be in lowercase --- .../code-editor/property-editor-ui-code-editor.element.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts index e15e1082bf..ff95a62c7f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/property-editor-ui-code-editor.element.ts @@ -15,7 +15,8 @@ export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implemen @property({ attribute: false }) public set config(config: UmbPropertyEditorConfigCollection | undefined) { - this._language = config?.getValueByAlias('language'); + //this._language = config?.getValueByAlias('language'); + console.log("language", config?.getValueByAlias('language')) } #onChange(e: Event) { @@ -25,7 +26,7 @@ export class UmbPropertyEditorUICodeEditorElement extends UmbLitElement implemen render() { return html``; } From 37a0ebcede6c25be75037ee8db4af486d0168fc5 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 18:44:42 +0100 Subject: [PATCH 010/325] Formatting --- .../src/mocks/data/document/document.data.ts | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts index fadca0fba0..ef3243dde1 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/document/document.data.ts @@ -51,33 +51,31 @@ export const data: Array = [ alias: 'codeEditor', culture: null, segment: null, - value: ` -

Lorem ipsum dolor sit amet consectetuer adipiscing elit

-
    -
  • Lorem ipsum dolor sit amet consectetuer.
  • -
  • Aenean commodo ligula eget dolor.
  • -
  • Aenean massa cum sociis natoque penatibus.
  • -
-

- Lorem ipsum dolor sit amet, consectetuer adipiscing - elit. Aenean commodo ligula eget dolor. -

-

-

- Lorem ipsum dolor sit amet, consectetuer - adipiscing elit. Aenean commodo ligula eget dolor. - Aenean massa strong. Cum sociis - natoque penatibus et magnis dis parturient montes, - nascetur ridiculus mus. Donec quam felis, ultricies - nec, pellentesque eu, pretium quis, sem. Nulla consequat - massa quis enim. Donec pede justo, fringilla vel, - aliquet nec, vulputate eget, arcu. In em - enim justo, rhoncus ut, imperdiet a, venenatis vitae, - justo. Nullam link - dictum felis eu pede mollis pretium. -
-

- `, + value: `

Lorem ipsum dolor sit amet consectetuer adipiscing elit

+
    +
  • Lorem ipsum dolor sit amet consectetuer.
  • +
  • Aenean commodo ligula eget dolor.
  • +
  • Aenean massa cum sociis natoque penatibus.
  • +
+

+ Lorem ipsum dolor sit amet, consectetuer adipiscing + elit. Aenean commodo ligula eget dolor. +

+

+

+ Lorem ipsum dolor sit amet, consectetuer + adipiscing elit. Aenean commodo ligula eget dolor. + Aenean massa strong. Cum sociis + natoque penatibus et magnis dis parturient montes, + nascetur ridiculus mus. Donec quam felis, ultricies + nec, pellentesque eu, pretium quis, sem. Nulla consequat + massa quis enim. Donec pede justo, fringilla vel, + aliquet nec, vulputate eget, arcu. In em + enim justo, rhoncus ut, imperdiet a, venenatis vitae, + justo. Nullam link + dictum felis eu pede mollis pretium. +
+

`, }, { alias: 'email', From 0d94309394d006be7d21afdd2c9ddf99e367ad3e Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 19:46:40 +0100 Subject: [PATCH 011/325] Cleanup --- .../input-code-editor/input-code-editor.element.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts index 18386f9e7c..1e7dfd62f3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-code-editor/input-code-editor.element.ts @@ -30,28 +30,15 @@ export class UmbInputCodeEditorElement extends FormControlMixin(UmbLitElement) { @property({ type: String }) language: string = 'HTML'; - @property() - overlaySize?: UUIModalSidebarSize; - #isCodeEditorReady = new UmbBooleanState(false); #editor?: UmbCodeEditorController; @query('umb-code-editor') _codeEditor?: UmbCodeEditorElement; - private _modalContext?: UmbModalManagerContext; - - private serverUrl?: string; - constructor() { super(); this.#loadCodeEditor(); - this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (instance) => { - this._modalContext = instance; - }); - this.consumeContext(UMB_APP_CONTEXT, (instance) => { - this.serverUrl = instance.getServerUrl(); - }); } async #loadCodeEditor() { From 3762bdbfb996406eb5ae2756934913780157c367 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sun, 18 Feb 2024 19:47:05 +0100 Subject: [PATCH 012/325] Add possible modes --- .../core/property-editor/uis/code-editor/manifests.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts index 9c7efaac80..4dacc7286f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/uis/code-editor/manifests.ts @@ -20,7 +20,15 @@ export const manifest: ManifestPropertyEditorUi = { config: [ { alias: 'items', - value: ['Razor', 'HTML', 'CSS', 'JavaScript'], + value: { + 0: { sortOrder: 1, value: 'Razor' }, + 1: { sortOrder: 2, value: 'HTML' }, + 2: { sortOrder: 3, value: 'CSS' }, + 3: { sortOrder: 3, value: 'JavaScript' }, + 4: { sortOrder: 3, value: 'TypeScript' }, + 5: { sortOrder: 3, value: 'Markdown' }, + 6: { sortOrder: 3, value: 'JSON' }, + }, }, ], }, From 3ca06aaef87a16b7427f7c15ed7a7323b5bdc050 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Sat, 24 Feb 2024 16:52:14 +0100 Subject: [PATCH 013/325] Add more languages --- .../src/mocks/data/data-type/data-type.data.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts index f3af6e6981..a49ce4a380 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts @@ -472,6 +472,9 @@ export const data: Array = [ 1: { sortOrder: 2, value: 'HTML' }, 2: { sortOrder: 3, value: 'CSS' }, 3: { sortOrder: 4, value: 'JavaScript' }, + 4: { sortOrder: 3, value: 'TypeScript' }, + 5: { sortOrder: 3, value: 'Markdown' }, + 6: { sortOrder: 3, value: 'JSON' }, }, }, ], From a88d7104ae5c1899ce1d57fe5d4c48c793d57370 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 24 Jun 2024 11:33:01 +0200 Subject: [PATCH 014/325] check paths in dist-cms instead of source --- 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 679141f9db..cebcf01b78 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -147,7 +147,7 @@ "build:workspaces": "npm run build -ws --if-present", "build": "tsc --project ./src/tsconfig.build.json && rollup -c ./src/rollup.config.js", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", - "check:paths": "node ./devops/build/check-path-length.js src 140", + "check:paths": "node ./devops/build/check-path-length.js dist-cms 140", "compile": "tsc", "dev": "vite", "dev:server": "VITE_UMBRACO_USE_MSW=off vite", From f1ba13f589817f0fc1fd174423668a70bb88b439 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:38:15 +0200 Subject: [PATCH 015/325] check the paths when building --- src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml index 6bccda7c83..be4e4d4158 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml @@ -40,6 +40,7 @@ jobs: - run: npm ci --no-audit --no-fund --prefer-offline - run: npm run lint:errors - run: npm run build + - run: npm run check:paths - run: npm run generate:jsonschema:dist - run: npx playwright install --with-deps - run: npm test From 19f75e180bdcf28f2033a2df214782d65c5c73c5 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:38:37 +0200 Subject: [PATCH 016/325] up the requirement to a max of 120 chars --- 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 3d8ab3bead..f573aed861 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -149,7 +149,7 @@ "build:workspaces": "npm run build -ws --if-present", "build": "tsc --project ./src/tsconfig.build.json && rollup -c ./src/rollup.config.js", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", - "check:paths": "node ./devops/build/check-path-length.js dist-cms 140", + "check:paths": "node ./devops/build/check-path-length.js dist-cms 120", "compile": "tsc", "dev": "vite", "dev:server": "VITE_UMBRACO_USE_MSW=off vite", From 2a9d575e23aa5c0ab22e7418853785faae0ef2ab Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:50:06 +0200 Subject: [PATCH 017/325] test workspaces build --- src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml index be4e4d4158..c87fc7c101 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml @@ -40,6 +40,7 @@ jobs: - run: npm ci --no-audit --no-fund --prefer-offline - run: npm run lint:errors - run: npm run build + - run: npm run build:workspaces - run: npm run check:paths - run: npm run generate:jsonschema:dist - run: npx playwright install --with-deps From 237928c89720595419436bfd5f54d4dece230a9d Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:50:56 +0200 Subject: [PATCH 018/325] turn off declaration generation and only generate those for npm --- src/Umbraco.Web.UI.Client/package.json | 2 +- src/Umbraco.Web.UI.Client/src/tsconfig.build.json | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index f573aed861..0825d639e3 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -143,7 +143,7 @@ "backoffice:test:e2e": "npx playwright test", "build-storybook": "npm run wc-analyze && storybook build", "build:for:cms": "npm run build && npm run build:workspaces && npm run generate:manifest && npm run package:validate && node ./devops/build/copy-to-cms.js", - "build:for:npm": "npm run build && npm run generate:manifest && npm run package:validate", + "build:for:npm": "tsc --project ./src/tsconfig.build.json --declaration && rollup -c ./src/rollup.config.js && npm run generate:manifest && npm run package:validate", "build:for:static": "vite build", "build:vite": "tsc && vite build --mode staging", "build:workspaces": "npm run build -ws --if-present", diff --git a/src/Umbraco.Web.UI.Client/src/tsconfig.build.json b/src/Umbraco.Web.UI.Client/src/tsconfig.build.json index fb00a47d31..600705db7e 100644 --- a/src/Umbraco.Web.UI.Client/src/tsconfig.build.json +++ b/src/Umbraco.Web.UI.Client/src/tsconfig.build.json @@ -5,9 +5,8 @@ "noEmit": false, "outDir": "../dist-cms", "rootDir": "./", - "composite": true, "sourceMap": false, - "declaration": true, + "declaration": false, "allowImportingTsExtensions": false }, "include": ["./**/*.ts", "./**/*.json", "./**/*.js"], From aa32aa0e9a8af7fca0a683ca9d6d724762788fa5 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:52:30 +0200 Subject: [PATCH 019/325] do not check paths for package:validate --- 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 0825d639e3..a9a596aca3 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -181,7 +181,7 @@ "wc-analyze": "wca **/*.element.ts --outFile dist-cms/custom-elements.json", "generate:tsconfig": "node ./devops/tsconfig/index.js", "generate:manifest": "node ./devops/build/create-umbraco-package.js", - "package:validate": "node ./devops/package/validate-exports.js && npm run check:paths", + "package:validate": "node ./devops/package/validate-exports.js", "generate:ui-api-docs": "typedoc --options typedoc.config.js" }, "engines": { From f98d3ae09cfc3c9a5b1792d7d1131aae402c2dc1 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:16:40 +0200 Subject: [PATCH 020/325] Bugfix: Export multi url and align element name --- .../src/packages/multi-url-picker/components/index.ts | 1 + .../components/input-multi-url/index.ts | 1 + .../input-multi-url/input-multi-url.element.ts} | 10 +++++----- .../input-multi-url/input-multi-url.stories.ts} | 6 +++--- .../src/packages/multi-url-picker/entry-point.ts | 1 + .../multi-url-picker/multi-url-picker/index.ts | 1 - .../property-editor-ui-multi-url-picker.element.ts | 11 ++++------- .../src/packages/multi-url-picker/umbraco-package.ts | 6 ++++++ 8 files changed, 21 insertions(+), 16 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/index.ts rename src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/{multi-url-picker/multi-url-picker.element.ts => components/input-multi-url/input-multi-url.element.ts} (95%) rename src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/{multi-url-picker/multi-url-picker.stories.ts => components/input-multi-url/input-multi-url.stories.ts} (59%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/entry-point.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/index.ts new file mode 100644 index 0000000000..4ef883ab59 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/index.ts @@ -0,0 +1 @@ +export * from './input-multi-url/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/index.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/index.ts new file mode 100644 index 0000000000..d197dc0c3d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/index.ts @@ -0,0 +1 @@ +export * from './input-multi-url.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/multi-url-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.ts similarity index 95% rename from src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/multi-url-picker.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.ts index b8a0b8b578..6c9e3eeba5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/multi-url-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.element.ts @@ -1,5 +1,5 @@ -import type { UmbLinkPickerLink } from '../link-picker-modal/types.js'; -import { UMB_LINK_PICKER_MODAL } from '../link-picker-modal/link-picker-modal.token.js'; +import type { UmbLinkPickerLink } from '../../link-picker-modal/types.js'; +import { UMB_LINK_PICKER_MODAL } from '../../link-picker-modal/link-picker-modal.token.js'; import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; import { simpleHashCode } from '@umbraco-cms/backoffice/observable-api'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; @@ -18,9 +18,9 @@ import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; * @fires blur - when the input loses focus * @fires focus - when the input gains focus */ -const elementName = 'umb-multi-url-picker'; +const elementName = 'umb-input-multi-url'; @customElement(elementName) -export class UmbMultiUrlPickerElement extends UUIFormControlMixin(UmbLitElement, '') { +export class UmbInputMultiUrlElement extends UUIFormControlMixin(UmbLitElement, '') { #sorter = new UmbSorterController(this, { getUniqueOfElement: (element) => { return element.id; @@ -296,6 +296,6 @@ export class UmbMultiUrlPickerElement extends UUIFormControlMixin(UmbLitElement, declare global { interface HTMLElementTagNameMap { - [elementName]: UmbMultiUrlPickerElement; + [elementName]: UmbInputMultiUrlElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/multi-url-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts similarity index 59% rename from src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/multi-url-picker.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts index 2772b6ccd2..7b794a12ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/multi-url-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts @@ -1,14 +1,14 @@ import type { Meta, StoryObj } from '@storybook/web-components'; import './multi-url-picker.element.js'; -import type { UmbMultiUrlPickerElement } from './multi-url-picker.element.js'; +import type { UmbInputMultiUrlElement } from './input-multi-url.element.js'; -const meta: Meta = { +const meta: Meta = { title: 'Components/Inputs/Multi URL', component: 'umb-input-multi-url', }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Overview: Story = { args: {}, diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/entry-point.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/entry-point.ts new file mode 100644 index 0000000000..8a8c2711ca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/entry-point.ts @@ -0,0 +1 @@ +export * from './components/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/index.ts deleted file mode 100644 index 2d2ffcb054..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/multi-url-picker/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './multi-url-picker.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts index ffb6e0ae35..eeab2d167d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.element.ts @@ -1,5 +1,5 @@ import type { UmbLinkPickerLink } from '../link-picker-modal/types.js'; -import type { UmbMultiUrlPickerElement } from '../multi-url-picker/multi-url-picker.element.js'; +import type { UmbInputMultiUrlElement } from '../components/input-multi-url/input-multi-url.element.js'; import { customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; @@ -8,9 +8,6 @@ import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/ import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; -// import of local component -import '../multi-url-picker/multi-url-picker.element.js'; - /** * @element umb-property-editor-ui-multi-url-picker */ @@ -60,14 +57,14 @@ export class UmbPropertyEditorUIMultiUrlPickerElement extends UmbLitElement impl }); } - #onChange(event: CustomEvent & { target: UmbMultiUrlPickerElement }) { + #onChange(event: CustomEvent & { target: UmbInputMultiUrlElement }) { this.value = event.target.urls; this.dispatchEvent(new UmbPropertyValueChangeEvent()); } override render() { return html` - - + `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/umbraco-package.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/umbraco-package.ts index 85548e535c..b4106c796c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/umbraco-package.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/umbraco-package.ts @@ -6,4 +6,10 @@ export const extensions = [ type: 'bundle', js: () => import('./manifests.js'), }, + { + name: 'Multi Url Picker Entry Point', + alias: 'Umb.EntryPoint.MultiUrlPicker', + type: 'entryPoint', + js: () => import('./entry-point.js'), + }, ]; From 85cced17e632c910d01e2cad0600684cdb3b8ed4 Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:26:42 +0200 Subject: [PATCH 021/325] path --- .../components/input-multi-url/input-multi-url.stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts index 7b794a12ad..1017d7d56d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/web-components'; -import './multi-url-picker.element.js'; +import './input-multi-url.element.js'; import type { UmbInputMultiUrlElement } from './input-multi-url.element.js'; const meta: Meta = { From 8177d89d470856de1ebf6384d39423c336db0732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 28 Jun 2024 19:30:42 +0200 Subject: [PATCH 022/325] sort imports --- .../block-grid-area-config-entry.element.ts | 2 +- ...-grid-area-type-workspace-editor.element.ts | 2 +- .../block-grid-areas-container.element.ts | 4 ++-- .../context/block-grid-entry.context.ts | 18 +++++++++--------- .../block-grid-scale-manager.controller.ts | 2 +- ...ditor-ui-block-grid-areas-config.element.ts | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts index 1254987417..70b4e30ee5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts @@ -1,7 +1,7 @@ -import { UmbBlockGridAreaConfigEntryContext } from './block-grid-area-config-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbBlockGridAreaConfigEntryContext } from './block-grid-area-config-entry.context.js'; import '../block-grid-block/index.js'; import '../block-scale-handler/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts index 20056eaf6e..46ebf32887 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace-editor.element.ts @@ -1,7 +1,7 @@ -import { UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_CONTEXT } from './block-grid-area-type-workspace.context.js'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { customElement, css, html, state, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_CONTEXT } from './block-grid-area-type-workspace.context.js'; @customElement('umb-block-grid-area-type-workspace-editor') export class UmbBlockGridAreaTypeWorkspaceEditorElement extends UmbLitElement { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts index 567c471be8..966d63ce0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts @@ -1,7 +1,7 @@ -import { UMB_BLOCK_GRID_MANAGER_CONTEXT } from '../../context/block-grid-manager.context-token.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { UMB_BLOCK_GRID_ENTRY_CONTEXT, type UmbBlockGridTypeAreaType } from '@umbraco-cms/backoffice/block-grid'; import { css, customElement, html, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { UMB_BLOCK_GRID_MANAGER_CONTEXT } from '../../context/block-grid-manager.context-token.js'; +import { UMB_BLOCK_GRID_ENTRY_CONTEXT, type UmbBlockGridTypeAreaType } from '@umbraco-cms/backoffice/block-grid'; import '../block-grid-entries/index.js'; /** diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts index fcbfbd8dce..eadf1ebeb9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entry.context.ts @@ -1,13 +1,4 @@ -import { closestColumnSpanOption } from '../utils/index.js'; -import { UMB_BLOCK_GRID_MANAGER_CONTEXT } from './block-grid-manager.context-token.js'; -import { UMB_BLOCK_GRID_ENTRIES_CONTEXT } from './block-grid-entries.context-token.js'; -import { - type UmbBlockGridScalableContext, - UmbBlockGridScaleManager, -} from './block-grid-scale-manager/block-grid-scale-manager.controller.js'; -import { UmbBlockEntryContext } from '@umbraco-cms/backoffice/block'; import type { UmbContentTypeModel, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import type { UmbBlockGridTypeModel, UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, @@ -17,6 +8,15 @@ import { appendToFrozenArray, observeMultiple, } from '@umbraco-cms/backoffice/observable-api'; +import { closestColumnSpanOption } from '../utils/index.js'; +import { UMB_BLOCK_GRID_MANAGER_CONTEXT } from './block-grid-manager.context-token.js'; +import { UMB_BLOCK_GRID_ENTRIES_CONTEXT } from './block-grid-entries.context-token.js'; +import { + type UmbBlockGridScalableContext, + UmbBlockGridScaleManager, +} from './block-grid-scale-manager/block-grid-scale-manager.controller.js'; +import { UmbBlockEntryContext } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockGridTypeModel, UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; export class UmbBlockGridEntryContext extends UmbBlockEntryContext< diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-scale-manager/block-grid-scale-manager.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-scale-manager/block-grid-scale-manager.controller.ts index d969f6e914..4fcfdd1f75 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-scale-manager/block-grid-scale-manager.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-scale-manager/block-grid-scale-manager.controller.ts @@ -1,7 +1,7 @@ -import { closestColumnSpanOption } from '../../utils/index.js'; import { getAccumulatedValueOfIndex, getInterpolatedIndexOfPositionInWeightMap } from '@umbraco-cms/backoffice/utils'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { closestColumnSpanOption } from '../../utils/index.js'; // This might be more generic than Block Grid, but this is where it belongs currently: export interface UmbBlockGridScalableContext extends UmbControllerHost { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts index 64b8879589..8588566500 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts @@ -1,7 +1,3 @@ -import type { UmbBlockGridTypeAreaType } from '../../index.js'; -import { UMB_BLOCK_GRID_DEFAULT_LAYOUT_STYLESHEET } from '../../context/block-grid-manager.context.js'; -import { UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_MODAL } from '../../components/block-grid-area-config-entry/index.js'; -import { UmbBlockGridAreaTypeEntriesContext } from './block-grid-area-type-entries.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; @@ -13,6 +9,10 @@ import { import { UmbId } from '@umbraco-cms/backoffice/id'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { incrementString } from '@umbraco-cms/backoffice/utils'; +import { UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_MODAL } from '../../components/block-grid-area-config-entry/index.js'; +import { UMB_BLOCK_GRID_DEFAULT_LAYOUT_STYLESHEET } from '../../context/block-grid-manager.context.js'; +import type { UmbBlockGridTypeAreaType } from '../../index.js'; +import { UmbBlockGridAreaTypeEntriesContext } from './block-grid-area-type-entries.context.js'; @customElement('umb-property-editor-ui-block-grid-areas-config') export class UmbPropertyEditorUIBlockGridAreasConfigElement From 7c6ae78ad147f61342fb8fb3dee5a52821d1f7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 28 Jun 2024 22:38:24 +0200 Subject: [PATCH 023/325] implementation of custom views for block editors --- .../block-grid-entry.element.ts | 23 +++++++--- .../src/packages/block/block/types.ts | 27 +----------- .../block/custom-view/custom-view.element.ts | 18 ++++++++ .../packages/block/custom-view/manifest.ts | 10 +++++ .../src/packages/block/manifests.ts | 4 +- ...ck-editor-custom-view-element.interface.ts | 43 +++++++++++++++++++ .../extension-registry/interfaces/index.ts | 1 + .../models/block-editor-custom-view.model.ts | 6 ++- .../models/entity-action.model.ts | 2 +- 9 files changed, 99 insertions(+), 35 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 0e86d455e8..76be03cd46 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -1,9 +1,8 @@ -import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; -import type { UmbBlockViewPropsType } from '@umbraco-cms/backoffice/block'; +import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js'; import type { UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; import '../block-grid-block-inline/index.js'; import '../block-grid-block/index.js'; @@ -40,6 +39,9 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper #context = new UmbBlockGridEntryContext(this); #renderTimeout: number | undefined; + @state() + _contentTypeAlias?:string; + @state() _columnSpan?: number; @@ -84,9 +86,9 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper // TODO: use this type on the Element Interface for the Manifest. @state() - _blockViewProps: UmbBlockViewPropsType = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. - #updateBlockViewProps(incoming: Partial>) { + #updateBlockViewProps(incoming: Partial>) { this._blockViewProps = { ...this._blockViewProps, ...incoming }; this.requestUpdate('_blockViewProps'); } @@ -176,6 +178,7 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper }); this.observe(this.#context.contentElementTypeAlias, (contentElementTypeAlias) => { if (contentElementTypeAlias) { + this._contentTypeAlias = contentElementTypeAlias; this.setAttribute('data-content-element-type-alias', contentElementTypeAlias); } }); @@ -235,8 +238,15 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper return html``; } + #extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => { + if(manifest.forContentTypeAlias?.indexOf(this._contentTypeAlias!) === -1) { + return false; + } + return true; + } + #renderBlock() { - return this.contentUdi + return this.contentUdi && this._contentTypeAlias ? html` ${this._createBeforePath && this._showInlineCreateBefore ? html`${this._inlineEditingMode ? this.#renderInlineEditBlock() : this.#renderRefBlock()} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index 433d8e28f7..a6e7722374 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,31 +1,8 @@ -export interface UmbBlockLayoutBaseModel { - contentUdi: string; - settingsUdi?: string | null; -} - -export interface UmbBlockDataType { - udi: string; - contentTypeKey: string; - [key: string]: unknown; -} +import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from "@umbraco-cms/backoffice/extension-registry"; +export type { UmbBlockViewUrlsPropType, UmbBlockDataType, UmbBlockLayoutBaseModel } from "@umbraco-cms/backoffice/extension-registry"; export interface UmbBlockValueType { layout: { [key: string]: Array | undefined }; contentData: Array; settingsData: Array; } - -export interface UmbBlockViewUrlsPropType { - editContent?: string; - editSettings?: string; -} - -export interface UmbBlockViewPropsType { - label?: string; - icon?: string; - contentUdi: string; - layout?: BlockLayoutType; - content?: UmbBlockDataType; - settings?: UmbBlockDataType; - urls: UmbBlockViewUrlsPropType; -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts new file mode 100644 index 0000000000..1217a95f4d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts @@ -0,0 +1,18 @@ +import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from "@umbraco-cms/backoffice/extension-registry"; +import { customElement, html, property } from "@umbraco-cms/backoffice/external/lit"; +import { UmbLitElement } from "@umbraco-cms/backoffice/lit-element"; + +@customElement('umb-custom-view-test') +export class UmbCustomViewTestElement extends UmbLitElement implements UmbBlockEditorCustomViewElement { + + @property({attribute: false}) + content?: UmbBlockDataType; + + protected override render() { + return html` + Hello ${this.content?.headline} + ` + } +} + +export {UmbCustomViewTestElement as element}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts new file mode 100644 index 0000000000..44e6dfbe54 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts @@ -0,0 +1,10 @@ +import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifest:ManifestBlockEditorCustomView = { + type: 'blockEditorCustomView', + alias: 'Umb.blockEditorCustomView.TestView', + name: 'Block Editor Custom View Test', + element: () => import('./custom-view.element.js'), + //forContentTypeAlias: [] + //forBlockType?: Array; +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts index 80e1e2bf86..6655135552 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts @@ -1,11 +1,13 @@ +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; import { manifests as blockManifests } from './block/manifests.js'; import { manifests as blockGridManifests } from './block-grid/manifests.js'; import { manifests as blockListManifests } from './block-list/manifests.js'; import { manifests as blockRteManifests } from './block-rte/manifests.js'; import { manifests as blockTypeManifests } from './block-type/manifests.js'; -import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; +import { manifest } from './custom-view/manifest.js'; export const manifests: Array = [ + manifest, ...blockManifests, ...blockTypeManifests, ...blockListManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts new file mode 100644 index 0000000000..cf4f0b8d4b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts @@ -0,0 +1,43 @@ +import type { ManifestBlockEditorCustomView } from "../index.js"; + +// Shared with the Property Editor +export interface UmbBlockLayoutBaseModel { + contentUdi: string; + settingsUdi?: string | null; +} + +// Shared with the Property Editor +export interface UmbBlockDataType { + udi: string; + contentTypeKey: string; + [key: string]: unknown; +} + +export interface UmbBlockEditorCustomViewConfiguration { + editContentPath: string; + editSettingsPath: string; + showEditBlock: boolean; +} + +export interface UmbBlockViewUrlsPropType { + editContent?: string; + editSettings?: string; +} + + +export interface UmbBlockEditorCustomViewProperties { + manifest?: ManifestBlockEditorCustomView; + config?: UmbBlockEditorCustomViewConfiguration; + urls?: UmbBlockViewUrlsPropType; + contentUdi?: string; + label?: string; + icon?: string; + index?: number; + layout?: LayoutType; + content?: UmbBlockDataType; + settings?: UmbBlockDataType; +} + +export interface UmbBlockEditorCustomViewElement extends UmbBlockEditorCustomViewProperties, HTMLElement { + +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/index.ts index 1721b7dfec..7585b5001b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/index.ts @@ -1,3 +1,4 @@ +export * from './block-editor-custom-view-element.interface.js'; export * from './dashboard-element.interface.js'; export * from './external-login-provider-element.interface.js'; export * from './menu-item-element.interface.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts index 002d6f0ecf..7ceea8278f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts @@ -1,6 +1,8 @@ -import type { UmbPropertyEditorUiElement } from '../interfaces/index.js'; import type { ManifestElement } from '@umbraco-cms/backoffice/extension-api'; +import type { UmbBlockEditorCustomViewElement } from '../interfaces/index.js'; -export interface ManifestBlockEditorCustomView extends ManifestElement { +export interface ManifestBlockEditorCustomView extends ManifestElement { type: 'blockEditorCustomView'; + forContentTypeAlias?: Array; + forBlockType?: Array; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts index a24470e952..54685e8106 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/entity-action.model.ts @@ -1,6 +1,6 @@ +import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; import type { ConditionTypes } from '../conditions/types.js'; import type { UmbEntityAction, UmbEntityActionElement } from '@umbraco-cms/backoffice/entity-action'; -import type { ManifestElementAndApi, ManifestWithDynamicConditions } from '@umbraco-cms/backoffice/extension-api'; import type { UmbModalToken, UmbPickerModalData, UmbPickerModalValue } from '@umbraco-cms/backoffice/modal'; /** From c7310c358a3ce02fffdbc0dac7aad467b4c3c5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Fri, 28 Jun 2024 22:39:16 +0200 Subject: [PATCH 024/325] extension slot fine tuning --- .../base-extensions-initializer.controller.ts | 19 ++++++++++++------- .../extension-slot/extension-slot.element.ts | 10 +++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts index c55c77bb36..5dd5f08506 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts @@ -1,5 +1,4 @@ import type { SpecificManifestTypeOrManifestBase } from '../types/map.types.js'; -import { map } from '@umbraco-cms/backoffice/external/rxjs'; import type { ManifestBase, UmbBaseExtensionInitializer, @@ -7,7 +6,6 @@ import type { } from '@umbraco-cms/backoffice/extension-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { createObservablePart } from '@umbraco-cms/backoffice/observable-api'; export type PermittedControllerType = ControllerType & { manifest: Required>; @@ -35,7 +33,7 @@ export abstract class UmbBaseExtensionsInitializer< #onChange?: (permittedManifests: Array) => void; protected _extensions: Array = []; #permittedExts: Array = []; - #exposedPermittedExts: Array = []; + #exposedPermittedExts?: Array; #changeDebounce?: number; asPromise(): Promise { @@ -92,6 +90,12 @@ export abstract class UmbBaseExtensionsInitializer< return; } + // If we get no manifests and we have not exposed any extensions yet, then we should notify to let the listener know that we have our first response. [NL] + if(manifests.length === 0 && this.#exposedPermittedExts === undefined) { + this.#exposedPermittedExts = []; + this.#onChange?.(this.#exposedPermittedExts); + } + // Clean up extensions that are no longer. this._extensions = this._extensions.filter((extension) => { if (!manifests.find((manifest) => manifest.alias === extension.alias)) { @@ -116,6 +120,7 @@ export abstract class UmbBaseExtensionsInitializer< protected _extensionChanged = (isPermitted: boolean, controller: ControllerType) => { let hasChanged = false; + // This might be called after this is destroyed, so we need to check if the _permittedExts is still available: const existingIndex = this.#permittedExts?.indexOf(controller as unknown as MyPermittedControllerType); if (isPermitted) { @@ -151,7 +156,7 @@ export abstract class UmbBaseExtensionsInitializer< // if so, look up the extension it overwrites, and remove it from the list. and check that for if it overwrites another extension and so on. if (extCtrl.overwrites.length > 0) { extCtrl.overwrites.forEach((overwrite) => { - this.#removeOverwrittenExtensions(this.#exposedPermittedExts, overwrite); + this.#removeOverwrittenExtensions(this.#exposedPermittedExts!, overwrite); }); } }); @@ -195,16 +200,16 @@ export abstract class UmbBaseExtensionsInitializer< // The this.#extensionRegistry is an indication of wether this is already destroyed. if (!this.#extensionRegistry) return; - const oldPermittedExtsLength = this.#exposedPermittedExts.length; + const oldPermittedExtsLength = this.#exposedPermittedExts?.length ?? 0; (this._extensions as any) = undefined; (this.#permittedExts as any) = undefined; - this.#exposedPermittedExts.length = 0; + this.#exposedPermittedExts = undefined; if (this.#changeDebounce) { cancelAnimationFrame(this.#changeDebounce); this.#changeDebounce = undefined; } if (oldPermittedExtsLength > 0) { - this.#onChange?.(this.#exposedPermittedExts); + this.#onChange?.([]); } this.#promiseResolvers.length = 0; this.#filter = undefined; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts index b5e64b5d8b..2650f5f78d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts @@ -1,11 +1,11 @@ -import { umbExtensionsRegistry } from '../../registry.js'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; import { css, repeat, customElement, property, state, html } from '@umbraco-cms/backoffice/external/lit'; import { type UmbExtensionElementInitializer, UmbExtensionsElementInitializer, } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry } from '../../registry.js'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; /** * @element umb-extension-slot @@ -24,7 +24,7 @@ export class UmbExtensionSlotElement extends UmbLitElement { #extensionsController?: UmbExtensionsElementInitializer; @state() - private _permitted: Array = []; + private _permitted?: Array; /** * The type or types of extensions to render. @@ -129,13 +129,13 @@ export class UmbExtensionSlotElement extends UmbLitElement { } override render() { - return this._permitted.length > 0 + return this._permitted ? this._permitted.length > 0 ? repeat( this._permitted, (ext) => ext.alias, (ext, i) => (this.renderMethod ? this.renderMethod(ext, i) : ext.component), ) - : html``; + : html`` : ''; } static override styles = css` From 3c1a9eef0dc0b6941d254e01fdd7ebe327ca1bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 1 Jul 2024 09:46:42 +0200 Subject: [PATCH 025/325] Block Editor Custom View specific conditionals --- .../block-grid-entry.element.ts | 53 ++++++------ .../src/packages/block/block-grid/types.ts | 1 + .../block-list-entry.element.ts | 85 +++++++++++++------ .../src/packages/block/block-list/types.ts | 1 + .../packages/block/custom-view/manifest.ts | 4 +- .../models/block-editor-custom-view.model.ts | 16 +++- .../src/packages/core/utils/index.ts | 1 + ...tring-or-string-array-contains.function.ts | 3 + 8 files changed, 108 insertions(+), 56 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/string/string-or-string-array-contains.function.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 76be03cd46..32ed7dc718 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -2,12 +2,13 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js'; -import type { UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; +import { UMB_BLOCK_GRID, type UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; + import '../block-grid-block-inline/index.js'; import '../block-grid-block/index.js'; import '../block-scale-handler/index.js'; - /** * @element umb-block-grid-entry */ @@ -84,7 +85,6 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper @state() _inlineCreateAboveWidth?: string; - // TODO: use this type on the Element Interface for the Manifest. @state() _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. @@ -99,55 +99,55 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper // Misc: this.observe(this.#context.showContentEdit, (show) => { this._showContentEdit = show; - }); + }, null); this.observe(this.#context.settingsElementTypeKey, (key) => { this._hasSettings = !!key; - }); + }, null); this.observe(this.#context.canScale, (canScale) => { this._canScale = canScale; - }); + }, null); this.observe(this.#context.label, (label) => { this.#updateBlockViewProps({ label }); this._label = label; - }); + }, null); this.observe(this.#context.contentElementTypeIcon, (icon) => { this.#updateBlockViewProps({ icon }); this._icon = icon; - }); + }, null); this.observe(this.#context.inlineEditingMode, (mode) => { this._inlineEditingMode = mode; - }); + }, null); // Data: this.observe(this.#context.layout, (layout) => { this.#updateBlockViewProps({ layout }); - }); + }, null); this.observe(this.#context.content, (content) => { this.#updateBlockViewProps({ content }); - }); + }, null); this.observe(this.#context.settings, (settings) => { this.#updateBlockViewProps({ settings }); - }); + }, null); // Paths: this.observe(this.#context.createBeforePath, (createPath) => { //const oldValue = this._createBeforePath; this._createBeforePath = createPath; //this.requestUpdate('_createPath', oldValue); - }); + }, null); this.observe(this.#context.createAfterPath, (createPath) => { //const oldValue = this._createAfterPath; this._createAfterPath = createPath; //this.requestUpdate('_createPath', oldValue); - }); + }, null); this.observe(this.#context.workspaceEditContentPath, (path) => { this._workspaceEditContentPath = path; this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editContent: path } }); - }); + }, null); this.observe(this.#context.workspaceEditSettingsPath, (path) => { this._workspaceEditSettingsPath = path; this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editSettings: path } }); - }); + }, null); } override connectedCallback(): void { @@ -175,13 +175,13 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper if (contentElementTypeKey) { this.setAttribute('data-content-element-type-key', contentElementTypeKey); } - }); + }, 'contentElementTypeKey'); this.observe(this.#context.contentElementTypeAlias, (contentElementTypeAlias) => { if (contentElementTypeAlias) { this._contentTypeAlias = contentElementTypeAlias; this.setAttribute('data-content-element-type-alias', contentElementTypeAlias); } - }); + }, 'contentElementTypeAlias'); this.#callUpdateInlineCreateButtons(); } @@ -228,6 +228,16 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper } }; + #extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => { + if(manifest.forContentTypeAlias && !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!)) { + return false; + } + if(manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_GRID)) { + return false; + } + return true; + } + #renderInlineEditBlock() { return html``; } - #extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => { - if(manifest.forContentTypeAlias?.indexOf(this._contentTypeAlias!) === -1) { - return false; - } - return true; - } - #renderBlock() { return this.contentUdi && this._contentTypeAlias ? html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts index 7925df893a..392c67f0f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/types.ts @@ -2,6 +2,7 @@ import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/ba import type { UmbBlockTypeWithGroupKey } from '@umbraco-cms/backoffice/block-type'; export const UMB_BLOCK_GRID_TYPE = 'block-grid-type'; +export const UMB_BLOCK_GRID = 'block-grid'; // Configuration models: export interface UmbBlockGridTypeModel extends UmbBlockTypeWithGroupKey { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index e7bc5a771f..02feff3482 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -1,11 +1,11 @@ -import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import '../ref-list-block/index.js'; import '../inline-list-block/index.js'; -import type { UmbBlockViewPropsType } from '@umbraco-cms/backoffice/block'; -import type { UmbBlockListLayoutModel } from '@umbraco-cms/backoffice/block-list'; +import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; +import { UmbBlockListEntryContext } from '../../context/block-list-entry.context.js'; +import { UMB_BLOCK_LIST, type UmbBlockListLayoutModel } from '../../types.js'; /** * @element umb-block-list-entry @@ -34,6 +34,9 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper #context = new UmbBlockListEntryContext(this); + @state() + _contentTypeAlias?:string; + @state() _showContentEdit = false; @state() @@ -54,52 +57,79 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper @state() _inlineEditingMode?: boolean; - // TODO: use this type on the Element Interface for the Manifest. @state() - _blockViewProps: UmbBlockViewPropsType = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. + + #updateBlockViewProps(incoming: Partial>) { + this._blockViewProps = { ...this._blockViewProps, ...incoming }; + this.requestUpdate('_blockViewProps'); + } constructor() { super(); this.observe(this.#context.showContentEdit, (showContentEdit) => { this._showContentEdit = showContentEdit; - }); + }, null); this.observe(this.#context.settingsElementTypeKey, (settingsElementTypeKey) => { this._hasSettings = !!settingsElementTypeKey; - }); + }, null); this.observe(this.#context.label, (label) => { + this.#updateBlockViewProps({ label }); this._label = label; - this._blockViewProps.label = label; - this.requestUpdate('_blockViewProps'); - }); + }, null); this.observe(this.#context.contentElementTypeIcon, (icon) => { + this.#updateBlockViewProps({ icon }); this._icon = icon; - this._blockViewProps.icon = icon; - this.requestUpdate('_blockViewProps'); - }); + }, null); this.observe(this.#context.inlineEditingMode, (inlineEditingMode) => { this._inlineEditingMode = inlineEditingMode; - }); + }, null); // Data props: this.observe(this.#context.layout, (layout) => { - this._blockViewProps.layout = layout; - }); + this.#updateBlockViewProps({ layout }); + }, null); this.observe(this.#context.content, (content) => { - this._blockViewProps.content = content; - }); + this.#updateBlockViewProps({ content }); + }, null); this.observe(this.#context.settings, (settings) => { - this._blockViewProps.settings = settings; - }); + this.#updateBlockViewProps({ settings }); + }, null); this.observe(this.#context.workspaceEditContentPath, (path) => { this._workspaceEditContentPath = path; - this._blockViewProps.urls.editContent = path; - this.requestUpdate('_blockViewProps'); - }); + this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editContent: path } }); + }, null); this.observe(this.#context.workspaceEditSettingsPath, (path) => { this._workspaceEditSettingsPath = path; - this._blockViewProps.urls.editSettings = path; - this.requestUpdate('_blockViewProps'); - }); + this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editSettings: path } }); + }, null); + } + + + override connectedCallback(): void { + super.connectedCallback(); + // element styling: + this.observe(this.#context.contentElementTypeKey, (contentElementTypeKey) => { + if (contentElementTypeKey) { + this.setAttribute('data-content-element-type-key', contentElementTypeKey); + } + }, 'contentElementTypeKey'); + this.observe(this.#context.contentElementTypeAlias, (contentElementTypeAlias) => { + if (contentElementTypeAlias) { + this._contentTypeAlias = contentElementTypeAlias; + this.setAttribute('data-content-element-type-alias', contentElementTypeAlias); + } + }, 'contentElementTypeAlias'); + } + + #extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => { + if(manifest.forContentTypeAlias && !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!)) { + return false; + } + if(manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_LIST)) { + return false; + } + return true; } #renderRefBlock() { @@ -116,6 +146,7 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper type="blockEditorCustomView" default-element=${this._inlineEditingMode ? 'umb-inline-list-block' : 'umb-ref-list-block'} .props=${this._blockViewProps} + .filter=${this.#extensionSlotFilterMethod} >${this._inlineEditingMode ? this.#renderInlineBlock() : this.#renderRefBlock()} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts index dc5894a548..a85c2635df 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts @@ -2,6 +2,7 @@ import type { UmbBlockTypeBaseModel } from '../block-type/index.js'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; +export const UMB_BLOCK_LIST = 'block-list'; export interface UmbBlockListTypeModel extends UmbBlockTypeBaseModel {} export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts index 44e6dfbe54..69b00c5af3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts @@ -5,6 +5,6 @@ export const manifest:ManifestBlockEditorCustomView = { alias: 'Umb.blockEditorCustomView.TestView', name: 'Block Editor Custom View Test', element: () => import('./custom-view.element.js'), - //forContentTypeAlias: [] - //forBlockType?: Array; + forContentTypeAlias: 'elementTypeHeadline', + forBlockEditor: 'block-grid' } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts index 7ceea8278f..72e0216a71 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/models/block-editor-custom-view.model.ts @@ -3,6 +3,18 @@ import type { UmbBlockEditorCustomViewElement } from '../interfaces/index.js'; export interface ManifestBlockEditorCustomView extends ManifestElement { type: 'blockEditorCustomView'; - forContentTypeAlias?: Array; - forBlockType?: Array; + /** + * @property {string | Array } - Declare if this Custom View only must appear at specific Content Types by Alias. + * @description Optional condition if you like this custom view to only appear at for one or more specific Content Types. + * @example 'my-element-type-alias' + * @example ['my-element-type-alias-A', 'my-element-type-alias-B'] + */ + forContentTypeAlias?: string | Array; + /** + * @property {string | Array } - Declare if this Custom View only must appear at specific Block Editors. + * @description Optional condition if you like this custom view to only appear at a specific type of Block Editor. + * @example 'block-list' + * @example ['block-list', 'block-grid'] + */ + forBlockEditor?: string | Array; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts index f7ec7dd723..a7e6fb6913 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/index.ts @@ -19,5 +19,6 @@ export * from './string/from-camel-case.function.js'; export * from './string/generate-umbraco-alias.function.js'; export * from './string/increment-string.function.js'; export * from './string/split-string-to-array.js'; +export * from './string/string-or-string-array-contains.function.js'; export * from './string/to-camel-case/to-camel-case.function.js'; export type * from './type/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/string/string-or-string-array-contains.function.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/string/string-or-string-array-contains.function.ts new file mode 100644 index 0000000000..54f8dc419f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/string/string-or-string-array-contains.function.ts @@ -0,0 +1,3 @@ +export function stringOrStringArrayContains(value: string | Array, search: string) { + return Array.isArray(value) ? value.indexOf(search) !== -1 : value === search; +} From b199425af372eabb56492231608e500cff8564ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 1 Jul 2024 10:16:20 +0200 Subject: [PATCH 026/325] implement all custom view props --- .../block-grid-block-inline.element.ts | 10 ++-- .../block-grid-entry.element.ts | 16 ++++-- .../block-list-entry.element.ts | 16 ++++-- .../property-editor-ui-block-list.element.ts | 15 +++-- ...i-block-list-type-configuration.element.ts | 6 +- .../src/packages/block/block-list/types.ts | 2 +- .../block-rte-entry.element.ts | 57 ++++++++++--------- .../tiny-mce-block-picker.plugin.ts | 6 +- .../src/packages/block/block-rte/types.ts | 2 +- .../input-block-type.element.ts | 3 +- .../src/packages/block/block-type/types.ts | 15 +---- .../workspace/block-type-workspace.context.ts | 6 +- .../context/block-entries.context-token.ts | 4 +- .../block/context/block-entries.context.ts | 10 ++-- .../context/block-entry.context-token.ts | 4 +- .../block/context/block-entry.context.ts | 8 +-- .../block/context/block-manager.context.ts | 8 +-- .../block-catalogue-modal.token.ts | 5 +- ...ck-editor-custom-view-element.interface.ts | 28 ++++++--- ...ui-block-rte-type-configuration.element.ts | 3 +- 20 files changed, 121 insertions(+), 103 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts index 81cb697ccc..6f4ea8de6b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block-inline/block-grid-block-inline.element.ts @@ -1,9 +1,9 @@ -import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; -import { UmbBlockGridInlinePropertyDatasetContext } from './block-grid-inline-property-dataset.context.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; -import type { UmbBlockViewUrlsPropType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; +import { UmbBlockGridInlinePropertyDatasetContext } from './block-grid-inline-property-dataset.context.js'; import '../block-grid-areas-container/index.js'; import '../ref-grid-block/index.js'; @@ -17,7 +17,7 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { label?: string; @property({ attribute: false }) - urls?: UmbBlockViewUrlsPropType; + config?: UmbBlockEditorCustomViewConfiguration; @state() _inlineProperty: UmbPropertyTypeModel | undefined; @@ -39,7 +39,7 @@ export class UmbBlockGridBlockInlineElement extends UmbLitElement { } override render() { - return html` + return html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 32ed7dc718..4e1c140bdb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -86,7 +86,7 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper _inlineCreateAboveWidth?: string; @state() - _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, config: { showContentEdit: false, showSettingsEdit: false} }; // Set to undefined cause it will be set before we render. #updateBlockViewProps(incoming: Partial>) { this._blockViewProps = { ...this._blockViewProps, ...incoming }; @@ -97,15 +97,21 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper super(); // Misc: - this.observe(this.#context.showContentEdit, (show) => { - this._showContentEdit = show; + this.observe(this.#context.showContentEdit, (showContentEdit) => { + this._showContentEdit = showContentEdit; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showContentEdit } }); }, null); this.observe(this.#context.settingsElementTypeKey, (key) => { this._hasSettings = !!key; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); }, null); this.observe(this.#context.canScale, (canScale) => { this._canScale = canScale; }, null); + this.observe(this.#context.blockType, (blockType) => { + this.#updateBlockViewProps({ blockType }); + }, null); + // TODO: Implement index. this.observe(this.#context.label, (label) => { this.#updateBlockViewProps({ label }); this._label = label; @@ -142,11 +148,11 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper }, null); this.observe(this.#context.workspaceEditContentPath, (path) => { this._workspaceEditContentPath = path; - this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editContent: path } }); + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); }, null); this.observe(this.#context.workspaceEditSettingsPath, (path) => { this._workspaceEditSettingsPath = path; - this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editSettings: path } }); + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); }, null); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts index 02feff3482..ce20034f35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/components/block-list-entry/block-list-entry.element.ts @@ -58,7 +58,7 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper _inlineEditingMode?: boolean; @state() - _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, config: { showContentEdit: false, showSettingsEdit: false} }; // Set to undefined cause it will be set before we render. #updateBlockViewProps(incoming: Partial>) { this._blockViewProps = { ...this._blockViewProps, ...incoming }; @@ -70,10 +70,16 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper this.observe(this.#context.showContentEdit, (showContentEdit) => { this._showContentEdit = showContentEdit; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showContentEdit } }); }, null); - this.observe(this.#context.settingsElementTypeKey, (settingsElementTypeKey) => { - this._hasSettings = !!settingsElementTypeKey; + this.observe(this.#context.settingsElementTypeKey, (key) => { + this._hasSettings = !!key; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); }, null); + this.observe(this.#context.blockType, (blockType) => { + this.#updateBlockViewProps({ blockType }); + }, null); + // TODO: Implement index. this.observe(this.#context.label, (label) => { this.#updateBlockViewProps({ label }); this._label = label; @@ -97,11 +103,11 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper }, null); this.observe(this.#context.workspaceEditContentPath, (path) => { this._workspaceEditContentPath = path; - this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editContent: path } }); + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); }, null); this.observe(this.#context.workspaceEditSettingsPath, (path) => { this._workspaceEditSettingsPath = path; - this.#updateBlockViewProps({ urls: { ...this._blockViewProps.urls, editSettings: path } }); + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); }, null); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index b3828ddd78..c9b1a35958 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -1,22 +1,21 @@ -import { UmbBlockListManagerContext } from '../../context/block-list-manager.context.js'; -import type { UmbBlockListEntryElement } from '../../components/block-list-entry/index.js'; -import type { UmbBlockListLayoutModel, UmbBlockListValueModel } from '../../types.js'; -import { UmbBlockListEntriesContext } from '../../context/block-list-entries.context.js'; -import { UMB_BLOCK_LIST_PROPERTY_EDITOR_ALIAS } from './manifests.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, customElement, property, state, repeat, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement , UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import { UmbPropertyValueChangeEvent, type UmbPropertyEditorConfigCollection, } from '@umbraco-cms/backoffice/property-editor'; -import type { UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/block'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import type { UmbNumberRangeValueType } from '@umbraco-cms/backoffice/models'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; +import { UmbBlockListEntriesContext } from '../../context/block-list-entries.context.js'; +import type { UmbBlockListLayoutModel, UmbBlockListValueModel } from '../../types.js'; +import type { UmbBlockListEntryElement } from '../../components/block-list-entry/index.js'; +import { UmbBlockListManagerContext } from '../../context/block-list-manager.context.js'; +import { UMB_BLOCK_LIST_PROPERTY_EDITOR_ALIAS } from './manifests.js'; +import type { UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/block'; import '../../components/block-list-entry/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts index ef1f279157..8a9bb9ed2c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.element.ts @@ -1,7 +1,5 @@ -import type { UmbBlockTypeBaseModel, UmbInputBlockTypeElement } from '../../../block-type/index.js'; import '../../../block-type/components/input-block-type/index.js'; -import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, @@ -10,6 +8,8 @@ import { import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_WORKSPACE_MODAL } from '@umbraco-cms/backoffice/modal'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; +import type { UmbInputBlockTypeElement } from '../../../block-type/index.js'; +import { UMB_BLOCK_LIST_TYPE } from '../../types.js'; /** * @element umb-property-editor-ui-block-list-type-configuration diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts index a85c2635df..4b58ab2ec2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/types.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeBaseModel } from '../block-type/index.js'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; export const UMB_BLOCK_LIST_TYPE = 'block-list-type'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 9637862929..396b96de89 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -1,10 +1,9 @@ -import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; -import type { UmbBlockRteLayoutModel } from '../../types.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockRteLayoutModel } from '../../types.js'; +import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; import '../ref-rte-block/index.js'; -import type { UmbBlockViewPropsType } from '@umbraco-cms/backoffice/block'; /** * @element umb-rte-block @@ -43,9 +42,13 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert @state() _workspaceEditSettingsPath?: string; - // TODO: use this type on the Element Interface for the Manifest. @state() - _blockViewProps: UmbBlockViewPropsType = { contentUdi: undefined!, urls: {} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, config: { showContentEdit: false, showSettingsEdit: false} }; // Set to undefined cause it will be set before we render. + + #updateBlockViewProps(incoming: Partial>) { + this._blockViewProps = { ...this._blockViewProps, ...incoming }; + this.requestUpdate('_blockViewProps'); + } constructor() { super(); @@ -55,40 +58,42 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert this.observe(this.#context.showContentEdit, (showContentEdit) => { this._showContentEdit = showContentEdit; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showContentEdit } }); }); - this.observe(this.#context.settingsElementTypeKey, (settingsElementTypeKey) => { - this._hasSettings = !!settingsElementTypeKey; + this.observe(this.#context.settingsElementTypeKey, (key) => { + this._hasSettings = !!key; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); }); + this.observe(this.#context.blockType, (blockType) => { + this.#updateBlockViewProps({ blockType }); + }, null); + // TODO: Implement index. this.observe(this.#context.label, (label) => { + this.#updateBlockViewProps({ label }); this._label = label; - this._blockViewProps.label = label; - this.requestUpdate('_blockViewProps'); - }); + }, null); this.observe(this.#context.contentElementTypeIcon, (icon) => { + this.#updateBlockViewProps({ icon }); this._icon = icon; - this._blockViewProps.icon = icon; - this.requestUpdate('_blockViewProps'); - }); + }, null); // Data props: this.observe(this.#context.layout, (layout) => { - this._blockViewProps.layout = layout; - }); + this.#updateBlockViewProps({ layout }); + }, null); this.observe(this.#context.content, (content) => { - this._blockViewProps.content = content; - }); + this.#updateBlockViewProps({ content }); + }, null); this.observe(this.#context.settings, (settings) => { - this._blockViewProps.settings = settings; - }); + this.#updateBlockViewProps({ settings }); + }, null); this.observe(this.#context.workspaceEditContentPath, (path) => { this._workspaceEditContentPath = path; - this._blockViewProps.urls.editContent = path; - this.requestUpdate('_blockViewProps'); - }); + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); + }, null); this.observe(this.#context.workspaceEditSettingsPath, (path) => { this._workspaceEditSettingsPath = path; - this._blockViewProps.urls.editSettings = path; - this.requestUpdate('_blockViewProps'); - }); + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); + }, null); } override connectedCallback() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts index fd7e3dc831..a924cf9d30 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/tiny-mce-plugin/tiny-mce-block-picker.plugin.ts @@ -1,8 +1,8 @@ -import { UMB_BLOCK_RTE_ENTRIES_CONTEXT } from '../context/block-rte-entries.context-token.js'; -import { UMB_BLOCK_RTE_MANAGER_CONTEXT } from '../context/block-rte-manager.context-token.js'; import { type TinyMcePluginArguments, UmbTinyMcePluginBase } from '@umbraco-cms/backoffice/tiny-mce'; import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_BLOCK_RTE_MANAGER_CONTEXT } from '../context/block-rte-manager.context-token.js'; +import { UMB_BLOCK_RTE_ENTRIES_CONTEXT } from '../context/block-rte-entries.context-token.js'; export default class UmbTinyMceMultiUrlPickerPlugin extends UmbTinyMcePluginBase { #localize = new UmbLocalizationController(this._host); diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts index 45404b976e..b5cedd32da 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/types.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeBaseModel } from '../block-type/index.js'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbBlockLayoutBaseModel, UmbBlockValueType } from '@umbraco-cms/backoffice/block'; export const UMB_BLOCK_RTE_TYPE = 'block-rte-type'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 1b587f214a..367a98fa70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -10,7 +10,8 @@ import { UMB_DOCUMENT_TYPE_PICKER_MODAL, } from '@umbraco-cms/backoffice/document-type'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; -import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../../types.js'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeWithGroupKey } from '../../types.js'; import type { UmbBlockTypeCardElement } from '../block-type-card/index.js'; import '../block-type-card/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts index 06bb9dce3c..aa5f55f519 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts @@ -1,17 +1,4 @@ -import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; - -export interface UmbBlockTypeBaseModel { - contentElementTypeKey: string; - settingsElementTypeKey?: string; - label?: string; - //view?: string; // TODO: remove/replace with custom element manifest type for block list. - //stylesheet?: string; // TODO: remove/replace with custom element manifest type for block list. - thumbnail?: string; - iconColor?: string; - backgroundColor?: string; - editorSize?: UUIModalSidebarSize; - forceHideContentEditorInOverlay: boolean; -} +import type { UmbBlockTypeBaseModel } from "@umbraco-cms/backoffice/extension-registry"; export interface UmbBlockTypeGroup { name?: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts index 667af0cdd1..0086312690 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts @@ -1,5 +1,3 @@ -import type { UmbBlockTypeBaseModel, UmbBlockTypeWithGroupKey } from '../types.js'; -import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-editor.element.js'; import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { @@ -13,7 +11,9 @@ import { } from '@umbraco-cms/backoffice/workspace'; import { UmbArrayState, UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { ManifestWorkspace, PropertyEditorSettingsProperty } from '@umbraco-cms/backoffice/extension-registry'; +import type { ManifestWorkspace, PropertyEditorSettingsProperty, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeWithGroupKey } from '../types.js'; +import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-editor.element.js'; export class UmbBlockTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context-token.ts index 5e8190151a..e9dbb55dc3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context-token.ts @@ -1,8 +1,8 @@ +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbBlockLayoutBaseModel } from '../types.js'; import type { UmbBlockEntriesContext } from './block-entries.context.js'; import type { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export const UMB_BLOCK_ENTRIES_CONTEXT = new UmbContextToken< UmbBlockEntriesContext< diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts index c16929d7b3..64cc09198e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entries.context.ts @@ -1,13 +1,13 @@ -import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '../types.js'; -import type { UmbBlockWorkspaceData } from '../workspace/block-workspace.modal-token.js'; -import { UMB_BLOCK_ENTRIES_CONTEXT } from './block-entries.context-token.js'; -import type { UmbBlockDataObjectModel, UmbBlockManagerContext } from './block-manager.context.js'; import { type Observable, UmbArrayState, UmbBasicState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbModalRouteBuilder } from '@umbraco-cms/backoffice/router'; +import type { UmbBlockWorkspaceData } from '../workspace/block-workspace.modal-token.js'; +import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '../types.js'; +import type { UmbBlockDataObjectModel, UmbBlockManagerContext } from './block-manager.context.js'; +import { UMB_BLOCK_ENTRIES_CONTEXT } from './block-entries.context-token.js'; export abstract class UmbBlockEntriesContext< BlockManagerContextTokenType extends UmbContextToken, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context-token.ts index adb50d369e..1d43662591 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context-token.ts @@ -1,10 +1,10 @@ +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbBlockLayoutBaseModel } from '../types.js'; import type { UMB_BLOCK_ENTRIES_CONTEXT } from './block-entries.context-token.js'; import type { UmbBlockEntriesContext } from './block-entries.context.js'; import type { UmbBlockEntryContext } from './block-entry.context.js'; import type { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; -import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; export const UMB_BLOCK_ENTRY_CONTEXT = new UmbContextToken< UmbBlockEntryContext< diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts index f2d136a648..240aff932a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-entry.context.ts @@ -1,7 +1,3 @@ -import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '../types.js'; -import type { UmbBlockManagerContext } from '../index.js'; -import type { UmbBlockEntriesContext } from './block-entries.context.js'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import type { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; @@ -16,6 +12,10 @@ import { encodeFilePath } from '@umbraco-cms/backoffice/utils'; import { umbConfirmModal } from '@umbraco-cms/backoffice/modal'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import type { Observable } from '@umbraco-cms/backoffice/external/rxjs'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockManagerContext } from '../index.js'; +import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '../types.js'; +import type { UmbBlockEntriesContext } from './block-entries.context.js'; export abstract class UmbBlockEntryContext< BlockManagerContextTokenType extends UmbContextToken, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts index fa4b2d7fb2..f729de6742 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts @@ -1,16 +1,16 @@ -import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '../types.js'; -import type { UmbBlockWorkspaceData } from '../workspace/index.js'; -import { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; import { UmbContextBase } from '@umbraco-cms/backoffice/class-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState, UmbClassState, UmbStringState } from '@umbraco-cms/backoffice/observable-api'; import { UmbDocumentTypeDetailRepository } from '@umbraco-cms/backoffice/document-type'; -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; import { UmbId } from '@umbraco-cms/backoffice/id'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; +import type { UmbBlockWorkspaceData } from '../workspace/index.js'; +import type { UmbBlockLayoutBaseModel, UmbBlockDataType } from '../types.js'; +import { UMB_BLOCK_MANAGER_CONTEXT } from './block-manager.context-token.js'; function buildUdi(entityType: string, guid: string) { return `umb://${entityType}/${guid.replace(/-/g, '')}`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts index 0558d7d8ff..db261ccc3d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts @@ -1,6 +1,7 @@ -import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; -import type { UmbBlockTypeBaseModel, UmbBlockTypeGroup } from '@umbraco-cms/backoffice/block-type'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; +import type { UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeGroup } from '@umbraco-cms/backoffice/block-type'; export interface UmbBlockCatalogueModalData { blocks: Array; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts index cf4f0b8d4b..ae380233e2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts @@ -1,4 +1,17 @@ + +import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; import type { ManifestBlockEditorCustomView } from "../index.js"; +// Shared with the Property Editor +export interface UmbBlockTypeBaseModel { + contentElementTypeKey: string; + settingsElementTypeKey?: string; + label?: string; + thumbnail?: string; + iconColor?: string; + backgroundColor?: string; + editorSize?: UUIModalSidebarSize; + forceHideContentEditorInOverlay: boolean; +} // Shared with the Property Editor export interface UmbBlockLayoutBaseModel { @@ -14,9 +27,10 @@ export interface UmbBlockDataType { } export interface UmbBlockEditorCustomViewConfiguration { - editContentPath: string; - editSettingsPath: string; - showEditBlock: boolean; + editContentPath?: string; + editSettingsPath?: string; + showContentEdit: boolean; + showSettingsEdit: boolean; } export interface UmbBlockViewUrlsPropType { @@ -25,10 +39,10 @@ export interface UmbBlockViewUrlsPropType { } -export interface UmbBlockEditorCustomViewProperties { +export interface UmbBlockEditorCustomViewProperties { manifest?: ManifestBlockEditorCustomView; - config?: UmbBlockEditorCustomViewConfiguration; - urls?: UmbBlockViewUrlsPropType; + config?: Partial; + blockType?: BlockType; contentUdi?: string; label?: string; icon?: string; @@ -38,6 +52,6 @@ export interface UmbBlockEditorCustomViewProperties extends UmbBlockEditorCustomViewProperties, HTMLElement { +export interface UmbBlockEditorCustomViewElement extends UmbBlockEditorCustomViewProperties, HTMLElement { } diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block-configuration/property-editor-ui-block-rte-type-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block-configuration/property-editor-ui-block-rte-type-configuration.element.ts index 0547db8671..2b59427770 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block-configuration/property-editor-ui-block-rte-type-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/property-editors/block-configuration/property-editor-ui-block-rte-type-configuration.element.ts @@ -1,7 +1,6 @@ -import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/block-type'; import { UmbInputBlockTypeElement } from '@umbraco-cms/backoffice/block-type'; import { UMB_BLOCK_RTE_TYPE } from '@umbraco-cms/backoffice/block-rte'; -import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbBlockTypeBaseModel, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbPropertyValueChangeEvent, From 0e3c870df8cf72af8223b3cf091e8ee2d4b2d280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 1 Jul 2024 10:24:00 +0200 Subject: [PATCH 027/325] remove UmbBlockViewUrlsPropType --- .../block-grid-block/block-grid-block.element.ts | 7 ++++--- .../src/packages/block/block/types.ts | 2 +- .../block-editor-custom-view-element.interface.ts | 5 ----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts index 3069fc1050..6b6629d8d0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-block/block-grid-block.element.ts @@ -1,7 +1,8 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; +import type { UmbBlockEditorCustomViewConfiguration } from '@umbraco-cms/backoffice/extension-registry'; import { UMB_BLOCK_GRID_ENTRY_CONTEXT } from '../../context/block-grid-entry.context-token.js'; -import type { UmbBlockDataType, UmbBlockViewUrlsPropType } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockDataType } from '@umbraco-cms/backoffice/block'; import '@umbraco-cms/backoffice/ufm'; import '../block-grid-areas-container/index.js'; @@ -17,7 +18,7 @@ export class UmbBlockGridBlockElement extends UmbLitElement { label?: string; @property({ attribute: false }) - urls?: UmbBlockViewUrlsPropType; + config?: UmbBlockEditorCustomViewConfiguration; @state() _content?: UmbBlockDataType; @@ -37,7 +38,7 @@ export class UmbBlockGridBlockElement extends UmbLitElement { } override render() { - return html` + return html` `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index a6e7722374..caf4f56803 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,5 +1,5 @@ import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from "@umbraco-cms/backoffice/extension-registry"; -export type { UmbBlockViewUrlsPropType, UmbBlockDataType, UmbBlockLayoutBaseModel } from "@umbraco-cms/backoffice/extension-registry"; +export type { UmbBlockDataType, UmbBlockLayoutBaseModel } from "@umbraco-cms/backoffice/extension-registry"; export interface UmbBlockValueType { layout: { [key: string]: Array | undefined }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts index ae380233e2..e3ffa6bec1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts @@ -33,11 +33,6 @@ export interface UmbBlockEditorCustomViewConfiguration { showSettingsEdit: boolean; } -export interface UmbBlockViewUrlsPropType { - editContent?: string; - editSettings?: string; -} - export interface UmbBlockEditorCustomViewProperties { manifest?: ManifestBlockEditorCustomView; From 9e3859ea649330a34c4604943ca1836796d6dd44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 1 Jul 2024 10:26:10 +0200 Subject: [PATCH 028/325] out comment test --- src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts index 6655135552..de0e7b0b3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts @@ -4,10 +4,11 @@ import { manifests as blockGridManifests } from './block-grid/manifests.js'; import { manifests as blockListManifests } from './block-list/manifests.js'; import { manifests as blockRteManifests } from './block-rte/manifests.js'; import { manifests as blockTypeManifests } from './block-type/manifests.js'; -import { manifest } from './custom-view/manifest.js'; +// TODO: Remove test custom view, or transfer to test or similar? +//import { manifest } from './custom-view/manifest.js'; export const manifests: Array = [ - manifest, +// manifest, ...blockManifests, ...blockTypeManifests, ...blockListManifests, From 19a2699b966f102afa2c15e3111ccbbb5880830e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 1 Jul 2024 10:30:59 +0200 Subject: [PATCH 029/325] custom view test element --- .../block-grid-entry/block-grid-entry.element.ts | 4 ---- .../block/custom-view/custom-view.element.ts | 15 ++++++++++++++- .../src/packages/block/manifests.ts | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 4e1c140bdb..5a4820a7aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -367,10 +367,6 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper border-color: var(--uui-color-interactive); } - uui-action-bar { - background-color: var(--uui-color-surface); - } - .umb-block-grid__block { height: 100%; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts index 1217a95f4d..7f5d1bcc1a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts @@ -1,5 +1,5 @@ import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from "@umbraco-cms/backoffice/extension-registry"; -import { customElement, html, property } from "@umbraco-cms/backoffice/external/lit"; +import { css, customElement, html, property } from "@umbraco-cms/backoffice/external/lit"; import { UmbLitElement } from "@umbraco-cms/backoffice/lit-element"; @customElement('umb-custom-view-test') @@ -13,6 +13,19 @@ export class UmbCustomViewTestElement extends UmbLitElement implements UmbBlockE Hello ${this.content?.headline} ` } + + static override styles = [ + css` + :host { + display: block; + height: 100%; + box-sizing: border-box; + background-color: #dddddd; + border-radius: 9px; + padding: 12px; + } + ` + ] } export {UmbCustomViewTestElement as element}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts index de0e7b0b3e..6acc156598 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/manifests.ts @@ -8,7 +8,7 @@ import { manifests as blockTypeManifests } from './block-type/manifests.js'; //import { manifest } from './custom-view/manifest.js'; export const manifests: Array = [ -// manifest, + //manifest, ...blockManifests, ...blockTypeManifests, ...blockListManifests, From 587fb4f0c620453f5dc4f56a5bdcab96e404c91a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 1 Jul 2024 10:42:26 +0200 Subject: [PATCH 030/325] do not render slot in extension-with-api-slot --- .../extension-with-api-slot.element.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts index d7d5fc09ab..539c1ac8e2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts @@ -26,7 +26,7 @@ export class UmbExtensionWithApiSlotElement extends UmbLitElement { #extensionsController?: UmbExtensionsElementAndApiInitializer; @state() - private _permitted: Array = []; + private _permitted?: Array; /** * The type or types of extensions to render. @@ -178,13 +178,13 @@ export class UmbExtensionWithApiSlotElement extends UmbLitElement { } override render() { - return this._permitted.length > 0 + return this._permitted ? this._permitted.length > 0 ? repeat( this._permitted, (ext) => ext.alias, (ext, i) => (this.renderMethod ? this.renderMethod(ext, i) : ext.component), ) - : html``; + : html`` : ''; } static override styles = css` From 7f515533fd1720e52327f557d25451b8bb767542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 1 Jul 2024 10:43:19 +0200 Subject: [PATCH 031/325] sort import --- .../extension-with-api-slot.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts index 539c1ac8e2..ab41814cf9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts @@ -1,5 +1,3 @@ -import { umbExtensionsRegistry } from '../../registry.js'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import type { TemplateResult } from '@umbraco-cms/backoffice/external/lit'; import { css, repeat, customElement, property, state, html } from '@umbraco-cms/backoffice/external/lit'; import { @@ -8,6 +6,8 @@ import { type UmbApiConstructorArgumentsMethodType, type ApiLoaderProperty, } from '@umbraco-cms/backoffice/extension-api'; +import { umbExtensionsRegistry } from '../../registry.js'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; /** * @element umb-extension-with-api-slot From 2ca2d27dd8200490f690498567fa8633ffe9becb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 Jul 2024 07:55:56 +0200 Subject: [PATCH 032/325] fix import order --- .../core/content/workspace/content-workspace.context-token.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace.context-token.ts index cf2c295263..8977bc8f59 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace.context-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/content-workspace.context-token.ts @@ -1,5 +1,5 @@ -import type { UmbContentWorkspaceContext } from './content-workspace-context.interface.js'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import type { UmbContentWorkspaceContext } from './content-workspace-context.interface.js'; export const UMB_CONTENT_WORKSPACE_CONTEXT = new UmbContextToken< UmbContentWorkspaceContext, From 5e3907df54164fc50bb2ee7374a94e11c37b53d5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 Jul 2024 07:56:58 +0200 Subject: [PATCH 033/325] add condition to check for content properties --- .../conditions/has-properties/constants.ts | 1 + ...ntent-has-properties.condition.manifest.ts | 8 +++++ .../content-has-properties.condition.ts | 34 +++++++++++++++++++ .../edit/conditions/has-properties/index.ts | 1 + 4 files changed, 44 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.manifest.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/constants.ts new file mode 100644 index 0000000000..a37e6add77 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/constants.ts @@ -0,0 +1 @@ +export const UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION = 'Umb.Condition.Workspace.ContentHasProperties'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.manifest.ts new file mode 100644 index 0000000000..654bbb853b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.manifest.ts @@ -0,0 +1,8 @@ +import type { ManifestCondition } from '@umbraco-cms/backoffice/extension-api'; + +export const manifest: ManifestCondition = { + type: 'condition', + name: 'Content has properties Workspace Condition', + alias: 'Umb.Condition.Workspace.ContentHasProperties', + api: () => import('./content-has-properties.condition.js'), +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts new file mode 100644 index 0000000000..b311e27b91 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts @@ -0,0 +1,34 @@ +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; +import { UMB_CONTENT_WORKSPACE_CONTEXT } from '../../../../content-workspace.context-token.js'; +import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; +import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/content-type'; + +export class UmbContentHasPropertiesWorkspaceCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + #propertyStructureHelper = new UmbContentTypePropertyStructureHelper(this); + + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + + this.consumeContext(UMB_CONTENT_WORKSPACE_CONTEXT, (context) => { + this.observe( + context.structure.contentTypes, + (contentTypes) => { + const hasProperties = contentTypes.some((contentType) => contentType.properties.length > 0); + this.permitted = hasProperties; + }, + 'contentTypesObserver', + ); + }); + } +} + +export { UmbContentHasPropertiesWorkspaceCondition as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/index.ts new file mode 100644 index 0000000000..4f07201dcf --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/index.ts @@ -0,0 +1 @@ +export * from './constants.js'; From 60b8cee752d562db3e414230066c818e431e8647 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 Jul 2024 07:57:24 +0200 Subject: [PATCH 034/325] do the exporting dance --- .../src/packages/core/content/workspace/index.ts | 1 + .../src/packages/core/content/workspace/manifests.ts | 4 ++-- .../content/workspace/views/edit/conditions/manifests.ts | 3 +++ .../src/packages/core/content/workspace/views/edit/index.ts | 1 + .../workspace/views/edit/{manifest.ts => manifests.ts} | 5 ++++- 5 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/index.ts rename src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/{manifest.ts => manifests.ts} (67%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/index.ts index 662c027fcb..4c72bcced7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/index.ts @@ -1,2 +1,3 @@ export type * from './content-workspace-context.interface.js'; export * from './content-workspace.context-token.js'; +export * from './views/edit/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/manifests.ts index d30be86fd2..81565ef37a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/manifests.ts @@ -1,3 +1,3 @@ -import { contentEditorManifest } from './views/edit/manifest.js'; +import { manifests as contentEditorManifests } from './views/edit/manifests.js'; -export const manifests = [contentEditorManifest]; +export const manifests = [...contentEditorManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/manifests.ts new file mode 100644 index 0000000000..d4221afab0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/manifests.ts @@ -0,0 +1,3 @@ +import { manifest as hasPropertiesManifest } from './has-properties/content-has-properties.condition.manifest.js'; + +export const manifests = [hasPropertiesManifest]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/index.ts new file mode 100644 index 0000000000..1637f3a5e7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/index.ts @@ -0,0 +1 @@ +export * from './conditions/has-properties/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/manifests.ts similarity index 67% rename from src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/manifest.ts rename to src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/manifests.ts index 3cb898bd97..caa2ec28d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/manifest.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/manifests.ts @@ -1,6 +1,7 @@ +import { manifests as conditionsManifests } from './conditions/manifests.js'; import type { UmbBackofficeManifestKind } from '@umbraco-cms/backoffice/extension-registry'; -export const contentEditorManifest: UmbBackofficeManifestKind = { +const contentEditorManifest: UmbBackofficeManifestKind = { type: 'kind', alias: 'Umb.Kind.WorkspaceView.ContentEditor', matchKind: 'contentEditor', @@ -17,3 +18,5 @@ export const contentEditorManifest: UmbBackofficeManifestKind = { }, }, }; + +export const manifests = [contentEditorManifest, ...conditionsManifests]; From 299dc9d1912dc65445c7ccf64675fda4441c38fa Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 Jul 2024 07:57:51 +0200 Subject: [PATCH 035/325] assign condition to document content workspace view --- .../documents/documents/workspace/manifests.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts index 15c0479ee3..a47c9feae4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/manifests.ts @@ -1,9 +1,3 @@ -import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; -import { - UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH, - UMB_USER_PERMISSION_DOCUMENT_UPDATE, - UMB_USER_PERMISSION_DOCUMENT_PUBLISH, -} from '../user-permissions/index.js'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; import type { ManifestWorkspaces, @@ -12,6 +6,13 @@ import type { ManifestWorkspaceView, ManifestTypes, } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION } from '@umbraco-cms/backoffice/content'; +import { + UMB_USER_PERMISSION_DOCUMENT_UNPUBLISH, + UMB_USER_PERMISSION_DOCUMENT_UPDATE, + UMB_USER_PERMISSION_DOCUMENT_PUBLISH, +} from '../user-permissions/index.js'; +import { UMB_DOCUMENT_ENTITY_TYPE } from '../entity.js'; export const UMB_DOCUMENT_WORKSPACE_ALIAS = 'Umb.Workspace.Document'; @@ -63,6 +64,9 @@ const workspaceViews: Array = [ alias: 'Umb.Condition.WorkspaceAlias', match: workspace.alias, }, + { + alias: UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION, + }, ], }, { From e385e5f1a11fb10a77fb94a8dc609d05221eb11f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 Jul 2024 07:59:13 +0200 Subject: [PATCH 036/325] add condition to media --- .../src/packages/media/media/workspace/manifests.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts index b26fbb35d9..7d62e0815c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/workspace/manifests.ts @@ -6,6 +6,7 @@ import type { ManifestTypes, } from '@umbraco-cms/backoffice/extension-registry'; import { UMB_ENTITY_IS_NOT_TRASHED_CONDITION_ALIAS } from '@umbraco-cms/backoffice/recycle-bin'; +import { UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION } from '@umbraco-cms/backoffice/content'; const workspace: ManifestWorkspaces = { type: 'workspace', @@ -55,6 +56,9 @@ const workspaceViews: Array = [ alias: 'Umb.Condition.WorkspaceAlias', match: workspace.alias, }, + { + alias: UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION, + }, ], }, { From a39d072ae45892f2ac392a5c3cf2d3dd4f4c6779 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 Jul 2024 07:59:49 +0200 Subject: [PATCH 037/325] add condition to member content editor --- .../src/packages/members/member/workspace/manifests.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/manifests.ts index 0c83475d5c..c47595c8fc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/workspace/manifests.ts @@ -6,6 +6,7 @@ import type { ManifestWorkspaceView, ManifestTypes, } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION } from '@umbraco-cms/backoffice/content'; export const UMB_MEMBER_WORKSPACE_ALIAS = 'Umb.Workspace.Member'; @@ -58,6 +59,9 @@ export const workspaceViews: Array = [ alias: 'Umb.Condition.WorkspaceAlias', match: UMB_MEMBER_WORKSPACE_ALIAS, }, + { + alias: UMB_CONTENT_HAS_PROPERTIES_WORKSPACE_CONDITION, + }, ], }, { From cebd19285ac6a57471159203d78a0a6f94c9df1c Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:52:44 +0200 Subject: [PATCH 038/325] show correct api error msg --- .../core/resources/resource.controller.ts | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts index 0c64f0bc8e..ebd873902b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts @@ -1,10 +1,11 @@ +import { html } from '@umbraco-cms/backoffice/external/lit'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; +import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; /* eslint-disable @typescript-eslint/no-explicit-any */ import { UMB_AUTH_CONTEXT } from '../auth/index.js'; import { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidators.function.js'; import { UMB_NOTIFICATION_CONTEXT, type UmbNotificationOptions } from '@umbraco-cms/backoffice/notification'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; export class UmbResourceController extends UmbControllerBase { @@ -36,6 +37,17 @@ export class UmbResourceController extends UmbControllerBase { this.cancel(); } + #buildApiErrorMessage(error: any) { + const entries: Array> = []; + + Object.entries(error).forEach(([category, message]) => { + entries.push({ category, messages: message as string[] }); + }); + const template = html` ${entries.map((e) => e.messages.map((msg: string) => html`
${msg}
`))}`; + + return template; + } + /** * Base execute function with a try/catch block and return a tuple with the result and the error. */ @@ -129,10 +141,11 @@ export class UmbResourceController extends UmbControllerBase { default: // Other errors if (this.#notificationContext) { + const message = error.body?.errors ? this.#buildApiErrorMessage(error.body.errors) : undefined; this.#notificationContext.peek('danger', { data: { headline: error.body?.title ?? error.name ?? 'Server Error', - message: error.body?.detail ?? error.message ?? 'Something went wrong', + message: message ?? error.body?.detail ?? error.message ?? 'Something went wrong', }, ...options, }); From ee003af80cc1a0c15f6ed8fa5f733c51e948d18b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 2 Jul 2024 14:34:14 +0200 Subject: [PATCH 039/325] Remove redirect to first workspace view --- .../workspace-editor/workspace-editor.element.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts index ccac1676b7..5028e18c8c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.element.ts @@ -71,11 +71,7 @@ export class UmbWorkspaceEditorElement extends UmbLitElement { } as UmbRoute; }); - newRoutes.push({ - path: '', - redirectTo: newRoutes[0]?.path, - }); - + newRoutes.push({ ...newRoutes[0], path: '' }); } newRoutes.push({ @@ -116,11 +112,12 @@ export class UmbWorkspaceEditorElement extends UmbLitElement { ${repeat( this._workspaceViews, (view) => view.alias, - (view) => html` + (view, index) => html` + ?active=${'view/' + view.meta.pathname === this._activePath || + (index === 0 && this._activePath === '')}> ${view.meta.label ? this.localize.string(view.meta.label) : view.name} From 5c876fd5509c5706852d463d6aeecf59f07a2812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 3 Jul 2024 09:17:58 +0200 Subject: [PATCH 040/325] stylesheet update condition # Conflicts: # src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts --- .../block-grid-areas-container.element.ts | 13 ++++++++----- .../block-grid-entries.element.ts | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts index 966d63ce0c..b6fab30d0c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-areas-container/block-grid-areas-container.element.ts @@ -12,7 +12,8 @@ import '../block-grid-entries/index.js'; @customElement('umb-block-grid-areas-container') export class UmbBlockGridAreasContainerElement extends UmbLitElement { // - #styleElement?: HTMLLinkElement; + @state() + _styleElement?: HTMLLinkElement; @state() _areas?: Array = []; @@ -44,9 +45,11 @@ export class UmbBlockGridAreasContainerElement extends UmbLitElement { this.observe( manager.layoutStylesheet, (stylesheet) => { - this.#styleElement = document.createElement('link'); - this.#styleElement.setAttribute('rel', 'stylesheet'); - this.#styleElement.setAttribute('href', stylesheet); + // Do not re-render stylesheet if its the same href. + if (!stylesheet || this._styleElement?.href === stylesheet) return; + this._styleElement = document.createElement('link'); + this._styleElement.rel = 'stylesheet'; + this._styleElement.href = stylesheet; }, 'observeStylesheet', ); @@ -55,7 +58,7 @@ export class UmbBlockGridAreasContainerElement extends UmbLitElement { override render() { return this._areas && this._areas.length > 0 - ? html` ${this.#styleElement} + ? html` ${this._styleElement}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts index 237811a06d..6087977211 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts @@ -209,10 +209,10 @@ export class UmbBlockGridEntriesElement extends UmbFormControlMixin(UmbLitElemen this.observe( manager.layoutStylesheet, (stylesheet) => { - if (this._styleElement && this._styleElement.href === stylesheet) return; + if (!stylesheet || this._styleElement?.href === stylesheet) return; this._styleElement = document.createElement('link'); - this._styleElement.setAttribute('rel', 'stylesheet'); - this._styleElement.setAttribute('href', stylesheet); + this._styleElement.rel = 'stylesheet'; + this._styleElement.href = stylesheet; }, 'observeStylesheet', ); From 47c7125b3c51df680eac01c20dc88962382a8a2a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 3 Jul 2024 10:19:31 +0200 Subject: [PATCH 041/325] Update package-lock.json --- src/Umbraco.Web.UI.Client/package-lock.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 3333dc4b2f..2e7be9bc15 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -22275,7 +22275,9 @@ "src/packages/tags": { "name": "@umbraco-backoffice/tag" }, - "src/packages/templating": {}, + "src/packages/templating": { + "name": "@umbraco-backoffice/templating" + }, "src/packages/umbraco-news": { "name": "@umbraco-backoffice/umbraco-news" }, From 953b70e2459973ecf6282ec6d5f3df3784612930 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 3 Jul 2024 10:27:22 +0200 Subject: [PATCH 042/325] remove unused --- .../has-properties/content-has-properties.condition.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts index b311e27b91..34d6ebe6aa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/conditions/has-properties/content-has-properties.condition.ts @@ -1,20 +1,16 @@ +import { UMB_CONTENT_WORKSPACE_CONTEXT } from '../../../../content-workspace.context-token.js'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import type { UmbConditionConfigBase, UmbConditionControllerArguments, UmbExtensionCondition, } from '@umbraco-cms/backoffice/extension-api'; -import { UMB_CONTENT_WORKSPACE_CONTEXT } from '../../../../content-workspace.context-token.js'; import { UmbConditionBase } from '@umbraco-cms/backoffice/extension-registry'; -import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; -import { UmbContentTypePropertyStructureHelper } from '@umbraco-cms/backoffice/content-type'; export class UmbContentHasPropertiesWorkspaceCondition extends UmbConditionBase implements UmbExtensionCondition { - #propertyStructureHelper = new UmbContentTypePropertyStructureHelper(this); - constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { super(host, args); From 1ad8f7db0372cf6559447c0b0b42a0c3c76024fa Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:56:56 +0200 Subject: [PATCH 043/325] build: run rollup after every build --- src/Umbraco.Web.UI.Client/package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 9a2c20fa60..3de401b8bb 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -145,11 +145,12 @@ "backoffice:test:e2e": "npx playwright test", "build-storybook": "npm run wc-analyze && storybook build", "build:for:cms": "npm run build && npm run build:workspaces && npm run generate:manifest && npm run package:validate && node ./devops/build/copy-to-cms.js", - "build:for:npm": "tsc --project ./src/tsconfig.build.json --declaration && rollup -c ./src/rollup.config.js && npm run generate:manifest && npm run package:validate", + "build:for:npm": "npm run build -- --declaration && npm run generate:manifest && npm run package:validate", "build:for:static": "vite build", "build:vite": "tsc && vite build --mode staging", "build:workspaces": "npm run build -ws --if-present", - "build": "tsc --project ./src/tsconfig.build.json && rollup -c ./src/rollup.config.js", + "build": "tsc --project ./src/tsconfig.build.json", + "postbuild": "rollup -c ./src/rollup.config.js", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", "check:paths": "node ./devops/build/check-path-length.js dist-cms 120", "compile": "tsc", From 02f37a211a5e51ed387dce8eab6596b0683a0277 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:57:03 +0200 Subject: [PATCH 044/325] build: check paths on github --- src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml index 7c5ee7ee44..b90c5f86d1 100644 --- a/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml +++ b/src/Umbraco.Web.UI.Client/.github/workflows/build_test.yml @@ -36,6 +36,7 @@ jobs: - run: npm ci --no-audit --no-fund --prefer-offline - run: npm run lint:errors - run: npm run build:for:cms + - run: npm run check:paths - run: npm run generate:jsonschema:dist test: From 4c3a7d491a0b5bebf04238851b497b289da76e35 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 11:58:52 +0200 Subject: [PATCH 045/325] build: scan the "src" folder --- 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 3de401b8bb..6a3747a01b 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -152,7 +152,7 @@ "build": "tsc --project ./src/tsconfig.build.json", "postbuild": "rollup -c ./src/rollup.config.js", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", - "check:paths": "node ./devops/build/check-path-length.js dist-cms 120", + "check:paths": "node ./devops/build/check-path-length.js src 120", "compile": "tsc", "dev": "vite", "dev:server": "VITE_UMBRACO_USE_MSW=off vite", From bf60fe90bab661f0ff2d739382709878c439aadb Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:05:08 +0200 Subject: [PATCH 046/325] build: change log type to error --- src/Umbraco.Web.UI.Client/devops/build/check-path-length.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js b/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js index e195c7e7c0..f45a622e7e 100644 --- a/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js +++ b/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js @@ -28,9 +28,9 @@ function checkPathLength(dir) { hasError = true; if (IS_AZURE_PIPELINES) { - console.error(`##vso[task.logissue type=warning;sourcepath=${filePath};]Path exceeds maximum length of ${MAX_PATH_LENGTH} characters: ${filePath} with ${filePath.length} characters`); + console.error(`##vso[task.logissue type=error;sourcepath=${filePath};]Path exceeds maximum length of ${MAX_PATH_LENGTH} characters: ${filePath} with ${filePath.length} characters`); } else if (IS_GITHUB_ACTIONS) { - console.error(`::warning file=${filePath},title=Path exceeds ${MAX_PATH_LENGTH} characters::Paths should not be longer than ${MAX_PATH_LENGTH} characters to support WIN32 systems. The file ${filePath} exceeds that with ${filePath.length - MAX_PATH_LENGTH} characters.`); + console.error(`::error file=${filePath},title=Path exceeds ${MAX_PATH_LENGTH} characters::Paths should not be longer than ${MAX_PATH_LENGTH} characters to support WIN32 systems. The file ${filePath} exceeds that with ${filePath.length - MAX_PATH_LENGTH} characters.`); } else { console.error(`Path exceeds maximum length of ${MAX_PATH_LENGTH} characters: ${FILE_PATH_COLOR}`, filePath, filePath.length - MAX_PATH_LENGTH); } From bce01f373b21ec9fdedf40abee9d98ac6272fd5e Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:52:07 +0200 Subject: [PATCH 047/325] build: check the dist_cms folder --- 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 6a3747a01b..3de401b8bb 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -152,7 +152,7 @@ "build": "tsc --project ./src/tsconfig.build.json", "postbuild": "rollup -c ./src/rollup.config.js", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", - "check:paths": "node ./devops/build/check-path-length.js src 120", + "check:paths": "node ./devops/build/check-path-length.js dist-cms 120", "compile": "tsc", "dev": "vite", "dev:server": "VITE_UMBRACO_USE_MSW=off vite", From 5ff3a01deed538d79c462ba6da8bfa9c6f2eb939 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 12:59:11 +0200 Subject: [PATCH 048/325] build: try and map the found files back to the src folder --- .../devops/build/check-path-length.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js b/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js index f45a622e7e..3b48ed22b0 100644 --- a/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js +++ b/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js @@ -28,9 +28,9 @@ function checkPathLength(dir) { hasError = true; if (IS_AZURE_PIPELINES) { - console.error(`##vso[task.logissue type=error;sourcepath=${filePath};]Path exceeds maximum length of ${MAX_PATH_LENGTH} characters: ${filePath} with ${filePath.length} characters`); + console.error(`##vso[task.logissue type=error;sourcepath=${mapFileToSourcePath(filePath)};]Path exceeds maximum length of ${MAX_PATH_LENGTH} characters: ${filePath} with ${filePath.length} characters`); } else if (IS_GITHUB_ACTIONS) { - console.error(`::error file=${filePath},title=Path exceeds ${MAX_PATH_LENGTH} characters::Paths should not be longer than ${MAX_PATH_LENGTH} characters to support WIN32 systems. The file ${filePath} exceeds that with ${filePath.length - MAX_PATH_LENGTH} characters.`); + console.error(`::error file=${mapFileToSourcePath(filePath)},title=Path exceeds ${MAX_PATH_LENGTH} characters::Paths should not be longer than ${MAX_PATH_LENGTH} characters to support WIN32 systems. The file ${filePath} exceeds that with ${filePath.length - MAX_PATH_LENGTH} characters.`); } else { console.error(`Path exceeds maximum length of ${MAX_PATH_LENGTH} characters: ${FILE_PATH_COLOR}`, filePath, filePath.length - MAX_PATH_LENGTH); } @@ -47,6 +47,16 @@ function checkPathLength(dir) { return hasError; } +/** + * Maps a file path to a source path for CI logs. + * @remark This might not always work as expected, especially on bundled files, but it's a best effort to map the file path to a source path. + * @param {string} file - The file path to map to a source path + * @returns {string} + */ +function mapFileToSourcePath(file) { + return file.replace(PROJECT_DIR, 'src'); +} + const hasError = checkPathLength(PROJECT_DIR, MAX_PATH_LENGTH); if (hasError) { From f4e171a7967357a86265e31d2d422c8c537d4be8 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 15:54:52 +0200 Subject: [PATCH 049/325] rearrange the flow a bit --- .../devops/build/check-path-length.js | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js b/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js index 3b48ed22b0..64fcb08eb4 100644 --- a/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js +++ b/src/Umbraco.Web.UI.Client/devops/build/check-path-length.js @@ -18,6 +18,28 @@ console.log('\n-----------------------------------'); console.log('Results:'); console.log('-----------------------------------\n'); +const hasError = checkPathLength(PROJECT_DIR, MAX_PATH_LENGTH); + +if (hasError) { + console.log('\n-----------------------------------'); + console.log(ERROR_COLOR, 'Path length check failed'); + console.log('-----------------------------------\n'); + if (IS_CI && processExitCode) { + process.exit(processExitCode); + } +} else { + console.log('\n-----------------------------------'); + console.log(SUCCESS_COLOR, 'Path length check passed'); + console.log('-----------------------------------\n'); +} + +// Functions + +/** + * Recursively check the path length of all files in a directory. + * @param {string} dir - The directory to check for path lengths + * @returns {boolean} + */ function checkPathLength(dir) { const files = readdirSync(dir); let hasError = false; @@ -32,7 +54,7 @@ function checkPathLength(dir) { } else if (IS_GITHUB_ACTIONS) { console.error(`::error file=${mapFileToSourcePath(filePath)},title=Path exceeds ${MAX_PATH_LENGTH} characters::Paths should not be longer than ${MAX_PATH_LENGTH} characters to support WIN32 systems. The file ${filePath} exceeds that with ${filePath.length - MAX_PATH_LENGTH} characters.`); } else { - console.error(`Path exceeds maximum length of ${MAX_PATH_LENGTH} characters: ${FILE_PATH_COLOR}`, filePath, filePath.length - MAX_PATH_LENGTH); + console.error(FILE_PATH_COLOR, mapFileToSourcePath(filePath), '(exceeds by', filePath.length - MAX_PATH_LENGTH, 'chars)'); } } @@ -54,20 +76,5 @@ function checkPathLength(dir) { * @returns {string} */ function mapFileToSourcePath(file) { - return file.replace(PROJECT_DIR, 'src'); -} - -const hasError = checkPathLength(PROJECT_DIR, MAX_PATH_LENGTH); - -if (hasError) { - console.error('\n-----------------------------------'); - console.error(ERROR_COLOR, 'Path length check failed'); - console.error('-----------------------------------\n'); - if (IS_CI && processExitCode) { - process.exit(processExitCode); - } -} else { - console.log('\n-----------------------------------'); - console.log(SUCCESS_COLOR, 'Path length check passed'); - console.log('-----------------------------------\n'); + return file.replace(PROJECT_DIR, 'src').replace('.js', '.ts'); } From d662aa0fcd2ff7fb047b9bab88187a94ef1c54ef Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:02:17 +0200 Subject: [PATCH 050/325] chore: optimise the path length of the property-editor-ui-image-crops-configuration element --- .../image-crops-configuration/index.ts | 1 - ...editor-ui-image-crops-configuration.stories.ts | 15 --------------- .../media/property-editors/image-crops/index.ts | 1 + .../manifests.ts | 4 ++-- .../property-editor-ui-image-crops.element.ts} | 13 +++++-------- .../property-editor-ui-image-crops.stories.ts | 15 +++++++++++++++ .../property-editor-ui-image-crops.test.ts} | 12 +++++------- .../media/media/property-editors/index.ts | 2 +- .../media/media/property-editors/manifests.ts | 2 +- 9 files changed, 30 insertions(+), 35 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/index.ts delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.stories.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/index.ts rename src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/{image-crops-configuration => image-crops}/manifests.ts (69%) rename src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/{image-crops-configuration/property-editor-ui-image-crops-configuration.element.ts => image-crops/property-editor-ui-image-crops.element.ts} (93%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts rename src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/{image-crops-configuration/property-editor-ui-image-crops-configuration.test.ts => image-crops/property-editor-ui-image-crops.test.ts} (61%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/index.ts deleted file mode 100644 index c68c521c08..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './property-editor-ui-image-crops-configuration.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.stories.ts deleted file mode 100644 index 2cd2ffdb18..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIImageCropsConfigurationElement } from './property-editor-ui-image-crops-configuration.element.js'; -import type { Meta, Story } from '@storybook/web-components'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-image-crops-configuration.element.js'; - -export default { - title: 'Property Editor UIs/Image Crops Configuration', - component: 'umb-property-editor-ui-image-crops-configuration', - id: 'umb-property-editor-ui-image-crops-configuration', -} as Meta; - -export const AAAOverview: Story = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/index.ts new file mode 100644 index 0000000000..e0bd6d0c5e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/index.ts @@ -0,0 +1 @@ +export * from './property-editor-ui-image-crops.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/manifests.ts similarity index 69% rename from src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/manifests.ts rename to src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/manifests.ts index d3bda8f6ee..03ee6346ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/manifests.ts @@ -3,8 +3,8 @@ import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension export const manifest: ManifestPropertyEditorUi = { type: 'propertyEditorUi', alias: 'Umb.PropertyEditorUi.ImageCropsConfiguration', - name: 'Image Crops Configuration Property Editor UI', - element: () => import('./property-editor-ui-image-crops-configuration.element.js'), + name: 'Image Crops Property Editor UI', + element: () => import('./property-editor-ui-image-crops.element.js'), meta: { label: 'Image Crops Configuration', icon: 'icon-autofill', diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.element.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.element.ts index 4661cb9fb8..52f8db37de 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.element.ts @@ -13,13 +13,10 @@ export type UmbCrop = { }; /** - * @element umb-property-editor-ui-image-crops-configuration + * @element umb-property-editor-ui-image-crops */ -@customElement('umb-property-editor-ui-image-crops-configuration') -export class UmbPropertyEditorUIImageCropsConfigurationElement - extends UmbLitElement - implements UmbPropertyEditorUiElement -{ +@customElement('umb-property-editor-ui-image-crops') +export class UmbPropertyEditorUIImageCropsElement extends UmbLitElement implements UmbPropertyEditorUiElement { @query('#label') private _labelInput!: HTMLInputElement; @@ -244,10 +241,10 @@ export class UmbPropertyEditorUIImageCropsConfigurationElement ]; } -export default UmbPropertyEditorUIImageCropsConfigurationElement; +export default UmbPropertyEditorUIImageCropsElement; declare global { interface HTMLElementTagNameMap { - 'umb-property-editor-ui-image-crops-configuration': UmbPropertyEditorUIImageCropsConfigurationElement; + 'umb-property-editor-ui-image-crops': UmbPropertyEditorUIImageCropsElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts new file mode 100644 index 0000000000..9e4fcc22ab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts @@ -0,0 +1,15 @@ +import type { UmbPropertyEditorUIImageCropsElement } from './property-editor-ui-image-crops.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components'; + +import './property-editor-ui-image-crops.element.js'; + +const meta: Meta = { + title: 'Property Editor UIs/Image Crops', + id: 'umb-property-editor-ui-image-crops', + component: 'umb-property-editor-ui-image-crops', +}; + +export default meta; +type Story = StoryObj; + +export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.test.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.test.ts similarity index 61% rename from src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.test.ts rename to src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.test.ts index 06c714d10c..e36bc07b0e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops-configuration/property-editor-ui-image-crops-configuration.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.test.ts @@ -1,19 +1,17 @@ -import { UmbPropertyEditorUIImageCropsConfigurationElement } from './property-editor-ui-image-crops-configuration.element.js'; +import { UmbPropertyEditorUIImageCropsElement } from './property-editor-ui-image-crops.element.js'; import { expect, fixture, html } from '@open-wc/testing'; import type { UmbTestRunnerWindow } from '@umbraco-cms/internal/test-utils'; //import { type UmbTestRunnerWindow, defaultA11yConfig } from '@umbraco-cms/internal/test-utils'; -describe('UmbPropertyEditorUIImageCropsConfigurationElement', () => { - let element: UmbPropertyEditorUIImageCropsConfigurationElement; +describe('UmbPropertyEditorUIImageCropsElement', () => { + let element: UmbPropertyEditorUIImageCropsElement; beforeEach(async () => { - element = await fixture(html` - - `); + element = await fixture(html` `); }); it('is defined with its own instance', () => { - expect(element).to.be.instanceOf(UmbPropertyEditorUIImageCropsConfigurationElement); + expect(element).to.be.instanceOf(UmbPropertyEditorUIImageCropsElement); }); /* diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/index.ts index 91ac2c4199..0dc3ef8cf2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/index.ts @@ -1,5 +1,5 @@ export * from './image-cropper/index.js'; -export * from './image-crops-configuration/index.js'; +export * from './image-crops/index.js'; export * from './media-entity-picker/index.js'; export * from './media-picker/index.js'; export * from './upload-field/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/manifests.ts index 0cd00a29b7..c824ef42b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/manifests.ts @@ -1,4 +1,4 @@ -import { manifest as imageCropsConfiguration } from './image-crops-configuration/manifests.js'; +import { manifest as imageCropsConfiguration } from './image-crops/manifests.js'; import { manifest as mediaEntityPicker } from './media-entity-picker/manifests.js'; import { manifests as imageCropperManifests } from './image-cropper/manifests.js'; import { manifests as mediaPickerManifests } from './media-picker/manifests.js'; From 1f467fbc12573607f17654a3833e9edf7e19f380 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:11:49 +0200 Subject: [PATCH 051/325] chore: optimise path lengths --- .../source/{input-content-picker-source => }/index.ts | 0 .../input-content-picker-source.element.ts | 6 +++--- .../property-editor-ui-content-picker-source.element.ts | 4 ++-- .../content-picker/dynamic-root/components/index.ts | 1 + .../input-content-picker-document-root.element.ts | 0 .../property-editors/content-picker/dynamic-root/index.ts | 1 + .../src/packages/property-editors/content-picker/index.ts | 4 ++++ 7 files changed, 11 insertions(+), 5 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/{input-content-picker-source => }/index.ts (100%) rename src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/{input-content-picker-source => }/input-content-picker-source.element.ts (93%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/components/index.ts rename src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/{input-content-picker-document-root => components}/input-content-picker-document-root.element.ts (100%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/index.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source/index.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/index.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source/input-content-picker-source.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source.element.ts similarity index 93% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source/input-content-picker-source.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source.element.ts index a9e2c622c8..5d02e9936c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source/input-content-picker-source.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/input-content-picker-source.element.ts @@ -1,12 +1,12 @@ -import type { UmbContentPickerDynamicRoot, UmbContentPickerSourceType } from '../../../types.js'; -import type { UmbInputContentPickerDocumentRootElement } from '../../../dynamic-root/input-content-picker-document-root/input-content-picker-document-root.element.js'; +import type { UmbContentPickerDynamicRoot, UmbContentPickerSourceType } from '../../types.js'; +import type { UmbInputContentPickerDocumentRootElement } from '../../dynamic-root/components/input-content-picker-document-root.element.js'; import { html, customElement, property, css, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; import { UUIFormControlMixin } from '@umbraco-cms/backoffice/external/uui'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import '../../../dynamic-root/input-content-picker-document-root/input-content-picker-document-root.element.js'; +import '../../dynamic-root/components/input-content-picker-document-root.element.js'; @customElement('umb-input-content-picker-source') export class UmbInputContentPickerSourceElement extends UUIFormControlMixin(UmbLitElement, '') { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/property-editor-ui-content-picker-source.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/property-editor-ui-content-picker-source.element.ts index 125a092893..51ba3a42e6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/property-editor-ui-content-picker-source.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source/property-editor-ui-content-picker-source.element.ts @@ -1,5 +1,5 @@ import type { UmbContentPickerSource } from '../../types.js'; -import type { UmbInputContentPickerSourceElement } from './input-content-picker-source/input-content-picker-source.element.js'; +import type { UmbInputContentPickerSourceElement } from './input-content-picker-source.element.js'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { @@ -9,7 +9,7 @@ import { import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; // import of local component -import './input-content-picker-source/index.js'; +import './index.js'; /** * @element umb-property-editor-ui-content-picker-source diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/components/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/components/index.ts new file mode 100644 index 0000000000..64c4b06e47 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/components/index.ts @@ -0,0 +1 @@ +export * from './input-content-picker-document-root.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/input-content-picker-document-root/input-content-picker-document-root.element.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/components/input-content-picker-document-root.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/input-content-picker-document-root/input-content-picker-document-root.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/components/input-content-picker-document-root.element.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/index.ts index 736a54915b..aaec6ea6d6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/dynamic-root/index.ts @@ -1,2 +1,3 @@ export * from './modals/index.js'; export * from './repository/index.js'; +export * from './components/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/index.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/index.ts new file mode 100644 index 0000000000..38fbc9df90 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/index.ts @@ -0,0 +1,4 @@ +export * from './components/index.js'; +export * from './config/source/index.js'; +export * from './dynamic-root/index.js'; +export type * from './types.js'; From f9f8d6a710c6ba2299baa6659c2f20724c084400 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:12:31 +0200 Subject: [PATCH 052/325] chore: optimise path lengths --- .../src/packages/user/user-permission/modals/manifests.ts | 2 +- .../entity-user-permission-settings-modal.element.ts | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/{entity-user-permission-settings => settings}/entity-user-permission-settings-modal.element.ts (100%) diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts index 0ae3077bd0..975a669312 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/manifests.ts @@ -5,6 +5,6 @@ export const manifests: Array = [ type: 'modal', alias: 'Umb.Modal.EntityUserPermissionSettings', name: 'Entity User Permission Settings Modal', - js: () => import('./entity-user-permission-settings/entity-user-permission-settings-modal.element.js'), + js: () => import('./settings/entity-user-permission-settings-modal.element.js'), }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/entity-user-permission-settings/entity-user-permission-settings-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts similarity index 100% rename from src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/entity-user-permission-settings/entity-user-permission-settings-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/user-permission/modals/settings/entity-user-permission-settings-modal.element.ts From 3bd7efc289db3d904f1c2ceaf78a934b7ed5d7fe Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:15:41 +0200 Subject: [PATCH 053/325] chore: optimise path lengths --- .../current-user-mfa-disable-modal.element.ts} | 12 ++++++------ .../current-user-mfa-disable-modal.stories.ts} | 12 ++++++------ .../current-user-mfa-disable-modal.token.ts} | 4 ++-- ...rrent-user-mfa-enable-provider-modal.token.ts | 16 ---------------- .../current-user-mfa-enable-modal.element.ts} | 12 ++++++------ .../current-user-mfa-enable-modal.stories.ts} | 12 ++++++------ .../current-user-mfa-enable-modal.token.ts | 16 ++++++++++++++++ .../current-user-mfa-modal.element.ts | 4 ++-- .../user/current-user/modals/manifests.ts | 4 ++-- 9 files changed, 46 insertions(+), 46 deletions(-) rename src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/{current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.element.ts => current-user-mfa-disable/current-user-mfa-disable-modal.element.ts} (90%) rename src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/{current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.stories.ts => current-user-mfa-disable/current-user-mfa-disable-modal.stories.ts} (50%) rename src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/{current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.token.ts => current-user-mfa-disable/current-user-mfa-disable-modal.token.ts} (73%) delete mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.token.ts rename src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/{current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.element.ts => current-user-mfa-enable/current-user-mfa-enable-modal.element.ts} (76%) rename src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/{current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.stories.ts => current-user-mfa-enable/current-user-mfa-enable-modal.stories.ts} (73%) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.token.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.element.ts similarity index 90% rename from src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.element.ts index dcca00eac9..3c3a0c288c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.element.ts @@ -1,5 +1,5 @@ import { UmbCurrentUserRepository } from '../../repository/index.js'; -import type { UmbCurrentUserMfaDisableProviderModalConfig } from './current-user-mfa-disable-provider-modal.token.js'; +import type { UmbCurrentUserMfaDisableModalConfig } from './current-user-mfa-disable-modal.token.js'; import { UMB_NOTIFICATION_CONTEXT, type UmbNotificationColor } from '@umbraco-cms/backoffice/notification'; import { css, customElement, html, query, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; @@ -7,9 +7,9 @@ import type { UUIButtonState } from '@umbraco-cms/backoffice/external/uui'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { isApiError } from '@umbraco-cms/backoffice/resources'; -@customElement('umb-current-user-mfa-disable-provider-modal') -export class UmbCurrentUserMfaDisableProviderModalElement extends UmbModalBaseElement< - UmbCurrentUserMfaDisableProviderModalConfig, +@customElement('umb-current-user-mfa-disable-modal') +export class UmbCurrentUserMfaDisableModalElement extends UmbModalBaseElement< + UmbCurrentUserMfaDisableModalConfig, never > { #currentUserRepository = new UmbCurrentUserRepository(this); @@ -156,10 +156,10 @@ export class UmbCurrentUserMfaDisableProviderModalElement extends UmbModalBaseEl ]; } -export default UmbCurrentUserMfaDisableProviderModalElement; +export default UmbCurrentUserMfaDisableModalElement; declare global { interface HTMLElementTagNameMap { - 'umb-current-user-mfa-disable-provider-modal': UmbCurrentUserMfaDisableProviderModalElement; + 'umb-current-user-mfa-disable-modal': UmbCurrentUserMfaDisableModalElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.stories.ts similarity index 50% rename from src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.stories.ts index 9a778191a1..6bf592f1ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.stories.ts @@ -1,12 +1,12 @@ -import type { UmbCurrentUserMfaDisableProviderModalElement } from './current-user-mfa-disable-provider-modal.element.js'; +import type { UmbCurrentUserMfaDisableModalElement } from './current-user-mfa-disable-modal.element.js'; import type { Meta, StoryObj } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; -import './current-user-mfa-disable-provider-modal.element.js'; +import './current-user-mfa-disable-modal.element.js'; -const meta: Meta = { - title: 'Current User/MFA/Disable MFA Provider', - component: 'umb-current-user-mfa-disable-provider-modal', +const meta: Meta = { + title: 'Current User/MFA/Disable MFA', + component: 'umb-current-user-mfa-disable-modal', decorators: [(Story) => html`
${Story()}
`], args: { data: { @@ -24,6 +24,6 @@ const meta: Meta = { export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.token.ts similarity index 73% rename from src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.token.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.token.ts index b24cf867b1..2daa703e0f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.token.ts @@ -1,12 +1,12 @@ import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; -export interface UmbCurrentUserMfaDisableProviderModalConfig { +export interface UmbCurrentUserMfaDisableModalConfig { providerName: string; displayName: string; } export const UMB_CURRENT_USER_MFA_DISABLE_PROVIDER_MODAL = new UmbModalToken< - UmbCurrentUserMfaDisableProviderModalConfig, + UmbCurrentUserMfaDisableModalConfig, never >('Umb.Modal.CurrentUserMfaDisableProvider', { modal: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.token.ts deleted file mode 100644 index 616588f597..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.token.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; - -export interface UmbCurrentUserMfaEnableProviderModalConfig { - providerName: string; - displayName: string; -} - -export const UMB_CURRENT_USER_MFA_ENABLE_PROVIDER_MODAL = new UmbModalToken< - UmbCurrentUserMfaEnableProviderModalConfig, - never ->('Umb.Modal.CurrentUserMfaEnableProvider', { - modal: { - type: 'sidebar', - size: 'small', - }, -}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.element.ts similarity index 76% rename from src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.element.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.element.ts index 85a0381f87..314592bebb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.element.ts @@ -1,15 +1,15 @@ import type { UmbMfaProviderConfigurationElementProps } from '../../types.js'; import { UmbCurrentUserRepository } from '../../repository/index.js'; -import type { UmbCurrentUserMfaEnableProviderModalConfig } from './current-user-mfa-enable-provider-modal.token.js'; +import type { UmbCurrentUserMfaEnableModalConfig } from './current-user-mfa-enable-modal.token.js'; import type { ManifestMfaLoginProvider } from '@umbraco-cms/backoffice/extension-registry'; import { customElement, html } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import '../../components/mfa-provider-default.element.js'; -@customElement('umb-current-user-mfa-enable-provider-modal') -export class UmbCurrentUserMfaEnableProviderModalElement extends UmbModalBaseElement< - UmbCurrentUserMfaEnableProviderModalConfig, +@customElement('umb-current-user-mfa-enable-modal') +export class UmbCurrentUserMfaEnableModalElement extends UmbModalBaseElement< + UmbCurrentUserMfaEnableModalConfig, never > { #currentUserRepository = new UmbCurrentUserRepository(this); @@ -48,10 +48,10 @@ export class UmbCurrentUserMfaEnableProviderModalElement extends UmbModalBaseEle }; } -export default UmbCurrentUserMfaEnableProviderModalElement; +export default UmbCurrentUserMfaEnableModalElement; declare global { interface HTMLElementTagNameMap { - 'umb-current-user-mfa-enable-provider-modal': UmbCurrentUserMfaEnableProviderModalElement; + 'umb-current-user-mfa-enable-modal': UmbCurrentUserMfaEnableModalElement; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.stories.ts similarity index 73% rename from src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.stories.ts rename to src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.stories.ts index 477a2363e1..bbe1cd4e94 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.stories.ts @@ -1,11 +1,11 @@ -import type { UmbCurrentUserMfaEnableProviderModalElement } from './current-user-mfa-enable-provider-modal.element.js'; +import type { UmbCurrentUserMfaEnableModalElement } from './current-user-mfa-enable-modal.element.js'; import type { Meta, StoryObj } from '@storybook/web-components'; import { html } from '@umbraco-cms/backoffice/external/lit'; import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import './current-user-mfa-enable-provider-modal.element.js'; +import './current-user-mfa-enable-modal.element.js'; class UmbServerExtensionsHostElement extends UmbLitElement { constructor() { @@ -22,9 +22,9 @@ if (window.customElements.get('umb-server-extensions-host') === undefined) { customElements.define('umb-server-extensions-host', UmbServerExtensionsHostElement); } -const meta: Meta = { - title: 'Current User/MFA/Enable MFA Provider', - component: 'umb-current-user-mfa-enable-provider-modal', +const meta: Meta = { + title: 'Current User/MFA/Enable MFA', + component: 'umb-current-user-mfa-enable-modal', decorators: [ (Story) => html` @@ -47,6 +47,6 @@ const meta: Meta = { export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.token.ts new file mode 100644 index 0000000000..31d845150f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.token.ts @@ -0,0 +1,16 @@ +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbCurrentUserMfaEnableModalConfig { + providerName: string; + displayName: string; +} + +export const UMB_CURRENT_USER_MFA_ENABLE_PROVIDER_MODAL = new UmbModalToken( + 'Umb.Modal.CurrentUserMfaEnableProvider', + { + modal: { + type: 'sidebar', + size: 'small', + }, + }, +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa/current-user-mfa-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa/current-user-mfa-modal.element.ts index f0b6a20b76..75cdc6558a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa/current-user-mfa-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa/current-user-mfa-modal.element.ts @@ -1,6 +1,6 @@ -import { UMB_CURRENT_USER_MFA_ENABLE_PROVIDER_MODAL } from '../current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.token.js'; +import { UMB_CURRENT_USER_MFA_ENABLE_PROVIDER_MODAL } from '../current-user-mfa-enable/current-user-mfa-enable-modal.token.js'; import { UmbCurrentUserRepository } from '../../repository/index.js'; -import { UMB_CURRENT_USER_MFA_DISABLE_PROVIDER_MODAL } from '../current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.token.js'; +import { UMB_CURRENT_USER_MFA_DISABLE_PROVIDER_MODAL } from '../current-user-mfa-disable/current-user-mfa-disable-modal.token.js'; import type { UmbCurrentUserMfaProviderModel } from '../../types.js'; import { css, customElement, html, nothing, property, repeat, state, when } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/manifests.ts index 8f1e7690ba..1125e6dacc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/manifests.ts @@ -17,13 +17,13 @@ const modals: Array = [ type: 'modal', alias: 'Umb.Modal.CurrentUserMfaEnableProvider', name: 'Current User MFA Enable Provider Modal', - js: () => import('./current-user-mfa-enable-provider/current-user-mfa-enable-provider-modal.element.js'), + js: () => import('./current-user-mfa-enable/current-user-mfa-enable-modal.element.js'), }, { type: 'modal', alias: 'Umb.Modal.CurrentUserMfaDisableProvider', name: 'Current User MFA Disable Provider Modal', - js: () => import('./current-user-mfa-disable-provider/current-user-mfa-disable-provider-modal.element.js'), + js: () => import('./current-user-mfa-disable/current-user-mfa-disable-modal.element.js'), }, ]; From 227c28c157e06d6aaa50eff06eac0905cb797975 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Wed, 3 Jul 2024 16:17:13 +0200 Subject: [PATCH 054/325] build: set max path to 125 --- 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 3de401b8bb..6ba4f0d1e1 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -152,7 +152,7 @@ "build": "tsc --project ./src/tsconfig.build.json", "postbuild": "rollup -c ./src/rollup.config.js", "check": "npm run lint:errors && npm run compile && npm run build-storybook && npm run generate:jsonschema:dist", - "check:paths": "node ./devops/build/check-path-length.js dist-cms 120", + "check:paths": "node ./devops/build/check-path-length.js dist-cms 125", "compile": "tsc", "dev": "vite", "dev:server": "VITE_UMBRACO_USE_MSW=off vite", From b88286039f638c213c9a0b0884a7cf21c5e619c4 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 4 Jul 2024 08:54:36 +0200 Subject: [PATCH 055/325] run prettier --- .../src/external/router-slot/router-slot.ts | 10 +- .../base-extensions-initializer.controller.ts | 2 +- .../block-grid-entry.element.ts | 214 ++++++++++++------ .../block-list-entry.element.ts | 177 ++++++++++----- .../property-editor-ui-block-list.element.ts | 2 +- .../block-rte-entry.element.ts | 98 +++++--- .../src/packages/block/block-type/types.ts | 2 +- .../workspace/block-type-workspace.context.ts | 6 +- .../src/packages/block/block/types.ts | 4 +- .../block/custom-view/custom-view.element.ts | 19 +- .../packages/block/custom-view/manifest.ts | 6 +- .../extension-slot/extension-slot.element.ts | 16 +- .../extension-with-api-slot.element.ts | 16 +- ...ck-editor-custom-view-element.interface.ts | 17 +- 14 files changed, 384 insertions(+), 205 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts b/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts index 1a2bec962f..14e6f7a1b5 100644 --- a/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts +++ b/src/Umbraco.Web.UI.Client/src/external/router-slot/router-slot.ts @@ -48,7 +48,7 @@ export class RouterSlot extends HTMLElement implements IRouter /** * Method to cancel navigation if changed. */ - private _cancelNavigation ?:() => void; + private _cancelNavigation?: () => void; /** * Listeners on the router. @@ -208,7 +208,7 @@ export class RouterSlot extends HTMLElement implements IRouter if (this.isConnected) { const newMatch = this.getRouteMatch(); // Check if this match matches the current match (aka. If the path has changed), if so we should navigate. [NL] - if(newMatch) { + if (newMatch) { navigate = shouldNavigate(this.match, newMatch); } } @@ -318,7 +318,6 @@ export class RouterSlot extends HTMLElement implements IRouter * Returns true if a navigation was made to a new page. */ protected async renderPath(path: string | PathFragment): Promise { - // Notice: Since this is never called from any other place than one higher in this file(when writing this...), we could just retrieve the path and find a match by using this.getRouteMatch() [NL] // Find the corresponding route. const match = matchRoutes(this._routes, path); @@ -336,7 +335,6 @@ export class RouterSlot extends HTMLElement implements IRouter // Only change route if its a new route. const navigate = shouldNavigate(this.match, match); if (navigate) { - // If another navigation is still begin resolved in this very moment, then we need to cancel that so it does not end up overriding this new navigation.[NL] this._cancelNavigation?.(); // Listen for another push state event. If another push state event happens @@ -412,7 +410,7 @@ export class RouterSlot extends HTMLElement implements IRouter // We have some routes that share the same component instance, those should not be removed and re-appended [NL] const isTheSameComponent = this.firstChild === page; - if(!isTheSameComponent) { + if (!isTheSameComponent) { // Remove the old page by clearing the slot this.clearChildren(); } @@ -421,7 +419,7 @@ export class RouterSlot extends HTMLElement implements IRouter // We do this to ensure that we can find the match in the connectedCallback of the page. this._routeMatch = match; - if(!isTheSameComponent) { + if (!isTheSameComponent) { if (page) { // Append the new page this.appendChild(page); diff --git a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts index 5dd5f08506..4893f340f9 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/extension-api/controller/base-extensions-initializer.controller.ts @@ -91,7 +91,7 @@ export abstract class UmbBaseExtensionsInitializer< } // If we get no manifests and we have not exposed any extensions yet, then we should notify to let the listener know that we have our first response. [NL] - if(manifests.length === 0 && this.#exposedPermittedExts === undefined) { + if (manifests.length === 0 && this.#exposedPermittedExts === undefined) { this.#exposedPermittedExts = []; this.#onChange?.(this.#exposedPermittedExts); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts index 5a4820a7aa..e50b53ecd4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entry/block-grid-entry.element.ts @@ -1,7 +1,11 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, customElement, property, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { PropertyValueMap } from '@umbraco-cms/backoffice/external/lit'; -import type { ManifestBlockEditorCustomView, UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { + ManifestBlockEditorCustomView, + UmbBlockEditorCustomViewProperties, + UmbPropertyEditorUiElement, +} from '@umbraco-cms/backoffice/extension-registry'; import { stringOrStringArrayContains } from '@umbraco-cms/backoffice/utils'; import { UmbBlockGridEntryContext } from '../../context/block-grid-entry.context.js'; import { UMB_BLOCK_GRID, type UmbBlockGridLayoutModel } from '@umbraco-cms/backoffice/block-grid'; @@ -41,7 +45,7 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper #renderTimeout: number | undefined; @state() - _contentTypeAlias?:string; + _contentTypeAlias?: string; @state() _columnSpan?: number; @@ -86,7 +90,10 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper _inlineCreateAboveWidth?: string; @state() - _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, config: { showContentEdit: false, showSettingsEdit: false} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { + contentUdi: undefined!, + config: { showContentEdit: false, showSettingsEdit: false }, + }; // Set to undefined cause it will be set before we render. #updateBlockViewProps(incoming: Partial>) { this._blockViewProps = { ...this._blockViewProps, ...incoming }; @@ -97,63 +104,119 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper super(); // Misc: - this.observe(this.#context.showContentEdit, (showContentEdit) => { - this._showContentEdit = showContentEdit; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showContentEdit } }); - }, null); - this.observe(this.#context.settingsElementTypeKey, (key) => { - this._hasSettings = !!key; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); - }, null); - this.observe(this.#context.canScale, (canScale) => { - this._canScale = canScale; - }, null); - this.observe(this.#context.blockType, (blockType) => { - this.#updateBlockViewProps({ blockType }); - }, null); + this.observe( + this.#context.showContentEdit, + (showContentEdit) => { + this._showContentEdit = showContentEdit; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showContentEdit } }); + }, + null, + ); + this.observe( + this.#context.settingsElementTypeKey, + (key) => { + this._hasSettings = !!key; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); + }, + null, + ); + this.observe( + this.#context.canScale, + (canScale) => { + this._canScale = canScale; + }, + null, + ); + this.observe( + this.#context.blockType, + (blockType) => { + this.#updateBlockViewProps({ blockType }); + }, + null, + ); // TODO: Implement index. - this.observe(this.#context.label, (label) => { - this.#updateBlockViewProps({ label }); - this._label = label; - }, null); - this.observe(this.#context.contentElementTypeIcon, (icon) => { - this.#updateBlockViewProps({ icon }); - this._icon = icon; - }, null); - this.observe(this.#context.inlineEditingMode, (mode) => { - this._inlineEditingMode = mode; - }, null); + this.observe( + this.#context.label, + (label) => { + this.#updateBlockViewProps({ label }); + this._label = label; + }, + null, + ); + this.observe( + this.#context.contentElementTypeIcon, + (icon) => { + this.#updateBlockViewProps({ icon }); + this._icon = icon; + }, + null, + ); + this.observe( + this.#context.inlineEditingMode, + (mode) => { + this._inlineEditingMode = mode; + }, + null, + ); // Data: - this.observe(this.#context.layout, (layout) => { - this.#updateBlockViewProps({ layout }); - }, null); - this.observe(this.#context.content, (content) => { - this.#updateBlockViewProps({ content }); - }, null); - this.observe(this.#context.settings, (settings) => { - this.#updateBlockViewProps({ settings }); - }, null); + this.observe( + this.#context.layout, + (layout) => { + this.#updateBlockViewProps({ layout }); + }, + null, + ); + this.observe( + this.#context.content, + (content) => { + this.#updateBlockViewProps({ content }); + }, + null, + ); + this.observe( + this.#context.settings, + (settings) => { + this.#updateBlockViewProps({ settings }); + }, + null, + ); // Paths: - this.observe(this.#context.createBeforePath, (createPath) => { - //const oldValue = this._createBeforePath; - this._createBeforePath = createPath; - //this.requestUpdate('_createPath', oldValue); - }, null); - this.observe(this.#context.createAfterPath, (createPath) => { - //const oldValue = this._createAfterPath; - this._createAfterPath = createPath; - //this.requestUpdate('_createPath', oldValue); - }, null); - this.observe(this.#context.workspaceEditContentPath, (path) => { - this._workspaceEditContentPath = path; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); - }, null); - this.observe(this.#context.workspaceEditSettingsPath, (path) => { - this._workspaceEditSettingsPath = path; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); - }, null); + this.observe( + this.#context.createBeforePath, + (createPath) => { + //const oldValue = this._createBeforePath; + this._createBeforePath = createPath; + //this.requestUpdate('_createPath', oldValue); + }, + null, + ); + this.observe( + this.#context.createAfterPath, + (createPath) => { + //const oldValue = this._createAfterPath; + this._createAfterPath = createPath; + //this.requestUpdate('_createPath', oldValue); + }, + null, + ); + this.observe( + this.#context.workspaceEditContentPath, + (path) => { + this._workspaceEditContentPath = path; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); + }, + null, + ); + this.observe( + this.#context.workspaceEditSettingsPath, + (path) => { + this._workspaceEditSettingsPath = path; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); + }, + null, + ); } override connectedCallback(): void { @@ -177,17 +240,25 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper }, 'rowSpan', ); - this.observe(this.#context.contentElementTypeKey, (contentElementTypeKey) => { - if (contentElementTypeKey) { - this.setAttribute('data-content-element-type-key', contentElementTypeKey); - } - }, 'contentElementTypeKey'); - this.observe(this.#context.contentElementTypeAlias, (contentElementTypeAlias) => { - if (contentElementTypeAlias) { - this._contentTypeAlias = contentElementTypeAlias; - this.setAttribute('data-content-element-type-alias', contentElementTypeAlias); - } - }, 'contentElementTypeAlias'); + this.observe( + this.#context.contentElementTypeKey, + (contentElementTypeKey) => { + if (contentElementTypeKey) { + this.setAttribute('data-content-element-type-key', contentElementTypeKey); + } + }, + 'contentElementTypeKey', + ); + this.observe( + this.#context.contentElementTypeAlias, + (contentElementTypeAlias) => { + if (contentElementTypeAlias) { + this._contentTypeAlias = contentElementTypeAlias; + this.setAttribute('data-content-element-type-alias', contentElementTypeAlias); + } + }, + 'contentElementTypeAlias', + ); this.#callUpdateInlineCreateButtons(); } @@ -234,15 +305,18 @@ export class UmbBlockGridEntryElement extends UmbLitElement implements UmbProper } }; - #extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => { - if(manifest.forContentTypeAlias && !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!)) { + #extensionSlotFilterMethod = (manifest: ManifestBlockEditorCustomView) => { + if ( + manifest.forContentTypeAlias && + !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!) + ) { return false; } - if(manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_GRID)) { + if (manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_GRID)) { return false; } return true; - } + }; #renderInlineEditBlock() { return html` = { contentUdi: undefined!, config: { showContentEdit: false, showSettingsEdit: false} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { + contentUdi: undefined!, + config: { showContentEdit: false, showSettingsEdit: false }, + }; // Set to undefined cause it will be set before we render. #updateBlockViewProps(incoming: Partial>) { this._blockViewProps = { ...this._blockViewProps, ...incoming }; @@ -68,75 +75,129 @@ export class UmbBlockListEntryElement extends UmbLitElement implements UmbProper constructor() { super(); - this.observe(this.#context.showContentEdit, (showContentEdit) => { - this._showContentEdit = showContentEdit; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showContentEdit } }); - }, null); - this.observe(this.#context.settingsElementTypeKey, (key) => { - this._hasSettings = !!key; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); - }, null); - this.observe(this.#context.blockType, (blockType) => { - this.#updateBlockViewProps({ blockType }); - }, null); + this.observe( + this.#context.showContentEdit, + (showContentEdit) => { + this._showContentEdit = showContentEdit; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showContentEdit } }); + }, + null, + ); + this.observe( + this.#context.settingsElementTypeKey, + (key) => { + this._hasSettings = !!key; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); + }, + null, + ); + this.observe( + this.#context.blockType, + (blockType) => { + this.#updateBlockViewProps({ blockType }); + }, + null, + ); // TODO: Implement index. - this.observe(this.#context.label, (label) => { - this.#updateBlockViewProps({ label }); - this._label = label; - }, null); - this.observe(this.#context.contentElementTypeIcon, (icon) => { - this.#updateBlockViewProps({ icon }); - this._icon = icon; - }, null); - this.observe(this.#context.inlineEditingMode, (inlineEditingMode) => { - this._inlineEditingMode = inlineEditingMode; - }, null); + this.observe( + this.#context.label, + (label) => { + this.#updateBlockViewProps({ label }); + this._label = label; + }, + null, + ); + this.observe( + this.#context.contentElementTypeIcon, + (icon) => { + this.#updateBlockViewProps({ icon }); + this._icon = icon; + }, + null, + ); + this.observe( + this.#context.inlineEditingMode, + (inlineEditingMode) => { + this._inlineEditingMode = inlineEditingMode; + }, + null, + ); // Data props: - this.observe(this.#context.layout, (layout) => { - this.#updateBlockViewProps({ layout }); - }, null); - this.observe(this.#context.content, (content) => { - this.#updateBlockViewProps({ content }); - }, null); - this.observe(this.#context.settings, (settings) => { - this.#updateBlockViewProps({ settings }); - }, null); - this.observe(this.#context.workspaceEditContentPath, (path) => { - this._workspaceEditContentPath = path; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); - }, null); - this.observe(this.#context.workspaceEditSettingsPath, (path) => { - this._workspaceEditSettingsPath = path; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); - }, null); + this.observe( + this.#context.layout, + (layout) => { + this.#updateBlockViewProps({ layout }); + }, + null, + ); + this.observe( + this.#context.content, + (content) => { + this.#updateBlockViewProps({ content }); + }, + null, + ); + this.observe( + this.#context.settings, + (settings) => { + this.#updateBlockViewProps({ settings }); + }, + null, + ); + this.observe( + this.#context.workspaceEditContentPath, + (path) => { + this._workspaceEditContentPath = path; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); + }, + null, + ); + this.observe( + this.#context.workspaceEditSettingsPath, + (path) => { + this._workspaceEditSettingsPath = path; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); + }, + null, + ); } - override connectedCallback(): void { super.connectedCallback(); // element styling: - this.observe(this.#context.contentElementTypeKey, (contentElementTypeKey) => { - if (contentElementTypeKey) { - this.setAttribute('data-content-element-type-key', contentElementTypeKey); - } - }, 'contentElementTypeKey'); - this.observe(this.#context.contentElementTypeAlias, (contentElementTypeAlias) => { - if (contentElementTypeAlias) { - this._contentTypeAlias = contentElementTypeAlias; - this.setAttribute('data-content-element-type-alias', contentElementTypeAlias); - } - }, 'contentElementTypeAlias'); + this.observe( + this.#context.contentElementTypeKey, + (contentElementTypeKey) => { + if (contentElementTypeKey) { + this.setAttribute('data-content-element-type-key', contentElementTypeKey); + } + }, + 'contentElementTypeKey', + ); + this.observe( + this.#context.contentElementTypeAlias, + (contentElementTypeAlias) => { + if (contentElementTypeAlias) { + this._contentTypeAlias = contentElementTypeAlias; + this.setAttribute('data-content-element-type-alias', contentElementTypeAlias); + } + }, + 'contentElementTypeAlias', + ); } - #extensionSlotFilterMethod = (manifest:ManifestBlockEditorCustomView) => { - if(manifest.forContentTypeAlias && !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!)) { + #extensionSlotFilterMethod = (manifest: ManifestBlockEditorCustomView) => { + if ( + manifest.forContentTypeAlias && + !stringOrStringArrayContains(manifest.forContentTypeAlias, this._contentTypeAlias!) + ) { return false; } - if(manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_LIST)) { + if (manifest.forBlockEditor && !stringOrStringArrayContains(manifest.forBlockEditor, UMB_BLOCK_LIST)) { return false; } return true; - } + }; #renderRefBlock() { return html``; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index c9b1a35958..bb7d574db6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -1,7 +1,7 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, customElement, property, state, repeat, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbPropertyEditorUiElement , UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { UmbPropertyEditorUiElement, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import { UmbPropertyValueChangeEvent, type UmbPropertyEditorConfigCollection, diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index e490028de7..487bbe5ac1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -1,6 +1,9 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { html, css, property, state, customElement } from '@umbraco-cms/backoffice/external/lit'; -import type { UmbBlockEditorCustomViewProperties, UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; +import type { + UmbBlockEditorCustomViewProperties, + UmbPropertyEditorUiElement, +} from '@umbraco-cms/backoffice/extension-registry'; import type { UmbBlockRteLayoutModel } from '../../types.js'; import { UmbBlockRteEntryContext } from '../../context/block-rte-entry.context.js'; import '../ref-rte-block/index.js'; @@ -43,7 +46,10 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert _workspaceEditSettingsPath?: string; @state() - _blockViewProps: UmbBlockEditorCustomViewProperties = { contentUdi: undefined!, config: { showContentEdit: false, showSettingsEdit: false} }; // Set to undefined cause it will be set before we render. + _blockViewProps: UmbBlockEditorCustomViewProperties = { + contentUdi: undefined!, + config: { showContentEdit: false, showSettingsEdit: false }, + }; // Set to undefined cause it will be set before we render. #updateBlockViewProps(incoming: Partial>) { this._blockViewProps = { ...this._blockViewProps, ...incoming }; @@ -64,36 +70,68 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert this._hasSettings = !!key; this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, showSettingsEdit: !!key } }); }); - this.observe(this.#context.blockType, (blockType) => { - this.#updateBlockViewProps({ blockType }); - }, null); + this.observe( + this.#context.blockType, + (blockType) => { + this.#updateBlockViewProps({ blockType }); + }, + null, + ); // TODO: Implement index. - this.observe(this.#context.label, (label) => { - this.#updateBlockViewProps({ label }); - this._label = label; - }, null); - this.observe(this.#context.contentElementTypeIcon, (icon) => { - this.#updateBlockViewProps({ icon }); - this._icon = icon; - }, null); + this.observe( + this.#context.label, + (label) => { + this.#updateBlockViewProps({ label }); + this._label = label; + }, + null, + ); + this.observe( + this.#context.contentElementTypeIcon, + (icon) => { + this.#updateBlockViewProps({ icon }); + this._icon = icon; + }, + null, + ); // Data props: - this.observe(this.#context.layout, (layout) => { - this.#updateBlockViewProps({ layout }); - }, null); - this.observe(this.#context.content, (content) => { - this.#updateBlockViewProps({ content }); - }, null); - this.observe(this.#context.settings, (settings) => { - this.#updateBlockViewProps({ settings }); - }, null); - this.observe(this.#context.workspaceEditContentPath, (path) => { - this._workspaceEditContentPath = path; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); - }, null); - this.observe(this.#context.workspaceEditSettingsPath, (path) => { - this._workspaceEditSettingsPath = path; - this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); - }, null); + this.observe( + this.#context.layout, + (layout) => { + this.#updateBlockViewProps({ layout }); + }, + null, + ); + this.observe( + this.#context.content, + (content) => { + this.#updateBlockViewProps({ content }); + }, + null, + ); + this.observe( + this.#context.settings, + (settings) => { + this.#updateBlockViewProps({ settings }); + }, + null, + ); + this.observe( + this.#context.workspaceEditContentPath, + (path) => { + this._workspaceEditContentPath = path; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editContentPath: path } }); + }, + null, + ); + this.observe( + this.#context.workspaceEditSettingsPath, + (path) => { + this._workspaceEditSettingsPath = path; + this.#updateBlockViewProps({ config: { ...this._blockViewProps.config, editSettingsPath: path } }); + }, + null, + ); } override connectedCallback() { diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts index aa5f55f519..dccd64dad7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/types.ts @@ -1,4 +1,4 @@ -import type { UmbBlockTypeBaseModel } from "@umbraco-cms/backoffice/extension-registry"; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; export interface UmbBlockTypeGroup { name?: string; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts index 39230828c0..c7ef98965c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/workspace/block-type-workspace.context.ts @@ -11,7 +11,11 @@ import { } from '@umbraco-cms/backoffice/workspace'; import { UmbArrayState, UmbObjectState, appendToFrozenArray } from '@umbraco-cms/backoffice/observable-api'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; -import type { ManifestWorkspace, PropertyEditorSettingsProperty, UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +import type { + ManifestWorkspace, + PropertyEditorSettingsProperty, + UmbBlockTypeBaseModel, +} from '@umbraco-cms/backoffice/extension-registry'; import type { UmbBlockTypeWithGroupKey } from '../types.js'; import { UmbBlockTypeWorkspaceEditorElement } from './block-type-workspace-editor.element.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts index caf4f56803..7c11cec0ac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/types.ts @@ -1,5 +1,5 @@ -import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from "@umbraco-cms/backoffice/extension-registry"; -export type { UmbBlockDataType, UmbBlockLayoutBaseModel } from "@umbraco-cms/backoffice/extension-registry"; +import type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/extension-registry'; +export type { UmbBlockDataType, UmbBlockLayoutBaseModel } from '@umbraco-cms/backoffice/extension-registry'; export interface UmbBlockValueType { layout: { [key: string]: Array | undefined }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts index 7f5d1bcc1a..9ac9fff679 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/custom-view.element.ts @@ -1,17 +1,14 @@ -import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from "@umbraco-cms/backoffice/extension-registry"; -import { css, customElement, html, property } from "@umbraco-cms/backoffice/external/lit"; -import { UmbLitElement } from "@umbraco-cms/backoffice/lit-element"; +import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import { css, customElement, html, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-custom-view-test') export class UmbCustomViewTestElement extends UmbLitElement implements UmbBlockEditorCustomViewElement { - - @property({attribute: false}) + @property({ attribute: false }) content?: UmbBlockDataType; protected override render() { - return html` - Hello ${this.content?.headline} - ` + return html` Hello ${this.content?.headline} `; } static override styles = [ @@ -24,8 +21,8 @@ export class UmbCustomViewTestElement extends UmbLitElement implements UmbBlockE border-radius: 9px; padding: 12px; } - ` - ] + `, + ]; } -export {UmbCustomViewTestElement as element}; +export { UmbCustomViewTestElement as element }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts index 69b00c5af3..71839f5ac4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/custom-view/manifest.ts @@ -1,10 +1,10 @@ import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; -export const manifest:ManifestBlockEditorCustomView = { +export const manifest: ManifestBlockEditorCustomView = { type: 'blockEditorCustomView', alias: 'Umb.blockEditorCustomView.TestView', name: 'Block Editor Custom View Test', element: () => import('./custom-view.element.js'), forContentTypeAlias: 'elementTypeHeadline', - forBlockEditor: 'block-grid' -} + forBlockEditor: 'block-grid', +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts index 2650f5f78d..64e181b997 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts @@ -129,13 +129,15 @@ export class UmbExtensionSlotElement extends UmbLitElement { } override render() { - return this._permitted ? this._permitted.length > 0 - ? repeat( - this._permitted, - (ext) => ext.alias, - (ext, i) => (this.renderMethod ? this.renderMethod(ext, i) : ext.component), - ) - : html`` : ''; + return this._permitted + ? this._permitted.length > 0 + ? repeat( + this._permitted, + (ext) => ext.alias, + (ext, i) => (this.renderMethod ? this.renderMethod(ext, i) : ext.component), + ) + : html`` + : ''; } static override styles = css` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts index ab41814cf9..fbd7c64640 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-with-api-slot/extension-with-api-slot.element.ts @@ -178,13 +178,15 @@ export class UmbExtensionWithApiSlotElement extends UmbLitElement { } override render() { - return this._permitted ? this._permitted.length > 0 - ? repeat( - this._permitted, - (ext) => ext.alias, - (ext, i) => (this.renderMethod ? this.renderMethod(ext, i) : ext.component), - ) - : html`` : ''; + return this._permitted + ? this._permitted.length > 0 + ? repeat( + this._permitted, + (ext) => ext.alias, + (ext, i) => (this.renderMethod ? this.renderMethod(ext, i) : ext.component), + ) + : html`` + : ''; } static override styles = css` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts index e3ffa6bec1..df8e645764 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/interfaces/block-editor-custom-view-element.interface.ts @@ -1,6 +1,5 @@ - import type { UUIModalSidebarSize } from '@umbraco-cms/backoffice/external/uui'; -import type { ManifestBlockEditorCustomView } from "../index.js"; +import type { ManifestBlockEditorCustomView } from '../index.js'; // Shared with the Property Editor export interface UmbBlockTypeBaseModel { contentElementTypeKey: string; @@ -33,8 +32,10 @@ export interface UmbBlockEditorCustomViewConfiguration { showSettingsEdit: boolean; } - -export interface UmbBlockEditorCustomViewProperties { +export interface UmbBlockEditorCustomViewProperties< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> { manifest?: ManifestBlockEditorCustomView; config?: Partial; blockType?: BlockType; @@ -47,6 +48,8 @@ export interface UmbBlockEditorCustomViewProperties extends UmbBlockEditorCustomViewProperties, HTMLElement { - -} +export interface UmbBlockEditorCustomViewElement< + LayoutType extends UmbBlockLayoutBaseModel = UmbBlockLayoutBaseModel, + BlockType extends UmbBlockTypeBaseModel = UmbBlockTypeBaseModel, +> extends UmbBlockEditorCustomViewProperties, + HTMLElement {} From e57999c9b80e09f52eff8608ff8a1e58539b18c1 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 4 Jul 2024 08:58:03 +0200 Subject: [PATCH 056/325] fix: import as type --- .../components/input-block-type/input-block-type.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts index 53f668c504..cade6212d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.element.ts @@ -12,9 +12,9 @@ import { UMB_DOCUMENT_TYPE_PICKER_MODAL, } from '@umbraco-cms/backoffice/document-type'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; +import type { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; import '../block-type-card/index.js'; -import { UmbBlockTypeBaseModel } from '@umbraco-cms/backoffice/extension-registry'; /** TODO: Look into sending a "change" event when there is a change, rather than create, delete, and change event. Make sure it doesn't break move for RTE/List/Grid. [LI] */ @customElement('umb-input-block-type') From 42af60e2ae2454c9455884d6403996ee61f9007d Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:12:34 +0200 Subject: [PATCH 057/325] type checking --- .../core/resources/resource.controller.ts | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts index ebd873902b..244a22e8f2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts @@ -1,13 +1,15 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { UMB_AUTH_CONTEXT } from '../auth/index.js'; +import { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidators.function.js'; import { html } from '@umbraco-cms/backoffice/external/lit'; import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-api'; -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { UMB_AUTH_CONTEXT } from '../auth/index.js'; -import { isApiError, isCancelError, isCancelablePromise } from './apiTypeValidators.function.js'; import { UMB_NOTIFICATION_CONTEXT, type UmbNotificationOptions } from '@umbraco-cms/backoffice/notification'; import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; +export type ErrorMessageText = { category: string; messages: string[] }; + export class UmbResourceController extends UmbControllerBase { #promise: Promise; @@ -37,12 +39,15 @@ export class UmbResourceController extends UmbControllerBase { this.cancel(); } - #buildApiErrorMessage(error: any) { - const entries: Array> = []; + #buildApiErrorMessage(error: ErrorMessageText) { + if (!error) return undefined; + if (typeof error !== 'object') return undefined; - Object.entries(error).forEach(([category, message]) => { - entries.push({ category, messages: message as string[] }); + const entries: Array> = []; + Object.entries(error).forEach(([property, message]) => { + entries.push({ property, messages: Array.isArray(message) ? message : [message] }); }); + const template = html` ${entries.map((e) => e.messages.map((msg: string) => html`
${msg}
`))}`; return template; @@ -141,7 +146,7 @@ export class UmbResourceController extends UmbControllerBase { default: // Other errors if (this.#notificationContext) { - const message = error.body?.errors ? this.#buildApiErrorMessage(error.body.errors) : undefined; + const message = this.#buildApiErrorMessage(error?.body?.errors); this.#notificationContext.peek('danger', { data: { headline: error.body?.title ?? error.name ?? 'Server Error', From efb9541cd45d7c942b173a8719972d57ae284ddd Mon Sep 17 00:00:00 2001 From: Lone Iversen <108085781+loivsen@users.noreply.github.com> Date: Thu, 4 Jul 2024 09:20:57 +0200 Subject: [PATCH 058/325] type --- .../src/packages/core/resources/resource.controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts index 244a22e8f2..b7e20d1df3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/resources/resource.controller.ts @@ -8,7 +8,7 @@ import { UmbContextConsumerController } from '@umbraco-cms/backoffice/context-ap import { UMB_NOTIFICATION_CONTEXT, type UmbNotificationOptions } from '@umbraco-cms/backoffice/notification'; import type { UmbDataSourceResponse } from '@umbraco-cms/backoffice/repository'; -export type ErrorMessageText = { category: string; messages: string[] }; +export type ErrorMessageText = { property: string; messages: string[] }; export class UmbResourceController extends UmbControllerBase { #promise: Promise; @@ -43,7 +43,7 @@ export class UmbResourceController extends UmbControllerBase { if (!error) return undefined; if (typeof error !== 'object') return undefined; - const entries: Array> = []; + const entries: Array = []; Object.entries(error).forEach(([property, message]) => { entries.push({ property, messages: Array.isArray(message) ? message : [message] }); }); From b2232cef6e9dabcddca8497b3bbef4a682276e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 4 Jul 2024 11:12:22 +0200 Subject: [PATCH 059/325] property type workspace --- src/Umbraco.Web.UI.Client/package.json | 7 +- .../src/packages/core/manifests.ts | 2 + .../src/packages/core/property-type/index.ts | 1 + .../packages/core/property-type/manifests.ts | 4 + .../src/packages/core/property-type/types.ts | 3 + .../core/property-type/workspace/constants.ts | 1 + .../core/property-type/workspace/index.ts | 2 + .../core/property-type/workspace/manifests.ts | 57 +++ .../property-type-workspace-editor.element.ts | 64 +++ .../property-type-workspace.context-token.ts | 12 + .../property-type-workspace.context.ts | 189 +++++++ .../property-type-workspace.modal-token.ts | 18 + ...roperty-workspace-view-settings.element.ts | 469 ++++++++++++++++++ src/Umbraco.Web.UI.Client/tsconfig.json | 7 +- 14 files changed, 830 insertions(+), 6 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/types.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/constants.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace-editor.element.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.modal-token.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/views/settings/property-workspace-view-settings.element.ts diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 51043adc87..75cf4b4e06 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -25,8 +25,8 @@ "./code-editor": "./dist-cms/packages/templating/code-editor/index.js", "./collection": "./dist-cms/packages/core/collection/index.js", "./components": "./dist-cms/packages/core/components/index.js", - "./content": "./dist-cms/packages/core/content/index.js", "./content-type": "./dist-cms/packages/core/content-type/index.js", + "./content": "./dist-cms/packages/core/content/index.js", "./culture": "./dist-cms/packages/core/culture/index.js", "./current-user": "./dist-cms/packages/user/current-user/index.js", "./data-type": "./dist-cms/packages/data-type/index.js", @@ -35,9 +35,9 @@ "./document-blueprint": "./dist-cms/packages/documents/document-blueprints/index.js", "./document-type": "./dist-cms/packages/documents/document-types/index.js", "./document": "./dist-cms/packages/documents/documents/index.js", - "./entity": "./dist-cms/packages/core/entity/index.js", "./entity-action": "./dist-cms/packages/core/entity-action/index.js", "./entity-bulk-action": "./dist-cms/packages/core/entity-bulk-action/index.js", + "./entity": "./dist-cms/packages/core/entity/index.js", "./event": "./dist-cms/packages/core/event/index.js", "./extension-registry": "./dist-cms/packages/core/extension-registry/index.js", "./icon": "./dist-cms/packages/core/icon-registry/index.js", @@ -63,6 +63,7 @@ "./picker-input": "./dist-cms/packages/core/picker-input/index.js", "./property-action": "./dist-cms/packages/core/property-action/index.js", "./property-editor": "./dist-cms/packages/core/property-editor/index.js", + "./property-type": "./dist-cms/packages/core/property-type/index.js", "./property": "./dist-cms/packages/core/property/index.js", "./recycle-bin": "./dist-cms/packages/core/recycle-bin/index.js", "./relation-type": "./dist-cms/packages/relations/relation-types/index.js", @@ -73,8 +74,8 @@ "./script": "./dist-cms/packages/templating/scripts/index.js", "./search": "./dist-cms/packages/search/index.js", "./section": "./dist-cms/packages/core/section/index.js", - "./settings": "./dist-cms/packages/settings/index.js", "./server-file-system": "./dist-cms/packages/core/server-file-system/index.js", + "./settings": "./dist-cms/packages/settings/index.js", "./sorter": "./dist-cms/packages/core/sorter/index.js", "./static-file": "./dist-cms/packages/static-file/index.js", "./store": "./dist-cms/packages/core/store/index.js", diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts index 460f7acc8d..5f6f036ea4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/manifests.ts @@ -10,6 +10,7 @@ import { manifests as iconRegistryManifests } from './icon-registry/manifests.js import { manifests as localizationManifests } from './localization/manifests.js'; import { manifests as modalManifests } from './modal/common/manifests.js'; import { manifests as propertyActionManifests } from './property-action/manifests.js'; +import { manifests as propertyTypeManifests } from './property-type/manifests.js'; import { manifests as recycleBinManifests } from './recycle-bin/manifests.js'; import { manifests as sectionManifests } from './section/manifests.js'; import { manifests as serverFileSystemManifests } from './server-file-system/manifests.js'; @@ -33,6 +34,7 @@ export const manifests: Array = [ ...workspaceManifests, ...contentManifests, ...contentTypeManifests, + ...propertyTypeManifests, ...settingsManifests, ...modalManifests, ...entityActionManifests, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/index.ts new file mode 100644 index 0000000000..60f06132a7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/index.ts @@ -0,0 +1 @@ +export * from './workspace/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/manifests.ts new file mode 100644 index 0000000000..71c165c901 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/manifests.ts @@ -0,0 +1,4 @@ +import { manifests as workspaceManifests } from './workspace/manifests.js'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [...workspaceManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/types.ts new file mode 100644 index 0000000000..b4e94d4763 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/types.ts @@ -0,0 +1,3 @@ +import type { UmbPropertyTypeModel, UmbPropertyTypeScaffoldModel } from '@umbraco-cms/backoffice/content-type'; + +export type UmbPropertyTypeData = UmbPropertyTypeModel | UmbPropertyTypeScaffoldModel; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/constants.ts new file mode 100644 index 0000000000..9ef9d5cc4e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/constants.ts @@ -0,0 +1 @@ +export const UMB_PROPERTY_TYPE_WORKSPACE_ALIAS = 'Umb.Workspace.PropertyType'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/index.ts new file mode 100644 index 0000000000..63e62a58f3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/index.ts @@ -0,0 +1,2 @@ +export * from './property-type-workspace.context-token.js'; +export * from './property-type-workspace.modal-token.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts new file mode 100644 index 0000000000..dc63643c96 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/manifests.ts @@ -0,0 +1,57 @@ +import { UMB_PROPERTY_TYPE_WORKSPACE_ALIAS } from './constants.js'; +import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; +import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'workspace', + kind: 'routable', + name: 'Block Workspace', + alias: UMB_PROPERTY_TYPE_WORKSPACE_ALIAS, + api: () => import('./property-type-workspace.context.js'), + meta: { + entityType: 'property-type', + }, + }, + { + type: 'workspaceView', + alias: 'Umb.WorkspaceView.PropertyType.Settings', + name: 'Block Workspace Content View', + js: () => import('./views/settings/property-workspace-view-settings.element.js'), + weight: 1000, + meta: { + label: '#general_content', + pathname: 'content', + icon: 'icon-document', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + match: UMB_PROPERTY_TYPE_WORKSPACE_ALIAS, + }, + ], + TODO_conditions: [ + { + alias: 'Umb.Condition.BlockEntryShowContentEdit', + }, + ], + }, + { + type: 'workspaceAction', + kind: 'default', + alias: 'Umb.WorkspaceAction.PropertyType.Submit', + name: 'Submit Property Type Workspace Action', + api: UmbSubmitWorkspaceAction, + meta: { + label: '#general_submit', + look: 'primary', + color: 'positive', + }, + conditions: [ + { + alias: 'Umb.Condition.WorkspaceAlias', + oneOf: [UMB_PROPERTY_TYPE_WORKSPACE_ALIAS], + }, + ], + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace-editor.element.ts new file mode 100644 index 0000000000..b3317b8407 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace-editor.element.ts @@ -0,0 +1,64 @@ +import { UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT } from './property-type-workspace.context-token.js'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { customElement, css, html, state, property } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UmbRepositoryItemsManager } from '@umbraco-cms/backoffice/repository'; +import type { UmbDocumentTypeItemModel } from '@umbraco-cms/backoffice/document-type'; +import { UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS } from '@umbraco-cms/backoffice/document-type'; + +@customElement('umb-property-type-workspace-editor') +export class UmbPropertyTypeWorkspaceEditorElement extends UmbLitElement { + // + #itemManager = new UmbRepositoryItemsManager( + this, + UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, + (x) => x.unique, + ); + + #workspaceContext?: typeof UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT.TYPE; + + @state() + _name?: string; + + @property({ type: String, attribute: false }) + workspaceAlias?: string; + + constructor() { + super(); + + this.consumeContext(UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT, (instance) => { + this.#workspaceContext = instance; + this.#workspaceContext?.createPropertyDatasetContext(this); + }); + } + + override render() { + return this.workspaceAlias + ? html` + + + ` + : ''; + } + + static override styles = [ + UmbTextStyles, + css` + :host { + display: block; + width: 100%; + height: 100%; + } + `, + ]; +} + +export default UmbPropertyTypeWorkspaceEditorElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-property-type-workspace-editor': UmbPropertyTypeWorkspaceEditorElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context-token.ts new file mode 100644 index 0000000000..60e6347d8f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context-token.ts @@ -0,0 +1,12 @@ +import type { UmbPropertyTypeWorkspaceContext } from './property-type-workspace.context.js'; +import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; +import type { UmbWorkspaceContext } from '@umbraco-cms/backoffice/workspace'; + +export const UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT = new UmbContextToken< + UmbWorkspaceContext, + UmbPropertyTypeWorkspaceContext +>( + 'UmbWorkspaceContext', + undefined, + (context): context is UmbPropertyTypeWorkspaceContext => (context as any).IS_PROPERTY_TYPE_WORKSPACE_CONTEXT, +); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts new file mode 100644 index 0000000000..d159e11a51 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.context.ts @@ -0,0 +1,189 @@ +import { UmbPropertyTypeWorkspaceEditorElement } from './property-type-workspace-editor.element.js'; +import type { UmbPropertyDatasetContext } from '@umbraco-cms/backoffice/property'; +import type { + UmbInvariantDatasetWorkspaceContext, + UmbRoutableWorkspaceContext, +} from '@umbraco-cms/backoffice/workspace'; +import { + UmbSubmittableWorkspaceContextBase, + UmbInvariantWorkspacePropertyDatasetContext, + UmbWorkspaceIsNewRedirectController, +} from '@umbraco-cms/backoffice/workspace'; +import { UmbObjectState } from '@umbraco-cms/backoffice/observable-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { ManifestWorkspace } from '@umbraco-cms/backoffice/extension-registry'; +import { + UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, + UmbPropertyTypeModel, + UmbPropertyTypeSettingsModalData, +} from '@umbraco-cms/backoffice/content-type'; +import { UmbId } from '@umbraco-cms/backoffice/id'; +import { UmbPropertyTypeData } from '../types.js'; + +export class UmbPropertyTypeWorkspaceContext + extends UmbSubmittableWorkspaceContextBase + implements UmbInvariantDatasetWorkspaceContext, UmbRoutableWorkspaceContext +{ + // Just for context token safety: + public readonly IS_PROPERTY_TYPE_WORKSPACE_CONTEXT = true; + + #entityType: string; + #data = new UmbObjectState(undefined); + readonly data = this.#data.asObservable(); + + readonly name = this.#data.asObservablePart((data) => data?.name); + readonly unique = this.#data.asObservablePart((data) => data?.id); + + constructor(host: UmbControllerHost, args: { manifest: ManifestWorkspace }) { + super(host, args.manifest.alias); + const manifest = args.manifest; + this.#entityType = manifest.meta?.entityType; + + this.routes.setRoutes([ + { + // Would it make more sense to have groupKey before elementTypeKey? + path: 'create/:containerUnique', + component: UmbPropertyTypeWorkspaceEditorElement, + setup: async (component, info) => { + (component as UmbPropertyTypeWorkspaceEditorElement).workspaceAlias = manifest.alias; + + const containerUnique = + info.match.params.containerUnique === 'null' ? null : info.match.params.containerUnique; + this.create(containerUnique); + + new UmbWorkspaceIsNewRedirectController( + this, + this, + this.getHostElement().shadowRoot!.querySelector('umb-router-slot')!, + ); + }, + }, + { + path: 'edit/:unique', + component: UmbPropertyTypeWorkspaceEditorElement, + setup: (component, info) => { + (component as UmbPropertyTypeWorkspaceEditorElement).workspaceAlias = manifest.alias; + + const unique = info.match.params.unique; + this.load(unique); + }, + }, + ]); + } + + protected override resetState() { + super.resetState(); + this.#data.setValue(undefined); + } + + createPropertyDatasetContext(host: UmbControllerHost): UmbPropertyDatasetContext { + return new UmbInvariantWorkspacePropertyDatasetContext(host, this); + } + + async load(unique: string) { + this.resetState(); + const context = await this.getContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT); + this.observe(await context.structure.propertyStructureById(unique), (property) => { + if (property) { + this.#data.setValue(property as PropertyTypeData); + } + // Fallback to undefined: + this.#data.setValue(undefined); + }); + } + + async create(containerId?: string | null) { + this.resetState(); + + let data: PropertyTypeData = { + id: UmbId.new(), + container: containerId ? { id: containerId } : null, + alias: '', + name: '', + description: '', + variesByCulture: false, + variesBySegment: false, + validation: { + mandatory: false, + mandatoryMessage: null, + regEx: null, + regExMessage: null, + }, + appearance: { + labelOnTop: false, + }, + sortOrder: 0, + } as PropertyTypeData; + + // If we have a modal context, we blend in the modal preset data: [NL] + if (this.modalContext) { + data = { ...data, ...this.modalContext.data.preset }; + } + + this.setIsNew(true); + this.#data.setValue(data); + return { data }; + } + + getData() { + return this.#data.getValue(); + } + updateData(partialData: Partial) { + this.#data?.update(partialData); + } + + getUnique() { + return this.getData()!.id; + } + + getEntityType() { + return this.#entityType; + } + + getName() { + return this.#data.getValue()?.name; + } + setName(name: string | undefined) { + this.#data.update({ name: name }); + } + + async propertyValueByAlias(propertyAlias: string) { + return this.#data.asObservablePart((data) => data?.[propertyAlias as keyof PropertyTypeData] as ReturnType); + } + + getPropertyValue(propertyAlias: string) { + return this.#data.getValue()?.[propertyAlias as keyof PropertyTypeData] as ReturnType; + } + + async setPropertyValue(alias: string, value: unknown) { + const currentData = this.#data.value; + if (currentData) { + this.#data.update({ ...currentData, [alias]: value }); + } + } + + async submit() { + if (!this.modalContext) { + throw new Error('Needs to be in a modal to submit.'); + } + const contentTypeUnique = (this.modalContext.data as unknown as UmbPropertyTypeSettingsModalData).contentTypeUnique; + + const data = this.#data.getValue(); + if (!data) { + throw new Error('No data to submit.'); + } + + const context = await this.getContext(UMB_CONTENT_TYPE_WORKSPACE_CONTEXT); + + context.structure.insertProperty(contentTypeUnique, data); + + this.setIsNew(false); + } + + public override destroy(): void { + this.#data.destroy(); + super.destroy(); + } +} + +export { UmbPropertyTypeWorkspaceContext as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.modal-token.ts new file mode 100644 index 0000000000..12d1784ffa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/property-type-workspace.modal-token.ts @@ -0,0 +1,18 @@ +import type { UmbWorkspaceModalData, UmbWorkspaceModalValue } from '@umbraco-cms/backoffice/modal'; +import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; + +export interface UmbBlockWorkspaceData extends UmbWorkspaceModalData { + originData: OriginDataType; +} + +export const UMB_PROPERTY_TYPE_WORKSPACE_MODAL = new UmbModalToken( + 'Umb.Modal.Workspace', + { + modal: { + type: 'sidebar', + size: 'small', + }, + data: { entityType: 'property-type', preset: {}, originData: {} }, + }, + // Recast the type, so the entityType data prop is not required: +) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/views/settings/property-workspace-view-settings.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/views/settings/property-workspace-view-settings.element.ts new file mode 100644 index 0000000000..59b5bf5115 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-type/workspace/views/settings/property-workspace-view-settings.element.ts @@ -0,0 +1,469 @@ +import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { UmbLitElement, umbFocus } from '@umbraco-cms/backoffice/lit-element'; +import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; +import { UMB_CONTENT_TYPE_WORKSPACE_CONTEXT, UmbPropertyTypeModel } from '@umbraco-cms/backoffice/content-type'; +import { UUIBooleanInputEvent, UUIInputEvent, UUISelectEvent } from '@umbraco-cms/backoffice/external/uui'; +import { generateAlias } from '@umbraco-cms/backoffice/utils'; +import { UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT } from '../../../index.js'; + +@customElement('umb-property-type-workspace-view-settings') +export class UmbPropertyTypeWorkspaceViewSettingsElement extends UmbLitElement implements UmbWorkspaceViewElement { + #context?: typeof UMB_PROPERTY_TYPE_WORKSPACE_CONTEXT.TYPE; + + @state() private _customValidationOptions: Array