Skip to content

Commit 34c633d

Browse files
refactor(dashboards): store dashboards in their own table
A dashboard is now a row in a dashboard table with its own id, keyed to its workspace by a unique index (dropping it later allows several). Reads and saves go through a small repository with a revision check, so the file-side guards, exclusions, fixed file name, and dashboard file previews are gone. Chat contexts reference dashboards by dashboardId, and saves are audited as dashboard events.
1 parent 48d90c0 commit 34c633d

42 files changed

Lines changed: 445 additions & 348 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/file-category.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ const TEXT_EDITABLE_MIME_TYPES = new Set([
2424
'text/x-mermaid',
2525
// Chart documents: declarative ECharts specs rendered live (chart-preview.tsx).
2626
'text/x-sim-chart',
27-
'text/x-sim-dashboard',
2827
])
2928

3029
const TEXT_EDITABLE_EXTENSIONS = new Set([

‎apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/preview-panel.tsx‎

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import { memo, useEffect, useMemo, useRef, useState } from 'react'
44
import { useRouter } from 'next/navigation'
55
import { useTheme } from 'next-themes'
66
import '@sim/emcn/components/code/code.css'
7-
import { DashboardFeatureGate } from '@/components/dashboards/dashboard-feature-gate'
8-
import { DashboardPreview } from '@/components/dashboards/dashboard-preview'
97
import { CSV_PREVIEW_MAX_ROWS } from '@/lib/api/contracts/workspace-file-table'
108
import { getFileExtension } from '@/lib/uploads/utils/file-utils'
119
import {
@@ -23,7 +21,7 @@ import { DataTable } from './data-table'
2321
import { MermaidDiagram } from './mermaid-diagram'
2422
import { ZoomablePreview } from './zoomable-preview'
2523

26-
type PreviewType = 'markdown' | 'html' | 'csv' | 'svg' | 'mermaid' | 'chart' | 'dashboard' | null
24+
type PreviewType = 'markdown' | 'html' | 'csv' | 'svg' | 'mermaid' | 'chart' | null
2725

2826
const PREVIEWABLE_MIME_TYPES: Record<string, PreviewType> = {
2927
// Sim pages store an EXTENSIONLESS name — without this mapping the record
@@ -36,7 +34,6 @@ const PREVIEWABLE_MIME_TYPES: Record<string, PreviewType> = {
3634
'image/svg+xml': 'svg',
3735
'text/x-mermaid': 'mermaid',
3836
'text/x-sim-chart': 'chart',
39-
'text/x-sim-dashboard': 'dashboard',
4037
}
4138

4239
const PREVIEWABLE_EXTENSIONS: Record<string, PreviewType> = {
@@ -47,7 +44,6 @@ const PREVIEWABLE_EXTENSIONS: Record<string, PreviewType> = {
4744
svg: 'svg',
4845
mmd: 'mermaid',
4946
chart: 'chart',
50-
dashboard: 'dashboard',
5147
}
5248

5349
/** All extensions that have a rich preview renderer. */
@@ -87,27 +83,6 @@ export const PreviewPanel = memo(function PreviewPanel({
8783
}: PreviewPanelProps) {
8884
const previewType = resolvePreviewType(mimeType, filename)
8985

90-
if (previewType === 'dashboard')
91-
return readOnly ? (
92-
<DashboardPreview
93-
content={content}
94-
workspaceId={workspaceId}
95-
fileId={fileId}
96-
isStreaming={isStreaming}
97-
readOnly
98-
/>
99-
) : (
100-
<DashboardFeatureGate>
101-
<DashboardPreview
102-
content={content}
103-
workspaceId={workspaceId}
104-
fileId={fileId}
105-
isStreaming={isStreaming}
106-
readOnly={readOnly}
107-
/>
108-
</DashboardFeatureGate>
109-
)
110-
11186
if (previewType === 'html')
11287
return (
11388
<HtmlPreview

‎apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/text-editor.tsx‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,6 @@ const MONACO_LANGUAGE_BY_EXTENSION: Partial<Record<string, string>> = {
332332
*/
333333
jsonl: 'plaintext',
334334
yaml: 'yaml',
335-
dashboard: 'yaml',
336335
yml: 'yaml',
337336
toml: 'toml',
338337
html: 'html',
@@ -370,7 +369,6 @@ const MONACO_LANGUAGE_BY_MIME: Partial<Record<string, string>> = {
370369
'image/svg+xml': 'xml',
371370
'text/x-sql': 'sql',
372371
'application/x-yaml': 'yaml',
373-
'text/x-sim-dashboard': 'yaml',
374372
'text/markdown': 'markdown',
375373
'text/x-mermaid': 'markdown',
376374
'text/plain': 'plaintext',

‎apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/special-tags/special-tags.tsx‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import { isBrowserAgentAvailable, sendBrowserPanelAction } from '@/lib/browser-a
3838
import { useDeploymentShape } from '@/lib/core/config/deployment-shape'
3939
import { isSafeHttpUrl } from '@/lib/core/utils/urls'
4040
import { readLatestOAuthChatAttempt } from '@/lib/credentials/oauth-chat-attempt'
41-
import { dashboardDisplayName } from '@/lib/dashboards/resource'
4241
import { getDesktopBridge } from '@/lib/desktop'
4342
import { desktopChatScopeId } from '@/lib/desktop/chat-scope'
4443
import { resolveCredentialDisplay } from '@/lib/integrations/credential-display'
@@ -1951,7 +1950,7 @@ function toChatMessageContext(data: WorkspaceResourceTagData, label: string): Ch
19511950
case 'table':
19521951
return { kind: 'table', label, tableId: data.id ?? '' }
19531952
case 'dashboard':
1954-
return { kind: 'dashboard', label, fileId: data.id ?? '' }
1953+
return { kind: 'dashboard', label, dashboardId: data.id ?? '' }
19551954
case 'file':
19561955
return { kind: 'file', label, fileId: data.id ?? data.path ?? '' }
19571956
}
@@ -2030,7 +2029,7 @@ function WorkspaceResourceDisplayContent({
20302029
type: toMothershipResourceType(data.type),
20312030
...(addressed ? { workspaceId } : {}),
20322031
...(id ? { id } : {}),
2033-
title: data.type === 'dashboard' ? dashboardDisplayName(title) : title,
2032+
title,
20342033
...(data.type === 'file' && data.path ? { path: data.path } : {}),
20352034
}
20362035
}, [

‎apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-tabs/resource-tabs.tsx‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import {
3030
reorderBrowserTab,
3131
sendBrowserPanelAction,
3232
} from '@/lib/browser-agent/transport'
33-
import { dashboardDisplayName } from '@/lib/dashboards/resource'
3433
import { SIM_RESOURCE_DRAG_TYPE, SIM_RESOURCES_DRAG_TYPE } from '@/lib/mothership/resource-types'
3534
import { getChatResourceSelectionId } from '@/lib/mothership/resources/types'
3635
import { requestTerminalFocus } from '@/lib/terminal/focus'
@@ -327,9 +326,7 @@ export function ResourceTabs({
327326
? terminalTabTitle(terminal, settledCommands)
328327
: nameLookup.get(`${resource.type}:${resource.id}`)
329328
)?.trim() ||
330-
(resource.type === 'dashboard'
331-
? dashboardDisplayName(resource.title).trim()
332-
: resource.title.trim()) ||
329+
resource.title.trim() ||
333330
getResourceConfig(resource.type).label,
334331
// A shell's label is a basename, and it may be running something it is
335332
// not naming yet, so hovering identifies the directory and program.

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/chip-clipboard-codec.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const CHIP_LINK_SCHEME = 'sim'
2626
const PORTABLE_KIND_TO_ID_FIELD = {
2727
table: 'tableId',
2828
file: 'fileId',
29-
dashboard: 'fileId',
29+
dashboard: 'dashboardId',
3030
folder: 'folderId',
3131
filefolder: 'fileFolderId',
3232
workspace: 'workspaceId',
@@ -285,7 +285,7 @@ function chipLinkBaseContext(link: ParsedChipLink): ChatContext {
285285
case 'table':
286286
return { kind: 'table', tableId: link.id, label: link.label }
287287
case 'dashboard':
288-
return { kind: 'dashboard', fileId: link.id, label: link.label }
288+
return { kind: 'dashboard', dashboardId: link.id, label: link.label }
289289
case 'file':
290290
return { kind: 'file', fileId: link.id, label: link.label }
291291
case 'folder':

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/constants.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ const RESOURCE_TO_CONTEXT: Record<
132132
label: r.title,
133133
...(r.viewId ? { viewId: r.viewId } : {}),
134134
}),
135-
dashboard: (r) => ({ kind: 'dashboard', fileId: r.id, label: r.title }),
135+
dashboard: (r) => ({ kind: 'dashboard', dashboardId: r.id, label: r.title }),
136136
file: (r) => ({ kind: 'file', fileId: r.id, label: r.title }),
137137
folder: (r) => ({ kind: 'folder', folderId: r.id, label: r.title }),
138138
filefolder: (r) => ({ kind: 'filefolder', fileFolderId: r.id, label: r.title }),

‎apps/sim/app/workspace/[workspaceId]/home/components/user-input/user-input.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,9 @@ const UserInputImpl = forwardRef<UserInputHandle, UserInputProps>(function UserI
260260
case 'table':
261261
return `table:${ctx.tableId}`
262262
case 'dashboard':
263+
return `dashboard:${ctx.dashboardId}`
263264
case 'file':
264-
return `${ctx.kind}:${ctx.fileId}`
265+
return `file:${ctx.fileId}`
265266
case 'folder':
266267
return `folder:${ctx.folderId}`
267268
case 'past_chat':

‎apps/sim/app/workspace/[workspaceId]/home/home.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ function HomeContent({ chatId, userName, userId }: HomeProps) {
315315
case 'file_selection':
316316
return context.fileId ? { type: 'file', id: context.fileId } : null
317317
case 'dashboard':
318-
return { type: 'dashboard', id: context.fileId }
318+
return { type: 'dashboard', id: context.dashboardId }
319319
default:
320320
return null
321321
}

‎apps/sim/app/workspace/[workspaceId]/home/types.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ export interface ChatMessageContext {
166166
tableId?: string
167167
viewId?: string
168168
fileId?: string
169+
dashboardId?: string
169170
folderId?: string
170171
chatId?: string
171172
blockType?: string

0 commit comments

Comments
 (0)