diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 0031db984f..7d12b6b29d 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -62,6 +62,7 @@ "./package": "./dist-cms/packages/packages/package/index.js", "./data-type": "./dist-cms/packages/core/data-type/index.js", "./language": "./dist-cms/packages/language/index.js", + "./dynamic-root": "./dist-cms/packages/dynamic-root/index.js", "./logviewer": "./dist-cms/packages/settings/logviewer/index.js", "./relation-type": "./dist-cms/packages/relations/relation-types/index.js", "./relation": "./dist-cms/packages/relations/relations/index.js", diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts index 0182d4c46e..05e3da2ccd 100644 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.element.ts @@ -32,6 +32,11 @@ const CORE_PACKAGES = [ import('../../packages/umbraco-news/umbraco-package.js'), import('../../packages/user/umbraco-package.js'), import('../../packages/models-builder/umbraco-package.js'), + import('../../packages/tags/umbraco-package.js'), + import('../../packages/log-viewer/umbraco-package.js'), + import('../../packages/health-check/umbraco-package.js'), + import('../../packages/static-file/umbraco-package.js'), + import('../../packages/dynamic-root/umbraco-package.js'), ]; @customElement('umb-backoffice') diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts index 9a5db47c5d..07529c2a54 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da-dk.ts @@ -1156,6 +1156,38 @@ export default { pickedTrashedItem: 'Du har valgt et dokument som er slettet eller lagt i papirkurven', pickedTrashedItems: 'Du har valgt dokumenter som er slettede eller lagt i papirkurven', }, + dynamicRoot: { + configurationTitle: 'Dynamisk udgangspunkts forespørgsel', + pickDynamicRootOriginTitle: 'Vælg begyndelsen', + pickDynamicRootOriginDesc: 'Beskriv begyndelsen for dynamisk udgangspunkts forespørgselen', + originRootTitle: 'Roden', + originRootDesc: 'Rod noden for denne kilde', + originParentTitle: 'Overliggende', + originParentDesc: 'Den overliggende node af kilden i denne redigerings session', + originCurrentTitle: 'Nuværende', + originCurrentDesc: 'Kilde noden for denne redigerings session', + originSiteTitle: 'Siden', + originSiteDesc: 'Nærmeste node med et domæne', + originByKeyTitle: 'Specifik Node', + originByKeyDesc: 'Vælg en specifik Node', + pickDynamicRootQueryStepTitle: 'Tilføj skridt til forespørgsel', + pickDynamicRootQueryStepDesc: 'Specificer næste skridt i din dynamisk udgangspunkts forespørgsel', + queryStepNearestAncestorOrSelfTitle: 'Nærmeste forældre eller selv', + queryStepNearestAncestorOrSelfDesc: 'Forespørg the nærmeste forældre eller selv der passer på en af de givne typer', + queryStepFurthestAncestorOrSelfTitle: 'Fjerneste forældre eller selv', + queryStepFurthestAncestorOrSelfDesc: 'Forespørg fjerneste forældre eller selv der passer på en af de givne typer', + queryStepNearestDescendantOrSelfTitle: 'Nærmeste barn eller selv', + queryStepNearestDescendantOrSelfDesc: 'Forespørg nærmeste barn eller selv der passer på en af de givne typer', + queryStepFurthestDescendantOrSelfTitle: 'Fjerneste barn eller selv', + queryStepFurthestDescendantOrSelfDesc: 'Forespørg fjerneste barn eller selv der passer på en af de givne typer', + queryStepCustomTitle: 'Brugerdefineret', + queryStepCustomDesc: 'Forespørg med et skræddersyet forespørgsels skridt', + addQueryStep: 'Tilføj skridt', + queryStepTypes: 'der passer med typerne: ', + noValidStartNodeTitle: 'Intet passende indhold', + noValidStartNodeDesc: + 'Konfigurationen af dette felt passer ikke med noget indhold. Opret det manglende indhold eller kontakt din adminnistrator for at tilpasse Dynamisk Udgangspunkts Forespørgselen for dette felt.', + }, mediaPicker: { deletedItem: 'Slettet medie', pickedTrashedItem: 'Du har valgt et medie som er slettet eller lagt i papirkurven', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts index 1c05c9a743..8a10ec8a7f 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en-us.ts @@ -1148,11 +1148,46 @@ export default { }, contentPicker: { allowedItemTypes: 'You can only select items of type(s): %0%', - defineDynamicRoot: 'Specify a Dynamic Root', + defineDynamicRoot: 'Specify root node', defineRootNode: 'Pick root node', pickedTrashedItem: 'You have picked a content item currently deleted or in the recycle bin', pickedTrashedItems: 'You have picked content items currently deleted or in the recycle bin', }, + dynamicRoot: { + configurationTitle: 'Dynamic Root Query', + pickDynamicRootOriginTitle: 'Pick origin', + pickDynamicRootOriginDesc: 'Define the origin for your Dynamic Root Query', + originRootTitle: 'Root', + originRootDesc: 'Root node of this editing session', + originParentTitle: 'Parent', + originParentDesc: 'The parent node of the source in this editing session', + originCurrentTitle: 'Current', + originCurrentDesc: 'The content node that is source for this editing session', + originSiteTitle: 'Site', + originSiteDesc: 'Find nearest node with a hostname', + originByKeyTitle: 'Specific Node', + originByKeyDesc: 'Pick a specific Node as the origin for this query', + pickDynamicRootQueryStepTitle: 'Append step to query', + pickDynamicRootQueryStepDesc: 'Define the next step of your Dynamic Root Query', + queryStepNearestAncestorOrSelfTitle: 'Nearest Ancestor Or Self', + queryStepNearestAncestorOrSelfDesc: 'Query the nearest ancestor or self that fits with one of the configured types', + queryStepFurthestAncestorOrSelfTitle: 'Furthest Ancestor Or Self', + queryStepFurthestAncestorOrSelfDesc: + 'Query the Furthest ancestor or self that fits with one of the configured types', + queryStepNearestDescendantOrSelfTitle: 'Nearest Descendant Or Self', + queryStepNearestDescendantOrSelfDesc: + 'Query the nearest descendant or self that fits with one of the configured types', + queryStepFurthestDescendantOrSelfTitle: 'Furthest Descendant Or Self', + queryStepFurthestDescendantOrSelfDesc: + 'Query the Furthest descendant or self that fits with one of the configured types', + queryStepCustomTitle: 'Custom', + queryStepCustomDesc: 'Query the using a custom Query Step', + addQueryStep: 'Add query step', + queryStepTypes: 'That matches types: ', + noValidStartNodeTitle: 'No matching content', + noValidStartNodeDesc: + 'The configuration of this property does not match any content. Create the missing content or contact your administrator to adjust the Dynamic Root settings for this property.', + }, mediaPicker: { deletedItem: 'Deleted item', pickedTrashedItem: 'You have picked a media item currently deleted or in the recycle bin', diff --git a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts index aebb7a35f1..7a74ddaf7f 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/browser-handlers.ts @@ -5,6 +5,7 @@ import { handlers as dataTypeHandlers } from './handlers/data-type/index.js'; import { handlers as dictionaryHandlers } from './handlers/dictionary/index.js'; import { handlers as documentHandlers } from './handlers/document/index.js'; import { handlers as documentTypeHandlers } from './handlers/document-type/index.js'; +import { handlers as dynamicRootHandlers } from './handlers/dynamic-root.handlers.js'; import { handlers as examineManagementHandlers } from './handlers/examine-management.handlers.js'; import { handlers as healthCheckHandlers } from './handlers/health-check.handlers.js'; import { handlers as installHandlers } from './handlers/install.handlers.js'; @@ -45,6 +46,7 @@ const handlers = [ ...dictionaryHandlers, ...documentHandlers, ...documentTypeHandlers, + ...dynamicRootHandlers, ...examineManagementHandlers, ...healthCheckHandlers, ...installHandlers, 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 f98be9245d..d31f650109 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 @@ -225,6 +225,15 @@ export const data: Array = [ value: { type: 'content', id: null, + dynamicRoot: { + originAlias: 'Root', + querySteps: [ + { + alias: 'FurthestAncestorOrSelf', + anyOfDocTypeKeys: ['all-property-editors-document-type-id'], + }, + ], + }, }, }, { diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/dynamic-root.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/dynamic-root.handlers.ts new file mode 100644 index 0000000000..c7c0072f06 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/dynamic-root.handlers.ts @@ -0,0 +1,15 @@ +import { umbDocumentMockDb } from '../data/document/document.db.js'; +import type { DynamicRootRequestModel } from '@umbraco-cms/backoffice/backend-api'; +import { umbracoPath } from '@umbraco-cms/backoffice/utils'; + +const { rest } = window.MockServiceWorker; + +export const handlers = [ + rest.post(umbracoPath('/dynamic-root/query'), async (req, res, ctx) => { + const response = umbDocumentMockDb.tree + .getRoot() + .items.map((item) => item.id) + .slice(0, 1); + return res(ctx.status(200), ctx.json(response)); + }), +]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts index 3c2afc0908..fccea2bcf0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.element.ts @@ -1,108 +1,154 @@ -import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; -import { html, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; +import { html, customElement, property, state, css } from '@umbraco-cms/backoffice/external/lit'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbVariantId } from '@umbraco-cms/backoffice/variant'; -import type { UmbRoute, UmbRouterSlotChangeEvent, UmbRouterSlotInitEvent } from '@umbraco-cms/backoffice/router'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/extension-registry'; import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import type { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; +import { + UMB_BLOCK_CATALOGUE_MODAL, + type UmbBlockLayoutBaseModel, + type UmbBlockTypeBaseModel, + type UmbBlockTypeGroup, +} from '@umbraco-cms/backoffice/block'; +import { type UmbModalRouteBuilder, UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/modal'; +import type { NumberRangeValueType } from '@umbraco-cms/backoffice/models'; +import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; /** * @element umb-property-editor-ui-block-grid */ @customElement('umb-property-editor-ui-block-grid') export class UmbPropertyEditorUIBlockGridElement extends UmbLitElement implements UmbPropertyEditorUiElement { + #catalogueModal: UmbModalRouteRegistrationController; + @property() value = ''; + @state() + private _limitMin?: number; + @state() + private _limitMax?: number; + + @state() + private _blocks?: Array; + + @state() + private _blockGroups?: Array; + + @state() + private _layouts: Array = []; + + @state() + private _catalogueRouteBuilder?: UmbModalRouteBuilder; + + @state() + private _directRoute?: string; + + @state() + private _createButtonLabel = this.localize.term('blockEditor_addBlock'); + @property({ attribute: false }) - public config?: UmbPropertyEditorConfigCollection; + public set config(config: UmbPropertyEditorConfigCollection | undefined) { + if (!config) return; - @state() - private _routes: UmbRoute[] = []; + const validationLimit = config.getValueByAlias('validationLimit'); - @state() - private _routerPath: string | undefined; + this._limitMin = validationLimit?.min; + this._limitMax = validationLimit?.max; - @state() - private _activePath: string | undefined; + this._blocks = config.getValueByAlias>('blocks') ?? []; + this._blockGroups = config.getValueByAlias>('blockGroups') ?? []; - @state() - private _variantId?: UmbVariantId; + const customCreateButtonLabel = config.getValueByAlias('createLabel'); + if (customCreateButtonLabel) { + this._createButtonLabel = customCreateButtonLabel; + } else if (this._blocks.length === 1) { + this._createButtonLabel = this.localize.term('blockEditor_addThis', [this._blocks[0].label]); + } + + //const useInlineEditingAsDefault = config.getValueByAlias('useInlineEditingAsDefault'); + + //this.#context.setInlineEditingMode(useInlineEditingAsDefault); + //config.useSingleBlockMode + //config.useLiveEditing + //config.useInlineEditingAsDefault + this.style.maxWidth = config.getValueByAlias('maxPropertyWidth') ?? ''; + + //this.#context.setEditorConfiguration(config); + } constructor() { super(); - this.consumeContext(UMB_PROPERTY_CONTEXT, (context) => { - this.observe(context?.variantId, (propertyVariantId) => { - this._variantId = propertyVariantId; - this.setupRoutes(); - }); + this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => { + this.observe( + propertyContext?.alias, + (alias) => { + this.#catalogueModal.setUniquePathValue('propertyAlias', alias); + }, + 'observePropertyAlias', + ); }); - } - setupRoutes() { - this._routes = []; - if (this._variantId !== undefined) { - this._routes = [ - { - path: 'modal-1', - component: () => { - return import('./property-editor-ui-block-grid-inner-test.element.js'); + this.#catalogueModal = new UmbModalRouteRegistrationController(this, UMB_BLOCK_CATALOGUE_MODAL) + .addUniquePaths(['propertyAlias']) + .addAdditionalPath(':view/:index') + .onSetup((routingInfo) => { + const index = routingInfo.index ? parseInt(routingInfo.index) : -1; + return { + data: { + blocks: this._blocks ?? [], + blockGroups: this._blockGroups ?? [], + openClipboard: routingInfo.view === 'clipboard', + blockOriginData: { index: index }, }, - setup: (component) => { - if (component instanceof HTMLElement) { - (component as any).name = 'block-grid-1'; - } - }, - }, - { - path: 'modal-2', - component: () => { - return import('./property-editor-ui-block-grid-inner-test.element.js'); - }, - setup: (component) => { - if (component instanceof HTMLElement) { - (component as any).name = 'block-grid-2'; - } - }, - }, - ]; - } + }; + }) + .observeRouteBuilder((routeBuilder) => { + this._catalogueRouteBuilder = routeBuilder; + }); } render() { - return this._variantId - ? html`
- umb-property-editor-ui-block-grid, inner routing test: - - - - - - - { - this._routerPath = event.target.absoluteRouterPath; - }} - @change=${(event: UmbRouterSlotChangeEvent) => { - this._activePath = event.target.localActiveViewPath; - }}> - -
` - : 'loading...'; + if (this._blocks?.length === 1) { + const elementKey = this._blocks[0].contentElementTypeKey; + this._directRoute = + this._catalogueRouteBuilder?.({ view: 'create', index: -1 }) + 'modal/umb-modal-workspace/create/' + elementKey; + } + return html` + + + + + `; } - static styles = [UmbTextStyles]; + static styles = [ + UmbTextStyles, + css` + :host { + display: grid; + gap: 1px; + } + > div { + display: flex; + flex-direction: column; + align-items: stretch; + } + + uui-button-group { + padding-top: 1px; + display: grid; + grid-template-columns: 1fr auto; + } + `, + ]; } export default UmbPropertyEditorUIBlockGridElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts index 2379afa77c..f8671c248d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts @@ -15,6 +15,7 @@ import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/mod import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import type { UmbSorterConfig } from '@umbraco-cms/backoffice/sorter'; import { UmbSorterController } from '@umbraco-cms/backoffice/sorter'; +import { UMB_PROPERTY_CONTEXT } from '@umbraco-cms/backoffice/property'; export interface UmbBlockListLayoutModel extends UmbBlockLayoutBaseModel {} @@ -45,6 +46,8 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement }, }); + #catalogueModal: UmbModalRouteRegistrationController; + private _value: UmbBlockListValueModel = { layout: {}, contentData: [], @@ -67,9 +70,13 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement this.#context.setSettings(buildUpValue.settingsData); } + @state() + private _createButtonLabel = this.localize.term('content_createEmpty'); + @property({ attribute: false }) public set config(config: UmbPropertyEditorConfigCollection | undefined) { if (!config) return; + const validationLimit = config.getValueByAlias('validationLimit'); this._limitMin = validationLimit?.min; @@ -78,6 +85,13 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement const blocks = config.getValueByAlias>('blocks') ?? []; this.#context.setBlockTypes(blocks); + const customCreateButtonLabel = config.getValueByAlias('createLabel'); + if (customCreateButtonLabel) { + this._createButtonLabel = customCreateButtonLabel; + } else if (blocks.length === 1) { + this._createButtonLabel = `${this.localize.term('general_add')} ${blocks[0].label}`; + } + const useInlineEditingAsDefault = config.getValueByAlias('useInlineEditingAsDefault'); this.#context.setInlineEditingMode(useInlineEditingAsDefault); //config.useSingleBlockMode @@ -97,16 +111,29 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement private _blocks?: Array; @state() - _layouts: Array = []; + private _layouts: Array = []; @state() - _catalogueRouteBuilder?: UmbModalRouteBuilder; + private _catalogueRouteBuilder?: UmbModalRouteBuilder; + + @state() + private _directRoute?: string; #context = new UmbBlockListManagerContext(this); constructor() { super(); + this.consumeContext(UMB_PROPERTY_CONTEXT, (propertyContext) => { + this.observe( + propertyContext?.alias, + (alias) => { + this.#catalogueModal.setUniquePathValue('propertyAlias', alias); + }, + 'observePropertyAlias', + ); + }); + // TODO: Prevent initial notification from these observes: this.observe(this.#context.layouts, (layouts) => { this._value = { ...this._value, layout: { [UMB_BLOCK_LIST_PROPERTY_EDITOR_ALIAS]: layouts } }; @@ -133,7 +160,8 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement this._blocks = blockTypes; }); - new UmbModalRouteRegistrationController(this, UMB_BLOCK_CATALOGUE_MODAL) + this.#catalogueModal = new UmbModalRouteRegistrationController(this, UMB_BLOCK_CATALOGUE_MODAL) + .addUniquePaths(['propertyAlias']) .addAdditionalPath(':view/:index') .onSetup((routingInfo) => { const index = routingInfo.index ? parseInt(routingInfo.index) : -1; @@ -151,6 +179,11 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement } render() { + if (this._blocks?.length === 1) { + const elementKey = this._blocks[0].contentElementTypeKey; + this._directRoute = + this._catalogueRouteBuilder?.({ view: 'create', index: -1 }) + 'modal/umb-modal-workspace/create/' + elementKey; + } return html` ${repeat( this._layouts, (x) => x.contentUdi, @@ -164,10 +197,8 @@ export class UmbPropertyEditorUIBlockListElement extends UmbLitElement implement - ${this.localize.term('content_createEmpty')} - + label=${this._createButtonLabel} + href=${this._directRoute ?? this._catalogueRouteBuilder?.({ view: 'create', index: -1 }) ?? ''}> { @state() - private _blocks: Array = []; - - @state() - private _blockGroups: Array<{ key: string; name: string }> = []; + private _groupedBlocks: Array<{ name?: string; blocks: Array }> = []; @state() _openClipboard?: boolean; @@ -55,16 +52,18 @@ export class UmbBlockCatalogueModalElement extends UmbModalBaseElement< if (!this.data) return; this._openClipboard = this.data.openClipboard ?? false; - this._blocks = this.data.blocks ?? []; - this._blockGroups = this.data.blockGroups ?? []; - } - /* - #onClickBlock(contentElementTypeKey: string) { - this.modalContext?.updateValue({ key: contentElementTypeKey }); - this.modalContext?.submit(); + const blocks: Array = this.data.blocks ?? []; + const blockGroups: Array = this.data.blockGroups ?? []; + + const noGroupBlocks = blocks.filter((block) => !blockGroups.find((group) => group.key === block.groupKey)); + const grouped = blockGroups.map((group) => ({ + name: group.name ?? '', + blocks: blocks.filter((block) => block.groupKey === group.key), + })); + + this._groupedBlocks = [{ blocks: noGroupBlocks }, ...grouped]; } - */ render() { return html` @@ -87,17 +86,10 @@ export class UmbBlockCatalogueModalElement extends UmbModalBaseElement< } #renderCreateEmpty() { - const blockArrays = groupBy(this._blocks, 'groupKey'); - - const mappedGroupsAndBlocks = Object.entries(blockArrays).map(([key, value]) => { - const group = this._blockGroups.find((group) => group.key === key); - return { name: group?.name, blocks: value }; - }); - return html` - ${mappedGroupsAndBlocks.map( + ${this._groupedBlocks.map( (group) => html` - ${group.name ? html`

${group.name}

` : nothing} + ${group.name ? html`

${group.name}

` : nothing}
${repeat( group.blocks, @@ -121,12 +113,18 @@ export class UmbBlockCatalogueModalElement extends UmbModalBaseElement< #renderViews() { return html` - (this._openClipboard = false)}> - Create Empty + (this._openClipboard = false)}> + Create Empty - (this._openClipboard = true)}> - Clipboard + (this._openClipboard = true)}> + Clipboard diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts index 6872272e0e..7a68521e47 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/modals/block-catalogue/block-catalogue-modal.token.ts @@ -1,9 +1,9 @@ -import type { UmbBlockTypeBaseModel, UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; +import type { UmbBlockTypeBaseModel, UmbBlockTypeGroup, UmbBlockWorkspaceData } from '@umbraco-cms/backoffice/block'; import { UmbModalToken } from '@umbraco-cms/backoffice/modal'; export interface UmbBlockCatalogueModalData { blocks: Array; - blockGroups?: Array<{ name: string; key: string }>; + blockGroups?: Array; openClipboard?: boolean; blockOriginData: UmbBlockWorkspaceData['originData']; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/input-tree-picker-source.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/input-tree-picker-source.element.ts index 79207bb441..c7337d6cac 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/input-tree-picker-source.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-tree-picker-source/input-tree-picker-source.element.ts @@ -6,21 +6,23 @@ import { UmbLitElement } from '@umbraco-cms/internal/lit-element'; import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; export type UmbTreePickerSource = { - type?: UmbTreePickerSourceType; - id?: string | null; - dynamicRoot?: UmbTreePickerDynamicRoot | null; + type: UmbTreePickerSourceType; + id?: string; + dynamicRoot?: UmbTreePickerDynamicRoot; }; export type UmbTreePickerSourceType = 'content' | 'member' | 'media'; export type UmbTreePickerDynamicRoot = { originAlias: string; - querySteps?: Array | null; + originKey?: string; + querySteps?: Array; }; export type UmbTreePickerDynamicRootQueryStep = { + unique: string; alias: string; - anyOfDocTypeKeys: Array; + anyOfDocTypeKeys?: Array; }; @customElement('umb-input-tree-picker-source') @@ -29,33 +31,33 @@ export class UmbInputTreePickerSourceElement extends FormControlMixin(UmbLitElem return undefined; } - private _type: UmbTreePickerSource['type'] = 'content'; + #type: UmbTreePickerSourceType = 'content'; @property() - public set type(value: UmbTreePickerSource['type']) { + public set type(value: UmbTreePickerSourceType) { if (value === undefined) { - value = this._type; + value = this.#type; } - const oldValue = this._type; + const oldValue = this.#type; this._options = this._options.map((option) => option.value === value ? { ...option, selected: true } : { ...option, selected: false }, ); - this._type = value; + this.#type = value; this.requestUpdate('type', oldValue); } - public get type(): UmbTreePickerSource['type'] { - return this._type; + public get type(): UmbTreePickerSourceType { + return this.#type; } @property({ attribute: 'node-id' }) - nodeId?: string | null; + nodeId?: string; @property({ attribute: false }) - dynamicRoot?: UmbTreePickerDynamicRoot | null; + dynamicRoot?: UmbTreePickerDynamicRoot | undefined; @state() _options: Array