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 3b684d937ecf..b6716c34ee7e 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 @@ -61,6 +61,13 @@ export class UmbWorkspaceSplitViewVariantSelectorElement< @state() private _labelDefault = ''; + /** + * Method to sort variants in the selector. + * Should be overwritten by actual implementation. + * @param {VariantOptionModelType} a - First variant option to compare + * @param {VariantOptionModelType} b - Second variant option to compare + * @returns {number} - Sorting value + */ // eslint-disable-next-line @typescript-eslint/no-unused-vars protected _variantSorter = (a: VariantOptionModelType, b: VariantOptionModelType) => { return 0; 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 43f0f0c23d7a..26c79125b873 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,4 +1,5 @@ import { UmbDocumentVariantState, type UmbDocumentVariantOptionModel } from '../../types.js'; +import { sortVariants } from '../../utils.js'; import type { UUIBooleanInputElement } from '@umbraco-cms/backoffice/external/uui'; import { css, @@ -19,7 +20,13 @@ export class UmbDocumentVariantLanguagePickerElement extends UmbLitElement { #selectionManager!: UmbSelectionManager; @property({ type: Array, attribute: false }) - variantLanguageOptions: Array = []; + public get variantLanguageOptions(): Array { + return this.#variantLanguageOptions; + } + public set variantLanguageOptions(value: Array) { + this.#variantLanguageOptions = [...value].sort(sortVariants); + } + #variantLanguageOptions: Array = []; @property({ attribute: false }) set selectionManager(value: UmbSelectionManager) { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/utils.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/utils.ts index 531bca043e55..1c937e0b5c4f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/utils.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/utils.ts @@ -21,23 +21,46 @@ const getVariantStateOrderValue = (variant?: UmbDocumentVariantOptionModel['vari return variantStatesOrder[variant.state] || fallbackOrder; }; -export const sortVariants = (a: VariantType, b: VariantType) => { - const compareDefault = (a: VariantType, b: VariantType) => - (a.language?.isDefault ? -1 : 1) - (b.language?.isDefault ? -1 : 1); - - // Make sure mandatory variants goes on top, unless they are published, cause then they already goes to the top and then we want to mix them with other published variants. - const compareMandatory = (a: VariantType, b: VariantType) => - a.variant?.state === DocumentVariantStateModel.PUBLISHED_PENDING_CHANGES || +// eslint-disable-next-line jsdoc/require-jsdoc +function compareDefault(a: VariantType, b: VariantType) { + return (a.language?.isDefault ? -1 : 1) - (b.language?.isDefault ? -1 : 1); +} +// Make sure mandatory variants goes on top, unless they are published, cause then they already goes to the top and then we want to mix them with other published variants. +// eslint-disable-next-line jsdoc/require-jsdoc +function compareMandatory(a: VariantType, b: VariantType) { + return a.variant?.state === DocumentVariantStateModel.PUBLISHED_PENDING_CHANGES || a.variant?.state === DocumentVariantStateModel.PUBLISHED - ? 0 - : (a.language?.isMandatory ? -1 : 1) - (b.language?.isMandatory ? -1 : 1); - const compareState = (a: VariantType, b: VariantType) => - getVariantStateOrderValue(a.variant) - getVariantStateOrderValue(b.variant); + ? 0 + : (a.language?.isMandatory ? -1 : 1) - (b.language?.isMandatory ? -1 : 1); +} + +// eslint-disable-next-line jsdoc/require-jsdoc +function compareState(a: VariantType, b: VariantType) { + return getVariantStateOrderValue(a.variant) - getVariantStateOrderValue(b.variant); +} - const compareName = (a: VariantType, b: VariantType) => a.variant?.name.localeCompare(b.variant?.name || '') || 99; +// eslint-disable-next-line jsdoc/require-jsdoc +function compareName(a: VariantType, b: VariantType) { + const nameA = a.language?.name; + const nameB = b.language?.name; + // If both names are missing, consider them equal. + if (!nameA && !nameB) return 0; + // If only one name is missing, sort the defined name first. + if (!nameA) return 1; + if (!nameB) return -1; + + return nameA.localeCompare(nameB); +} +/** + * Sorts document variants based on multiple criteria: + * @param {VariantType} a - First variant to compare + * @param {VariantType} b - Second variant to compare + * @returns {number} - Sorting value + */ +export function sortVariants(a: VariantType, b: VariantType) { return compareDefault(a, b) || compareMandatory(a, b) || compareState(a, b) || compareName(a, b); -}; +} export const TimeOptions: Intl.DateTimeFormatOptions = { year: 'numeric',