diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts index ebbec1134f..21ef577a45 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/context/block-grid-entries.context.ts @@ -20,6 +20,14 @@ import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/rou import { pathFolderName } from '@umbraco-cms/backoffice/utils'; import type { UmbNumberRangeValueType } from '@umbraco-cms/backoffice/models'; +interface UmbBlockGridAreaTypeInvalidRuleType { + groupKey?: string; + key?: string; + name: string; + amount: number; + minRequirement: number; + maxRequirement: number; +} export class UmbBlockGridEntriesContext extends UmbBlockEntriesContext< typeof UMB_BLOCK_GRID_MANAGER_CONTEXT, @@ -455,14 +463,7 @@ export class UmbBlockGridEntriesContext } } - #invalidBlockTypeLimits?: Array<{ - groupKey?: string; - key?: string; - name: string; - amount: number; - minRequirement: number; - maxRequirement: number; - }>; + #invalidBlockTypeLimits?: Array; getInvalidBlockTypeLimits() { return this.#invalidBlockTypeLimits ?? []; @@ -476,57 +477,58 @@ export class UmbBlockGridEntriesContext const layoutEntries = this._layoutEntries.getValue(); - this.#invalidBlockTypeLimits = []; + this.#invalidBlockTypeLimits = this.#areaType.specifiedAllowance + .map((rule) => { + const minAllowed = rule.minAllowed || 0; + const maxAllowed = rule.maxAllowed || 0; - const hasInvalidRules = this.#areaType.specifiedAllowance.some((rule) => { - const minAllowed = rule.minAllowed || 0; - const maxAllowed = rule.maxAllowed || 0; + // For block groups: + if (rule.groupKey) { + const groupElementTypeKeys = + this._manager + ?.getBlockTypes() + .filter((blockType) => blockType.groupKey === rule.groupKey && blockType.allowInAreas === true) + .map((x) => x.contentElementTypeKey) ?? []; + const groupAmount = layoutEntries.filter((entry) => { + const contentTypeKey = this._manager!.getContentTypeKeyOfContentUdi(entry.contentUdi); + return contentTypeKey ? groupElementTypeKeys.indexOf(contentTypeKey) !== -1 : false; + }).length; - // For block groups: - if (rule.groupKey) { - const groupElementTypeKeys = - this._manager - ?.getBlockTypes() - .filter((blockType) => blockType.groupKey === rule.groupKey && blockType.allowInAreas === true) - .map((x) => x.contentElementTypeKey) ?? []; - const groupAmount = layoutEntries.filter((entry) => { - const contentTypeKey = this._manager!.getContentTypeKeyOf(entry.contentUdi); - return contentTypeKey ? groupElementTypeKeys.indexOf(contentTypeKey) !== -1 : false; - }).length; - - if (groupAmount < minAllowed || (maxAllowed > 0 && groupAmount > maxAllowed)) { - this.#invalidBlockTypeLimits!.push({ - groupKey: rule.groupKey, - name: this._manager!.getBlockGroupName(rule.groupKey) ?? '?', - amount: groupAmount, - minRequirement: minAllowed, - maxRequirement: maxAllowed, - }); - return true; + if (groupAmount < minAllowed || (maxAllowed > 0 && groupAmount > maxAllowed)) { + return { + groupKey: rule.groupKey, + name: this._manager!.getBlockGroupName(rule.groupKey) ?? '?', + amount: groupAmount, + minRequirement: minAllowed, + maxRequirement: maxAllowed, + }; + } + return undefined; } - } - // For specific elementTypes: - else if (rule.elementTypeKey) { - const amount = layoutEntries.filter((entry) => { - const contentTypeKey = this._manager!.getContentOf(entry.contentUdi)?.contentTypeKey; - return contentTypeKey === rule.elementTypeKey; - }).length; - if (amount < minAllowed || (maxAllowed > 0 ? amount > maxAllowed : false)) { - this.#invalidBlockTypeLimits!.push({ - key: rule.elementTypeKey, - name: this._manager!.getContentTypeNameOf(rule.elementTypeKey) ?? '?', - amount: amount, - minRequirement: minAllowed, - maxRequirement: maxAllowed, - }); - return true; + // For specific elementTypes: + else if (rule.elementTypeKey) { + const amount = layoutEntries.filter((entry) => { + const contentTypeKey = this._manager!.getContentOf(entry.contentUdi)?.contentTypeKey; + return contentTypeKey === rule.elementTypeKey; + }).length; + if (amount < minAllowed || (maxAllowed > 0 ? amount > maxAllowed : false)) { + return { + key: rule.elementTypeKey, + name: this._manager!.getContentTypeNameOf(rule.elementTypeKey) ?? '?', + amount: amount, + minRequirement: minAllowed, + maxRequirement: maxAllowed, + }; + } + return undefined; } - } - // Lets fail cause the rule was bad. - console.error('Invalid block type limit rule.', rule); - return false; - }); + // Lets fail cause the rule was bad. + console.error('Invalid block type limit rule.', rule); + return undefined; + }) + .filter((x) => x !== undefined) as Array; + const hasInvalidRules = this.#invalidBlockTypeLimits.length > 0; return hasInvalidRules === false; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts index f45bce646e..19d76caa88 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/workspace/block-grid-type-workspace.modal-token.ts @@ -14,7 +14,7 @@ export const UMB_BLOCK_GRID_TYPE_WORKSPACE_MODAL = new UmbModalToken< type: 'sidebar', size: 'large', }, - data: { entityType: UMB_BLOCK_GRID_TYPE, preset: { allowAtRoot: true } }, + data: { entityType: UMB_BLOCK_GRID_TYPE, preset: { allowAtRoot: true, allowInAreas: true } }, }, // Recast the type, so the entityType data prop is not required: ) as UmbModalToken, UmbWorkspaceModalValue>; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts index df113d9b81..f44da55be5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block/context/block-manager.context.ts @@ -139,6 +139,9 @@ export abstract class UmbBlockManagerContext< this.#contentTypes.appendOne(data); } + getContentTypeKeyOfContentUdi(contentUdi: string) { + return this.getContentOf(contentUdi)?.contentTypeKey; + } contentTypeOf(contentTypeKey: string) { return this.#contentTypes.asObservablePart((source) => source.find((x) => x.unique === contentTypeKey)); } @@ -148,9 +151,6 @@ export abstract class UmbBlockManagerContext< getContentTypeNameOf(contentTypeKey: string) { return this.#contentTypes.getValue().find((x) => x.unique === contentTypeKey)?.name; } - getContentTypeKeyOf(contentTypeKey: string) { - return this.#contentTypes.getValue().find((x) => x.unique === contentTypeKey)?.unique; - } getContentTypeHasProperties(contentTypeKey: string) { const properties = this.#contentTypes.getValue().find((x) => x.unique === contentTypeKey)?.properties; return properties ? properties.length > 0 : false; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/validation/mixins/form-control.mixin.ts b/src/Umbraco.Web.UI.Client/src/packages/core/validation/mixins/form-control.mixin.ts index e4f45a5518..e3b13b79be 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/validation/mixins/form-control.mixin.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/validation/mixins/form-control.mixin.ts @@ -165,6 +165,9 @@ export function UmbFormControlMixin< this._internals = this.attachInternals(); this.addEventListener('blur', () => { + /*if (e.composedPath().some((x) => x === this)) { + return; + }*/ this.pristine = false; this.checkValidity(); }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts index e6579bf1f6..df1cc59049 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-flow-input/data-type-flow-input.element.ts @@ -101,7 +101,7 @@ export class UmbInputDataTypeElement extends UmbFormControlMixin(UmbLitElement, label="Select Property Editor" look="placeholder" color="default" - @focus=${() => { + @blur=${() => { this.pristine = false; }} .href=${this._createRoute}>