Custom field ordering (#9926)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov
2025-09-24 13:34:25 +07:00
committed by GitHub
parent 2988a78b3d
commit 40e641f289
4 changed files with 57 additions and 6 deletions
@@ -15,9 +15,9 @@
<script lang="ts">
import { getClient } from '@hcengineering/presentation'
import { ButtonIcon, showPopup, closeTooltip, IconOptions } from '@hcengineering/ui'
import view, { ViewOptionsModel, Viewlet } from '@hcengineering/view'
import view, { OrderOption, ViewOptionsModel, Viewlet } from '@hcengineering/view'
import { ViewOptions as ViewOptionsEditor } from '@hcengineering/view-resources'
import core, { Data } from '@hcengineering/core'
import core, { Class, Data, Ref, SortingOrder, Type } from '@hcengineering/core'
export let viewlet: Data<Viewlet> | undefined = undefined
export let kind: 'primary' | 'secondary' | 'tertiary' | 'negative' = 'secondary'
@@ -58,6 +58,30 @@
}
mergedModel.groupBy = Array.from(new Set([...mergedModel.groupBy, ...customAttributes]))
const sortableTypes: Ref<Class<Type<any>>>[] = [
core.class.EnumOf,
core.class.TypeString,
core.class.TypeNumber,
core.class.TypeDate,
core.class.TypeBoolean
]
const customSortableAttributes: OrderOption[] = classes
.flatMap((c) => {
const hierarchy = client.getHierarchy()
return hierarchy.isMixin(c)
? [
...Array.from(hierarchy.getOwnAttributes(c).values()),
...Array.from(hierarchy.getOwnAttributes(hierarchy.getBaseClass(c)).values())
]
: Array.from(client.getHierarchy().getOwnAttributes(c).values())
})
.filter((attr) => attr.isCustom && !attr.isHidden && sortableTypes.includes(attr.type._class))
.map((a) => {
return [a.name, SortingOrder.Ascending]
})
mergedModel.orderBy = Array.from(new Set([...mergedModel.orderBy, ...customSortableAttributes]))
mergedModel.groupBy = mergedModel.groupBy.filter((it, idx, arr) => arr.indexOf(it) === idx)
mergedModel.orderBy = mergedModel.orderBy.filter((it, idx, arr) => arr.findIndex((q) => it[0] === q[0]) === idx)
mergedModel.other = mergedModel.other.filter((it, idx, arr) => arr.findIndex((q) => q.key === it.key) === idx)
@@ -6,6 +6,7 @@
import view from '../plugin'
import { buildConfigLookup, getKeyLabel } from '../utils'
import { isDropdownType, isToggleType, noCategory } from '../viewOptions'
import { SortingOrder } from '@hcengineering/core'
export let viewlet: Viewlet
export let config: ViewOptionsModel
@@ -113,8 +114,13 @@
const key = e.detail
const value = config.orderBy.find((p) => p[0] === key)
if (value !== undefined) {
viewOptions.orderBy = value
dispatch('update', { key: 'orderBy', value })
if (viewOptions.orderBy[0] === key) {
viewOptions.orderBy[1] =
viewOptions.orderBy[1] === SortingOrder.Ascending ? SortingOrder.Descending : SortingOrder.Ascending
} else {
viewOptions.orderBy = value
}
dispatch('update', { key: 'orderBy', value: viewOptions.orderBy })
}
}}
/>
@@ -15,13 +15,13 @@
<script lang="ts">
import { getClient } from '@hcengineering/presentation'
import { ButtonIcon, closeTooltip, IconOptions, showPopup } from '@hcengineering/ui'
import { Viewlet, ViewOptionModel, ViewOptions } from '@hcengineering/view'
import { OrderOption, Viewlet, ViewOptionModel, ViewOptions } from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
import view from '../plugin'
import { focusStore } from '../selection'
import { setViewOptions } from '../viewOptions'
import ViewOptionsEditor from './ViewOptions.svelte'
import core, { Class, Doc, Hierarchy, Ref } from '@hcengineering/core'
import core, { Class, Doc, Hierarchy, Ref, SortingOrder, Type } from '@hcengineering/core'
export let viewlet: Viewlet | undefined
export let kind: 'primary' | 'secondary' | 'tertiary' | 'negative' = 'secondary'
@@ -44,6 +44,23 @@
return customAttributes
}
function getCustomSortingAttributes (h: Hierarchy, _class: Ref<Class<Doc>>): OrderOption[] {
const sortableTypes: Ref<Class<Type<any>>>[] = [
core.class.EnumOf,
core.class.TypeString,
core.class.TypeNumber,
core.class.TypeDate,
core.class.TypeBoolean
]
const customSortableAttributes: OrderOption[] = [...h.getOwnAttributes(_class).values()]
.filter((attr) => attr.isCustom && !attr.isHidden && sortableTypes.includes(attr.type._class))
.map((a) => {
return [a.name, SortingOrder.Ascending]
})
return customSortableAttributes
}
async function clickHandler (): Promise<void> {
if (viewlet === undefined) {
return
@@ -58,6 +75,9 @@
const customAttributes = getGroupingCustomAttributes(h, viewlet.attachTo)
const customSort = getCustomSortingAttributes(h, viewlet.attachTo)
config.orderBy = Array.from(new Set([...config.orderBy, ...customSort]))
config.groupBy = Array.from(new Set([...config.groupBy, ...customAttributes]))
showPopup(
@@ -189,6 +189,7 @@ test.describe('tracker layout tests', () => {
await issuesPage.clickModelSelectorAll()
await page.click(ViewletSelectors.Board)
await setViewGroup(page, 'No grouping')
await setViewOrder(page, 'Manual')
await setViewOrder(page, order)
await fillSearch(page, id)