mirror of
https://github.com/hcengineering/platform.git
synced 2026-10-01 22:15:04 +02:00
Display documents table source (#10433)
* Display documents table source Signed-off-by: Artem Savchenko <armisav@gmail.com> * Clean up Signed-off-by: Artem Savchenko <armisav@gmail.com> * Fix warning Signed-off-by: Artem Savchenko <armisav@gmail.com> * Fix review comments Signed-off-by: Artem Savchenko <armisav@gmail.com> --------- Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
@@ -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}})"
|
||||
}
|
||||
}
|
||||
@@ -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}})"
|
||||
}
|
||||
}
|
||||
@@ -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}})"
|
||||
}
|
||||
}
|
||||
@@ -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}})"
|
||||
}
|
||||
}
|
||||
@@ -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}})"
|
||||
}
|
||||
}
|
||||
@@ -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}})"
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,8 @@
|
||||
"ConvertToLinkPreview": "リンクとして表示",
|
||||
"ConvertToEmbedPreview": "コンテンツプレビューとして表示",
|
||||
"UnableToLoadEmbeddedContent": "リンクのプレビューを読み込めません。権限設定または非対応のコンテンツが原因です",
|
||||
"CannotConnectToCollaborationService": "コラボレーションサービスに接続できません"
|
||||
"CannotConnectToCollaborationService": "コラボレーションサービスに接続できません",
|
||||
"SourceURL": "ソースURL",
|
||||
"SelectedDocuments": "選択されたドキュメント ({count, plural, =1 {1 項目} other {# 項目}})"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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}})"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
"ConvertToLinkPreview": "Показать как ссылку",
|
||||
"ConvertToEmbedPreview": "Показать как превью контента",
|
||||
"UnableToLoadEmbeddedContent": "Не удалось загрузить превью ссылки из-за настроек доступа или неподдерживаемого содержимого",
|
||||
"CannotConnectToCollaborationService": "Не удалось подключиться к сервису совместной работы"
|
||||
"CannotConnectToCollaborationService": "Не удалось подключиться к сервису совместной работы",
|
||||
"SourceURL": "Исходный URL",
|
||||
"SelectedDocuments": "Выбранные документы ({count, plural, =1 {1 элемент} other {# элементов}})"
|
||||
}
|
||||
}
|
||||
@@ -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}})"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
"ConvertToLinkPreview": "显示为链接",
|
||||
"ConvertToEmbedPreview": "显示为内容预览",
|
||||
"UnableToLoadEmbeddedContent": "由于权限设置或不支持的内容,无法加载链接预览",
|
||||
"CannotConnectToCollaborationService": "无法连接到协作者"
|
||||
"CannotConnectToCollaborationService": "无法连接到协作者",
|
||||
"SourceURL": "源URL",
|
||||
"SelectedDocuments": "选定的文档 ({count, plural, =1 {1 项} other {# 项}})"
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -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<Class<Doc>>
|
||||
export let config: Array<string | BuildModelKey> | undefined = undefined
|
||||
@@ -27,6 +30,7 @@
|
||||
export let query: DocumentQuery<Doc> | 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 @@
|
||||
<Loading />
|
||||
{/if}
|
||||
</div>
|
||||
{#if metadata}
|
||||
<TableSourceInfo {metadata} />
|
||||
{/if}
|
||||
</Card>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
+5
-1
@@ -18,11 +18,14 @@
|
||||
import presentation, { Card } from '@hcengineering/presentation'
|
||||
import textEditor from '@hcengineering/text-editor'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import type { TableMetadata } from '../tableMetadata'
|
||||
|
||||
import MarkupDiffViewer from '../../../MarkupDiffViewer.svelte'
|
||||
import TableSourceInfo from './TableSourceInfo.svelte'
|
||||
|
||||
export let oldMarkdown: string
|
||||
export let newMarkdown: string
|
||||
export let metadata: TableMetadata
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -47,11 +50,12 @@
|
||||
<div class="table-diff-container">
|
||||
<MarkupDiffViewer content={newContent} comparedVersion={oldContent} />
|
||||
</div>
|
||||
<TableSourceInfo {metadata} />
|
||||
</Card>
|
||||
|
||||
<style>
|
||||
.table-diff-container {
|
||||
padding: 1rem;
|
||||
padding: 0rem 1rem;
|
||||
overflow: auto;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
+5
-1
@@ -19,11 +19,14 @@
|
||||
import textEditor from '@hcengineering/text-editor'
|
||||
import { Button } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import type { TableMetadata } from '../tableMetadata'
|
||||
|
||||
import MarkupDiffViewer from '../../../MarkupDiffViewer.svelte'
|
||||
import TableSourceInfo from './TableSourceInfo.svelte'
|
||||
|
||||
export let oldMarkdown: string
|
||||
export let newMarkdown: string
|
||||
export let metadata: TableMetadata
|
||||
export let onApply: () => void = () => {}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
@@ -53,6 +56,7 @@
|
||||
<div class="table-diff-container">
|
||||
<MarkupDiffViewer content={newContent} comparedVersion={oldContent} />
|
||||
</div>
|
||||
<TableSourceInfo {metadata} />
|
||||
<svelte:fragment slot="buttons">
|
||||
<Button label={presentation.string.Cancel} kind="secondary" size="large" on:click={handleCancel} />
|
||||
</svelte:fragment>
|
||||
@@ -60,7 +64,7 @@
|
||||
|
||||
<style>
|
||||
.table-diff-container {
|
||||
padding: 1rem;
|
||||
padding: 0rem 1rem;
|
||||
overflow: auto;
|
||||
max-height: 80vh;
|
||||
}
|
||||
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
<!--
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core from '@hcengineering/core'
|
||||
import { IconWithEmoji, getClient } from '@hcengineering/presentation'
|
||||
import ui, { Icon, Label } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import textEditor from '@hcengineering/text-editor'
|
||||
import type { TableMetadata } from '../tableMetadata'
|
||||
|
||||
export let metadata: TableMetadata
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
$: cardClassRef = metadata.cardClass as any
|
||||
$: cardClass = hierarchy.findClass(cardClassRef)
|
||||
$: classLabel = cardClass?.label
|
||||
$: classIcon = cardClass?.icon
|
||||
|
||||
// Format query information
|
||||
$: queryInfo = (() => {
|
||||
if (metadata.documentIds !== undefined && metadata.documentIds.length > 0) {
|
||||
return undefined
|
||||
} else if (metadata.query !== null && metadata.query !== undefined) {
|
||||
try {
|
||||
return JSON.stringify(metadata.query, null, 2)
|
||||
} catch {
|
||||
return String(metadata.query)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
})()
|
||||
|
||||
$: documentCount = metadata.documentIds?.length ?? 0
|
||||
|
||||
$: originalUrlDisplay = (() => {
|
||||
if (metadata.originalUrl == null || metadata.originalUrl === '') {
|
||||
return undefined
|
||||
}
|
||||
try {
|
||||
const url = new URL(metadata.originalUrl)
|
||||
const path = url.pathname.replace(/\/$/, '')
|
||||
return url.hostname + path
|
||||
} catch {
|
||||
return metadata.originalUrl.replace(/^https?:\/\//, '').replace(/\/$/, '')
|
||||
}
|
||||
})()
|
||||
</script>
|
||||
|
||||
<div class="table-source-info">
|
||||
<div class="source-content">
|
||||
{#if originalUrlDisplay != null && metadata.originalUrl != null}
|
||||
<div class="source-row">
|
||||
<span class="source-label">
|
||||
<Label label={textEditor.string.SourceURL} />
|
||||
</span>
|
||||
<div class="source-value">
|
||||
<a href={metadata.originalUrl} target="_blank" rel="noopener noreferrer" class="link">
|
||||
{originalUrlDisplay}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{:else if cardClass !== undefined && cardClass !== null && classLabel !== undefined}
|
||||
<div class="source-row">
|
||||
<span class="source-label">
|
||||
<Label label={core.string.Class} />
|
||||
</span>
|
||||
<div class="source-value">
|
||||
{#if classIcon}
|
||||
<Icon
|
||||
icon={classIcon === view.ids.IconWithEmoji ? IconWithEmoji : classIcon}
|
||||
iconProps={classIcon === view.ids.IconWithEmoji ? { icon: cardClass.color } : {}}
|
||||
size="small"
|
||||
/>
|
||||
{/if}
|
||||
<Label label={classLabel} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if queryInfo != null || (metadata.documentIds !== undefined && metadata.documentIds.length > 0)}
|
||||
<div class="source-row">
|
||||
<span class="source-label">
|
||||
<Label label={ui.string.Filter} />
|
||||
</span>
|
||||
<div class="source-value query-value">
|
||||
{#if metadata.documentIds !== undefined && metadata.documentIds.length > 0}
|
||||
<span class="query-text">
|
||||
<Label label={textEditor.string.SelectedDocuments} params={{ count: documentCount }} />
|
||||
</span>
|
||||
{:else if queryInfo}
|
||||
<pre class="query-json"><code>{queryInfo}</code></pre>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.table-source-info {
|
||||
margin-top: 0.5rem;
|
||||
border: 1px solid var(--theme-border);
|
||||
border-radius: 0.5rem;
|
||||
background: var(--theme-surface-01);
|
||||
overflow: hidden;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.source-content {
|
||||
padding: 0.5rem 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: flex-start;
|
||||
gap: 0.75rem;
|
||||
row-gap: 0.5rem;
|
||||
}
|
||||
|
||||
.source-row {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
.source-label {
|
||||
color: var(--caption-color);
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.source-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.query-value {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.query-text {
|
||||
color: var(--theme-text-primary);
|
||||
}
|
||||
|
||||
.query-json {
|
||||
margin: 0;
|
||||
padding: 0.75rem;
|
||||
background: var(--theme-surface-02);
|
||||
border: 1px solid var(--theme-border);
|
||||
border-radius: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-text-primary);
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
max-height: 10rem;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
code {
|
||||
display: block;
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
color: var(--theme-link-color);
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -97,6 +97,7 @@ export async function refreshTable (editor: Editor): Promise<void> {
|
||||
{
|
||||
oldMarkdown: currentTableMarkdown,
|
||||
newMarkdown: freshTableMarkdown,
|
||||
metadata,
|
||||
onApply: () => {
|
||||
applyTableRefresh(editor, table, freshTableMarkdown, metadata)
|
||||
}
|
||||
|
||||
+2
-1
@@ -95,7 +95,8 @@ export async function seeOriginalTableData (editor: Editor): Promise<void> {
|
||||
documentIds: documentIds.length > 0 ? documentIds : [],
|
||||
query: documentIds.length === 0 ? metadata.query : undefined,
|
||||
viewlet,
|
||||
viewletWithLookup
|
||||
viewletWithLookup,
|
||||
metadata
|
||||
},
|
||||
'center'
|
||||
)
|
||||
|
||||
+2
-1
@@ -50,7 +50,8 @@ export async function showTableDiff (editor: Editor): Promise<void> {
|
||||
TableDiffViewer,
|
||||
{
|
||||
oldMarkdown: currentTableMarkdown,
|
||||
newMarkdown: freshTableMarkdown
|
||||
newMarkdown: freshTableMarkdown,
|
||||
metadata
|
||||
},
|
||||
'center'
|
||||
)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<Ref<Doc>>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -904,4 +904,5 @@ export interface BuildMarkdownTableMetadata {
|
||||
viewletId?: string | Ref<Viewlet>
|
||||
config?: Array<string | BuildModelKey>
|
||||
query?: Record<string, any> | DocumentQuery<Doc>
|
||||
originalUrl?: string // Original URL of the page/view where the table was created
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user