From c86869f980c579747d201af07cfe75a9a704cf64 Mon Sep 17 00:00:00 2001 From: Artyom Savchenko Date: Sat, 31 Jan 2026 18:01:48 +0700 Subject: [PATCH] Copy ids and attributes to markdown card title (#10467) Signed-off-by: Artem Savchenko --- .../card-resources/src/cardTableFormatter.ts | 15 ++++- plugins/card-resources/src/cardUtils.ts | 55 +++++++++++++++++++ .../src/components/CardPresenter.svelte | 40 ++------------ 3 files changed, 73 insertions(+), 37 deletions(-) create mode 100644 plugins/card-resources/src/cardUtils.ts diff --git a/plugins/card-resources/src/cardTableFormatter.ts b/plugins/card-resources/src/cardTableFormatter.ts index ac999dcdbc..258968dc37 100644 --- a/plugins/card-resources/src/cardTableFormatter.ts +++ b/plugins/card-resources/src/cardTableFormatter.ts @@ -15,10 +15,11 @@ import { type Class, type Doc, type Hierarchy, type Ref } from '@hcengineering/core' import { translate, type IntlString } from '@hcengineering/platform' -import cardPlugin, { type CardSpace } from '@hcengineering/card' +import cardPlugin, { type Card, type CardSpace } from '@hcengineering/card' import { type AttributeModel } from '@hcengineering/view' import { getClient } from '@hcengineering/presentation' import { isIntlString } from '@hcengineering/converter-resources' +import { getCardIds, getCardVersion } from './cardUtils' /** * Cache for MasterTag ID -> label mappings to reduce database calls @@ -110,6 +111,18 @@ export async function formatCardValue ( const cardDoc = card as unknown as Record + if (attr.key === '') { + const labelStr = typeof attr.label === 'string' ? attr.label : '' + if (labelStr.startsWith('custom') || attr.isLookup) { + return undefined + } + const cardObj = card as unknown as Card + const ids = getCardIds(cardObj, hierarchy) + const version = getCardVersion(cardObj, hierarchy) + const parts = [ids, cardObj.title, version].filter(Boolean) + return parts.join(' ') + } + // Handle _class field (MasterTag/Type) - format MasterTag ID to label if (attr.key === '_class') { const classValue: unknown = cardDoc._class diff --git a/plugins/card-resources/src/cardUtils.ts b/plugins/card-resources/src/cardUtils.ts new file mode 100644 index 0000000000..aec4fd4d25 --- /dev/null +++ b/plugins/card-resources/src/cardUtils.ts @@ -0,0 +1,55 @@ +// +// Copyright © 2026 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import core, { type Hierarchy, toRank } from '@hcengineering/core' +import { type Card } from '@hcengineering/card' + +/** + * Get the IDs string for a card (attributes with showInPresenter, sorted by rank). + * Same logic as CardPresenter title line prefix. + */ +export function getCardIds (object: Card | undefined, hierarchy: Hierarchy): string { + if (object === undefined) return '' + const attrs = [...hierarchy.getAllAttributes(object._class, core.class.Doc).values()].sort((a, b) => { + const rankA = a.rank ?? toRank(a._id) ?? '' + const rankB = b.rank ?? toRank(b._id) ?? '' + return rankA.localeCompare(rankB) + }) + const res: string[] = [] + for (const attr of attrs) { + const val = (object as any)[attr.name] + if ((attr as { showInPresenter?: boolean }).showInPresenter === true && val !== undefined) { + if (typeof val === 'string' || typeof val === 'number') { + res.push(val.toString()) + } else if (typeof val === 'boolean') { + res.push(val ? '✅' : '❌️') + } + } + } + return res.join(' ') +} + +/** + * Get the version string for a card (e.g. "v1") when VersionableClass is enabled. + * Same logic as CardPresenter title line suffix. + */ +export function getCardVersion (val: Card | undefined, hierarchy: Hierarchy): string { + if (val === undefined) return '' + const mixin = hierarchy.classHierarchyMixin(val._class, core.mixin.VersionableClass) + if (mixin != null && mixin.enabled) { + return 'v' + (val.version ?? 1) + } + return '' +} diff --git a/plugins/card-resources/src/components/CardPresenter.svelte b/plugins/card-resources/src/components/CardPresenter.svelte index 6ef9980ada..9a9e81554e 100644 --- a/plugins/card-resources/src/components/CardPresenter.svelte +++ b/plugins/card-resources/src/components/CardPresenter.svelte @@ -14,7 +14,7 @@ --> {#if inline && cardObj}