From 1d450682b1b858645f4e852dafa97e5a891c15c2 Mon Sep 17 00:00:00 2001 From: Artyom Savchenko Date: Fri, 23 Jan 2026 11:20:06 +0700 Subject: [PATCH] Display documents table source (#10433) * Display documents table source Signed-off-by: Artem Savchenko * Clean up Signed-off-by: Artem Savchenko * Fix warning Signed-off-by: Artem Savchenko * Fix review comments Signed-off-by: Artem Savchenko --------- Signed-off-by: Artem Savchenko --- plugins/text-editor-assets/lang/cs.json | 4 +- plugins/text-editor-assets/lang/de.json | 4 +- plugins/text-editor-assets/lang/en.json | 4 +- plugins/text-editor-assets/lang/es.json | 4 +- plugins/text-editor-assets/lang/fr.json | 4 +- plugins/text-editor-assets/lang/it.json | 4 +- plugins/text-editor-assets/lang/ja.json | 4 +- plugins/text-editor-assets/lang/pt.json | 4 +- plugins/text-editor-assets/lang/ru.json | 4 +- plugins/text-editor-assets/lang/tr.json | 4 +- plugins/text-editor-assets/lang/zh.json | 4 +- .../actions/OriginalTableDataViewer.svelte | 7 + .../table/actions/TableDiffViewer.svelte | 6 +- .../actions/TableRefreshConfirmation.svelte | 6 +- .../table/actions/TableSourceInfo.svelte | 188 ++++++++++++++++++ .../extension/table/actions/refreshTable.ts | 1 + .../table/actions/seeOriginalTableData.ts | 3 +- .../extension/table/actions/showTableDiff.ts | 3 +- .../extension/table/refreshTable.ts | 3 +- .../extension/table/tableMetadata.ts | 1 + plugins/text-editor-resources/src/plugin.ts | 3 +- plugins/text-editor/src/plugin.ts | 4 +- .../view-resources/src/copyAsMarkdownTable.ts | 33 ++- plugins/view/src/types.ts | 1 + 24 files changed, 282 insertions(+), 21 deletions(-) create mode 100644 plugins/text-editor-resources/src/components/extension/table/actions/TableSourceInfo.svelte diff --git a/plugins/text-editor-assets/lang/cs.json b/plugins/text-editor-assets/lang/cs.json index 45fd2fa177..232c7e726c 100644 --- a/plugins/text-editor-assets/lang/cs.json +++ b/plugins/text-editor-assets/lang/cs.json @@ -79,6 +79,8 @@ "ConvertToLinkPreview": "Zobrazit jako odkaz", "ConvertToEmbedPreview": "Zobrazit jako náhled obsahu", "UnableToLoadEmbeddedContent": "Náhled odkazu nelze načíst kvůli nastavení oprávnění nebo nepodporovanému obsahu", - "CannotConnectToCollaborationService": "Nelze se připojit k službě spolupráce" + "CannotConnectToCollaborationService": "Nelze se připojit k službě spolupráce", + "SourceURL": "Zdrojová URL", + "SelectedDocuments": "Vybrané dokumenty ({count, plural, =1 {1 položka} other {# položek}})" } } \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/de.json b/plugins/text-editor-assets/lang/de.json index 4befbc7a24..1b8204d1a2 100644 --- a/plugins/text-editor-assets/lang/de.json +++ b/plugins/text-editor-assets/lang/de.json @@ -78,6 +78,8 @@ "ConvertToLinkPreview": "Als Link anzeigen", "ConvertToEmbedPreview": "Als Inhaltsvorschau anzeigen", "UnableToLoadEmbeddedContent": "Die Linkvorschau konnte aufgrund von Berechtigungseinstellungen oder nicht unterstütztem Inhalt nicht geladen werden", - "CannotConnectToCollaborationService": "Kann keine Verbindung zum Kollaborationsdienst herstellen" + "CannotConnectToCollaborationService": "Kann keine Verbindung zum Kollaborationsdienst herstellen", + "SourceURL": "Quell-URL", + "SelectedDocuments": "Ausgewählte Dokumente ({count, plural, =1 {1 Element} other {# Elemente}})" } } \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/en.json b/plugins/text-editor-assets/lang/en.json index 0de83843d6..d84d1460ca 100644 --- a/plugins/text-editor-assets/lang/en.json +++ b/plugins/text-editor-assets/lang/en.json @@ -80,6 +80,8 @@ "ConvertToLinkPreview": "Show as a link", "ConvertToEmbedPreview": "Show as a content preview", "UnableToLoadEmbeddedContent": "Link preview couldn't be loaded due to permission settings or unsupported content", - "CannotConnectToCollaborationService": "Cannot connect to collaboration service" + "CannotConnectToCollaborationService": "Cannot connect to collaboration service", + "SourceURL": "Source URL", + "SelectedDocuments": "Selected documents ({count, plural, =1 {1 item} other {# items}})" } } \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/es.json b/plugins/text-editor-assets/lang/es.json index be26f787da..0056c25fa5 100644 --- a/plugins/text-editor-assets/lang/es.json +++ b/plugins/text-editor-assets/lang/es.json @@ -69,6 +69,8 @@ "ConvertToLinkPreview": "Mostrar como enlace", "ConvertToEmbedPreview": "Mostrar como vista previa de contenido", "UnableToLoadEmbeddedContent": "No se pudo cargar la vista previa del enlace debido a la configuración de permisos o contenido no compatible", - "CannotConnectToCollaborationService": "No se puede conectar con el colaborador" + "CannotConnectToCollaborationService": "No se puede conectar con el colaborador", + "SourceURL": "URL de origen", + "SelectedDocuments": "Documentos seleccionados ({count, plural, =1 {1 elemento} other {# elementos}})" } } \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/fr.json b/plugins/text-editor-assets/lang/fr.json index 7ae34f9716..6910691a08 100644 --- a/plugins/text-editor-assets/lang/fr.json +++ b/plugins/text-editor-assets/lang/fr.json @@ -69,6 +69,8 @@ "ConvertToLinkPreview": "Afficher comme lien", "ConvertToEmbedPreview": "Afficher comme aperçu de contenu", "UnableToLoadEmbeddedContent": "L’aperçu du lien n’a pas pu être chargé en raison des paramètres d’autorisation ou d’un contenu non pris en charge", - "CannotConnectToCollaborationService": "Impossible de se connecter au collaborateur" + "CannotConnectToCollaborationService": "Impossible de se connecter au collaborateur", + "SourceURL": "URL source", + "SelectedDocuments": "Documents sélectionnés ({count, plural, =1 {1 élément} other {# éléments}})" } } \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/it.json b/plugins/text-editor-assets/lang/it.json index 4cb6cbe401..4c3762628e 100644 --- a/plugins/text-editor-assets/lang/it.json +++ b/plugins/text-editor-assets/lang/it.json @@ -78,6 +78,8 @@ "ConvertToLinkPreview": "Mostra come link", "ConvertToEmbedPreview": "Mostra come anteprima del contenuto", "UnableToLoadEmbeddedContent": "Impossibile caricare l'anteprima del link a causa delle impostazioni dei permessi o di contenuto non supportato", - "CannotConnectToCollaborationService": "Impossibile connettersi al servizio di collaborazione" + "CannotConnectToCollaborationService": "Impossibile connettersi al servizio di collaborazione", + "SourceURL": "URL di origine", + "SelectedDocuments": "Documenti selezionati ({count, plural, =1 {1 elemento} other {# elementi}})" } } \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/ja.json b/plugins/text-editor-assets/lang/ja.json index b702e98ffb..7a5dd59e33 100644 --- a/plugins/text-editor-assets/lang/ja.json +++ b/plugins/text-editor-assets/lang/ja.json @@ -79,6 +79,8 @@ "ConvertToLinkPreview": "リンクとして表示", "ConvertToEmbedPreview": "コンテンツプレビューとして表示", "UnableToLoadEmbeddedContent": "リンクのプレビューを読み込めません。権限設定または非対応のコンテンツが原因です", - "CannotConnectToCollaborationService": "コラボレーションサービスに接続できません" + "CannotConnectToCollaborationService": "コラボレーションサービスに接続できません", + "SourceURL": "ソースURL", + "SelectedDocuments": "選択されたドキュメント ({count, plural, =1 {1 項目} other {# 項目}})" } } diff --git a/plugins/text-editor-assets/lang/pt.json b/plugins/text-editor-assets/lang/pt.json index 5edde03d64..5da1bd110a 100644 --- a/plugins/text-editor-assets/lang/pt.json +++ b/plugins/text-editor-assets/lang/pt.json @@ -69,6 +69,8 @@ "ConvertToLinkPreview": "Mostrar como link", "ConvertToEmbedPreview": "Mostrar como pré-visualização de conteúdo", "UnableToLoadEmbeddedContent": "Não foi possível carregar a pré-visualização do link devido às permissões ou a conteúdo não suportado", - "CannotConnectToCollaborationService": "Não foi possível conectar ao serviço de colaboração" + "CannotConnectToCollaborationService": "Não foi possível conectar ao serviço de colaboração", + "SourceURL": "URL de origem", + "SelectedDocuments": "Documentos selecionados ({count, plural, =1 {1 item} other {# itens}})" } } diff --git a/plugins/text-editor-assets/lang/ru.json b/plugins/text-editor-assets/lang/ru.json index f2ceb38d8d..b388c4c810 100644 --- a/plugins/text-editor-assets/lang/ru.json +++ b/plugins/text-editor-assets/lang/ru.json @@ -79,6 +79,8 @@ "ConvertToLinkPreview": "Показать как ссылку", "ConvertToEmbedPreview": "Показать как превью контента", "UnableToLoadEmbeddedContent": "Не удалось загрузить превью ссылки из-за настроек доступа или неподдерживаемого содержимого", - "CannotConnectToCollaborationService": "Не удалось подключиться к сервису совместной работы" + "CannotConnectToCollaborationService": "Не удалось подключиться к сервису совместной работы", + "SourceURL": "Исходный URL", + "SelectedDocuments": "Выбранные документы ({count, plural, =1 {1 элемент} other {# элементов}})" } } \ No newline at end of file diff --git a/plugins/text-editor-assets/lang/tr.json b/plugins/text-editor-assets/lang/tr.json index d9bc887f10..aa8b8cc281 100644 --- a/plugins/text-editor-assets/lang/tr.json +++ b/plugins/text-editor-assets/lang/tr.json @@ -79,6 +79,8 @@ "ConvertToLinkPreview": "Bağlantı olarak göster", "ConvertToEmbedPreview": "İçerik önizlemesi olarak göster", "UnableToLoadEmbeddedContent": "Bağlantı önizlemesi izin ayarları veya desteklenmeyen içerik nedeniyle yüklenemedi", - "CannotConnectToCollaborationService": "İşbirliği servisine bağlanılamıyor" + "CannotConnectToCollaborationService": "İşbirliği servisine bağlanılamıyor", + "SourceURL": "Kaynak URL", + "SelectedDocuments": "Seçilen belgeler ({count, plural, =1 {1 öğe} other {# öğe}})" } } diff --git a/plugins/text-editor-assets/lang/zh.json b/plugins/text-editor-assets/lang/zh.json index ba24833839..bb286a005f 100644 --- a/plugins/text-editor-assets/lang/zh.json +++ b/plugins/text-editor-assets/lang/zh.json @@ -71,6 +71,8 @@ "ConvertToLinkPreview": "显示为链接", "ConvertToEmbedPreview": "显示为内容预览", "UnableToLoadEmbeddedContent": "由于权限设置或不支持的内容,无法加载链接预览", - "CannotConnectToCollaborationService": "无法连接到协作者" + "CannotConnectToCollaborationService": "无法连接到协作者", + "SourceURL": "源URL", + "SelectedDocuments": "选定的文档 ({count, plural, =1 {1 项} other {# 项}})" } } diff --git a/plugins/text-editor-resources/src/components/extension/table/actions/OriginalTableDataViewer.svelte b/plugins/text-editor-resources/src/components/extension/table/actions/OriginalTableDataViewer.svelte index eca24643e7..226b36177e 100644 --- a/plugins/text-editor-resources/src/components/extension/table/actions/OriginalTableDataViewer.svelte +++ b/plugins/text-editor-resources/src/components/extension/table/actions/OriginalTableDataViewer.svelte @@ -20,6 +20,9 @@ import { Component, Loading } from '@hcengineering/ui' import type { BuildModelKey, Viewlet } from '@hcengineering/view' import { createEventDispatcher } from 'svelte' + import type { TableMetadata } from '../tableMetadata' + + import TableSourceInfo from './TableSourceInfo.svelte' export let _class: Ref> export let config: Array | undefined = undefined @@ -27,6 +30,7 @@ export let query: DocumentQuery | undefined = undefined export let viewlet: Viewlet | undefined = undefined export let viewletWithLookup: any | undefined = undefined + export let metadata: TableMetadata | undefined = undefined const dispatch = createEventDispatcher() @@ -84,6 +88,9 @@ {/if} + {#if metadata} + + {/if} diff --git a/plugins/text-editor-resources/src/components/extension/table/actions/refreshTable.ts b/plugins/text-editor-resources/src/components/extension/table/actions/refreshTable.ts index da0a8de8f3..ca6a307822 100644 --- a/plugins/text-editor-resources/src/components/extension/table/actions/refreshTable.ts +++ b/plugins/text-editor-resources/src/components/extension/table/actions/refreshTable.ts @@ -97,6 +97,7 @@ export async function refreshTable (editor: Editor): Promise { { oldMarkdown: currentTableMarkdown, newMarkdown: freshTableMarkdown, + metadata, onApply: () => { applyTableRefresh(editor, table, freshTableMarkdown, metadata) } diff --git a/plugins/text-editor-resources/src/components/extension/table/actions/seeOriginalTableData.ts b/plugins/text-editor-resources/src/components/extension/table/actions/seeOriginalTableData.ts index 1eddf467b1..1949acfe1a 100644 --- a/plugins/text-editor-resources/src/components/extension/table/actions/seeOriginalTableData.ts +++ b/plugins/text-editor-resources/src/components/extension/table/actions/seeOriginalTableData.ts @@ -95,7 +95,8 @@ export async function seeOriginalTableData (editor: Editor): Promise { documentIds: documentIds.length > 0 ? documentIds : [], query: documentIds.length === 0 ? metadata.query : undefined, viewlet, - viewletWithLookup + viewletWithLookup, + metadata }, 'center' ) diff --git a/plugins/text-editor-resources/src/components/extension/table/actions/showTableDiff.ts b/plugins/text-editor-resources/src/components/extension/table/actions/showTableDiff.ts index dcaa1012fc..50b02bd1c8 100644 --- a/plugins/text-editor-resources/src/components/extension/table/actions/showTableDiff.ts +++ b/plugins/text-editor-resources/src/components/extension/table/actions/showTableDiff.ts @@ -50,7 +50,8 @@ export async function showTableDiff (editor: Editor): Promise { TableDiffViewer, { oldMarkdown: currentTableMarkdown, - newMarkdown: freshTableMarkdown + newMarkdown: freshTableMarkdown, + metadata }, 'center' ) diff --git a/plugins/text-editor-resources/src/components/extension/table/refreshTable.ts b/plugins/text-editor-resources/src/components/extension/table/refreshTable.ts index 56741bcd6a..a9b2ed7ed1 100644 --- a/plugins/text-editor-resources/src/components/extension/table/refreshTable.ts +++ b/plugins/text-editor-resources/src/components/extension/table/refreshTable.ts @@ -33,7 +33,8 @@ export async function buildMarkdownTableFromDocs ( cardClass: metadata.cardClass, viewletId: metadata.viewletId, config: metadata.config, - query: metadata.query + query: metadata.query, + originalUrl: metadata.originalUrl } return await buildFunction(docs, buildMetadata, client) } catch (error) { diff --git a/plugins/text-editor-resources/src/components/extension/table/tableMetadata.ts b/plugins/text-editor-resources/src/components/extension/table/tableMetadata.ts index 3f01b9d7c0..e0f5d6f552 100644 --- a/plugins/text-editor-resources/src/components/extension/table/tableMetadata.ts +++ b/plugins/text-editor-resources/src/components/extension/table/tableMetadata.ts @@ -21,6 +21,7 @@ export interface TableMetadata extends BuildMarkdownTableMetadata { documentIds: string[] timestamp: number workspace?: string + originalUrl?: string // Original URL of the page/view where the table was created } /** diff --git a/plugins/text-editor-resources/src/plugin.ts b/plugins/text-editor-resources/src/plugin.ts index 9b80fac0ae..3d53f7f498 100644 --- a/plugins/text-editor-resources/src/plugin.ts +++ b/plugins/text-editor-resources/src/plugin.ts @@ -19,6 +19,7 @@ import { type IntlString, plugin } from '@hcengineering/platform' export default plugin(textEditorId, { string: { - CannotConnectToCollaborationService: '' as IntlString + CannotConnectToCollaborationService: '' as IntlString, + SourceURL: '' as IntlString } }) diff --git a/plugins/text-editor/src/plugin.ts b/plugins/text-editor/src/plugin.ts index e8e4e7dcd5..b74dba97c2 100644 --- a/plugins/text-editor/src/plugin.ts +++ b/plugins/text-editor/src/plugin.ts @@ -117,7 +117,9 @@ export default plugin(textEditorId, { ConvertToLinkPreview: '' as IntlString, ConvertToEmbedPreview: '' as IntlString, - UnableToLoadEmbeddedContent: '' as IntlString + UnableToLoadEmbeddedContent: '' as IntlString, + SourceURL: '' as IntlString, + SelectedDocuments: '' as IntlString<{ count: number }> }, icon: { Header1: '' as Asset, diff --git a/plugins/view-resources/src/copyAsMarkdownTable.ts b/plugins/view-resources/src/copyAsMarkdownTable.ts index d16ff6a240..8e252dd4e7 100644 --- a/plugins/view-resources/src/copyAsMarkdownTable.ts +++ b/plugins/view-resources/src/copyAsMarkdownTable.ts @@ -26,7 +26,7 @@ import core, { getObjectValue } from '@hcengineering/core' import { translate, type IntlString, getMetadata } from '@hcengineering/platform' -import { addNotification, NotificationSeverity, locationToUrl } from '@hcengineering/ui' +import { addNotification, NotificationSeverity, locationToUrl, getCurrentResolvedLocation } from '@hcengineering/ui' import { getCurrentLanguage } from '@hcengineering/theme' import viewPlugin, { type Viewlet, @@ -492,6 +492,7 @@ export interface TableMetadata { documentIds: Array> timestamp: number workspace?: string // Optional workspace identifier + originalUrl?: string // Original URL of the page/view where the table was created } /** @@ -510,6 +511,19 @@ async function buildTableMetadata ( viewletId = viewlet?._id } + // Capture the original URL of the current page/view + let originalUrl: string | undefined + try { + const currentLocation = getCurrentResolvedLocation() + const relativeUrl = locationToUrl(currentLocation) + const frontUrl = + getMetadata(presentation.metadata.FrontUrl) ?? (typeof window !== 'undefined' ? window.location.origin : '') + originalUrl = concatLink(frontUrl, relativeUrl) + } catch (error) { + // If URL capture fails, continue without it + console.warn('Failed to capture original URL for table metadata:', error) + } + return { version: '1.0', cardClass: props.cardClass, @@ -517,7 +531,8 @@ async function buildTableMetadata ( config: props.config, query: props.query, documentIds: docs.map((d) => d._id), - timestamp: Date.now() + timestamp: Date.now(), + originalUrl } } @@ -528,6 +543,17 @@ export function buildRelationshipTableMetadata ( props: CopyRelationshipTableAsMarkdownProps, docs: Doc[] ): TableMetadata { + let originalUrl: string | undefined + try { + const currentLocation = getCurrentResolvedLocation() + const relativeUrl = locationToUrl(currentLocation) + const frontUrl = + getMetadata(presentation.metadata.FrontUrl) ?? (typeof window !== 'undefined' ? window.location.origin : '') + originalUrl = concatLink(frontUrl, relativeUrl) + } catch (error) { + console.warn('Failed to capture original URL for relationship table metadata:', error) + } + return { version: '1.0', cardClass: props.cardClass, @@ -535,7 +561,8 @@ export function buildRelationshipTableMetadata ( config: props.model.map((m) => m.key), query: props.query, documentIds: docs.map((d) => d._id), - timestamp: Date.now() + timestamp: Date.now(), + originalUrl } } diff --git a/plugins/view/src/types.ts b/plugins/view/src/types.ts index d4f33578ae..3c07a45cec 100644 --- a/plugins/view/src/types.ts +++ b/plugins/view/src/types.ts @@ -904,4 +904,5 @@ export interface BuildMarkdownTableMetadata { viewletId?: string | Ref config?: Array query?: Record | DocumentQuery + originalUrl?: string // Original URL of the page/view where the table was created }