diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts index 428b407cae..2b4f4af2b3 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/data-type/data-type.data.ts @@ -703,7 +703,13 @@ export const data: Array = [ rowSpan: 1, minAllowed: 1, maxAllowed: 2, - specifiedAllowance: [], + specifiedAllowance: [ + { + elementTypeKey: '4f68ba66-6fb2-4778-83b8-6ab4ca3a7c5c', + minAllowed: 1, + maxAllowed: 2, + }, + ], }, { key: 'area2_key', 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 7a05967621..c0a803ed71 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 @@ -1,10 +1,12 @@ -import type { UmbBlockGridTypeAreaTypePermission } from '../../index.js'; +import type { UmbBlockGridTypeAreaTypePermission, UmbBlockGridTypeGroupType } from '../../index.js'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, css, state, repeat, nothing } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import { UmbPropertyValueChangeEvent } from '@umbraco-cms/backoffice/property-editor'; 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'; @customElement('umb-property-editor-ui-block-grid-area-type-permission') export class UmbPropertyEditorUIBlockGridAreaTypePermissionElement @@ -21,21 +23,27 @@ export class UmbPropertyEditorUIBlockGridAreaTypePermissionElement @state() private _value: Array = []; + @state() + private _blockTypes: Array = []; + + @state() + private _blockGroups: Array = []; + constructor() { super(); this.consumeContext(UMB_DATA_TYPE_WORKSPACE_CONTEXT, async (context) => { this.observe( - await context.propertyValueByAlias('blocks'), + await context.propertyValueByAlias>('blocks'), (blockTypes) => { - console.log('blockTypes', blockTypes); + this._blockTypes = blockTypes ?? []; }, 'observeBlockType', ); this.observe( - await context.propertyValueByAlias('blockGroups'), + await context.propertyValueByAlias>('blockGroups'), (blockGroups) => { - console.log('blockGroups', blockGroups); + this._blockGroups = blockGroups ?? []; }, 'observeBlockGroups', ); @@ -47,23 +55,165 @@ export class UmbPropertyEditorUIBlockGridAreaTypePermissionElement this.dispatchEvent(new UmbPropertyValueChangeEvent()); } - // TODO: Needs localizations: + #setPermissionKey(e: UUIComboboxEvent, index: number) { + const value = [...this.value]; + const optionElement = e.composedPath()[0] as UUIComboboxElement; + const optionKey = optionElement.value as string; + + // If optionKey exists (new option picked), we just assume its a elementType if the key is not from blockGroups. + // If optionKey is empty (the option removed was removed), set both to undefined. + const setting: UmbBlockGridTypeAreaTypePermission = optionKey + ? this._blockGroups.find((group) => group.key === optionKey) + ? { elementTypeKey: undefined, groupKey: optionKey } + : { elementTypeKey: optionKey, groupKey: undefined } + : { elementTypeKey: undefined, groupKey: undefined }; + + this.value = value.map((permission, i) => (i === index ? { ...permission, ...setting } : permission)); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); + } + + #setPermissionMinimumRange(e: UUIInputEvent, index: number) { + const value = [...this.value]; + const input = e.target.value as string; + + this.value = value.map((permission, i) => + i === index ? { ...permission, minAllowed: parseInt(input) ?? 0 } : permission, + ); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); + } + #setPermissionMaximumRange(e: UUIInputEvent, index: number) { + const value = [...this.value]; + const input = e.target.value as string; + + this.value = value.map((permission, i) => + i === index ? { ...permission, maxAllowed: parseInt(input) ?? undefined } : permission, + ); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); + } + + #remove(index: number) { + this.value = [...this.value].filter((_, i) => i !== index); + this.dispatchEvent(new UmbPropertyValueChangeEvent()); + } + render() { - return html`
+ return html`
${repeat( - this.value, - (area) => area, - (area) => html`Missing component for a value entry`, + this._value, + (permission) => permission, + (permission, index) => { + const showCategoryHeader = this._blockGroups.length && this._blockTypes.length; + + return html`
+ this.#setPermissionKey(e, index)} + .value=${permission.elementTypeKey ?? permission.groupKey ?? ''}> + + ${showCategoryHeader ? html`${this.localize.term('general_groups')}` : nothing} + ${this.#renderBlockGroups(permission)} + ${showCategoryHeader ? html`${this.localize.term('general_elements')}` : nothing} + ${this.#renderBlockTypes(permission)} + + + + this.#setPermissionMinimumRange(e, index)}> + - + this.#setPermissionMaximumRange(e, index)}> + this.#remove(index)}> + + + +
`; + }, )}
`; + label=${this.localize.term('general_add')} + @click=${this.#addNewPermission}> + ${!this._value.length + ? html` + + By default, all block types are allowed in an Area, Use this option to allow only selected types. + + ` + : nothing} `; } - static styles = [UmbTextStyles]; + #renderBlockGroups(area: UmbBlockGridTypeAreaTypePermission) { + return repeat( + this._blockGroups, + (group) => group.key, + (group) => + html` + ${group.name} + `, + ); + } + + #renderBlockTypes(area: UmbBlockGridTypeAreaTypePermission) { + return repeat( + this._blockTypes, + (block) => block.contentElementTypeKey, + (block) => + html` + ${block.label} + `, + ); + } + + static styles = [ + UmbTextStyles, + css` + #permissions { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + margin-bottom: var(--uui-size-space-3); + } + + #add-button { + width: 100%; + } + + .permission-setting { + flex: 1; + display: flex; + gap: var(--uui-size-space-6); + } + + .permission-setting > uui-combobox { + flex: 1; + } + + .permission-setting > span { + display: flex; + gap: var(--uui-size-space-1); + align-items: center; + } + + uui-combobox strong { + padding: 0 var(--uui-size-space-1); + } + `, + ]; } export default UmbPropertyEditorUIBlockGridAreaTypePermissionElement;