From bd49774d28036f96f02ac9d1a14e86cc9fdd4d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 29 Jul 2024 14:56:08 +0200 Subject: [PATCH 01/48] example --- .../examples/property-editor/README.md | 7 ++++++ .../examples/property-editor/index.ts | 25 +++++++++++++++++++ .../property-editor/property-editor.ts | 20 +++++++++++++++ .../property-editor-config.element.ts | 5 ++-- 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/examples/property-editor/README.md create mode 100644 src/Umbraco.Web.UI.Client/examples/property-editor/index.ts create mode 100644 src/Umbraco.Web.UI.Client/examples/property-editor/property-editor.ts diff --git a/src/Umbraco.Web.UI.Client/examples/property-editor/README.md b/src/Umbraco.Web.UI.Client/examples/property-editor/README.md new file mode 100644 index 0000000000..e0894b30b7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/property-editor/README.md @@ -0,0 +1,7 @@ +# Property Dataset Dashboard Example + +This example is a work in progress example of how to write a property editor. + +This example covers a few points: + +- Using an existing Property Editor Schema diff --git a/src/Umbraco.Web.UI.Client/examples/property-editor/index.ts b/src/Umbraco.Web.UI.Client/examples/property-editor/index.ts new file mode 100644 index 0000000000..4d7c9c26fa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/property-editor/index.ts @@ -0,0 +1,25 @@ +import type { ManifestPropertyEditorUi } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'propertyEditorUi', + alias: 'example.propertyEditorUi.propertyEditor', + name: 'Example Property Editor UI', + element: () => import('./property-editor.js'), + meta: { + label: 'Example Editor', + propertyEditorSchemaAlias: 'Umbraco.ListView', + icon: 'icon-code', + group: 'common', + settings: { + properties: [ + { + alias: 'customText', + label: 'Custom text', + propertyEditorUiAlias: 'Umb.PropertyEditorUi.TextBox', + }, + ], + }, + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/examples/property-editor/property-editor.ts b/src/Umbraco.Web.UI.Client/examples/property-editor/property-editor.ts new file mode 100644 index 0000000000..029d1f9b4e --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/property-editor/property-editor.ts @@ -0,0 +1,20 @@ +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { html, customElement, LitElement } from '@umbraco-cms/backoffice/external/lit'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; + +@customElement('example-property-editor') +export class ExamplePropertyEditor extends UmbElementMixin(LitElement) { + override render() { + return html`

Property Editor Example

