feat: add show all versions toggle to card view options and implement version query filtering (#10809)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov
2026-04-29 01:30:46 +05:00
committed by GitHub
parent 62f06940df
commit 9a847386ae
19 changed files with 117 additions and 24 deletions
+1 -1
View File
@@ -1 +1 @@
"0.7.410"
"0.7.422"
+34 -5
View File
@@ -82,7 +82,7 @@ import { type Asset, getEmbeddedLabel, type IntlString, type Resource } from '@h
import time, { type ToDo } from '@hcengineering/time'
import { PaletteColorIndexes } from '@hcengineering/ui/src/colors'
import { type AnyComponent } from '@hcengineering/ui/src/types'
import { type BuildModelKey } from '@hcengineering/view'
import { type BuildModelKey, type ViewOptionModel } from '@hcengineering/view'
import { createActions } from './actions'
import { defineActionPermissions, definePermissions } from './permissions'
import card from './plugin'
@@ -225,6 +225,15 @@ export class TExportExtension extends TDoc implements ExportExtension {
export * from './migration'
const showAllVersionsOption: ViewOptionModel = {
key: 'showAllVersions',
type: 'toggle',
defaultValue: false,
actionTarget: 'query',
action: card.function.ShowAllVersions,
label: card.string.ShowAllVersions
}
const listConfig: (BuildModelKey | string)[] = [
{ key: '' },
{ key: '_class' },
@@ -350,6 +359,11 @@ export function createSystemType (
hiddenKeys: ['content', 'title'],
sortable: true
},
viewOptions: {
groupBy: [],
orderBy: [],
other: [showAllVersionsOption]
},
baseQuery: {
isLatest: true
},
@@ -383,7 +397,7 @@ export function createSystemType (
['modifiedOn', SortingOrder.Descending],
['rank', SortingOrder.Ascending]
],
other: []
other: [showAllVersionsOption]
},
baseQuery: {
isLatest: true
@@ -397,6 +411,11 @@ export function createSystemType (
builder.createDoc(view.class.Viewlet, core.space.Model, {
attachTo: type,
descriptor: card.viewlet.CardGridDescriptor,
viewOptions: {
groupBy: [],
orderBy: [],
other: [showAllVersionsOption]
},
baseQuery: {
isLatest: true
},
@@ -681,6 +700,11 @@ export function createModel (builder: Builder): void {
hiddenKeys: ['content', 'title'],
sortable: true
},
viewOptions: {
groupBy: [],
orderBy: [],
other: [showAllVersionsOption]
},
baseQuery: {
isLatest: true
},
@@ -713,7 +737,7 @@ export function createModel (builder: Builder): void {
['modifiedOn', SortingOrder.Descending],
['rank', SortingOrder.Ascending]
],
other: []
other: [showAllVersionsOption]
},
configOptions: {
hiddenKeys: ['content', 'title']
@@ -739,7 +763,7 @@ export function createModel (builder: Builder): void {
['modifiedOn', SortingOrder.Descending],
['rank', SortingOrder.Ascending]
],
other: []
other: [showAllVersionsOption]
},
configOptions: {
strict: true,
@@ -782,6 +806,11 @@ export function createModel (builder: Builder): void {
hiddenKeys: ['content', 'title'],
sortable: true
},
viewOptions: {
groupBy: [],
orderBy: [],
other: [showAllVersionsOption]
},
baseQuery: {
isLatest: true
},
@@ -821,7 +850,7 @@ export function createModel (builder: Builder): void {
['rank', SortingOrder.Ascending],
['title', SortingOrder.Descending]
],
other: []
other: [showAllVersionsOption]
}
},
card.viewlet.CardGrid
+42 -1
View File
@@ -36,7 +36,7 @@ import {
type MigrationUpgradeClient
} from '@hcengineering/model'
import tags from '@hcengineering/tags'
import view, { type Viewlet } from '@hcengineering/view'
import view, { type ViewOptionModel, type Viewlet } from '@hcengineering/view'
import card from '.'
export const cardOperation: MigrateOperation = {
@@ -134,6 +134,11 @@ export const cardOperation: MigrateOperation = {
state: 'add-grid-viewlet',
mode: 'upgrade',
func: addGridViewlet
},
{
state: 'add-show-all-versions-view-option',
mode: 'upgrade',
func: addShowAllVersionsViewOption
}
])
}
@@ -668,3 +673,39 @@ async function fillVersioning (client: MigrationClient): Promise<void> {
await iterator.close()
}
}
async function addShowAllVersionsViewOption (client: MigrationUpgradeClient): Promise<void> {
const txOp = new TxOperations(client, core.account.System)
const masterTags = await client.findAll(card.class.MasterTag, {})
const cardDescendants = client.getHierarchy().getDescendants(card.class.Card)
const allViewletTargets = [...masterTags.map((p) => p._id), ...cardDescendants, card.class.Card]
const viewlets = await client.findAll(view.class.Viewlet, {
attachTo: { $in: allViewletTargets }
})
const showAllVersionsOption: ViewOptionModel = {
key: 'showAllVersions',
type: 'toggle',
defaultValue: false,
actionTarget: 'query',
action: card.function.ShowAllVersions,
label: card.string.ShowAllVersions
}
for (const v of viewlets) {
// Skip CardSpace viewlets if any (though they shouldn't be in allViewletTargets)
if (v.attachTo === card.class.CardSpace) continue
const viewOptions = v.viewOptions ?? { groupBy: [], orderBy: [], other: [] }
const other = viewOptions.other ?? []
if (other.find((o: any) => o.key === 'showAllVersions') === undefined) {
await txOp.update(v, {
viewOptions: {
...viewOptions,
other: [...other, showAllVersionsOption]
}
})
}
}
}
+3 -2
View File
@@ -16,7 +16,7 @@
import type { ViewletViewAction, Action, ActionCategory, ViewAction } from '@hcengineering/view'
import { type Card, cardId } from '@hcengineering/card'
import card from '@hcengineering/card-resources/src/plugin'
import type { Client, Doc, Ref } from '@hcengineering/core'
import type { Client, Doc, DocumentQuery, Ref } from '@hcengineering/core'
import {} from '@hcengineering/core'
import { mergeIds, type Resource } from '@hcengineering/platform'
import { type TagCategory } from '@hcengineering/tags'
@@ -72,6 +72,7 @@ export default mergeIds(cardId, card, {
CardCustomLinkEncode: '' as Resource<(doc: Doc) => Location>,
CheckRelationsSectionVisibility: '' as Resource<(doc: Card) => Promise<boolean>>,
CheckOldMessagesSectionVisibility: '' as Resource<(doc: Card) => Promise<boolean>>,
CheckCommunicationMessagesSectionVisibility: '' as Resource<(doc: Card) => Promise<boolean>>
CheckCommunicationMessagesSectionVisibility: '' as Resource<(doc: Card) => Promise<boolean>>,
ShowAllVersions: '' as Resource<(value: any, query: DocumentQuery<Doc>) => DocumentQuery<Doc>>
}
})
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Jeden sloupec",
"TwoColumns": "Dva sloupce",
"Grid": "Mřížka",
"RichtextProperties": "Textová pole"
"RichtextProperties": "Textová pole",
"ShowAllVersions": "Ukázat všechny verze"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Einspaltig",
"TwoColumns": "Zwei spaltig",
"Grid": "Gitter",
"RichtextProperties": "Textfelder"
"RichtextProperties": "Textfelder",
"ShowAllVersions": "Alle Versionen anzeigen"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Single column",
"TwoColumns": "Two columns",
"Grid": "Grid",
"RichtextProperties": "Richtext Properties"
"RichtextProperties": "Richtext Properties",
"ShowAllVersions": "Show all versions"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Una columna",
"TwoColumns": "Dos columnas",
"Grid": "Cuadrícula",
"RichtextProperties": "Campos de texto"
"RichtextProperties": "Campos de texto",
"ShowAllVersions": "Mostrar todas las versiones"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Une colonne",
"TwoColumns": "Deux colonnes",
"Grid": "Grille",
"RichtextProperties": "Champs de texte"
"RichtextProperties": "Champs de texte",
"ShowAllVersions": "Toutes les versions"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Una colonna",
"TwoColumns": "Due colonne",
"Grid": "Griglia",
"RichtextProperties": "Campo di testo"
"RichtextProperties": "Campo di testo",
"ShowAllVersions": "Tutte le versioni"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "1列",
"TwoColumns": "2列",
"Grid": "グリッド",
"RichtextProperties": "リッチテキストフィールド"
"RichtextProperties": "リッチテキストフィールド",
"ShowAllVersions": "すべてのバージョンを表示"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Uma coluna",
"TwoColumns": "Duas colunas",
"Grid": "Grade",
"RichtextProperties": "Campos de texto"
"RichtextProperties": "Campos de texto",
"ShowAllVersions": "Todas as versões"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Uma coluna",
"TwoColumns": "Duas colunas",
"Grid": "Grade",
"RichtextProperties": "Campo de texto"
"RichtextProperties": "Campo de texto",
"ShowAllVersions": "Todas as versões"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Один столбец",
"TwoColumns": "Два столбца",
"Grid": "Сетка",
"RichtextProperties": "Текстовые поля"
"RichtextProperties": "Текстовые поля",
"ShowAllVersions": "Показывать все версии"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "Tek sütun",
"TwoColumns": "İki sütun",
"Grid": "Izgara",
"RichtextProperties": "Zengin metin alanları"
"RichtextProperties": "Zengin metin alanları",
"ShowAllVersions": "Tüm sürümleri göster"
}
}
+2 -1
View File
@@ -84,6 +84,7 @@
"SingleColumn": "单列",
"TwoColumns": "两列",
"Grid": "网格",
"RichtextProperties": "富文本字段"
"RichtextProperties": "富文本字段",
"ShowAllVersions": "显示所有版本"
}
}
+4 -2
View File
@@ -37,7 +37,8 @@ import {
cardFactory,
duplicateCard,
checkChildrenSectionVisibility,
createChildAction
createChildAction,
showAllVersions
} from './utils'
import { formatCardValue } from './cardTableFormatter'
import CardGridView from './components/CardGridView.svelte'
@@ -179,6 +180,7 @@ export default async (): Promise<Resources> => ({
GetSpaceAccessPublicLink: getSpaceAccessPublicLink,
CanGetSpaceAccessPublicLink: canGetSpaceAccessPublicLink,
CardFactory: cardFactory,
FormatCardMarkdownValue: formatCardValue
FormatCardMarkdownValue: formatCardValue,
ShowAllVersions: showAllVersions
}
})
+7
View File
@@ -778,6 +778,13 @@ export function canUnlockSection (space: Ref<Space>, store: PermissionsStore): b
return !store.restrictedSpaces.has(space)
}
export function showAllVersions (value: any, query: DocumentQuery<Doc>): DocumentQuery<Doc> {
if (value === true) {
return { ...query, isLatest: { $in: [true, false] } }
}
return query
}
export const viewStore = writable<Record<Ref<MasterTag>, string>>(
JSON.parse(localStorage.getItem('card.layout') ?? '{}')
)
+2 -1
View File
@@ -214,7 +214,8 @@ const cardPlugin = plugin(cardId, {
LockSection: '' as IntlString,
UnLockSection: '' as IntlString,
SectionLocked: '' as IntlString,
SectionUnlocked: '' as IntlString
SectionUnlocked: '' as IntlString,
ShowAllVersions: '' as IntlString
},
section: {
Attachments: '' as Ref<CardSection>,