diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts index c5a6cfff65..18d8647457 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.test.ts @@ -76,6 +76,10 @@ describe('UmbSelectionManager', () => { it('has a clearSelection method', () => { expect(manager).to.have.property('clearSelection').that.is.a('function'); }); + + it('has a setAllowLimitation method', () => { + expect(manager).to.have.property('setAllowLimitation').that.is.a('function'); + }); }); }); @@ -150,6 +154,15 @@ describe('UmbSelectionManager', () => { manager.select('3'); expect(manager.getSelection()).to.deep.equal([]); }); + + it('can not select an item if it does not pass the allow function', () => { + manager.setAllowLimitation((item) => item !== '2'); + expect(() => manager.select('2')).to.throw(); + expect(manager.getSelection()).to.deep.equal([]); + + manager.select('1'); + expect(manager.getSelection()).to.deep.equal(['1']); + }); }); describe('Deselect', () => { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts index d1127cbb8d..3e1cd91ca1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/selection-manager/selection.manager.ts @@ -18,6 +18,9 @@ export class UmbSelectionManager true; + constructor(host: UmbControllerHost) { super(host); } @@ -109,6 +112,9 @@ export class UmbSelectionManager boolean): void { + this.#allow = compareFn; + } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts index 643285640c..dc850eb0ad 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/schedule-modal/document-schedule-modal.element.ts @@ -41,6 +41,15 @@ export class UmbDocumentScheduleModalElement extends UmbModalBaseElement< this.#selectionManager.setMultiple(true); this.#selectionManager.setSelectable(true); + const pickableFilter = this.data?.pickableFilter; + + if (pickableFilter) { + this.#selectionManager.setAllowLimitation((unique) => { + const option = this.data?.options.find((o) => o.unique === unique); + return option ? pickableFilter(option) : true; + }); + } + // Only display variants that are relevant to pick from, i.e. variants that are draft or published with pending changes: this._options = this.data?.options.filter( diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts index 52d69df997..ccfd6c36d4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/shared/document-variant-language-picker.element.ts @@ -1,5 +1,14 @@ import { UmbDocumentVariantState, type UmbDocumentVariantOptionModel } from '../../types.js'; -import { css, customElement, html, nothing, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { + css, + customElement, + html, + nothing, + property, + repeat, + state, + type PropertyValues, +} from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; import type { UmbSelectionManager } from '@umbraco-cms/backoffice/utils'; @@ -37,6 +46,17 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { @property({ attribute: false }) public pickableFilter?: (item: UmbDocumentVariantOptionModel) => boolean; + protected override updated(_changedProperties: PropertyValues): void { + super.updated(_changedProperties); + + if (this.selectionManager && this.pickableFilter) { + this.#selectionManager.setAllowLimitation((unique) => { + const option = this.variantLanguageOptions.find((o) => o.unique === unique); + return option ? this.pickableFilter!(option) : true; + }); + } + } + override render() { return this.variantLanguageOptions.length ? repeat( diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts index a560e4405f..9f11620d47 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/document-workspace.context.ts @@ -536,11 +536,15 @@ export class UmbDocumentWorkspaceContext const selected = activeVariantIds.concat(changedVariantIds); // Selected can contain entries that are not part of the options, therefor the modal filters selection based on options. + const readOnlyCultures = this.readOnlyState.getStates().map((s) => s.variantId.culture); + const selectedCultures = selected.map((x) => x.toString()).filter((v, i, a) => a.indexOf(v) === i); + const writable = selectedCultures.filter((x) => readOnlyCultures.includes(x) === false); + const options = await firstValueFrom(this.variantOptions); return { options, - selected: selected.map((x) => x.toString()).filter((v, i, a) => a.indexOf(v) === i), + selected: writable, }; }