From 9a847386ae9d692c20c6c974966a87bfa6422416 Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Wed, 29 Apr 2026 01:30:46 +0500 Subject: [PATCH] feat: add show all versions toggle to card view options and implement version query filtering (#10809) Signed-off-by: Denis Bykhov --- common/scripts/version.txt | 2 +- models/card/src/index.ts | 39 ++++++++++++++++++++++---- models/card/src/migration.ts | 43 ++++++++++++++++++++++++++++- models/card/src/plugin.ts | 5 ++-- plugins/card-assets/lang/cs.json | 3 +- plugins/card-assets/lang/de.json | 3 +- plugins/card-assets/lang/en.json | 3 +- plugins/card-assets/lang/es.json | 3 +- plugins/card-assets/lang/fr.json | 3 +- plugins/card-assets/lang/it.json | 3 +- plugins/card-assets/lang/ja.json | 3 +- plugins/card-assets/lang/pt-br.json | 3 +- plugins/card-assets/lang/pt.json | 3 +- plugins/card-assets/lang/ru.json | 3 +- plugins/card-assets/lang/tr.json | 3 +- plugins/card-assets/lang/zh.json | 3 +- plugins/card-resources/src/index.ts | 6 ++-- plugins/card-resources/src/utils.ts | 7 +++++ plugins/card/src/index.ts | 3 +- 19 files changed, 117 insertions(+), 24 deletions(-) diff --git a/common/scripts/version.txt b/common/scripts/version.txt index 8214af1f31..b8caacae73 100644 --- a/common/scripts/version.txt +++ b/common/scripts/version.txt @@ -1 +1 @@ -"0.7.410" +"0.7.422" diff --git a/models/card/src/index.ts b/models/card/src/index.ts index 96607841dc..e7c21586c4 100644 --- a/models/card/src/index.ts +++ b/models/card/src/index.ts @@ -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 diff --git a/models/card/src/migration.ts b/models/card/src/migration.ts index f34279c618..648791ef47 100644 --- a/models/card/src/migration.ts +++ b/models/card/src/migration.ts @@ -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 { await iterator.close() } } + +async function addShowAllVersionsViewOption (client: MigrationUpgradeClient): Promise { + 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] + } + }) + } + } +} diff --git a/models/card/src/plugin.ts b/models/card/src/plugin.ts index 464e6f8946..74a3e31fef 100644 --- a/models/card/src/plugin.ts +++ b/models/card/src/plugin.ts @@ -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>, CheckOldMessagesSectionVisibility: '' as Resource<(doc: Card) => Promise>, - CheckCommunicationMessagesSectionVisibility: '' as Resource<(doc: Card) => Promise> + CheckCommunicationMessagesSectionVisibility: '' as Resource<(doc: Card) => Promise>, + ShowAllVersions: '' as Resource<(value: any, query: DocumentQuery) => DocumentQuery> } }) diff --git a/plugins/card-assets/lang/cs.json b/plugins/card-assets/lang/cs.json index 372d34ef4b..a725b76d0a 100644 --- a/plugins/card-assets/lang/cs.json +++ b/plugins/card-assets/lang/cs.json @@ -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" } } diff --git a/plugins/card-assets/lang/de.json b/plugins/card-assets/lang/de.json index f6b77c6b6d..9bf7ff0c3f 100644 --- a/plugins/card-assets/lang/de.json +++ b/plugins/card-assets/lang/de.json @@ -84,6 +84,7 @@ "SingleColumn": "Einspaltig", "TwoColumns": "Zwei spaltig", "Grid": "Gitter", - "RichtextProperties": "Textfelder" + "RichtextProperties": "Textfelder", + "ShowAllVersions": "Alle Versionen anzeigen" } } diff --git a/plugins/card-assets/lang/en.json b/plugins/card-assets/lang/en.json index 717fb819ff..0c94f01369 100644 --- a/plugins/card-assets/lang/en.json +++ b/plugins/card-assets/lang/en.json @@ -84,6 +84,7 @@ "SingleColumn": "Single column", "TwoColumns": "Two columns", "Grid": "Grid", - "RichtextProperties": "Richtext Properties" + "RichtextProperties": "Richtext Properties", + "ShowAllVersions": "Show all versions" } } diff --git a/plugins/card-assets/lang/es.json b/plugins/card-assets/lang/es.json index 942269d68b..02a6c623ef 100644 --- a/plugins/card-assets/lang/es.json +++ b/plugins/card-assets/lang/es.json @@ -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" } } diff --git a/plugins/card-assets/lang/fr.json b/plugins/card-assets/lang/fr.json index 2272350cb3..00c20f1219 100644 --- a/plugins/card-assets/lang/fr.json +++ b/plugins/card-assets/lang/fr.json @@ -84,6 +84,7 @@ "SingleColumn": "Une colonne", "TwoColumns": "Deux colonnes", "Grid": "Grille", - "RichtextProperties": "Champs de texte" + "RichtextProperties": "Champs de texte", + "ShowAllVersions": "Toutes les versions" } } diff --git a/plugins/card-assets/lang/it.json b/plugins/card-assets/lang/it.json index fe56cec4d9..757878562f 100644 --- a/plugins/card-assets/lang/it.json +++ b/plugins/card-assets/lang/it.json @@ -84,6 +84,7 @@ "SingleColumn": "Una colonna", "TwoColumns": "Due colonne", "Grid": "Griglia", - "RichtextProperties": "Campo di testo" + "RichtextProperties": "Campo di testo", + "ShowAllVersions": "Tutte le versioni" } } diff --git a/plugins/card-assets/lang/ja.json b/plugins/card-assets/lang/ja.json index 8463868194..966760b5f6 100644 --- a/plugins/card-assets/lang/ja.json +++ b/plugins/card-assets/lang/ja.json @@ -84,6 +84,7 @@ "SingleColumn": "1列", "TwoColumns": "2列", "Grid": "グリッド", - "RichtextProperties": "リッチテキストフィールド" + "RichtextProperties": "リッチテキストフィールド", + "ShowAllVersions": "すべてのバージョンを表示" } } diff --git a/plugins/card-assets/lang/pt-br.json b/plugins/card-assets/lang/pt-br.json index 1e6210575c..de422b51f9 100644 --- a/plugins/card-assets/lang/pt-br.json +++ b/plugins/card-assets/lang/pt-br.json @@ -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" } } diff --git a/plugins/card-assets/lang/pt.json b/plugins/card-assets/lang/pt.json index d8740a0eae..dbd78c3fa9 100644 --- a/plugins/card-assets/lang/pt.json +++ b/plugins/card-assets/lang/pt.json @@ -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" } } diff --git a/plugins/card-assets/lang/ru.json b/plugins/card-assets/lang/ru.json index 875525ae31..eab9141d3b 100644 --- a/plugins/card-assets/lang/ru.json +++ b/plugins/card-assets/lang/ru.json @@ -84,6 +84,7 @@ "SingleColumn": "Один столбец", "TwoColumns": "Два столбца", "Grid": "Сетка", - "RichtextProperties": "Текстовые поля" + "RichtextProperties": "Текстовые поля", + "ShowAllVersions": "Показывать все версии" } } diff --git a/plugins/card-assets/lang/tr.json b/plugins/card-assets/lang/tr.json index fac4c73e4d..99dd866e85 100644 --- a/plugins/card-assets/lang/tr.json +++ b/plugins/card-assets/lang/tr.json @@ -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" } } diff --git a/plugins/card-assets/lang/zh.json b/plugins/card-assets/lang/zh.json index 5b87423088..81a0a88366 100644 --- a/plugins/card-assets/lang/zh.json +++ b/plugins/card-assets/lang/zh.json @@ -84,6 +84,7 @@ "SingleColumn": "单列", "TwoColumns": "两列", "Grid": "网格", - "RichtextProperties": "富文本字段" + "RichtextProperties": "富文本字段", + "ShowAllVersions": "显示所有版本" } } diff --git a/plugins/card-resources/src/index.ts b/plugins/card-resources/src/index.ts index 4e5409b18c..cb3716bf8a 100644 --- a/plugins/card-resources/src/index.ts +++ b/plugins/card-resources/src/index.ts @@ -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 => ({ GetSpaceAccessPublicLink: getSpaceAccessPublicLink, CanGetSpaceAccessPublicLink: canGetSpaceAccessPublicLink, CardFactory: cardFactory, - FormatCardMarkdownValue: formatCardValue + FormatCardMarkdownValue: formatCardValue, + ShowAllVersions: showAllVersions } }) diff --git a/plugins/card-resources/src/utils.ts b/plugins/card-resources/src/utils.ts index 397fb74d6c..66f6afc06a 100644 --- a/plugins/card-resources/src/utils.ts +++ b/plugins/card-resources/src/utils.ts @@ -778,6 +778,13 @@ export function canUnlockSection (space: Ref, store: PermissionsStore): b return !store.restrictedSpaces.has(space) } +export function showAllVersions (value: any, query: DocumentQuery): DocumentQuery { + if (value === true) { + return { ...query, isLatest: { $in: [true, false] } } + } + return query +} + export const viewStore = writable, string>>( JSON.parse(localStorage.getItem('card.layout') ?? '{}') ) diff --git a/plugins/card/src/index.ts b/plugins/card/src/index.ts index 21b1fa87fb..ca59d56d16 100644 --- a/plugins/card/src/index.ts +++ b/plugins/card/src/index.ts @@ -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,