`; + } + + static override styles = [UmbTextStyles]; +} + +export default ExamplePropertyEditor; + +declare global { + interface HTMLElementTagNameMap { + 'example-property-editor': ExamplePropertyEditor; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts index 58953b5163..1282735778 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts @@ -12,7 +12,7 @@ import { UmbDataPathPropertyValueFilter } from '@umbraco-cms/backoffice/validati */ @customElement('umb-property-editor-config') export class UmbPropertyEditorConfigElement extends UmbLitElement { - // TODO: Make this element generic, so its not bound to DATA-TYPEs. This will require moving some functionality of Data-Type-Context to this. and this might need to self provide a variant Context for its inner property editor UIs. + // TODO: Make this element generic, so its not bound to DATA-TYPEs. This will require moving some functionality of Data-Type-Context to this. and this might need to self provide a variant Context for its inner property editor UIs. [NL] #workspaceContext?: typeof UMB_DATA_TYPE_WORKSPACE_CONTEXT.TYPE; @state() @@ -53,7 +53,8 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement { property-editor-ui-alias=${property.propertyEditorUiAlias} .config=${property.config}>`, ) - : html`
No configuration
`; + : // TODO: Localize this [NL] + html`
No configuration
`; } static override styles = [UmbTextStyles]; From 76be31eb3f1452602627f61d00c0b407dbc44e05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 29 Jul 2024 16:11:30 +0200 Subject: [PATCH 02/48] set default data --- src/Umbraco.Web.UI.Client/examples/property-editor/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/examples/property-editor/index.ts b/src/Umbraco.Web.UI.Client/examples/property-editor/index.ts index 4d7c9c26fa..389e110866 100644 --- a/src/Umbraco.Web.UI.Client/examples/property-editor/index.ts +++ b/src/Umbraco.Web.UI.Client/examples/property-editor/index.ts @@ -19,6 +19,12 @@ export const manifests: Array = [ propertyEditorUiAlias: 'Umb.PropertyEditorUi.TextBox', }, ], + defaultData: [ + { + alias: 'customText', + value: 'Default value', + }, + ], }, }, }, From 7bcc429137a60ff6e6115389ffa7cce1e784119d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 29 Jul 2024 16:11:50 +0200 Subject: [PATCH 03/48] refactor merge data flow --- .../workspace/data-type-workspace.context.ts | 79 +++++++++++-------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index 4442f73ec6..59b38280ef 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -72,8 +72,6 @@ export class UmbDataTypeWorkspaceContext #settingsDefaultData?: Array; - #propertyEditorUISettingsSchemaAlias?: string; - #propertyEditorUiIcon = new UmbStringState(null); readonly propertyEditorUiIcon = this.#propertyEditorUiIcon.asObservable(); @@ -82,6 +80,8 @@ export class UmbDataTypeWorkspaceContext constructor(host: UmbControllerHost) { super(host, 'Umb.Workspace.DataType'); + + this.#observePropertyEditorSchemaAlias(); this.#observePropertyEditorUIAlias(); this.routes.setRoutes([ @@ -121,7 +121,7 @@ export class UmbDataTypeWorkspaceContext this.#propertyEditorUISettingsDefaultData = []; this.#settingsDefaultData = undefined; - this._mergeConfigProperties(); + this.#mergeConfigProperties(); } // Hold the last set property editor ui alias, so we know when it changes, so we can reset values. [NL] @@ -131,30 +131,13 @@ export class UmbDataTypeWorkspaceContext this.observe( this.propertyEditorUiAlias, async (propertyEditorUiAlias) => { - const previousPropertyEditorUIAlias = this.#lastPropertyEditorUIAlias; - this.#lastPropertyEditorUIAlias = propertyEditorUiAlias; + this.#propertyEditorUISettingsProperties = []; + this.#propertyEditorUISettingsDefaultData = []; + // we only want to react on the change if the alias is set or null. When it is undefined something is still loading if (propertyEditorUiAlias === undefined) return; - // if the property editor ui alias is not set, we use the default alias from the schema - if (propertyEditorUiAlias === null) { - await this.#observePropertyEditorSchemaAlias(); - if (this.#propertyEditorSchemaConfigDefaultUIAlias !== null) { - this.setPropertyEditorUiAlias(this.#propertyEditorSchemaConfigDefaultUIAlias); - } - } else { - await this.#setPropertyEditorUIConfig(propertyEditorUiAlias); - this.setPropertyEditorSchemaAlias(this.#propertyEditorUISettingsSchemaAlias!); - await this.#observePropertyEditorSchemaAlias(); - } - - if ( - this.getIsNew() || - (previousPropertyEditorUIAlias && previousPropertyEditorUIAlias !== propertyEditorUiAlias) - ) { - this.#transferConfigDefaultData(); - } - this._mergeConfigProperties(); + this.#observePropertyEditorUIConfig(propertyEditorUiAlias); }, 'editorUiAlias', ); @@ -164,13 +147,19 @@ export class UmbDataTypeWorkspaceContext return this.observe( this.propertyEditorSchemaAlias, (propertyEditorSchemaAlias) => { - this.#setPropertyEditorSchemaConfig(propertyEditorSchemaAlias); + this.#propertyEditorSchemaSettingsProperties = []; + this.#propertyEditorSchemaSettingsDefaultData = []; + this.#observePropertyEditorSchemaConfig(propertyEditorSchemaAlias); }, 'schemaAlias', - ).asPromise(); + ); } - #setPropertyEditorSchemaConfig(propertyEditorSchemaAlias?: string) { + #observePropertyEditorSchemaConfig(propertyEditorSchemaAlias?: string) { + if (!propertyEditorSchemaAlias) { + this.removeUmbControllerByAlias('schema'); + return; + } this.observe( propertyEditorSchemaAlias ? umbExtensionsRegistry.byTypeAndAlias('propertyEditorSchema', propertyEditorSchemaAlias) @@ -183,36 +172,56 @@ export class UmbDataTypeWorkspaceContext })); this.#propertyEditorSchemaSettingsDefaultData = manifest?.meta.settings?.defaultData || []; this.#propertyEditorSchemaConfigDefaultUIAlias = manifest?.meta.defaultPropertyEditorUiAlias || null; + if (this.#propertyEditorSchemaConfigDefaultUIAlias && this.getPropertyEditorUiAlias() === null) { + // Fallback to the default property editor ui for this property editor schema. + this.setPropertyEditorUiAlias(this.#propertyEditorSchemaConfigDefaultUIAlias); + } + this.#mergeConfigProperties(); }, 'schema', ); } - #setPropertyEditorUIConfig(propertyEditorUIAlias: string) { - return this.observe( + #observePropertyEditorUIConfig(propertyEditorUIAlias: string | null) { + if (!propertyEditorUIAlias) { + this.removeUmbControllerByAlias('editorUi'); + return; + } + this.observe( umbExtensionsRegistry.byTypeAndAlias('propertyEditorUi', propertyEditorUIAlias), (manifest) => { this.#propertyEditorUiIcon.setValue(manifest?.meta.icon || null); this.#propertyEditorUiName.setValue(manifest?.name || null); - this.#propertyEditorUISettingsSchemaAlias = manifest?.meta.propertyEditorSchemaAlias; // Maps properties to have a weight, so they can be sorted, notice UI properties have a +1000 weight compared to schema properties. this.#propertyEditorUISettingsProperties = (manifest?.meta.settings?.properties ?? []).map((x, i) => ({ ...x, weight: x.weight ?? 1000 + i, })); this.#propertyEditorUISettingsDefaultData = manifest?.meta.settings?.defaultData || []; + this.setPropertyEditorSchemaAlias(manifest?.meta.propertyEditorSchemaAlias); + this.#mergeConfigProperties(); }, 'editorUi', - ).asPromise(); + ); } - private _mergeConfigProperties() { + #mergeConfigProperties() { if (this.#propertyEditorSchemaSettingsProperties && this.#propertyEditorUISettingsProperties) { // Reset the value to this array, and then afterwards append: this.#properties.setValue(this.#propertyEditorSchemaSettingsProperties); // Append the UI settings properties to the schema properties, so they can override the schema properties: this.#properties.append(this.#propertyEditorUISettingsProperties); + + // If new or if the alias was changed then set default values. + const previousPropertyEditorUIAlias = this.#lastPropertyEditorUIAlias; + this.#lastPropertyEditorUIAlias = this.getPropertyEditorUiAlias(); + if ( + this.getIsNew() || + (previousPropertyEditorUIAlias && previousPropertyEditorUIAlias !== this.#lastPropertyEditorUIAlias) + ) { + this.#transferConfigDefaultData(); + } } } @@ -301,9 +310,15 @@ export class UmbDataTypeWorkspaceContext this.#currentData.update({ name }); } + getPropertyEditorSchemaAlias() { + return this.#currentData.getValue()?.editorAlias; + } setPropertyEditorSchemaAlias(alias?: string) { this.#currentData.update({ editorAlias: alias }); } + getPropertyEditorUiAlias() { + return this.#currentData.getValue()?.editorUiAlias; + } setPropertyEditorUiAlias(alias?: string) { this.#currentData.update({ editorUiAlias: alias }); } From 6f1e48d72e666aba0ddda04eddfcfc7ce0a1e1f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 08:52:18 +0200 Subject: [PATCH 04/48] setting default data --- .../packages/data-type/workspace/data-type-workspace.context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index 59b38280ef..6a26a5acf9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -213,7 +213,7 @@ export class UmbDataTypeWorkspaceContext // Append the UI settings properties to the schema properties, so they can override the schema properties: this.#properties.append(this.#propertyEditorUISettingsProperties); - // If new or if the alias was changed then set default values. + // If new or if the alias was changed then set default values. This 'complexity' to prevent setting default data when initialized [NL] const previousPropertyEditorUIAlias = this.#lastPropertyEditorUIAlias; this.#lastPropertyEditorUIAlias = this.getPropertyEditorUiAlias(); if ( From cfcca5bd812578f6bc1fdfe99933736e6baace9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 09:32:31 +0200 Subject: [PATCH 05/48] comments --- .../workspace/data-type-workspace.context.ts | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index 6a26a5acf9..90d1dffc5a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -30,6 +30,24 @@ import { } from '@umbraco-cms/backoffice/entity-action'; type EntityType = UmbDataTypeDetailModel; + +/** + * @class uUmbDataTypeWorkspaceContext + * @description - Context for handling data type workspace + * There is two overall code flows to be aware about: + * + * propertyEditorUiAlias is observed + * loads propertyEditorUi manifest + * then the propertyEditorSchemaAlias is set to what the UI is configured for. + * + * propertyEditorSchemaAlias is observed + * loads the propertyEditorSchema manifest + * if no UI is defined then the propertyEditorSchema manifest default ui is set for the propertyEditorUiAlias. + * + * This supports two cases: + * - when editing an existing data type that only has a schema alias set, then it gets the UI set. + * - a new property editor ui is picked for a data-type, uses the data-type configuration to set the schema, if such is configured for the Property Editor UI. (The user picks the UI via the UI, the schema comes from the UI that the user picked, we store both on the data-type) + */ export class UmbDataTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase implements UmbInvariantDatasetWorkspaceContext, UmbRoutableWorkspaceContext @@ -137,7 +155,7 @@ export class UmbDataTypeWorkspaceContext // we only want to react on the change if the alias is set or null. When it is undefined something is still loading if (propertyEditorUiAlias === undefined) return; - this.#observePropertyEditorUIConfig(propertyEditorUiAlias); + this.#observePropertyEditorUIManifest(propertyEditorUiAlias); }, 'editorUiAlias', ); @@ -149,13 +167,13 @@ export class UmbDataTypeWorkspaceContext (propertyEditorSchemaAlias) => { this.#propertyEditorSchemaSettingsProperties = []; this.#propertyEditorSchemaSettingsDefaultData = []; - this.#observePropertyEditorSchemaConfig(propertyEditorSchemaAlias); + this.#observePropertyEditorSchemaManifest(propertyEditorSchemaAlias); }, 'schemaAlias', ); } - #observePropertyEditorSchemaConfig(propertyEditorSchemaAlias?: string) { + #observePropertyEditorSchemaManifest(propertyEditorSchemaAlias?: string) { if (!propertyEditorSchemaAlias) { this.removeUmbControllerByAlias('schema'); return; @@ -182,7 +200,7 @@ export class UmbDataTypeWorkspaceContext ); } - #observePropertyEditorUIConfig(propertyEditorUIAlias: string | null) { + #observePropertyEditorUIManifest(propertyEditorUIAlias: string | null) { if (!propertyEditorUIAlias) { this.removeUmbControllerByAlias('editorUi'); return; From b2815fdfd174c3c4127a4047a880acafe3686a07 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 30 Jul 2024 09:52:37 +0100 Subject: [PATCH 06/48] Adds localization for "No configuration" --- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + .../property-editor-config/property-editor-config.element.ts | 5 +++-- .../data-type/workspace/data-type-workspace.context.ts | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 0aca405fba..c6a84438d9 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -695,6 +695,7 @@ export default { hasReferencesDeleteConsequence: 'Deleting %0% will delete the properties and their data from the following items', acceptDeleteConsequence: 'I understand this action will delete the properties and data based on this Data Type', + noConfiguration: 'There is no configuration for this property editor.', }, errorHandling: { errorButDataWasSaved: diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts index 1282735778..46a9136d23 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.element.ts @@ -53,8 +53,9 @@ export class UmbPropertyEditorConfigElement extends UmbLitElement { property-editor-ui-alias=${property.propertyEditorUiAlias} .config=${property.config}>`, ) - : // TODO: Localize this [NL] - html`
No configuration
`; + : html`There is no configuration for this property editor.`; } static override styles = [UmbTextStyles]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts index 90d1dffc5a..49aa80140f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/data-type-workspace.context.ts @@ -32,7 +32,7 @@ import { type EntityType = UmbDataTypeDetailModel; /** - * @class uUmbDataTypeWorkspaceContext + * @class UmbDataTypeWorkspaceContext * @description - Context for handling data type workspace * There is two overall code flows to be aware about: * From 8af37ceff85ec45764d1fb60035230f36feb6e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 10:59:55 +0200 Subject: [PATCH 07/48] change path --- ...property-editor-ui-block-grid-layout-stylesheet.element.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts index 7d16db32d8..e1103cdf7c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.element.ts @@ -79,7 +79,9 @@ export class UmbPropertyEditorUIBlockGridLayoutStylesheetElement .min=${this._limitMin} .max=${this._limitMax}>
- Link to default layout stylesheet + Link to default layout stylesheet `; } From 4767065507fd516f7e8cbefabb89b924f3334125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 11:00:04 +0200 Subject: [PATCH 08/48] remove duplicates --- .../css/umbraco-blockgridlayout-flexbox.css | 35 -------------- .../assets/css/umbraco-blockgridlayout.css | 46 ------------------- 2 files changed, 81 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout-flexbox.css delete mode 100644 src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout.css diff --git a/src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout-flexbox.css b/src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout-flexbox.css deleted file mode 100644 index 3f921c0470..0000000000 --- a/src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout-flexbox.css +++ /dev/null @@ -1,35 +0,0 @@ -/** Example of how a grid layout stylehseet could be done with Flex box: */ - -.umb-block-grid__layout-container { - position: relative; - display: flex; - flex-wrap: wrap; - gap: var(--umb-block-grid--row-gap, 0) var(--umb-block-grid--column-gap, 0); -} -.umb-block-grid__layout-item { - position: relative; - --umb-block-grid__layout-item-calc: calc(var(--umb-block-grid--item-column-span) / var(--umb-block-grid--grid-columns)); - width: calc(var(--umb-block-grid__layout-item-calc) * 100% - (1 - var(--umb-block-grid__layout-item-calc)) * var(--umb-block-grid--column-gap, 0px)); -} - - -.umb-block-grid__area-container, .umb-block-grid__block--view::part(area-container) { - position: relative; - display: flex; - flex-wrap: wrap; - width: 100%; - gap: var(--umb-block-grid--areas-row-gap, 0) var(--umb-block-grid--areas-column-gap, 0); -} -.umb-block-grid__area { - position: relative; - height: 100%; - display: flex; - flex-direction: column; - --umb-block-grid__area-calc: calc(var(--umb-block-grid--area-column-span) / var(--umb-block-grid--area-grid-columns, 1)); - width: calc(var(--umb-block-grid__area-calc) * 100% - (1 - var(--umb-block-grid__area-calc)) * var(--umb-block-grid--areas-column-gap, 0px)); -} - - -.umb-block-grid__actions { - clear: both; -} diff --git a/src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout.css b/src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout.css deleted file mode 100644 index 8a4f567cac..0000000000 --- a/src/Umbraco.Web.UI.Client/src/assets/css/umbraco-blockgridlayout.css +++ /dev/null @@ -1,46 +0,0 @@ -.umb-block-grid__layout-container { - position: relative; - display: grid; - grid-template-columns: repeat(var(--umb-block-grid--grid-columns, 1), minmax(0, 1fr)); - grid-auto-flow: row; - grid-auto-rows: minmax(50px, min-content); - - column-gap: var(--umb-block-grid--column-gap, 0); - row-gap: var(--umb-block-grid--row-gap, 0); -} -.umb-block-grid__layout-item { - position: relative; - /* For small devices we scale columnSpan by three, to make everything bigger than 1/3 take full width: */ - grid-column-end: span min(calc(var(--umb-block-grid--item-column-span, 1) * 3), var(--umb-block-grid--grid-columns)); - grid-row: span var(--umb-block-grid--item-row-span, 1); -} - - -.umb-block-grid__area-container, .umb-block-grid__block--view::part(area-container) { - position: relative; - display: grid; - grid-template-columns: repeat(var(--umb-block-grid--area-grid-columns, var(--umb-block-grid--grid-columns, 1)), minmax(0, 1fr)); - grid-auto-flow: row; - grid-auto-rows: minmax(50px, min-content); - - column-gap: var(--umb-block-grid--areas-column-gap, 0); - row-gap: var(--umb-block-grid--areas-row-gap, 0); -} -.umb-block-grid__area { - position: relative; - height: 100%; - display: flex; - flex-direction: column; - /* For small devices we scale columnSpan by three, to make everything bigger than 1/3 take full width: */ - grid-column-end: span min(calc(var(--umb-block-grid--area-column-span, 1) * 3), var(--umb-block-grid--area-grid-columns)); - grid-row: span var(--umb-block-grid--area-row-span, 1); -} - -@media (min-width:1024px) { - .umb-block-grid__layout-item { - grid-column-end: span min(var(--umb-block-grid--item-column-span, 1), var(--umb-block-grid--grid-columns)); - } - .umb-block-grid__area { - grid-column-end: span min(var(--umb-block-grid--area-column-span, 1), var(--umb-block-grid--area-grid-columns)); - } -} \ No newline at end of file From ad7d3a56cc868cb71cda00716cce9bd5be57e0c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 14:03:01 +0200 Subject: [PATCH 09/48] refactor directive to support scenarios where things are not ready --- .../directives/focus.lit-directive.ts | 52 ++++++++++++++++--- ...ace-split-view-variant-selector.element.ts | 3 +- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts index 5d237844ea..c8fb9156fa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts @@ -1,9 +1,31 @@ import { AsyncDirective, directive, nothing, type ElementPart } from '@umbraco-cms/backoffice/external/lit'; +function isDescendant(parent: any, child: any) { + let node = child.parentNode; + while (node != null) { + if (node == parent) { + return true; + } + node = node.host ? node.host : node.parentNode; + } + return false; +} + +function hasFocus(current: any) { + if (current.shadowRoot) { + const node = current.shadowRoot.activeElement; + if (node) { + return hasFocus(node); + } + } + return current; +} + /** * The `focus` directive sets focus on the given element once its connected to the DOM. */ class UmbFocusDirective extends AsyncDirective { + static _latestElement?: HTMLElement; private _el?: HTMLElement; override render() { @@ -12,18 +34,34 @@ class UmbFocusDirective extends AsyncDirective { override update(part: ElementPart) { if (this._el !== part.element) { - // This does feel wrong that we need to wait one render. [NL] - // Because even if our elements focus method is implemented so it can be called initially, my research shows that calling the focus method at this point is too early, thought the element is connected to the DOM and the focus method is available. [NL] - // This smells a bit like the DOMPart of which the directive is in is not connected to the main DOM yet, and therefor cant receive focus. [NL] - // Which is why we need to await one render: [NL] - requestAnimationFrame(() => { - (this._el = part.element as HTMLElement).focus(); - }); + UmbFocusDirective._latestElement = this._el = part.element as HTMLElement; + this.#setFocus(); } return nothing; } + /** + * This method tries to set focus, if it did not succeed, it will try again. + * It always tests against the latest element, because the directive can be used multiple times in the same render. + * This is NOT needed because the elements focus method isn't ready to be called, but due to something with rendering of the DOM. + * But I'm not completely sure at this movement why the browser does not accept the focus call. + * But I have tested that everything is in place for it to be good, so something else must have an effect, + * setting the focus somewhere else, maybe a re-appending of some sort? + * cause Lit does not re-render the element but also notice reconnect callback on the directive is not triggered either. [NL] + */ + #setFocus = () => { + if (this._el && this._el === UmbFocusDirective._latestElement) { + this._el.focus(); + if (hasFocus(document.activeElement)) { + setTimeout(this.#setFocus, 100); + } + } + }; + override disconnected() { + if (this._el === UmbFocusDirective._latestElement) { + UmbFocusDirective._latestElement = undefined; + } this._el = undefined; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts index 2fd9078243..e8a4f0ee96 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts @@ -209,10 +209,11 @@ export class UmbWorkspaceSplitViewVariantSelectorElement extends UmbLitElement { } override render() { + // TODO: Localize [NL] return html` Date: Tue, 30 Jul 2024 14:05:37 +0200 Subject: [PATCH 10/48] stop retry if success --- .../directives/focus.lit-directive.ts | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts index c8fb9156fa..51337f192f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts @@ -1,16 +1,5 @@ import { AsyncDirective, directive, nothing, type ElementPart } from '@umbraco-cms/backoffice/external/lit'; -function isDescendant(parent: any, child: any) { - let node = child.parentNode; - while (node != null) { - if (node == parent) { - return true; - } - node = node.host ? node.host : node.parentNode; - } - return false; -} - function hasFocus(current: any) { if (current.shadowRoot) { const node = current.shadowRoot.activeElement; @@ -25,16 +14,16 @@ function hasFocus(current: any) { * The `focus` directive sets focus on the given element once its connected to the DOM. */ class UmbFocusDirective extends AsyncDirective { - static _latestElement?: HTMLElement; - private _el?: HTMLElement; + static #next?: HTMLElement; + #el?: HTMLElement; override render() { return nothing; } override update(part: ElementPart) { - if (this._el !== part.element) { - UmbFocusDirective._latestElement = this._el = part.element as HTMLElement; + if (this.#el !== part.element) { + UmbFocusDirective.#next = this.#el = part.element as HTMLElement; this.#setFocus(); } return nothing; @@ -50,19 +39,21 @@ class UmbFocusDirective extends AsyncDirective { * cause Lit does not re-render the element but also notice reconnect callback on the directive is not triggered either. [NL] */ #setFocus = () => { - if (this._el && this._el === UmbFocusDirective._latestElement) { - this._el.focus(); - if (hasFocus(document.activeElement)) { + if (this.#el && this.#el === UmbFocusDirective.#next) { + this.#el.focus(); + if (hasFocus(document.activeElement) !== this.#el) { setTimeout(this.#setFocus, 100); + } else { + UmbFocusDirective.#next = undefined; } } }; override disconnected() { - if (this._el === UmbFocusDirective._latestElement) { - UmbFocusDirective._latestElement = undefined; + if (this.#el === UmbFocusDirective.#next) { + UmbFocusDirective.#next = undefined; } - this._el = undefined; + this.#el = undefined; } //override reconnected() {} From a3237e53e7d3d2ca3ac24e6dbe791384f83d3d78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 14:07:38 +0200 Subject: [PATCH 11/48] comments and clearing --- .../core/lit-element/directives/focus.lit-directive.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts index 51337f192f..e806e4d11b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts @@ -16,6 +16,7 @@ function hasFocus(current: any) { class UmbFocusDirective extends AsyncDirective { static #next?: HTMLElement; #el?: HTMLElement; + #timeout?: number; override render() { return nothing; @@ -39,10 +40,16 @@ class UmbFocusDirective extends AsyncDirective { * cause Lit does not re-render the element but also notice reconnect callback on the directive is not triggered either. [NL] */ #setFocus = () => { + // Make sure we clear the timeout, so we don't get multiple timeouts running. + if (this.#timeout) { + clearTimeout(this.#timeout); + this.#timeout = undefined; + } + // If this is the next element to focus, then try to focus it. if (this.#el && this.#el === UmbFocusDirective.#next) { this.#el.focus(); if (hasFocus(document.activeElement) !== this.#el) { - setTimeout(this.#setFocus, 100); + this.#timeout = setTimeout(this.#setFocus, 100) as unknown as number; } else { UmbFocusDirective.#next = undefined; } From eda9b1041a2db07815e02ba8375567cc61b0bf46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 14:54:50 +0200 Subject: [PATCH 12/48] fix inner focused elements --- .../directives/focus.lit-directive.ts | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts index e806e4d11b..f4e7032fd8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/lit-element/directives/focus.lit-directive.ts @@ -1,13 +1,23 @@ import { AsyncDirective, directive, nothing, type ElementPart } from '@umbraco-cms/backoffice/external/lit'; - -function hasFocus(current: any) { +/** + * + * test if a element has focus + * this also returns true if the focused element is a child of the target. + * @param current + * @param target + * @returns bool + */ +function hasFocus(current: any, target: HTMLElement): boolean { + if (current === target) { + return true; + } if (current.shadowRoot) { const node = current.shadowRoot.activeElement; if (node) { - return hasFocus(node); + return hasFocus(node, target); } } - return current; + return false; } /** @@ -48,7 +58,7 @@ class UmbFocusDirective extends AsyncDirective { // If this is the next element to focus, then try to focus it. if (this.#el && this.#el === UmbFocusDirective.#next) { this.#el.focus(); - if (hasFocus(document.activeElement) !== this.#el) { + if (hasFocus(document.activeElement, this.#el) === false) { this.#timeout = setTimeout(this.#setFocus, 100) as unknown as number; } else { UmbFocusDirective.#next = undefined; From f2306733fd25adfdcbd4bb156b67684e49eb797e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 16:19:17 +0200 Subject: [PATCH 13/48] media composition --- .../repository/composition/index.ts | 1 - .../repository/composition/manifests.ts | 4 +- .../src/packages/media/media-types/index.ts | 7 +- .../repository/composition/index.ts | 1 + .../repository/composition/manifests.ts | 12 +++ .../media-type-composition.repository.ts | 36 ++++++++ ...dia-type-composition.server.data-source.ts | 86 +++++++++++++++++++ .../media/media-types/repository/index.ts | 3 +- .../src/packages/media/media-types/types.ts | 13 ++- .../media/media-types/workspace/manifests.ts | 2 + 10 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.repository.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/index.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/index.ts index 99c179ec94..8a9f7eae16 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/index.ts @@ -1,2 +1 @@ -export { UmbDocumentTypeCompositionRepository } from './document-type-composition.repository.js'; export { UMB_DOCUMENT_TYPE_COMPOSITION_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/manifests.ts index 1732701de6..b01f3b0be9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/repository/composition/manifests.ts @@ -2,11 +2,11 @@ import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/ export const UMB_DOCUMENT_TYPE_COMPOSITION_REPOSITORY_ALIAS = 'Umb.Repository.DocumentType.Composition'; -const queryRepository: ManifestRepository = { +const compositionRepository: ManifestRepository = { type: 'repository', alias: UMB_DOCUMENT_TYPE_COMPOSITION_REPOSITORY_ALIAS, name: 'Document Type Composition Repository', api: () => import('./document-type-composition.repository.js'), }; -export const manifests: Array = [queryRepository]; +export const manifests: Array = [compositionRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts index 39c2b4ea8b..4fdc741116 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/index.ts @@ -1,12 +1,11 @@ import './components/index.js'; export * from './components/index.js'; -export * from './workspace/index.js'; - +export * from './entity.js'; export * from './repository/index.js'; export * from './tree/types.js'; -export * from './utils.ts/index.js'; export * from './types.js'; -export * from './entity.js'; +export * from './utils.ts/index.js'; +export * from './workspace/index.js'; export { UMB_MEDIA_TYPE_PICKER_MODAL } from './tree/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/index.ts new file mode 100644 index 0000000000..e9c3158173 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/index.ts @@ -0,0 +1 @@ +export { UMB_MEDIA_TYPE_COMPOSITION_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/manifests.ts new file mode 100644 index 0000000000..16ad5b903c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/manifests.ts @@ -0,0 +1,12 @@ +import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_MEDIA_TYPE_COMPOSITION_REPOSITORY_ALIAS = 'Umb.Repository.MediaType.Composition'; + +const compositionRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MEDIA_TYPE_COMPOSITION_REPOSITORY_ALIAS, + name: 'Media Type Composition Repository', + api: () => import('./media-type-composition.repository.js'), +}; + +export const manifests: Array = [compositionRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.repository.ts new file mode 100644 index 0000000000..a73570e069 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.repository.ts @@ -0,0 +1,36 @@ +import { UmbMediaTypeCompositionServerDataSource } from './media-type-composition.server.data-source.js'; +import type { UmbContentTypeCompositionRepository } from '@umbraco-cms/backoffice/content-type'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbMediaTypeAvailableCompositionRequestModel, + UmbMediaTypeCompositionCompatibleModel, + UmbMediaTypeCompositionReferenceModel, +} from '@umbraco-cms/backoffice/media-type'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMediaTypeCompositionRepository + extends UmbRepositoryBase + implements + UmbContentTypeCompositionRepository< + UmbMediaTypeCompositionReferenceModel, + UmbMediaTypeCompositionCompatibleModel, + UmbMediaTypeAvailableCompositionRequestModel + > +{ + #compositionSource: UmbMediaTypeCompositionServerDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#compositionSource = new UmbMediaTypeCompositionServerDataSource(this); + } + + async getReferences(unique: string) { + return this.#compositionSource.getReferences(unique); + } + + async availableCompositions(args: UmbMediaTypeAvailableCompositionRequestModel) { + return this.#compositionSource.availableCompositions(args); + } +} + +export { UmbMediaTypeCompositionRepository as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts new file mode 100644 index 0000000000..81e1e7d28b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/composition/media-type-composition.server.data-source.ts @@ -0,0 +1,86 @@ +import type { + UmbMediaTypeCompositionCompatibleModel, + UmbMediaTypeCompositionReferenceModel, + UmbMediaTypeAvailableCompositionRequestModel, +} from '../../types.js'; +import { type MediaTypeCompositionRequestModel, MediaTypeService } from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbContentTypeCompositionDataSource } from '@umbraco-cms/backoffice/content-type'; + +/** + * A data source for the Media Type Composition that fetches data from the server + * @export + * @class UmbMediaTypeCompositionServerDataSource + */ +export class UmbMediaTypeCompositionServerDataSource + implements + UmbContentTypeCompositionDataSource< + UmbMediaTypeCompositionReferenceModel, + UmbMediaTypeCompositionCompatibleModel, + UmbMediaTypeAvailableCompositionRequestModel + > +{ + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMediaTypeCompositionServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMediaTypeCompositionServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + /** + * Fetches the compatible compositions for a Media type from the server + * @param {string} unique + * @return {*} + * @memberof UmbMediaTypeCompositionServerDataSource + */ + async getReferences(unique: string) { + const response = await tryExecuteAndNotify( + this.#host, + MediaTypeService.getMediaTypeByIdCompositionReferences({ id: unique }), + ); + const error = response.error; + const data: Array | undefined = response.data?.map((reference) => { + return { + unique: reference.id, + icon: reference.icon, + name: reference.name, + }; + }); + + return { data, error }; + } + /** + * Updates the compositions for a media type on the server + * @param {MediaTypeCompositionRequestModel} requestBody + * @return {*} + * @memberof UmbMediaTypeCompositionServerDataSource + */ + async availableCompositions(args: UmbMediaTypeAvailableCompositionRequestModel) { + const requestBody: MediaTypeCompositionRequestModel = { + id: args.unique, + currentCompositeIds: args.currentCompositeUniques, + currentPropertyAliases: args.currentPropertyAliases, + }; + + const response = await tryExecuteAndNotify( + this.#host, + MediaTypeService.postMediaTypeAvailableCompositions({ requestBody }), + ); + const error = response.error; + const data: Array | undefined = response.data?.map((composition) => { + return { + unique: composition.id, + name: composition.name, + icon: composition.icon, + folderPath: composition.folderPath, + isCompatible: composition.isCompatible, + }; + }); + + return { data, error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts index e84c58d982..e3bd416604 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/index.ts @@ -1,3 +1,4 @@ -export * from './item/index.js'; +export * from './composition/index.js'; export * from './detail/index.js'; +export * from './item/index.js'; export * from './structure/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/types.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/types.ts index 828514db06..17acb2e86e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/types.ts @@ -1,6 +1,17 @@ import type { UmbMediaTypeEntityType } from './entity.js'; -import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; +import type { + UmbContentTypeAvailableCompositionRequestModel, + UmbContentTypeCompositionCompatibleModel, + UmbContentTypeCompositionReferenceModel, + UmbContentTypeModel, +} from '@umbraco-cms/backoffice/content-type'; export interface UmbMediaTypeDetailModel extends UmbContentTypeModel { entityType: UmbMediaTypeEntityType; } + +export interface UmbMediaTypeAvailableCompositionRequestModel extends UmbContentTypeAvailableCompositionRequestModel {} + +export interface UmbMediaTypeCompositionCompatibleModel extends UmbContentTypeCompositionCompatibleModel {} + +export interface UmbMediaTypeCompositionReferenceModel extends UmbContentTypeCompositionReferenceModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts index a0cb73a866..01293d0d96 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/workspace/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_MEDIA_TYPE_COMPOSITION_REPOSITORY_ALIAS } from '../repository/index.js'; import { UMB_MEDIA_TYPE_WORKSPACE_ALIAS } from './constants.js'; import type { ManifestWorkspaces, @@ -29,6 +30,7 @@ const workspaceViews: Array = [ label: '#general_design', pathname: 'design', icon: 'icon-document-dashed-line', + compositionRepositoryAlias: UMB_MEDIA_TYPE_COMPOSITION_REPOSITORY_ALIAS, }, conditions: [ { From cce90c3c8e96f97952c85cfcca7645c8d4b8f427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 30 Jul 2024 16:19:21 +0200 Subject: [PATCH 14/48] member composition --- .../src/packages/members/member-type/index.ts | 9 +- .../repository/composition/index.ts | 1 + .../repository/composition/manifests.ts | 12 +++ .../member-type-composition.repository.ts | 36 ++++++++ ...ber-type-composition.server.data-source.ts | 89 +++++++++++++++++++ .../members/member-type/repository/index.ts | 1 + .../src/packages/members/member-type/types.ts | 13 ++- .../member-type/workspace/manifests.ts | 6 +- 8 files changed, 159 insertions(+), 8 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/index.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/manifests.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.repository.ts create mode 100644 src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.server.data-source.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/index.ts index 7a1a270d73..66b072b145 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/index.ts @@ -1,10 +1,9 @@ import './components/index.js'; -export * from './workspace/index.js'; export * from './components/index.js'; -export * from './repository/index.js'; export * from './entity.js'; -export * from './tree/index.js'; export * from './modal/member-type-picker-modal.token.js'; - -export type { UmbMemberTypeDetailModel } from './types.js'; +export * from './repository/index.js'; +export * from './tree/index.js'; +export * from './types.js'; +export * from './workspace/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/index.ts new file mode 100644 index 0000000000..7c68fa6579 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/index.ts @@ -0,0 +1 @@ +export { UMB_MEMBER_TYPE_COMPOSITION_REPOSITORY_ALIAS } from './manifests.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/manifests.ts new file mode 100644 index 0000000000..bf8f9fa79f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/manifests.ts @@ -0,0 +1,12 @@ +import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; + +export const UMB_MEMBER_TYPE_COMPOSITION_REPOSITORY_ALIAS = 'Umb.Repository.MemberType.Composition'; + +const compositionRepository: ManifestRepository = { + type: 'repository', + alias: UMB_MEMBER_TYPE_COMPOSITION_REPOSITORY_ALIAS, + name: 'Member Type Composition Repository', + api: () => import('./member-type-composition.repository.js'), +}; + +export const manifests: Array = [compositionRepository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.repository.ts new file mode 100644 index 0000000000..a64e0a3ef8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.repository.ts @@ -0,0 +1,36 @@ +import { UmbMemberTypeCompositionServerDataSource } from './member-type-composition.server.data-source.js'; +import type { UmbContentTypeCompositionRepository } from '@umbraco-cms/backoffice/content-type'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + UmbMemberTypeAvailableCompositionRequestModel, + UmbMemberTypeCompositionCompatibleModel, + UmbMemberTypeCompositionReferenceModel, +} from '@umbraco-cms/backoffice/member-type'; +import { UmbRepositoryBase } from '@umbraco-cms/backoffice/repository'; + +export class UmbMemberTypeCompositionRepository + extends UmbRepositoryBase + implements + UmbContentTypeCompositionRepository< + UmbMemberTypeCompositionReferenceModel, + UmbMemberTypeCompositionCompatibleModel, + UmbMemberTypeAvailableCompositionRequestModel + > +{ + #compositionSource: UmbMemberTypeCompositionServerDataSource; + + constructor(host: UmbControllerHost) { + super(host); + this.#compositionSource = new UmbMemberTypeCompositionServerDataSource(this); + } + + async getReferences(unique: string) { + return this.#compositionSource.getReferences(unique); + } + + async availableCompositions(args: UmbMemberTypeAvailableCompositionRequestModel) { + return this.#compositionSource.availableCompositions(args); + } +} + +export { UmbMemberTypeCompositionRepository as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.server.data-source.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.server.data-source.ts new file mode 100644 index 0000000000..dc38ede4a2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/composition/member-type-composition.server.data-source.ts @@ -0,0 +1,89 @@ +import type { + UmbMemberTypeCompositionCompatibleModel, + UmbMemberTypeCompositionReferenceModel, + UmbMemberTypeAvailableCompositionRequestModel, +} from '../../types.js'; +import { + type MemberTypeCompositionRequestModel, + MemberTypeService, +} from '@umbraco-cms/backoffice/external/backend-api'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import { tryExecuteAndNotify } from '@umbraco-cms/backoffice/resources'; +import type { UmbContentTypeCompositionDataSource } from '@umbraco-cms/backoffice/content-type'; + +/** + * A data source for the Member Type Composition that fetches data from the server + * @export + * @class UmbMemberTypeCompositionServerDataSource + */ +export class UmbMemberTypeCompositionServerDataSource + implements + UmbContentTypeCompositionDataSource< + UmbMemberTypeCompositionReferenceModel, + UmbMemberTypeCompositionCompatibleModel, + UmbMemberTypeAvailableCompositionRequestModel + > +{ + #host: UmbControllerHost; + + /** + * Creates an instance of UmbMemberTypeCompositionServerDataSource. + * @param {UmbControllerHost} host + * @memberof UmbMemberTypeCompositionServerDataSource + */ + constructor(host: UmbControllerHost) { + this.#host = host; + } + /** + * Fetches the compatible compositions for a document type from the server + * @param {string} unique + * @return {*} + * @memberof UmbMemberTypeCompositionServerDataSource + */ + async getReferences(unique: string) { + const response = await tryExecuteAndNotify( + this.#host, + MemberTypeService.getMemberTypeByIdCompositionReferences({ id: unique }), + ); + const error = response.error; + const data: Array | undefined = response.data?.map((reference) => { + return { + unique: reference.id, + icon: reference.icon, + name: reference.name, + }; + }); + + return { data, error }; + } + /** + * Updates the compositions for a document type on the server + * @param {MemberTypeCompositionRequestModel} requestBody + * @return {*} + * @memberof UmbMemberTypeCompositionServerDataSource + */ + async availableCompositions(args: UmbMemberTypeAvailableCompositionRequestModel) { + const requestBody: MemberTypeCompositionRequestModel = { + id: args.unique, + currentCompositeIds: args.currentCompositeUniques, + currentPropertyAliases: args.currentPropertyAliases, + }; + + const response = await tryExecuteAndNotify( + this.#host, + MemberTypeService.postMemberTypeAvailableCompositions({ requestBody }), + ); + const error = response.error; + const data: Array | undefined = response.data?.map((composition) => { + return { + unique: composition.id, + name: composition.name, + icon: composition.icon, + folderPath: composition.folderPath, + isCompatible: composition.isCompatible, + }; + }); + + return { data, error }; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/index.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/index.ts index f396068800..5a07494cdb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/index.ts @@ -1,2 +1,3 @@ export { UmbMemberTypeDetailRepository, UMB_MEMBER_TYPE_DETAIL_REPOSITORY_ALIAS } from './detail/index.js'; export { UmbMemberTypeItemRepository, UMB_MEMBER_TYPE_ITEM_REPOSITORY_ALIAS } from './item/index.js'; +export { UMB_MEMBER_TYPE_COMPOSITION_REPOSITORY_ALIAS } from './composition/index.js'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/types.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/types.ts index 41bb9c2f08..c17ebcebe6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/types.ts @@ -1,6 +1,17 @@ import type { UmbMemberTypeEntityType } from './entity.js'; -import type { UmbContentTypeModel } from '@umbraco-cms/backoffice/content-type'; +import type { + UmbContentTypeAvailableCompositionRequestModel, + UmbContentTypeCompositionCompatibleModel, + UmbContentTypeCompositionReferenceModel, + UmbContentTypeModel, +} from '@umbraco-cms/backoffice/content-type'; export interface UmbMemberTypeDetailModel extends UmbContentTypeModel { entityType: UmbMemberTypeEntityType; } + +export interface UmbMemberTypeAvailableCompositionRequestModel extends UmbContentTypeAvailableCompositionRequestModel {} + +export interface UmbMemberTypeCompositionCompatibleModel extends UmbContentTypeCompositionCompatibleModel {} + +export interface UmbMemberTypeCompositionReferenceModel extends UmbContentTypeCompositionReferenceModel {} diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts index ac2e37d3da..fbac4d07c2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/workspace/manifests.ts @@ -1,7 +1,8 @@ +import { UMB_MEMBER_TYPE_COMPOSITION_REPOSITORY_ALIAS } from '../repository/index.js'; import type { ManifestWorkspaces, ManifestWorkspaceActions, - ManifestWorkspaceView, + ManifestWorkspaceViews, ManifestTypes, } from '@umbraco-cms/backoffice/extension-registry'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; @@ -19,7 +20,7 @@ const workspace: ManifestWorkspaces = { }, }; -const workspaceViews: Array = [ +const workspaceViews: Array = [ { type: 'workspaceView', kind: 'contentTypeDesignEditor', @@ -29,6 +30,7 @@ const workspaceViews: Array = [ label: '#general_design', pathname: 'design', icon: 'icon-member-dashed-line', + compositionRepositoryAlias: UMB_MEMBER_TYPE_COMPOSITION_REPOSITORY_ALIAS, }, conditions: [ { From fd5d76fabdbc20bde80064569df058f1f6af6823 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 30 Jul 2024 16:04:38 +0100 Subject: [PATCH 15/48] Webhooks localizations plus other bug fixes. --- .../src/assets/lang/en.ts | 5 +- ...ook-table-boolean-column-layout.element.ts | 4 +- ...ebhook-table-name-column-layout.element.ts | 2 +- .../webhook-table-collection-view.element.ts | 16 +++-- .../input-webhook-events.element.ts | 39 ++++++------ .../input-webhook-headers.element.ts | 8 +-- .../webhook-events-modal.element.ts | 58 ++++++++--------- .../webhook-root-workspace.element.ts | 8 ++- .../webhook-details-workspace-view.element.ts | 62 +++++++++++-------- .../webhook-workspace-editor.element.ts | 8 ++- 10 files changed, 113 insertions(+), 97 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index c6a84438d9..7e0e77d5cd 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -1735,11 +1735,11 @@ export default { enabled: 'Enabled', events: 'Events', event: 'Event', - url: 'Url', + url: 'URL', types: 'Types', webhookKey: 'Webhook key', retryCount: 'Retry count', - urlDescription: 'The url to call when the webhook is triggered.', + urlDescription: 'The URL to call when the webhook is triggered.', eventDescription: 'The events for which the webhook should be triggered.', contentTypeDescription: 'Only trigger the webhook for a specific content type.', enabledDescription: 'Is the webhook enabled?', @@ -1747,6 +1747,7 @@ export default { contentType: 'Content Type', headers: 'Headers', selectEventFirst: 'Please select an event first.', + selectEvents: 'Select events', }, languages: { addLanguage: 'Add language', diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/boolean/webhook-table-boolean-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/boolean/webhook-table-boolean-column-layout.element.ts index 21f972c729..e16d4f4bb7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/boolean/webhook-table-boolean-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/boolean/webhook-table-boolean-column-layout.element.ts @@ -1,4 +1,4 @@ -import { html, nothing, customElement, property } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-webhook-table-boolean-column-layout') @@ -7,7 +7,7 @@ export class UmbWebhookTableBooleanColumnLayoutElement extends UmbLitElement { value = false; override render() { - return this.value ? html`` : nothing; + return html``; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/content-type/webhook-table-name-column-layout.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/content-type/webhook-table-name-column-layout.element.ts index 032ca105a4..116bd06841 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/content-type/webhook-table-name-column-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/column-layouts/content-type/webhook-table-name-column-layout.element.ts @@ -32,7 +32,7 @@ export class UmbWebhookTableContentTypeColumnLayoutElement extends UmbLitElement if (this.value?.contentTypeName && this.#repository) { const { data } = await this.#repository.requestItems(this.value.contentTypes); - this._contentTypes = data?.map((item) => item.name).join(', ') ?? ''; + this._contentTypes = data?.map((item) => this.localize.string(item.name)).join(', ') ?? ''; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/webhook-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/webhook-table-collection-view.element.ts index 5ac9a83cf8..4128f4e9d2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/webhook-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/collection/views/table/webhook-table-collection-view.element.ts @@ -1,10 +1,9 @@ import type { UmbWebhookDetailModel } from '../../../types.js'; import type { UmbDefaultCollectionContext } from '@umbraco-cms/backoffice/collection'; +import { css, customElement, html, state } from '@umbraco-cms/backoffice/external/lit'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UMB_COLLECTION_CONTEXT } from '@umbraco-cms/backoffice/collection'; import type { UmbTableColumn, UmbTableConfig, UmbTableItem } from '@umbraco-cms/backoffice/components'; -import { css, html, customElement, state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import './column-layouts/boolean/webhook-table-boolean-column-layout.element.js'; import './column-layouts/name/webhook-table-name-column-layout.element.js'; @@ -21,25 +20,25 @@ export class UmbWebhookTableCollectionViewElement extends UmbLitElement { @state() private _tableColumns: Array = [ { - name: 'Name', + name: this.localize.term('general_name'), alias: 'name', elementName: 'umb-webhook-table-name-column-layout', }, { - name: 'Enabled', + name: this.localize.term('webhooks_enabled'), alias: 'enabled', elementName: 'umb-webhook-table-boolean-column-layout', }, { - name: 'URL', + name: this.localize.term('webhooks_url'), alias: 'url', }, { - name: 'Events', + name: this.localize.term('webhooks_events'), alias: 'events', }, { - name: 'Types', + name: this.localize.term('webhooks_types'), alias: 'types', elementName: 'umb-webhook-table-content-type-column-layout', }, @@ -112,7 +111,6 @@ export class UmbWebhookTableCollectionViewElement extends UmbLitElement { } static override styles = [ - UmbTextStyles, css` :host { display: flex; diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-events.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-events.element.ts index 901dc34e41..f17bea9008 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-events.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-events.element.ts @@ -47,23 +47,29 @@ export class UmbInputWebhookEventsElement extends UmbLitElement { if (!this.events.length) return nothing; return html` - ${repeat( - this.events, - (item) => item.alias, - (item) => html` - ${item.eventName} - this.#removeEvent(item.alias)}> - `, - )} + + ${repeat( + this.events, + (item) => item.alias, + (item) => html` + + + + this.#removeEvent(item.alias)}> + + + `, + )} + `; } override render() { return html`${this.#renderEvents()} `; @@ -72,15 +78,8 @@ export class UmbInputWebhookEventsElement extends UmbLitElement { static override styles = [ UmbTextStyles, css` - :host { - display: grid; - grid-template-columns: 1fr auto; - gap: var(--uui-size-space-2) var(--uui-size-space-2); - align-items: center; - } - - #choose { - grid-column: -1 / 1; + #btn-add { + display: block; } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-headers.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-headers.element.ts index 6819cd267a..68bc822494 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-headers.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/components/input-webhook-headers.element.ts @@ -14,7 +14,7 @@ export class UmbInputWebhookHeadersElement extends UmbLitElement { private _headers: Array<{ name: string; value: string }> = []; @state() - private _headerNames: string[] = ['Accept', 'Content-Type', 'User-Agent', 'Content-Length']; + private _headerNames: string[] = ['Accept', 'Content-Length', 'Content-Type', 'User-Agent']; get #filterHeaderNames() { return this._headerNames.filter((name) => !this._headers.find((header) => header.name === name)); @@ -78,7 +78,7 @@ export class UmbInputWebhookHeadersElement extends UmbLitElement { .value=${header.value} @input=${(e: InputEvent) => this.#onInput(e, 'value', index)} list="valueList" /> - this.#removeHeader(index)} label="Remove"> + this.#removeHeader(index)} label=${this.localize.term('general_remove')}> `; } @@ -105,8 +105,8 @@ export class UmbInputWebhookHeadersElement extends UmbLitElement { if (!this._headers.length) return nothing; return html` - KEY - VALUE + Name + Value ${repeat( this._headers, diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/components/webhook-events-modal/webhook-events-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/components/webhook-events-modal/webhook-events-modal.element.ts index d6b2fb13f5..7df91e91c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/components/webhook-events-modal/webhook-events-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/components/webhook-events-modal/webhook-events-modal.element.ts @@ -1,9 +1,7 @@ import { UmbWebhookEventRepository } from '../../repository/event/webhook-event.repository.js'; import type { UmbWebhookEventModel } from '../../types.js'; import type { UmbWebhookPickerModalData, UmbWebhookPickerModalValue } from './webhook-events-modal.token.js'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import { css, html, customElement, state, repeat } from '@umbraco-cms/backoffice/external/lit'; - +import { customElement, html, state, repeat } from '@umbraco-cms/backoffice/external/lit'; import { UmbModalBaseElement } from '@umbraco-cms/backoffice/modal'; import { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; @@ -67,32 +65,36 @@ export class UmbWebhookEventsModalElement extends UmbModalBaseElement< } override render() { - return html` - - ${repeat( - this._events, - (item) => item.alias, - (item) => html` - this.#selectionManager.select(item.alias)} - @deselected=${() => this.#selectionManager.deselect(item.alias)} - ?selected=${this.value.events.includes(item)}> - - - `, - )} - -
- - -
-
`; + return html` + + + ${repeat( + this._events, + (item) => item.alias, + (item) => html` + this.#selectionManager.select(item.alias)} + @deselected=${() => this.#selectionManager.deselect(item.alias)} + ?selected=${this.value.events.includes(item)}> + + + `, + )} + +
+ + +
+
+ `; } - - static override styles = [UmbTextStyles, css``]; } export default UmbWebhookEventsModalElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/webhook-root-workspace.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/webhook-root-workspace.element.ts index 071ecf38ef..3149d847cc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/webhook-root-workspace.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook-root/webhook-root-workspace.element.ts @@ -5,9 +5,11 @@ import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; @customElement('umb-webhook-root-workspace') export class UmbWebhookRootWorkspaceElement extends UmbLitElement { override render() { - return html` - ; - `; + return html` + + ; + + `; } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts index c9f9ea0eb6..874d2b3764 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts @@ -1,17 +1,16 @@ -import type { UmbInputWebhookHeadersElement } from '../../../components/input-webhook-headers.element.js'; import { UMB_WEBHOOK_WORKSPACE_CONTEXT } from '../webhook-workspace.context-token.js'; +import type { UmbInputWebhookHeadersElement } from '../../../components/input-webhook-headers.element.js'; import type { UmbInputWebhookEventsElement } from '../../../components/input-webhook-events.element.js'; -import { css, html, customElement, state, nothing } from '@umbraco-cms/backoffice/external/lit'; +import { css, customElement, html, state, nothing } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import '@umbraco-cms/backoffice/culture'; -import type { UmbWebhookDetailModel } from '@umbraco-cms/backoffice/webhook'; - import type { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbInputDocumentTypeElement } from '@umbraco-cms/backoffice/document-type'; +import type { UmbWebhookDetailModel } from '@umbraco-cms/backoffice/webhook'; +import type { UmbWorkspaceViewElement } from '@umbraco-cms/backoffice/extension-registry'; import type { UUIBooleanInputEvent, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; +import '@umbraco-cms/backoffice/culture'; import '../../../components/input-webhook-headers.element.js'; import '../../../components/input-webhook-events.element.js'; @@ -43,9 +42,9 @@ export class UmbWebhookDetailsWorkspaceViewElement extends UmbLitElement impleme }); } - #onEventsChange(event: UmbChangeEvent) { - const events = (event.target as UmbInputWebhookEventsElement).events; - if (events[0].eventType !== this.contentType) { + #onEventsChange(event: UmbChangeEvent & { target: UmbInputWebhookEventsElement }) { + const events = event.target.events ?? []; + if (events.length && events[0].eventType !== this.contentType) { this.#webhookWorkspaceContext?.setTypes([]); } this.#webhookWorkspaceContext?.setEvents(events); @@ -75,7 +74,9 @@ export class UmbWebhookDetailsWorkspaceViewElement extends UmbLitElement impleme if (this.contentType !== 'Content' && this.contentType !== 'Media') return nothing; return html` - + ${this.#renderContentTypePickerEditor()} `; @@ -84,17 +85,20 @@ export class UmbWebhookDetailsWorkspaceViewElement extends UmbLitElement impleme #renderContentTypePickerEditor() { switch (this.contentType) { case 'Content': - return html``; + return html` + + `; case 'Media': - return html``; + return html` + + `; default: return nothing; } @@ -105,20 +109,28 @@ export class UmbWebhookDetailsWorkspaceViewElement extends UmbLitElement impleme return html` - + - + ${this.#renderContentTypePicker()} - - + + - + `; + return html` + + `; } static override styles = [UmbTextStyles]; From 35fe4dbb554c001aa05e7d87f1bd9529bf2bee9c Mon Sep 17 00:00:00 2001 From: leekelleher Date: Tue, 30 Jul 2024 11:07:16 +0100 Subject: [PATCH 16/48] Lazy-load repositories Found a couple of repositories that hadn't been lazy-loaded. --- .../src/packages/core/culture/repository/culture.repository.ts | 2 ++ .../src/packages/core/culture/repository/manifests.ts | 3 +-- .../core/modal/common/embedded-media/repository/manifests.ts | 3 +-- .../common/embedded-media/repository/oembed.repository.ts | 2 ++ 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/culture.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/culture.repository.ts index 042e39713a..0d9ec60291 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/culture.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/culture.repository.ts @@ -18,3 +18,5 @@ export class UmbCultureRepository extends UmbControllerBase implements UmbApi { override destroy() {} } + +export { UmbCultureRepository as api }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/manifests.ts index 5e3e1ac52a..2862e1e2ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/culture/repository/manifests.ts @@ -1,4 +1,3 @@ -import { UmbCultureRepository } from './culture.repository.js'; import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const UMB_CULTURE_REPOSITORY_ALIAS = 'Umb.Repository.Culture'; @@ -7,7 +6,7 @@ const repository: ManifestRepository = { type: 'repository', alias: UMB_CULTURE_REPOSITORY_ALIAS, name: 'Cultures Repository', - api: UmbCultureRepository, + api: () => import('./culture.repository.js'), }; export const manifests: Array = [repository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/manifests.ts index 580f3e1026..dbce95b73d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/manifests.ts @@ -1,4 +1,3 @@ -import { UmbOEmbedRepository } from './oembed.repository.js'; import type { ManifestRepository, ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; export const UMB_OEMBED_REPOSITORY_ALIAS = 'Umb.Repository.OEmbed'; @@ -7,7 +6,7 @@ const repository: ManifestRepository = { type: 'repository', alias: UMB_OEMBED_REPOSITORY_ALIAS, name: 'OEmbed Repository', - api: UmbOEmbedRepository, + api: () => import('./oembed.repository.js'), }; export const manifests: Array = [repository]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.repository.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.repository.ts index 344c067453..983232efe2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.repository.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/embedded-media/repository/oembed.repository.ts @@ -18,3 +18,5 @@ export class UmbOEmbedRepository extends UmbControllerBase implements UmbApi { return { error }; } } + +export { UmbOEmbedRepository as api }; From fa16ea6639b4523dfef360516805a9483d3bcf38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 31 Jul 2024 11:31:16 +0200 Subject: [PATCH 17/48] register repository manifests --- .../composition-picker-modal.element.ts | 9 +++++---- .../packages/media/media-types/repository/manifests.ts | 3 ++- .../packages/members/member-type/repository/manifests.ts | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts index eb9739e8c0..12e7c60eec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts @@ -90,17 +90,18 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< await this.#init; if (!this.#compositionRepository) return; - const isElement = this.data?.isElement; - const currentPropertyAliases = this.data?.currentPropertyAliases; + // Notice isElement is not available on all types that can be composed. + const isElement = this.data?.isElement ?? undefined; + const currentPropertyAliases = this.data?.currentPropertyAliases ?? []; const { data } = await this.#compositionRepository.availableCompositions({ unique: this.#unique, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // TODO: isElement is not available on all types that can be composed. - isElement: isElement ?? false, + isElement: isElement, currentCompositeUniques: this._selection, - currentPropertyAliases: currentPropertyAliases ?? [], + currentPropertyAliases: currentPropertyAliases, }); if (!data) return; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts index 37dcb889ef..ce74b2570d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/repository/manifests.ts @@ -1,5 +1,6 @@ import { manifests as detailManifests } from './detail/manifests.js'; import { manifests as itemManifests } from './item/manifests.js'; +import { manifests as compositionManifests } from './composition/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...detailManifests, ...itemManifests]; +export const manifests: Array = [...detailManifests, ...itemManifests, ...compositionManifests]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/manifests.ts index 37dcb889ef..ce74b2570d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/repository/manifests.ts @@ -1,5 +1,6 @@ import { manifests as detailManifests } from './detail/manifests.js'; import { manifests as itemManifests } from './item/manifests.js'; +import { manifests as compositionManifests } from './composition/manifests.js'; import type { ManifestTypes } from '@umbraco-cms/backoffice/extension-registry'; -export const manifests: Array = [...detailManifests, ...itemManifests]; +export const manifests: Array = [...detailManifests, ...itemManifests, ...compositionManifests]; From a975f0e9cf81513d7425f43756cece0546a85396 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 31 Jul 2024 11:17:33 +0100 Subject: [PATCH 18/48] Localized references of Document Type name + description, tab label, group label and property label. --- .../composition-picker-modal.element.ts | 8 ++++---- .../workspace/views/edit/content-editor-tab.element.ts | 2 +- .../workspace/views/edit/content-editor.element.ts | 2 +- .../modal/common/item-picker/item-picker-modal.element.ts | 4 ++-- .../data-type-workspace-view-info-reference.element.ts | 4 +++- .../input-document-type/input-document-type.element.ts | 2 +- .../views/info/document-workspace-view-info.element.ts | 2 +- .../input-media-type/input-media-type.element.ts | 2 +- .../create/media-create-options-modal.element.ts | 4 ++-- .../input-member-type/input-member-type.element.ts | 2 +- .../template-field-dropdown-list.element.ts | 3 ++- 11 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts index eb9739e8c0..5877404a69 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts @@ -157,7 +157,7 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< (item) => html` + name=${this.localize.string(item.name)}> `, )} @@ -196,9 +196,9 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< return repeat( compositionsList, (compositions) => compositions.unique, - (compositions) => - html` html` + this.#onSelectionAdd(compositions.unique)} @deselected=${() => this.#onSelectionRemove(compositions.unique)} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-tab.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-tab.element.ts index 1fb52834a2..bb8a5a451f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-tab.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor-tab.element.ts @@ -63,7 +63,7 @@ export class UmbContentWorkspaceViewEditTabElement extends UmbLitElement { this._groups, (group) => group.id, (group) => - html` + html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor.element.ts index f37657e16d..87db2c05b8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content/workspace/views/edit/content-editor.element.ts @@ -138,7 +138,7 @@ export class UmbContentWorkspaceViewEditElement extends UmbLitElement implements (tab) => { const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || ''); return html`${tab.name}${this.localize.string(tab.name)}`; }, )} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts index 20f8747a4f..0f5fa9b803 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/item-picker/item-picker-modal.element.ts @@ -51,7 +51,7 @@ export class UmbItemPickerModalElement extends UmbModalBaseElement +
item.value, (item) => html` this.#submit(item)}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts index 310b633c3d..29f19e05fd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/data-type-workspace-view-info-reference.element.ts @@ -87,7 +87,9 @@ export class UmbDataTypeWorkspaceViewInfoReferenceElement extends UmbLitElement (item) => html` - + diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts index ce3702cb23..a0a7d6a13c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts @@ -204,7 +204,7 @@ export class UmbInputDocumentTypeElement extends UmbFormControlMixin + ${this.#renderIcon(item)} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts index 0a650e22e4..13344c29a1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.element.ts @@ -252,7 +252,7 @@ export class UmbDocumentWorkspaceViewInfoElement extends UmbLitElement { + name=${ifDefined(this.localize.string(this._documentTypeName ?? ''))}>
diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts index 5c2173cdd9..9b7c64f927 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/components/input-media-type/input-media-type.element.ts @@ -174,7 +174,7 @@ export class UmbInputMediaTypeElement extends UmbFormControlMixin + ${this.#renderIcon(item)} diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts index 2773d3c991..d689fac6be 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts @@ -109,8 +109,8 @@ export class UmbMediaCreateOptionsModalElement extends UmbModalBaseElement< (mediaType) => html` this.#onNavigate(mediaType)}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/components/input-member-type/input-member-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/components/input-member-type/input-member-type.element.ts index 02d36f5921..d66e61df7e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-type/components/input-member-type/input-member-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-type/components/input-member-type/input-member-type.element.ts @@ -137,7 +137,7 @@ export class UmbInputMemberTypeElement extends UmbFormControlMixin + ${when(item.icon, () => html``)} ${this._uniqueName} + return html` + ${this.localize.string(this._uniqueName ?? '')} ${repeat( From 33476dcb70842a0f95dfd1ceff3a4a4f234a1723 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 31 Jul 2024 11:18:06 +0100 Subject: [PATCH 19/48] Adds missing localization (for "System fields") --- src/Umbraco.Web.UI.Client/src/assets/lang/en.ts | 1 + .../template-field-dropdown-list.element.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 7e0e77d5cd..f5419e0bea 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -1562,6 +1562,7 @@ export default { ascending: 'ascending', descending: 'descending', template: 'Template', + systemFields: 'System fields', }, grid: { media: 'Image', diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts index cbfc149a86..1cd6357fb0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts @@ -152,7 +152,7 @@ export class UmbTemplateFieldDropdownListElement extends UmbLitElement { - ${this.localize.term('formSettings_systemFields')} + ${this.localize.term('template_systemFields')} ${this.localize.term('content_documentType')} From 42083efbb36f1f7c287d6d319bd3c10d15fb700b Mon Sep 17 00:00:00 2001 From: leekelleher Date: Wed, 31 Jul 2024 11:18:45 +0100 Subject: [PATCH 20/48] Markup tidy-up of the components with doctype localizations --- .../input-entity/input-entity.element.ts | 2 +- .../composition-picker-modal.element.ts | 42 ++++--- .../content-type-design-editor.element.ts | 18 +-- .../document-create-options-modal.element.ts | 107 +++++++++--------- .../media-create-options-modal.element.ts | 13 ++- .../template-field-dropdown-list.element.ts | 3 +- 6 files changed, 103 insertions(+), 82 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-entity/input-entity.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-entity/input-entity.element.ts index a36c456d51..5946030eb4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-entity/input-entity.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-entity/input-entity.element.ts @@ -148,7 +148,7 @@ export class UmbInputEntityElement extends UmbFormControlMixin + label=${this.localize.term('general_choose')}> `; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts index 5877404a69..f45eea348d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/modals/composition-picker/composition-picker-modal.element.ts @@ -129,11 +129,13 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement<
${!this._references.length - ? html`` + ? html` + + ` : nothing}
@@ -141,7 +143,8 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< } #renderHasReference() { - return html` + return html` + This Content Type is used in a composition, and therefore cannot be composed itself.

@@ -154,19 +157,22 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< ${repeat( this._references, (item) => item.unique, - (item) => - html` html` + - `, + + `, )} - `; + + `; } #renderAvailableCompositions() { if (this._compatibleCompositions) { - return html` + return html` + Inherit tabs and properties from an existing Document Type. New tabs will be
added to the current Document Type or merged if a tab with an identical name exists.
@@ -184,11 +190,14 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< : nothing} ${this.#renderCompositionsItems(folder.compositions)}`, )} - `; + + `; } else { - return html` - There are no Content Types available to use as a composition - `; + return html` + + There are no Content Types available to use as a composition + + `; } } @@ -204,7 +213,8 @@ export class UmbCompositionPickerModalElement extends UmbModalBaseElement< @deselected=${() => this.#onSelectionRemove(compositions.unique)} ?selected=${this._selection.find((unique) => unique === compositions.unique)}> - `, + + `, ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts index 109077161d..34e5c02eeb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/workspace/views/design/content-type-design-editor.element.ts @@ -416,14 +416,16 @@ export class UmbContentTypeDesignEditorElement extends UmbLitElement implements return html`
${this._compositionRepositoryAlias - ? html` - - ${this.localize.term('contentTypeEditor_compositions')} - ` + ? html` + + + ${this.localize.term('contentTypeEditor_compositions')} + + ` : ''} diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts index c6e010236a..3f6751d76b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/entity-actions/create/document-create-options-modal.element.ts @@ -133,60 +133,65 @@ export class UmbDocumentCreateOptionsModalElement extends UmbModalBaseElement< } #renderDocumentTypes() { - return html` - ${when( - this._allowedDocumentTypes.length === 0, - () => html` - - There are no allowed Document Types available for creating content here. You must enable these in - Document Types within the Settings section, by editing the - Allowed child node types under Permissions.
-
- this._rejectModal()} - href=${`/section/settings/workspace/document-type/edit/${this.data?.documentType?.unique}/view/structure`} - label=${this.localize.term('create_noDocumentTypesEditPermissions')}> - `, - () => - repeat( - this._allowedDocumentTypes, - (documentType) => documentType.unique, - (documentType) => - html` this.#onSelectDocumentType(documentType.unique)}> - - `, - ), - )} -
`; + return html` + + ${when( + this._allowedDocumentTypes.length === 0, + () => html` + + There are no allowed Document Types available for creating content here. You must enable these in + Document Types within the Settings section, by editing the + Allowed child node types under Permissions.
+
+ this._rejectModal()}> + `, + () => + repeat( + this._allowedDocumentTypes, + (documentType) => documentType.unique, + (documentType) => html` + this.#onSelectDocumentType(documentType.unique)}> + + + `, + ), + )} +
+ `; } #renderBlueprints() { - return html` - this.#onNavigate(this.#documentTypeUnique)}> - - - ${repeat( - this._availableBlueprints, - (blueprint) => blueprint.unique, - (blueprint) => - html` this.#onNavigate(this.#documentTypeUnique, blueprint.unique)}> - - `, - )} `; + return html` + + this.#onNavigate(this.#documentTypeUnique)}> + + + ${repeat( + this._availableBlueprints, + (blueprint) => blueprint.unique, + (blueprint) => + html` this.#onNavigate(this.#documentTypeUnique, blueprint.unique)}> + + `, + )} + + `; } static override styles = [ diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts index d689fac6be..8de7a5fef3 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/entity-actions/create/media-create-options-modal.element.ts @@ -89,7 +89,8 @@ export class UmbMediaCreateOptionsModalElement extends UmbModalBaseElement< } #renderNotAllowed() { - return html` + return html` + There are no allowed Media Types available for creating media here. You must enable these in Media Types within the Settings section, by editing the Allowed child node types under Permissions. this._rejectModal()} href=${`/section/settings/workspace/media-type/edit/${this.data?.mediaType?.unique}/view/structure`} - label=${this.localize.term('create_noMediaTypesEditPermissions')}>
`; + label=${this.localize.term('create_noMediaTypesEditPermissions')}> + `; } #renderAllowedMediaTypes() { return repeat( this._allowedMediaTypes, (mediaType) => mediaType.unique, - (mediaType) => - html` html` + this.#onNavigate(mediaType)}> ${mediaType.icon ? html`` : nothing} - `, + + `, ); } diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts index 1cd6357fb0..ef744bf99c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.element.ts @@ -185,7 +185,8 @@ export class UmbTemplateFieldDropdownListElement extends UmbLitElement { html`${field.alias}`, )} - `; + + `; } static override styles = [ From 63e3fc4de502b668ad7fe0f6b730e1c915daaec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 31 Jul 2024 13:06:39 +0200 Subject: [PATCH 21/48] block custom view example --- .../examples/block-custom-view/README.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/examples/block-custom-view/README.md diff --git a/src/Umbraco.Web.UI.Client/examples/block-custom-view/README.md b/src/Umbraco.Web.UI.Client/examples/block-custom-view/README.md new file mode 100644 index 0000000000..e0894b30b7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/block-custom-view/README.md @@ -0,0 +1,7 @@ +# Property Dataset Dashboard Example + +This example is a work in progress example of how to write a property editor. + +This example covers a few points: + +- Using an existing Property Editor Schema From 1b4f1193625e22475816ed3b53e2a1b76b99fdad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Wed, 31 Jul 2024 13:06:54 +0200 Subject: [PATCH 22/48] more code --- .../block-custom-view/block-custom-view.ts | 42 +++++++++++++++++++ .../examples/block-custom-view/index.ts | 12 ++++++ 2 files changed, 54 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts create mode 100644 src/Umbraco.Web.UI.Client/examples/block-custom-view/index.ts diff --git a/src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts b/src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts new file mode 100644 index 0000000000..abd194cf81 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts @@ -0,0 +1,42 @@ +import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; +import { html, customElement, LitElement, property, css } from '@umbraco-cms/backoffice/external/lit'; +import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; +import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/extension-registry'; + +@customElement('example-block-custom-view') +export class ExampleBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement { + // + @property({ attribute: false }) + content?: UmbBlockDataType; + + override render() { + return html` +
+
My Custom View
+

Headline: ${this.content.headline}

+
+ `; + } + + static override styles = [ + UmbTextStyles, + css` + :host { + display: block; + height: 100%; + box-sizing: border-box; + background-color: #dddddd; + border-radius: 9px; + padding: 12px; + } + `, + ]; +} + +export default ExampleBlockCustomView; + +declare global { + interface HTMLElementTagNameMap { + 'example-block-custom-view': ExampleBlockCustomView; + } +} diff --git a/src/Umbraco.Web.UI.Client/examples/block-custom-view/index.ts b/src/Umbraco.Web.UI.Client/examples/block-custom-view/index.ts new file mode 100644 index 0000000000..e50355a08b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/block-custom-view/index.ts @@ -0,0 +1,12 @@ +import type { ManifestBlockEditorCustomView } from '@umbraco-cms/backoffice/extension-registry'; + +export const manifests: Array = [ + { + type: 'blockEditorCustomView', + alias: 'Umb.blockEditorCustomView.TestView', + name: 'Block Editor Custom View Test', + element: () => import('./block-custom-view.js'), + forContentTypeAlias: 'headlineUmbracoDemoBlock', + forBlockEditor: 'block-grid', + }, +]; From 862b9493972887b4efdce7d49b818c6f5e059499 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 31 Jul 2024 14:57:24 +0200 Subject: [PATCH 23/48] Use constant for language workspace alias --- .../language/workspace/language/language-workspace.context.ts | 3 ++- .../src/packages/language/workspace/language/manifests.ts | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts index 87d2816bd5..646982ea70 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts @@ -1,6 +1,7 @@ import { UmbLanguageDetailRepository } from '../../repository/index.js'; import type { UmbLanguageDetailModel } from '../../types.js'; import { UmbLanguageWorkspaceEditorElement } from './language-workspace-editor.element.js'; +import { UMB_LANGUAGE_WORKSPACE_ALIAS } from './manifests.js'; import { type UmbSubmittableWorkspaceContext, UmbSubmittableWorkspaceContextBase, @@ -27,7 +28,7 @@ export class UmbLanguageWorkspaceContext readonly validationErrors = this.#validationErrors.asObservable(); constructor(host: UmbControllerHost) { - super(host, 'Umb.Workspace.Language'); + super(host, UMB_LANGUAGE_WORKSPACE_ALIAS); this.routes.setRoutes([ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts index 6abbf9bf69..db9c56185f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts @@ -6,10 +6,12 @@ import type { ManifestTypes, } from '@umbraco-cms/backoffice/extension-registry'; +export const UMB_LANGUAGE_WORKSPACE_ALIAS = 'Umb.Workspace.Language'; + const workspace: ManifestWorkspaces = { type: 'workspace', kind: 'routable', - alias: 'Umb.Workspace.Language', + alias: UMB_LANGUAGE_WORKSPACE_ALIAS, name: 'Language Workspace', api: () => import('./language-workspace.context.js'), meta: { From ed6cc35de34e9a7e44a61e20779ca4c1a8c78eea Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 31 Jul 2024 16:44:27 +0200 Subject: [PATCH 24/48] Make icons consistent with icon under each health check --- .../views/health-check-group-box-overview.element.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group-box-overview.element.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group-box-overview.element.ts index 42d8679729..3dadc4cee6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group-box-overview.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group-box-overview.element.ts @@ -64,25 +64,25 @@ export class UmbHealthCheckGroupBoxOverviewElement extends UmbLitElement { _renderCheckResults(resultObject: any) { return html`${resultObject.success > 0 ? html` - + ${resultObject.success} ` : nothing} ${resultObject.warning > 0 ? html` - + ${resultObject.warning} ` : nothing} ${resultObject.error > 0 ? html` - + ${resultObject.error} ` : nothing} ${resultObject.info > 0 ? html` - + ${resultObject.info} ` : nothing} `; From 717ddc5f24c4e8049992a8fdeaf583b37698d641 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 31 Jul 2024 16:45:19 +0200 Subject: [PATCH 25/48] Adjust alert icon color to match overview icon and increased contrast --- .../packages/health-check/views/health-check-group.element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group.element.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group.element.ts index 787edc26c6..084d41a1a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/health-check/views/health-check-group.element.ts @@ -129,7 +129,7 @@ export class UmbDashboardHealthCheckGroupElement extends UmbLitElement { case StatusResultTypeModel.SUCCESS: return html``; case StatusResultTypeModel.WARNING: - return html``; + return html``; case StatusResultTypeModel.ERROR: return html``; case StatusResultTypeModel.INFO: From 9864f0b3015f31c083fe51cc6070f0b8cb91ac2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 1 Aug 2024 09:27:32 +0200 Subject: [PATCH 26/48] retrieve and render content type name --- ...block-grid-area-type-permission.element.ts | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts index 645906e4d7..3af917e303 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-area-type-permission/block-grid-area-type-permission.element.ts @@ -7,6 +7,11 @@ import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-ed import { UMB_DATA_TYPE_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/data-type'; import type { UmbBlockTypeWithGroupKey } from '@umbraco-cms/backoffice/block-type'; import type { UUIComboboxElement, UUIComboboxEvent, UUIInputEvent } from '@umbraco-cms/backoffice/external/uui'; +import { UmbRepositoryItemsManager } from '@umbraco-cms/backoffice/repository'; +import { + UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, + type UmbDocumentTypeItemModel, +} from '@umbraco-cms/backoffice/document-type'; @customElement('umb-property-editor-ui-block-grid-area-type-permission') export class UmbPropertyEditorUIBlockGridAreaTypePermissionElement @@ -24,20 +29,41 @@ export class UmbPropertyEditorUIBlockGridAreaTypePermissionElement @state() private _value: Array = []; + _blockTypes: Array = []; + @state() - private _blockTypes: Array = []; + private _blockTypesWithElementName: Array<{ type: UmbBlockTypeWithGroupKey; name: string }> = []; @state() private _blockGroups: Array = []; + #itemsManager = new UmbRepositoryItemsManager( + this, + UMB_DOCUMENT_TYPE_ITEM_REPOSITORY_ALIAS, + (x) => x.unique, + ); + constructor() { super(); + this.observe(this.#itemsManager.items, (items) => { + this._blockTypesWithElementName = items + .map((item) => { + const blockType = this._blockTypes.find((block) => block.contentElementTypeKey === item.unique); + if (blockType) { + return { type: blockType, name: item.name }; + } + return undefined; + }) + .filter((x) => x !== undefined) as Array<{ type: UmbBlockTypeWithGroupKey; name: string }>; + }); + this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, async (context) => { this.observe( await context.propertyValueByAlias>('blocks'), (blockTypes) => { this._blockTypes = blockTypes ?? []; + this.#itemsManager.setUniques(blockTypes.map((block) => block.contentElementTypeKey)); }, 'observeBlockType', ); @@ -103,7 +129,7 @@ export class UmbPropertyEditorUIBlockGridAreaTypePermissionElement this._value, (permission) => permission, (permission, index) => { - const showCategoryHeader = this._blockGroups.length && this._blockTypes.length; + const showCategoryHeader = this._blockGroups.length > 0 && this._blockTypesWithElementName.length > 0; return html`
block.contentElementTypeKey, + this._blockTypesWithElementName, + (block) => block.type.contentElementTypeKey, (block) => html` - ${block.label} + .value=${block.type.contentElementTypeKey} + ?selected=${area.elementTypeKey === block.type.contentElementTypeKey}> + ${block.name} `, ); } From 438ee72714a65a3f3f223583d3f2317bc293c155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 1 Aug 2024 09:57:24 +0200 Subject: [PATCH 27/48] remove unused data return --- .../block/block-type/workspace/block-type-workspace.context.ts | 1 - 1 file changed, 1 deletion(-) 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 7585986cb5..74b2b8bfcb 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 @@ -112,7 +112,6 @@ export class UmbBlockTypeWorkspaceContext Date: Thu, 1 Aug 2024 09:57:48 +0200 Subject: [PATCH 28/48] use workspace create --- .../block-grid-area-type-workspace.context.ts | 32 +++++++++++---- ...itor-ui-block-grid-areas-config.element.ts | 41 ++++++++----------- 2 files changed, 40 insertions(+), 33 deletions(-) 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.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts index 875b2333d2..10dd58fa03 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/workspace/block-grid-area-type-workspace.context.ts @@ -14,6 +14,7 @@ import { UmbArrayState, UmbObjectState, appendToFrozenArray } from '@umbraco-cms import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbContextToken } from '@umbraco-cms/backoffice/context-api'; import type { ManifestWorkspace, PropertyEditorSettingsProperty } from '@umbraco-cms/backoffice/extension-registry'; +import { UmbId } from '@umbraco-cms/backoffice/id'; export class UmbBlockGridAreaTypeWorkspaceContext extends UmbSubmittableWorkspaceContextBase @@ -43,12 +44,20 @@ export class UmbBlockGridAreaTypeWorkspaceContext { path: 'edit/:id', component: () => import('./block-grid-area-type-workspace-editor.element.js'), - setup: (_component, info) => { + setup: (component, info) => { const id = info.match.params.id; - (_component as any).workspaceAlias = manifest.alias; + (component as any).workspaceAlias = manifest.alias; this.load(id); }, }, + { + path: 'create', + component: () => import('./block-grid-area-type-workspace-editor.element.js'), + setup: (component) => { + (component as any).workspaceAlias = manifest.alias; + this.create(); + }, + }, ]); } @@ -78,17 +87,24 @@ export class UmbBlockGridAreaTypeWorkspaceContext } async create() { - throw new Error('Method not implemented.'); - /* - //Only set groupKey property if it exists - const data: UmbBlockGridTypeAreaType = { + this.resetState(); + let data: UmbBlockGridTypeAreaType = { + key: UmbId.new(), + alias: '', + columnSpan: 12, + rowSpan: 1, + minAllowed: 0, + maxAllowed: undefined, + specifiedAllowance: [], + }; + // 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() { 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 3f102682ed..44d9d69055 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 @@ -61,7 +61,17 @@ export class UmbPropertyEditorUIBlockGridAreasConfigElement new UmbModalRouteRegistrationController(this, UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_MODAL) .addAdditionalPath('block-grid-area-type') .onSetup(() => { - return { data: { entityType: 'block-grid-area-type', preset: {} }, modal: { size: 'large' } }; + if (!this._areaGridColumns) return false; + const halfGridColumns = this._areaGridColumns * 0.5; + const columnSpan = halfGridColumns === Math.round(halfGridColumns) ? halfGridColumns : this._areaGridColumns; + + return { + data: { + entityType: 'block-grid-area-type', + preset: { columnSpan, alias: this.#generateUniqueAreaAlias('area') }, + }, + modal: { size: 'large' }, + }; }) .observeRouteBuilder((routeBuilder) => { this._workspacePath = routeBuilder({}); @@ -104,29 +114,6 @@ export class UmbPropertyEditorUIBlockGridAreasConfigElement return alias; } - #addNewArea() { - if (!this._areaGridColumns) return; - const halfGridColumns = this._areaGridColumns * 0.5; - const columnSpan = halfGridColumns === Math.round(halfGridColumns) ? halfGridColumns : this._areaGridColumns; - - this._value = [ - ...this._value, - { - key: UmbId.new(), - alias: this.#generateUniqueAreaAlias('area'), - columnSpan: columnSpan, - rowSpan: 1, - minAllowed: 0, - maxAllowed: undefined, - specifiedAllowance: [], - }, - ]; - this.requestUpdate('_value'); - this.dispatchEvent(new UmbPropertyValueChangeEvent()); - - //TODO: open area edit workspace - } - override render() { return this._areaGridColumns ? html`${this._styleElement} @@ -144,7 +131,11 @@ export class UmbPropertyEditorUIBlockGridAreasConfigElement .key=${area.key}>`, )}
- ` + ` : ''; } } From 61cbd35b41a3c8e07f53b4d783ebda6e479cfb78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 1 Aug 2024 15:18:43 +0200 Subject: [PATCH 29/48] refactor composition logic --- ...t-type-container-structure-helper.class.ts | 37 +++++++------- ...nt-type-property-structure-helper.class.ts | 14 ++--- .../content-type-structure-manager.class.ts | 51 ++++++++++++------- 3 files changed, 60 insertions(+), 42 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-container-structure-helper.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-container-structure-helper.class.ts index 07b2268a71..32912b50e8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-container-structure-helper.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-container-structure-helper.class.ts @@ -1,7 +1,7 @@ import type { UmbContentTypeModel, UmbPropertyContainerTypes, UmbPropertyTypeContainerModel } from '../types.js'; import type { UmbContentTypeStructureManager } from './content-type-structure-manager.class.js'; import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api'; -import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { UmbController, UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; import { UmbArrayState } from '@umbraco-cms/backoffice/observable-api'; /** @@ -17,6 +17,8 @@ export class UmbContentTypeContainerStructureHelper; + #containerObservers: Array = []; + // State containing the all containers defined in the data: #childContainers = new UmbArrayState([], (x) => x.id); readonly containers = this.#childContainers.asObservable(); @@ -150,30 +152,31 @@ export class UmbContentTypeContainerStructureHelper { - // We want to remove hasProperties of groups that does not exist anymore.: - // this.#removeHasPropertiesOfGroup() this.#hasProperties.setValue([]); this.#childContainers.setValue([]); + this.#containerObservers.forEach((x) => x.destroy()); + this.#containerObservers = []; containers.forEach((container) => { this.#observeHasPropertiesOf(container.id); - this.observe( - this.#structure!.containersOfParentId(container.id, this.#childType!), - (containers) => { - // get the direct owner containers of this container id: - this.#ownerChildContainers = - this.#structure!.getOwnerContainers(this.#childType!, this.#containerId!) ?? []; - // TODO: Maybe check for dif before setting it? Cause currently we are setting it every time one of the containers change. [NL] + this.#containerObservers.push( + this.observe( + this.#structure!.containersOfParentId(container.id, this.#childType!), + (containers) => { + // get the direct owner containers of this container id: [NL] + this.#ownerChildContainers = + this.#structure!.getOwnerContainers(this.#childType!, this.#containerId!) ?? []; - // Remove existing containers that are not the parent of the new containers: - this.#childContainers.filter( - (x) => x.parent?.id !== container.id || containers.some((y) => y.id === x.id), - ); + // Remove existing containers that are not the parent of the new containers: [NL] + this.#childContainers.filter( + (x) => x.parent?.id !== container.id || containers.some((y) => y.id === x.id), + ); - this.#childContainers.append(containers); - }, - '_observeGroupsOf_' + container.id, + this.#childContainers.append(containers); + }, + '_observeGroupsOf_' + container.id, + ), ); }); }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-property-structure-helper.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-property-structure-helper.class.ts index 55be7cf04d..14753917ba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-property-structure-helper.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-property-structure-helper.class.ts @@ -21,7 +21,7 @@ export class UmbContentTypePropertyStructureHelper; - private _containerId?: string | null; + #containerId?: string | null; // State which holds all the properties of the current container, this is a composition of all properties from the containers that matches our target [NL] #propertyStructure = new UmbArrayState([], (x) => x.id); @@ -59,12 +59,12 @@ export class UmbContentTypePropertyStructureHelper; #observeContainers() { - if (!this.#structure || this._containerId === undefined) return; + if (!this.#structure || this.#containerId === undefined) return; - if (this._containerId === null) { + if (this.#containerId === null) { this.observe( this.#structure.propertyStructuresOf(null), (properties) => { @@ -87,7 +87,7 @@ export class UmbContentTypePropertyStructureHelper { if (container) { this._containerName = container.name ?? ''; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 3c811652d4..7e846ba8a2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -42,10 +42,13 @@ export class UmbContentTypeStructureManager< readonly ownerContentType = this.#contentTypes.asObservablePart((x) => x.find((y) => y.unique === this.#ownerContentTypeUnique), ); - - private readonly _contentTypeContainers = this.#contentTypes.asObservablePart((x) => - x.flatMap((x) => x.containers ?? []), + readonly ownerContentTypeCompositions = this.#contentTypes.asObservablePart( + (x) => x.find((y) => y.unique === this.#ownerContentTypeUnique)?.compositions, ); + + readonly #contentTypeContainers = this.#contentTypes.asObservablePart((x) => { + return this.#contentTypes.getValue().flatMap((x) => x.containers ?? []); + }); readonly contentTypeUniques = this.#contentTypes.asObservablePart((x) => x.map((y) => y.unique)); readonly contentTypeAliases = this.#contentTypes.asObservablePart((x) => x.map((y) => y.alias)); @@ -61,12 +64,12 @@ export class UmbContentTypeStructureManager< super(host); this.#repository = typeRepository; - this.observe(this.contentTypes, (contentTypes) => { - contentTypes.forEach((contentType) => { - this._loadContentTypeCompositions(contentType); - }); + // Observe owner content type compositions, as we only allow one level of compositions at this moment. [NL] + // But, we could support more, we would just need to flatMap all compositions and make sure the entries are unique and then base the observation on that. [NL] + this.observe(this.ownerContentTypeCompositions, (ownerContentTypeCompositions) => { + this._loadContentTypeCompositions(ownerContentTypeCompositions); }); - this.observe(this._contentTypeContainers, (contentTypeContainers) => { + this.observe(this.#contentTypeContainers, (contentTypeContainers) => { this.#containers.setValue(contentTypeContainers); }); } @@ -136,8 +139,24 @@ export class UmbContentTypeStructureManager< this._observeContentType(data); } - private async _loadContentTypeCompositions(contentType: T) { - contentType.compositions?.forEach((composition) => { + private async _loadContentTypeCompositions(ownerContentTypeCompositions: T['compositions'] | undefined) { + if (!ownerContentTypeCompositions) { + // Owner content type was undefined, so we can not load compositions. But at this point we neither offload existing compositions, this is most likely not a case that needs to be handled. + return; + } + + const ownerUnique = this.getOwnerContentTypeUnique(); + // Remove content types that does not exist as compositions anymore: + this.#contentTypes.getValue().forEach((x) => { + if ( + x.unique !== ownerUnique && + !ownerContentTypeCompositions.find((comp) => comp.contentType.unique === x.unique) + ) { + this.#contentTypeObservers.find((y) => y.controllerAlias === 'observeContentType_' + x.unique)?.destroy(); + this.#contentTypes.removeOne(x.unique); + } + }); + ownerContentTypeCompositions.forEach((composition) => { this._ensureType(composition.contentType.unique); }); } @@ -164,23 +183,19 @@ export class UmbContentTypeStructureManager< // Notice we do not store the content type in the store here, cause it will happen shortly after when the observations gets its first initial callback. [NL] - // Load inherited and composed types: - //this._loadContentTypeCompositions(data);// Should not be necessary as this will be done when appended to the contentTypes state. [NL] - const ctrl = this.observe( // Then lets start observation of the content type: await this.#repository.byUnique(data.unique), (docType) => { if (docType) { - // TODO: Handle if there was changes made to the owner document type in this context. [NL] - /* - possible easy solutions could be to notify user wether they want to update(Discard the changes to accept the new ones). [NL] - */ this.#contentTypes.appendOne(docType); + } else { + // Remove the content type from the store, if it does not exist anymore. + this.#contentTypes.removeOne(data.unique); } - // TODO: Do we need to handle the undefined case? [NL] }, 'observeContentType_' + data.unique, + // Controller Alias is used to stop observation when no longer needed. [NL] ); this.#contentTypeObservers.push(ctrl); From c7276ab4acc045d92d362f4536279eacaffee42a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:55:27 +0000 Subject: [PATCH 30/48] build(deps-dev): bump typedoc from 0.26.4 to 0.26.5 Bumps [typedoc](https://github.com/TypeStrong/TypeDoc) from 0.26.4 to 0.26.5. - [Release notes](https://github.com/TypeStrong/TypeDoc/releases) - [Changelog](https://github.com/TypeStrong/typedoc/blob/master/CHANGELOG.md) - [Commits](https://github.com/TypeStrong/TypeDoc/compare/v0.26.4...v0.26.5) --- updated-dependencies: - dependency-name: typedoc dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Umbraco.Web.UI.Client/package-lock.json | 8 ++++---- src/Umbraco.Web.UI.Client/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index dafc1e3c8f..3397fd5722 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -97,7 +97,7 @@ "storybook": "^7.6.17", "tiny-glob": "^0.2.9", "tsc-alias": "^1.8.10", - "typedoc": "^0.26.4", + "typedoc": "^0.26.5", "typescript": "^5.5.3", "typescript-eslint": "^7.16.1", "typescript-json-schema": "^0.64.0", @@ -20084,9 +20084,9 @@ "dev": true }, "node_modules/typedoc": { - "version": "0.26.4", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.4.tgz", - "integrity": "sha512-FlW6HpvULDKgc3rK04V+nbFyXogPV88hurarDPOjuuB5HAwuAlrCMQ5NeH7Zt68a/ikOKu6Z/0hFXAeC9xPccQ==", + "version": "0.26.5", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.5.tgz", + "integrity": "sha512-Vn9YKdjKtDZqSk+by7beZ+xzkkr8T8CYoiasqyt4TTRFy5+UHzL/mF/o4wGBjRF+rlWQHDb0t6xCpA3JNL5phg==", "dev": true, "dependencies": { "lunr": "^2.3.9", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 3ed5ffa50b..65272c56d3 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -267,7 +267,7 @@ "storybook": "^7.6.17", "tiny-glob": "^0.2.9", "tsc-alias": "^1.8.10", - "typedoc": "^0.26.4", + "typedoc": "^0.26.5", "typescript": "^5.5.3", "typescript-eslint": "^7.16.1", "typescript-json-schema": "^0.64.0", From ff7e3e04002c094d39e245ca0f10b9defa051ebb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:56:00 +0000 Subject: [PATCH 31/48] build(deps-dev): bump @playwright/test from 1.45.2 to 1.45.3 Bumps [@playwright/test](https://github.com/microsoft/playwright) from 1.45.2 to 1.45.3. - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.45.2...v1.45.3) --- updated-dependencies: - dependency-name: "@playwright/test" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Umbraco.Web.UI.Client/package-lock.json | 24 ++++++++++----------- src/Umbraco.Web.UI.Client/package.json | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index dafc1e3c8f..bafe597091 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -52,7 +52,7 @@ "@hey-api/openapi-ts": "^0.48.3", "@mdx-js/react": "^3.0.1", "@open-wc/testing": "^4.0.0", - "@playwright/test": "^1.45.2", + "@playwright/test": "^1.45.3", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", @@ -3386,12 +3386,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.2.tgz", - "integrity": "sha512-JxG9eq92ET75EbVi3s+4sYbcG7q72ECeZNbdBlaMkGcNbiDQ4cAi8U2QP5oKkOx+1gpaiL1LDStmzCaEM1Z6fQ==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.45.3.tgz", + "integrity": "sha512-UKF4XsBfy+u3MFWEH44hva1Q8Da28G6RFtR2+5saw+jgAFQV5yYnB1fu68Mz7fO+5GJF3wgwAIs0UelU8TxFrA==", "dev": true, "dependencies": { - "playwright": "1.45.2" + "playwright": "1.45.3" }, "bin": { "playwright": "cli.js" @@ -17498,12 +17498,12 @@ } }, "node_modules/playwright": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.2.tgz", - "integrity": "sha512-ReywF2t/0teRvNBpfIgh5e4wnrI/8Su8ssdo5XsQKpjxJj+jspm00jSoz9BTg91TT0c9HRjXO7LBNVrgYj9X0g==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz", + "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", "dev": true, "dependencies": { - "playwright-core": "1.45.2" + "playwright-core": "1.45.3" }, "bin": { "playwright": "cli.js" @@ -17516,9 +17516,9 @@ } }, "node_modules/playwright-core": { - "version": "1.45.2", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.2.tgz", - "integrity": "sha512-ha175tAWb0dTK0X4orvBIqi3jGEt701SMxMhyujxNrgd8K0Uy5wMSwwcQHtyB4om7INUkfndx02XnQ2p6dvLDw==", + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz", + "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", "dev": true, "bin": { "playwright-core": "cli.js" diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 3ed5ffa50b..29db6d77c1 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -222,7 +222,7 @@ "@hey-api/openapi-ts": "^0.48.3", "@mdx-js/react": "^3.0.1", "@open-wc/testing": "^4.0.0", - "@playwright/test": "^1.45.2", + "@playwright/test": "^1.45.3", "@rollup/plugin-commonjs": "^26.0.1", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.2.3", From ced2cdf781bfd0ad55d2a04c83405d0e56193be2 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 5 Aug 2024 08:50:20 +0100 Subject: [PATCH 32/48] Localized workspace split view name input label --- .../workspace-split-view-variant-selector.element.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts index e8a4f0ee96..c4bfbf0cab 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-split-view/workspace-split-view-variant-selector.element.ts @@ -209,11 +209,10 @@ export class UmbWorkspaceSplitViewVariantSelectorElement extends UmbLitElement { } override render() { - // TODO: Localize [NL] return html` Date: Mon, 5 Aug 2024 09:55:54 +0200 Subject: [PATCH 33/48] remove parameter --- .../structure/content-type-structure-manager.class.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts index 7e846ba8a2..8fe26a1460 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/content-type/structure/content-type-structure-manager.class.ts @@ -46,7 +46,7 @@ export class UmbContentTypeStructureManager< (x) => x.find((y) => y.unique === this.#ownerContentTypeUnique)?.compositions, ); - readonly #contentTypeContainers = this.#contentTypes.asObservablePart((x) => { + readonly #contentTypeContainers = this.#contentTypes.asObservablePart(() => { return this.#contentTypes.getValue().flatMap((x) => x.containers ?? []); }); readonly contentTypeUniques = this.#contentTypes.asObservablePart((x) => x.map((y) => y.unique)); From 407e8b1babe5301fe9ccf8eb74d532de2f856e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 5 Aug 2024 09:57:32 +0200 Subject: [PATCH 34/48] fix lint issue --- .../property-editor-ui-block-grid-areas-config.element.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 44d9d69055..380ea33f83 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 @@ -6,11 +6,7 @@ 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'; import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -import { - UmbPropertyValueChangeEvent, - type UmbPropertyEditorConfigCollection, -} from '@umbraco-cms/backoffice/property-editor'; -import { UmbId } from '@umbraco-cms/backoffice/id'; +import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; import { incrementString } from '@umbraco-cms/backoffice/utils'; From f38b82a39e229ee6ff2de2140350f674f96b574b Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:14:55 +0200 Subject: [PATCH 35/48] feat: add bundling for the 'tiny-mce' package --- src/Umbraco.Web.UI.Client/package-lock.json | 6 ++++++ src/Umbraco.Web.UI.Client/package.json | 1 + .../src/packages/tiny-mce/package.json | 8 ++++++++ .../src/packages/tiny-mce/vite.config.ts | 19 +++++++++++++++++++ 4 files changed, 34 insertions(+) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiny-mce/package.json create mode 100644 src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 51e8c32c74..f52190d087 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -24,6 +24,7 @@ "./src/packages/property-editors", "./src/packages/tags", "./src/packages/templating", + "./src/packages/tiny-mce", "./src/packages/umbraco-news", "./src/packages/user", "./src/packages/webhook" @@ -7412,6 +7413,10 @@ "resolved": "src/packages/templating", "link": true }, + "node_modules/@umbraco-backoffice/tiny-mce": { + "resolved": "src/packages/tiny-mce", + "link": true + }, "node_modules/@umbraco-backoffice/umbraco-news": { "resolved": "src/packages/umbraco-news", "link": true @@ -21741,6 +21746,7 @@ "src/packages/templating": { "name": "@umbraco-backoffice/templating" }, + "src/packages/tiny-mce": {}, "src/packages/umbraco-news": { "name": "@umbraco-backoffice/umbraco-news" }, diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 64bdf43510..766ac0c7bb 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -143,6 +143,7 @@ "./src/packages/property-editors", "./src/packages/tags", "./src/packages/templating", + "./src/packages/tiny-mce", "./src/packages/umbraco-news", "./src/packages/user", "./src/packages/webhook" diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/package.json b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/package.json new file mode 100644 index 0000000000..6362dc5347 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/package.json @@ -0,0 +1,8 @@ +{ + "name": "@umbraco-backoffice/tiny-mce", + "private": true, + "type": "module", + "scripts": { + "build": "vite build" + } +} diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts new file mode 100644 index 0000000000..72556d1777 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vite'; +import { rmSync } from 'fs'; +import { getDefaultConfig } from '../../vite-config-base'; + +const dist = '../../../dist-cms/packages/tiny-mce'; + +// delete the unbundled dist folder +rmSync(dist, { recursive: true, force: true }); + +export default defineConfig({ + ...getDefaultConfig({ + dist, + entry: { + index: 'index.ts', + 'umbraco-package': 'umbraco-package.ts', + manifests: 'manifests.ts', + }, + }), +}); From 6fbcc608c189e6a0b1ec59609dc105c4d6b9d89f Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:29:47 +0200 Subject: [PATCH 36/48] update lockfile --- 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 f52190d087..bfe157ce3a 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -21746,7 +21746,9 @@ "src/packages/templating": { "name": "@umbraco-backoffice/templating" }, - "src/packages/tiny-mce": {}, + "src/packages/tiny-mce": { + "name": "@umbraco-backoffice/tiny-mce" + }, "src/packages/umbraco-news": { "name": "@umbraco-backoffice/umbraco-news" }, From 2b11b8b0a13cd05e82e109b16f348c04b6f92456 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:37:31 +0200 Subject: [PATCH 37/48] add fallback for tinymce --- .../core/localization/registry/localization.registry.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts index f2b5e98a4e..89174aecfd 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts @@ -1,8 +1,8 @@ -import type { +import { UmbLocalizationSetBase, UmbLocalizationDictionary, - UmbLocalizationFlatDictionary, -} from '@umbraco-cms/backoffice/localization-api'; + UmbLocalizationFlatDictionary, UMB_DEFAULT_LOCALIZATION_CULTURE +} from "@umbraco-cms/backoffice/localization-api"; import { umbLocalizationManager } from '@umbraco-cms/backoffice/localization-api'; import type { ManifestLocalization, UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry'; import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; @@ -36,7 +36,7 @@ export class UmbLocalizationRegistry { constructor(extensionRegistry: UmbBackofficeExtensionRegistry) { combineLatest([this.currentLanguage, extensionRegistry.byType('localization')]).subscribe( async ([currentLanguage, extensions]) => { - const locale = new Intl.Locale(currentLanguage); + const locale = new Intl.Locale(!!currentLanguage ? currentLanguage : UMB_DEFAULT_LOCALIZATION_CULTURE); const filteredExt = extensions.filter( (ext) => ext.meta.culture.toLowerCase() === locale.baseName.toLowerCase() || From 8b0e12ee109c07cc5106062ddb1d8bd7ad257556 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:44:47 +0200 Subject: [PATCH 38/48] chore: linting --- .../core/localization/registry/localization.registry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts index 89174aecfd..d63cdce44b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts @@ -36,7 +36,7 @@ export class UmbLocalizationRegistry { constructor(extensionRegistry: UmbBackofficeExtensionRegistry) { combineLatest([this.currentLanguage, extensionRegistry.byType('localization')]).subscribe( async ([currentLanguage, extensions]) => { - const locale = new Intl.Locale(!!currentLanguage ? currentLanguage : UMB_DEFAULT_LOCALIZATION_CULTURE); + const locale = new Intl.Locale(currentLanguage ? currentLanguage : UMB_DEFAULT_LOCALIZATION_CULTURE); const filteredExt = extensions.filter( (ext) => ext.meta.culture.toLowerCase() === locale.baseName.toLowerCase() || From 9c165bf52b23d92bf7bf10a5d0354bf782308d6c Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:45:22 +0200 Subject: [PATCH 39/48] chore: linting --- .../core/localization/registry/localization.registry.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts index d63cdce44b..60ac072049 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts @@ -1,7 +1,8 @@ import { - UmbLocalizationSetBase, - UmbLocalizationDictionary, - UmbLocalizationFlatDictionary, UMB_DEFAULT_LOCALIZATION_CULTURE + type UmbLocalizationSetBase, + type UmbLocalizationDictionary, + type UmbLocalizationFlatDictionary, + UMB_DEFAULT_LOCALIZATION_CULTURE } from "@umbraco-cms/backoffice/localization-api"; import { umbLocalizationManager } from '@umbraco-cms/backoffice/localization-api'; import type { ManifestLocalization, UmbBackofficeExtensionRegistry } from '@umbraco-cms/backoffice/extension-registry'; From 5fe5f566f0f185ba9d60f29f56345d86ce911b36 Mon Sep 17 00:00:00 2001 From: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Date: Fri, 26 Jul 2024 11:50:11 +0200 Subject: [PATCH 40/48] fix: move assignment to state --- .../core/localization/registry/localization.registry.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts index 60ac072049..cc755ebd24 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/registry/localization.registry.ts @@ -22,7 +22,7 @@ function addOrUpdateDictionary( } export class UmbLocalizationRegistry { - #currentLanguage = new UmbStringState(document.documentElement.lang ?? 'en-us'); + #currentLanguage = new UmbStringState(document.documentElement.lang !== '' ? document.documentElement.lang : UMB_DEFAULT_LOCALIZATION_CULTURE); readonly currentLanguage = this.#currentLanguage.asObservable(); #loadedExtAliases: Array = []; @@ -37,7 +37,7 @@ export class UmbLocalizationRegistry { constructor(extensionRegistry: UmbBackofficeExtensionRegistry) { combineLatest([this.currentLanguage, extensionRegistry.byType('localization')]).subscribe( async ([currentLanguage, extensions]) => { - const locale = new Intl.Locale(currentLanguage ? currentLanguage : UMB_DEFAULT_LOCALIZATION_CULTURE); + const locale = new Intl.Locale(currentLanguage); const filteredExt = extensions.filter( (ext) => ext.meta.culture.toLowerCase() === locale.baseName.toLowerCase() || From 2e120e761e966702607b07c1924a823cb9772eec Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 5 Aug 2024 10:49:50 +0200 Subject: [PATCH 41/48] remove entry as they are already set as default --- .../src/packages/tiny-mce/vite.config.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts index 72556d1777..d0c457d1e9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiny-mce/vite.config.ts @@ -8,12 +8,5 @@ const dist = '../../../dist-cms/packages/tiny-mce'; rmSync(dist, { recursive: true, force: true }); export default defineConfig({ - ...getDefaultConfig({ - dist, - entry: { - index: 'index.ts', - 'umbraco-package': 'umbraco-package.ts', - manifests: 'manifests.ts', - }, - }), + ...getDefaultConfig({ dist }), }); From 3bd174faa81cc4d9f5167762aa405879c722c8eb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 5 Aug 2024 12:27:46 +0200 Subject: [PATCH 42/48] move const to a constants file --- .../src/packages/language/workspace/language/constants.ts | 1 + .../language/workspace/language/language-workspace.context.ts | 2 +- .../src/packages/language/workspace/language/manifests.ts | 3 +-- 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/constants.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/constants.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/constants.ts new file mode 100644 index 0000000000..43f9eb4861 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/constants.ts @@ -0,0 +1 @@ +export const UMB_LANGUAGE_WORKSPACE_ALIAS = 'Umb.Workspace.Language'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts index 646982ea70..934b5700d8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/language-workspace.context.ts @@ -1,7 +1,7 @@ import { UmbLanguageDetailRepository } from '../../repository/index.js'; import type { UmbLanguageDetailModel } from '../../types.js'; import { UmbLanguageWorkspaceEditorElement } from './language-workspace-editor.element.js'; -import { UMB_LANGUAGE_WORKSPACE_ALIAS } from './manifests.js'; +import { UMB_LANGUAGE_WORKSPACE_ALIAS } from './constants.js'; import { type UmbSubmittableWorkspaceContext, UmbSubmittableWorkspaceContextBase, diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts index db9c56185f..ce98f96aaa 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/workspace/language/manifests.ts @@ -1,3 +1,4 @@ +import { UMB_LANGUAGE_WORKSPACE_ALIAS } from './constants.js'; import { UmbSubmitWorkspaceAction } from '@umbraco-cms/backoffice/workspace'; import type { ManifestWorkspaces, @@ -6,8 +7,6 @@ import type { ManifestTypes, } from '@umbraco-cms/backoffice/extension-registry'; -export const UMB_LANGUAGE_WORKSPACE_ALIAS = 'Umb.Workspace.Language'; - const workspace: ManifestWorkspaces = { type: 'workspace', kind: 'routable', From 63e4d1496cc34ce9fec47cd5bc195b23acb745d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Mon, 5 Aug 2024 21:25:30 +0200 Subject: [PATCH 43/48] multiple-app-languages-condition --- .../conditions/manifests.ts | 2 + .../conditions/menu-alias.condition.ts | 10 +++-- .../multiple-app-languages.condition.ts | 37 +++++++++++++++++++ .../conditions/section-alias.condition.ts | 10 +++-- .../extension-registry/conditions/types.ts | 6 ++- .../language/app-language-select/manifests.ts | 3 ++ .../global-contexts/app-language.context.ts | 1 + 7 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/multiple-app-languages.condition.ts diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts index 7b63b02b4e..48b22385bb 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/manifests.ts @@ -1,10 +1,12 @@ import type { ManifestTypes } from '../models/index.js'; import { manifest as menuAliasConditionManifest } from './menu-alias.condition.js'; +import { manifest as multipleAppLanguagesConditionManifest } from './multiple-app-languages.condition.js'; import { manifest as sectionAliasConditionManifest } from './section-alias.condition.js'; import { manifest as switchConditionManifest } from './switch.condition.js'; export const manifests: Array = [ menuAliasConditionManifest, + multipleAppLanguagesConditionManifest, sectionAliasConditionManifest, switchConditionManifest, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/menu-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/menu-alias.condition.ts index f03bcd1173..5d08fb2b73 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/menu-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/menu-alias.condition.ts @@ -17,9 +17,13 @@ export class UmbMenuAliasCondition extends UmbConditionBase { - this.observe(context.alias, (MenuAlias) => { - this.permitted = MenuAlias === this.config.match; - }); + this.observe( + context.alias, + (MenuAlias) => { + this.permitted = MenuAlias === this.config.match; + }, + 'observeAlias', + ); }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/multiple-app-languages.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/multiple-app-languages.condition.ts new file mode 100644 index 0000000000..361cbbcb38 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/multiple-app-languages.condition.ts @@ -0,0 +1,37 @@ +import { UmbConditionBase } from './condition-base.controller.js'; +import { UMB_APP_LANGUAGE_CONTEXT } from '@umbraco-cms/backoffice/language'; +import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api'; +import type { + ManifestCondition, + UmbConditionConfigBase, + UmbConditionControllerArguments, + UmbExtensionCondition, +} from '@umbraco-cms/backoffice/extension-api'; + +export type UmbMultipleAppLanguageConditionConfig = UmbConditionConfigBase; + +export class UmbMultipleAppLanguageCondition + extends UmbConditionBase + implements UmbExtensionCondition +{ + constructor(host: UmbControllerHost, args: UmbConditionControllerArguments) { + super(host, args); + + this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (context) => { + this.observe( + context.moreThanOneLanguage, + (moreThanOneLanguage) => { + this.permitted = moreThanOneLanguage; + }, + 'observeLanguages', + ); + }); + } +} + +export const manifest: ManifestCondition = { + type: 'condition', + name: 'Multiple App Languages Condition', + alias: 'Umb.Condition.MultipleAppLanguages', + api: UmbMultipleAppLanguageCondition, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/section-alias.condition.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/section-alias.condition.ts index dc163ed815..b4fd34b93c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/section-alias.condition.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/section-alias.condition.ts @@ -24,9 +24,13 @@ export class UmbSectionAliasCondition if (permissionCheck !== undefined) { this.consumeContext(UMB_SECTION_CONTEXT, (context) => { - this.observe(context.alias, (sectionAlias) => { - this.permitted = sectionAlias ? permissionCheck!(sectionAlias) : false; - }); + this.observe( + context.alias, + (sectionAlias) => { + this.permitted = sectionAlias ? permissionCheck!(sectionAlias) : false; + }, + 'observeAlias', + ); }); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts index 0481a6cb5f..f1e92fbe34 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/conditions/types.ts @@ -3,6 +3,7 @@ import type { CollectionBulkActionPermissionConditionConfig } from '../../collec import type { UmbSectionUserPermissionConditionConfig } from '../../section/conditions/index.js'; import type { SectionAliasConditionConfig } from './section-alias.condition.js'; import type { SwitchConditionConfig } from './switch.condition.js'; +import type { UmbMultipleAppLanguageConditionConfig } from './multiple-app-languages.condition.js'; import type { WorkspaceAliasConditionConfig, WorkspaceEntityTypeConditionConfig, @@ -29,8 +30,9 @@ export type ConditionTypes = | CollectionBulkActionPermissionConditionConfig | SectionAliasConditionConfig | SwitchConditionConfig + | UmbConditionConfigBase | UmbDocumentUserPermissionConditionConfig + | UmbMultipleAppLanguageConditionConfig | UmbSectionUserPermissionConditionConfig | WorkspaceAliasConditionConfig - | WorkspaceEntityTypeConditionConfig - | UmbConditionConfigBase; + | WorkspaceEntityTypeConditionConfig; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts index b29b0dde84..e67c16493d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/app-language-select/manifests.ts @@ -12,6 +12,9 @@ const entityActions: Array = [ alias: 'Umb.Condition.SectionAlias', match: 'Umb.Section.Content', }, + { + alias: 'Umb.Condition.MultipleAppLanguages', + }, ], }, ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts index 1383eee7c8..6a0d4b7d8b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/global-contexts/app-language.context.ts @@ -12,6 +12,7 @@ import { UMB_AUTH_CONTEXT } from '@umbraco-cms/backoffice/auth'; export class UmbAppLanguageContext extends UmbContextBase implements UmbApi { #languageCollectionRepository: UmbLanguageCollectionRepository; #languages = new UmbArrayState([], (x) => x.unique); + moreThanOneLanguage = this.#languages.asObservablePart((x) => x.length > 1); #appLanguage = new UmbObjectState(undefined); appLanguage = this.#appLanguage.asObservable(); From f29031326c7c53f5bbf0eaf8076134be63fbae11 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 6 Aug 2024 09:19:30 +0200 Subject: [PATCH 44/48] make build happy --- .../examples/block-custom-view/block-custom-view.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts b/src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts index abd194cf81..40b88d0ce9 100644 --- a/src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts +++ b/src/Umbraco.Web.UI.Client/examples/block-custom-view/block-custom-view.ts @@ -3,7 +3,9 @@ import { html, customElement, LitElement, property, css } from '@umbraco-cms/bac import { UmbElementMixin } from '@umbraco-cms/backoffice/element-api'; import type { UmbBlockDataType, UmbBlockEditorCustomViewElement } from '@umbraco-cms/backoffice/extension-registry'; +// eslint-disable-next-line local-rules/enforce-umb-prefix-on-element-name @customElement('example-block-custom-view') +// eslint-disable-next-line local-rules/umb-class-prefix export class ExampleBlockCustomView extends UmbElementMixin(LitElement) implements UmbBlockEditorCustomViewElement { // @property({ attribute: false }) @@ -13,7 +15,7 @@ export class ExampleBlockCustomView extends UmbElementMixin(LitElement) implemen return html`
My Custom View
-

Headline: ${this.content.headline}

+

Headline: ${this.content?.headline}

`; } From d5b40694e891eb35f88c94d554575086681f7da2 Mon Sep 17 00:00:00 2001 From: leekelleher Date: Mon, 5 Aug 2024 15:25:19 +0100 Subject: [PATCH 45/48] Document Type Picker - enabled boolean properties Previously the `?elementTypesOnly` attribute wasn't reading the value --- .../input-document-type/input-document-type.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts index a0a7d6a13c..4bdaa37d2f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts @@ -37,7 +37,7 @@ export class UmbInputDocumentTypeElement extends UmbFormControlMixin Date: Tue, 6 Aug 2024 10:32:11 +0200 Subject: [PATCH 46/48] set as properties --- .../property-editor-ui-document-type-picker.element.ts | 2 +- .../webhook/views/webhook-details-workspace-view.element.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.element.ts index b73d7b9998..e1604bb787 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.element.ts @@ -45,7 +45,7 @@ export class UmbPropertyEditorUIDocumentTypePickerElement extends UmbLitElement .min=${this.min} .max=${this.max} .value=${this.value} - ?elementTypesOnly=${this.onlyElementTypes} + .elementTypesOnly=${this.onlyElementTypes ?? false} ?showOpenButton=${this.showOpenButton} @change=${this.#onChange}> diff --git a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts index 874d2b3764..0be8864bd5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/webhook/workspace/webhook/views/webhook-details-workspace-view.element.ts @@ -90,7 +90,7 @@ export class UmbWebhookDetailsWorkspaceViewElement extends UmbLitElement impleme slot="editor" @change=${this.#onTypesChange} .selection=${this._webhook?.contentTypes ?? []} - ?documentTypesOnly=${true}> + .documentTypesOnly=${true}> `; case 'Media': return html` From ce76b5c2a6664009b513d53d1a370750803e822d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 6 Aug 2024 10:32:45 +0200 Subject: [PATCH 47/48] disable attributes --- .../input-document-type/input-document-type.element.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts index 4bdaa37d2f..a0a7d6a13c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/components/input-document-type/input-document-type.element.ts @@ -37,7 +37,7 @@ export class UmbInputDocumentTypeElement extends UmbFormControlMixin Date: Tue, 6 Aug 2024 11:28:32 +0200 Subject: [PATCH 48/48] correct name --- .../src/apps/backoffice/backoffice.context.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts index adcdeeda39..1ae88c7721 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.context.ts @@ -19,8 +19,8 @@ export class UmbBackofficeContext extends UmbContextBase { #allowedSections = new UmbBasicState>>([]); public readonly allowedSections = this.#allowedSections.asObservable(); - #verison = new UmbStringState(undefined); - public readonly version = this.#verison.asObservable(); + #version = new UmbStringState(undefined); + public readonly version = this.#version.asObservable(); constructor(host: UmbControllerHost) { super(host, UMB_BACKOFFICE_CONTEXT); @@ -70,7 +70,7 @@ export class UmbBackofficeContext extends UmbContextBase { ) ?? []; const version = [major, minor, patch].join('.') + (prerelease ? `-${prerelease}` : ''); - this.#verison.setValue(version); + this.#version.setValue(version); } public setActiveSectionAlias(alias: string) {