Skip to content

Commit 54d918d

Browse files
refactor(dashboards): keep the authoring reference in Mothership's skill
Mothership's create-dashboard skill now carries the dashboard syntax like every other worker skill, so the builtin-create-dashboard workspace skill, its source, and its flag gating are removed.
1 parent bcbad6b commit 54d918d

6 files changed

Lines changed: 7 additions & 103 deletions

File tree

‎apps/sim/app/o/[organizationId]/home/components/composer/composer.tsx‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import {
2525
} from '@/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor'
2626
import { organizationSkillOptions } from '@/app/workspace/[workspaceId]/home/components/user-input/components/skills-menu-dropdown/organization-skill-options'
2727
import type { ChatRequestMode } from '@/app/workspace/[workspaceId]/home/types'
28-
import { useFeatureFlag } from '@/app/workspace/[workspaceId]/providers/feature-flags-provider'
2928
import type { useFileAttachments } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/hooks/use-file-attachments'
3029
import { SKILL_CHIP_TRIGGER } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/copilot/components/user-input/utils'
3130
import { getSkillsQueryOptions } from '@/hooks/queries/skills'
@@ -76,7 +75,6 @@ export function Composer({
7675
attachedFilesRef.current = files.attachedFiles
7776
const imagesOnly = requestMode === 'assistant'
7877
const { organization } = useOrganizationContext()
79-
const dashboardsEnabled = useFeatureFlag('dashboards')
8078
const { data: allWorkspaces = [] } = useWorkspacesQuery(!imagesOnly)
8179
const workspaces = (imagesOnly ? [] : allWorkspaces).filter(
8280
(workspace) => workspace.organizationId === organization.id
@@ -90,8 +88,7 @@ export function Composer({
9088
workspaces.map((workspace, index) => ({
9189
...workspace,
9290
skills: skillQueries[index].isPlaceholderData ? [] : (skillQueries[index].data ?? []),
93-
})),
94-
dashboardsEnabled ? [] : ['builtin-create-dashboard']
91+
}))
9592
)
9693
const editor = usePromptEditor({
9794
workspaceId: '',

‎apps/sim/lib/dashboards/README.md‎

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# Table-backed dashboards
22

3-
Each workspace has at most one dashboard, a separate resource with its own sidebar page, resource tab, and Mothership `dashboards get` / `dashboards set` commands. Sim builds it: the page shows an empty state until the first save, and there is no create, rename, move, or folder operation. A partial unique index (migration 0392) keeps one live dashboard per workspace; lifting the limit means dropping it. Storage reuses workspace files with MIME type `text/x-sim-dashboard`; the backing `.dashboard` suffix is hidden from display names. The built-in **create-dashboard** skill documents the syntax without example dashboards or prescribed layouts. Sharing is deferred.
3+
Each workspace has at most one dashboard, a separate resource with its own sidebar page, resource tab, and Mothership `dashboards get` / `dashboards set` commands. Sim builds it: the page shows an empty state until the first save, and there is no create, rename, move, or folder operation. Dashboards live in the `dashboard` table (migration 0392) with their own id; a unique index on `workspace_id` keeps one per workspace, and dropping it allows several. Saves compare the stored `revision`, so a concurrent edit is never overwritten. Mothership's **create-dashboard** skill documents the syntax. Sharing and fork copies are deferred.
44

55
The implementation has three boundaries:
66

7-
- `spec.ts` validates a bounded YAML document and normalizes ECharts options through the existing `.chart` safety rules. It rejects unknown layout/source keys and reports errors in the viewer and the file VFS `compiled-check` path.
7+
- `spec.ts` validates a bounded YAML document and normalizes ECharts options through the existing `.chart` safety rules. It rejects unknown layout/source keys; saves reject invalid YAML and the viewer reports panel errors.
88
- `table/analytics` computes exact aggregates over authorized table rows. The internal POST `/api/table/[tableId]/analytics` is a session-authenticated adapter for `tables.rows.analytics`, requiring the current viewer's workspace read role and `tables.use`. The operation is session-only because this release's sole query caller is the workspace renderer. Public/versioned query APIs, workflow/executor callers and log queries are deferred. Dashboard APIs and Mothership tools share the dashboard application operations.
99
- `components/dashboards` owns EMCN layout, controls and states. `components/charts/echarts-view.tsx` also renders existing `.chart` files, using the local EMCN tokens for its canvas theme. `.chart` retains its existing sampled source behavior; dashboard aggregation is performed on the server.
1010

@@ -45,7 +45,7 @@ Queries reuse the table predicate compiler and the existing read-only repeatable
4545

4646
Bounds: 128 KB source, 48 blocks, 4 layout levels, 2 grouping fields, 8 measures, 12 projected columns, 500 result rows and 8 KB per returned row. Limits apply after aggregation. An explicit limit yields a labeled top-N result; unrequested group overflow is an error. API rate admission is per viewer. Errors are never turned into successful zeros. Only visible tabs mount their query observers; identical queries share React Query cache entries for one minute, and Refresh requests fresh data.
4747

48-
Public file shares show a workspace-only message and issue no table requests. This release does not embed live dashboards in public HTML pages or export them as self-contained HTML. Row/query data is not persisted inside the dashboard file.
48+
Dashboards are workspace-only: there is no public sharing, embedding in public HTML pages, or self-contained export. Row/query data is never persisted with the dashboard.
4949

5050
## Validation
5151

@@ -67,21 +67,12 @@ global switch. Local development uses `DASHBOARDS=true` in the app's ignored
6767
environment file.
6868

6969
The server resolves the flag for the canonical workspace organization. It gates
70-
dashboard operations, table analytics, UI entry points, and the
71-
built-in authoring skill. Mothership receives that availability per turn and
72-
persists it for continuation; disabled runs omit dashboard commands and skills.
70+
dashboard operations, table analytics, and UI entry points. Mothership receives it per
71+
turn as the `dashboards` entitlement and persists it for continuation; runs without it
72+
omit the dashboard commands, the create-dashboard skill, and dashboard prompt text.
7373
The Sim server checks current availability on every dashboard operation, including
7474
calls from a run admitted before the flag changed.
7575

7676
Apply both repositories' additive migrations and deploy the companion worker
7777
before enabling the flag. Sharing and a tool for capturing the user's displayed
7878
data are deferred.
79-
80-
81-
## Storage
82-
83-
The workspace dashboard is a workspace file at the root with content type
84-
`text/x-sim-dashboard`. Files listings, file search, and workflow file pickers exclude that
85-
content type, and only the dashboard use case may write it, so the backing file never appears
86-
or changes as an ordinary file. Versions, billing, cleanup, and complete workspace copies
87-
still include it.

‎apps/sim/lib/dashboards/authoring.ts‎

Lines changed: 0 additions & 49 deletions
This file was deleted.

‎apps/sim/lib/skills/application/use-cases.test.ts‎

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
1414

1515
const { hoisted } = vi.hoisted(() => ({
1616
hoisted: {
17-
flag: vi.fn(),
1817
getById: vi.fn(),
1918
update: vi.fn(),
2019
},
2120
}))
2221

23-
vi.mock('@/lib/dashboards/feature-flag', () => ({ requireDashboardsEnabled: hoisted.flag }))
2422
vi.mock('@/lib/uploads/contexts/workspace', () => workspaceUploadsMock)
2523
vi.mock('@sim/platform-authz/workspace', () => workspaceAuthzMock)
2624
vi.mock('@sim/audit', () => auditMock)
@@ -63,24 +61,12 @@ const skill = {
6361

6462
describe('skill application use cases', () => {
6563
beforeEach(() => {
66-
mocks.flag.mockResolvedValue(undefined)
6764
mocks.loadContext.mockResolvedValue(workspace)
6865
mocks.resolvePermission.mockResolvedValue('read')
6966
mocks.getById.mockResolvedValue(skill)
7067
mocks.update.mockResolvedValue({ ...skill, content: '# Updated' })
7168
})
7269

73-
it('refuses the dashboard authoring skill when dashboards are disabled', async () => {
74-
mocks.getById.mockResolvedValue({ ...skill, id: 'builtin-create-dashboard' })
75-
mocks.flag.mockRejectedValue(new Error('Dashboards are not enabled'))
76-
await expect(
77-
getSkillUseCase.execute({
78-
principal: { kind: 'session', userId: 'reader' },
79-
input: { workspaceId: workspace.workspaceId, skillId: 'builtin-create-dashboard' },
80-
})
81-
).rejects.toThrow('Dashboards are not enabled')
82-
})
83-
8470
it.each(['skill-1', 'builtin-research'])(
8571
'reads %s with read permission in the asserted workspace',
8672
async (skillId) => {

‎apps/sim/lib/skills/application/use-cases.ts‎

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
ForbiddenOperationError,
1212
} from '@/lib/core/application'
1313
import { OrchestrationError } from '@/lib/core/orchestration/types'
14-
import { isDashboardsEnabled, requireDashboardsEnabled } from '@/lib/dashboards/feature-flag'
1514
import { getSkillActorContext, listSkillEditors, type SkillEditor } from '@/lib/skills/access'
1615
import { skillDelegationPolicy } from '@/lib/skills/application/authorization'
1716
import { skillOperations } from '@/lib/skills/application/operations'
@@ -212,9 +211,6 @@ export const listSkillsUseCase = defineAuthorizedWorkspaceUseCase({
212211
async execute({ input, context }) {
213212
const page = await listSkillSummariesPage({
214213
workspaceId: context.workspaceId,
215-
excludedBuiltinIds: (await isDashboardsEnabled(context.workspaceOrganizationId))
216-
? []
217-
: ['builtin-create-dashboard'],
218214
search: input.search,
219215
sortBy: input.sortBy,
220216
sortOrder: input.sortOrder,
@@ -243,9 +239,6 @@ export const listAvailableSkillsUseCase = defineAuthorizedWorkspaceUseCase({
243239
const skills = await listSkillsForUser({
244240
workspaceId: context.workspaceId,
245241
userId: requirePrincipalSubjectUserId(principal),
246-
excludedBuiltinIds: (await isDashboardsEnabled(context.workspaceOrganizationId))
247-
? []
248-
: ['builtin-create-dashboard'],
249242
})
250243
return { skills }
251244
},
@@ -261,11 +254,6 @@ export const getSkillUseCase = defineAuthorizedWorkspaceUseCase({
261254
resolveContext: ({ input }: { input: GetSkillInput }) =>
262255
resolveSkillContext(input.workspaceId, input.skillId),
263256
authorizationOptions,
264-
async authorizeResource({ context }) {
265-
if (context.skill.id === 'builtin-create-dashboard') {
266-
await requireDashboardsEnabled(context.workspaceOrganizationId)
267-
}
268-
},
269257
async execute({ context }) {
270258
return { skill: context.skill }
271259
},

‎apps/sim/lib/workflows/skills/builtin-skills.ts‎

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { DASHBOARD_AUTHORING_CONTENT } from '@/lib/dashboards/authoring'
2-
31
/**
42
* Built-in (template) skills that ship with every workspace.
53
*
@@ -192,13 +190,6 @@ You can attach an existing workflow to a table so it runs once for every row, wi
192190
`
193191

194192
export const BUILTIN_SKILLS: readonly BuiltinSkill[] = [
195-
{
196-
id: 'builtin-create-dashboard',
197-
name: 'create-dashboard',
198-
description:
199-
'Build a live table-backed dashboard with YAML, ECharts, time filters, rows, and tabs.',
200-
content: DASHBOARD_AUTHORING_CONTENT,
201-
},
202193
{
203194
id: 'builtin-connect-integration',
204195
name: 'connect-integration',

0 commit comments

Comments
 (0)