Skip to content

Commit ee79d32

Browse files
feat(tables): add PostHog events for table-workflow run/stop gestures
1 parent 919fa52 commit ee79d32

2 files changed

Lines changed: 80 additions & 9 deletions

File tree

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { useCallback, useMemo, useReducer, useRef, useState } from 'react'
44
import { createLogger } from '@sim/logger'
55
import { useParams, useRouter } from 'next/navigation'
6+
import { usePostHog } from 'posthog-js/react'
67
import {
78
Button,
89
Modal,
@@ -15,6 +16,7 @@ import {
1516
} from '@/components/emcn'
1617
import { Download, Pencil, Table as TableIcon, Trash, Upload } from '@/components/emcn/icons'
1718
import type { RunLimit, RunMode } from '@/lib/api/contracts/tables'
19+
import { captureEvent } from '@/lib/posthog/client'
1820
import type { ColumnDefinition, Filter, TableRow as TableRowType, WorkflowGroup } from '@/lib/table'
1921
import {
2022
type ColumnOption,
@@ -123,6 +125,10 @@ export function Table({
123125
const workspaceId = propWorkspaceId || (params.workspaceId as string)
124126
const tableId = propTableId || (params.tableId as string)
125127

128+
const posthog = usePostHog()
129+
const posthogRef = useRef(posthog)
130+
posthogRef.current = posthog
131+
126132
useTableEventStream({ tableId, workspaceId })
127133

128134
const [slideout, dispatch] = useReducer(slideoutReducer, { kind: 'none' })
@@ -225,24 +231,40 @@ export function Table({
225231
// gutter, action-bar Play/Refresh, right-click context menu) reduces to a
226232
// (groupIds, rowIds?, runMode) triple. Empty groupIds = no-op.
227233
const runScope = useCallback(
228-
(args: { groupIds: string[]; rowIds?: string[]; runMode: RunMode; limit?: RunLimit }) => {
229-
if (args.groupIds.length === 0) return
230-
if (args.rowIds && args.rowIds.length === 0) return
231-
runColumnMutate(args)
234+
(args: {
235+
groupIds: string[]
236+
rowIds?: string[]
237+
runMode: RunMode
238+
limit?: RunLimit
239+
source: 'row' | 'rows' | 'column'
240+
}) => {
241+
const { source, ...mutateArgs } = args
242+
if (mutateArgs.groupIds.length === 0) return
243+
if (mutateArgs.rowIds && mutateArgs.rowIds.length === 0) return
244+
runColumnMutate(mutateArgs)
245+
captureEvent(posthogRef.current, 'table_workflow_run', {
246+
table_id: tableId,
247+
workspace_id: workspaceId,
248+
source,
249+
run_mode: mutateArgs.runMode,
250+
group_count: mutateArgs.groupIds.length,
251+
row_count: mutateArgs.rowIds?.length ?? null,
252+
has_limit: mutateArgs.limit != null,
253+
})
232254
},
233-
[runColumnMutate]
255+
[runColumnMutate, tableId, workspaceId]
234256
)
235257

236258
const onRunColumn = useCallback(
237259
(groupId: string, runMode: RunMode, rowIds?: string[], limit?: RunLimit) => {
238-
runScope({ groupIds: [groupId], rowIds, runMode, limit })
260+
runScope({ groupIds: [groupId], rowIds, runMode, limit, source: 'column' })
239261
},
240262
[runScope]
241263
)
242264

243265
const onRunRows = useCallback(
244266
(rowIds: string[], runMode: RunMode) => {
245-
runScope({ groupIds: tableWorkflowGroups.map((g) => g.id), rowIds, runMode })
267+
runScope({ groupIds: tableWorkflowGroups.map((g) => g.id), rowIds, runMode, source: 'rows' })
246268
},
247269
[runScope, tableWorkflowGroups]
248270
)
@@ -253,6 +275,7 @@ export function Table({
253275
groupIds: tableWorkflowGroups.map((g) => g.id),
254276
rowIds: [rowId],
255277
runMode: 'incomplete',
278+
source: 'row',
256279
})
257280
},
258281
[runScope, tableWorkflowGroups]
@@ -263,21 +286,39 @@ export function Table({
263286
const onStopRow = useCallback(
264287
(rowId: string) => {
265288
cancelRunsMutate({ scope: 'row', rowId })
289+
captureEvent(posthogRef.current, 'table_workflow_stopped', {
290+
table_id: tableId,
291+
workspace_id: workspaceId,
292+
scope: 'row',
293+
row_count: 1,
294+
})
266295
},
267-
[cancelRunsMutate]
296+
[cancelRunsMutate, tableId, workspaceId]
268297
)
269298

270299
const onStopRows = (rowIds: string[]) => {
271300
if (rowIds.length === 0) return
272301
for (const rowId of rowIds) {
273302
cancelRunsMutate({ scope: 'row', rowId })
274303
}
304+
captureEvent(posthogRef.current, 'table_workflow_stopped', {
305+
table_id: tableId,
306+
workspace_id: workspaceId,
307+
scope: 'rows',
308+
row_count: rowIds.length,
309+
})
275310
}
276311

277312
// useCallback because <RunStatusControl> is memo-wrapped.
278313
const onStopAll = useCallback(() => {
279314
cancelRunsMutate({ scope: 'all' })
280-
}, [cancelRunsMutate])
315+
captureEvent(posthogRef.current, 'table_workflow_stopped', {
316+
table_id: tableId,
317+
workspace_id: workspaceId,
318+
scope: 'all',
319+
row_count: null,
320+
})
321+
}, [cancelRunsMutate, tableId, workspaceId])
281322

282323
const onSelectionChange = (next: SelectionSnapshot) => {
283324
setSelection(next)

apps/sim/lib/posthog/events.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,36 @@ export interface PostHogEventMap {
379379
workspace_id: string
380380
}
381381

382+
/**
383+
* A table-workflow run was dispatched from the grid.
384+
* `source` distinguishes the gesture: a single row's gutter Play (`row`),
385+
* a multi-row selection across every workflow column (`rows`), or a single
386+
* workflow column header / column-scoped selection (`column`).
387+
*/
388+
table_workflow_run: {
389+
table_id: string
390+
workspace_id: string
391+
source: 'row' | 'rows' | 'column'
392+
run_mode: 'all' | 'incomplete'
393+
group_count: number
394+
/** Number of explicitly targeted rows; `null` when the run targets all rows in scope. */
395+
row_count: number | null
396+
has_limit: boolean
397+
}
398+
399+
/**
400+
* Running table workflows were cancelled.
401+
* `scope` is `all` (every running row), `row` (one row's gutter Stop), or
402+
* `rows` (a multi-row selection).
403+
*/
404+
table_workflow_stopped: {
405+
table_id: string
406+
workspace_id: string
407+
scope: 'all' | 'row' | 'rows'
408+
/** Number of rows targeted; `null` for the `all` scope. */
409+
row_count: number | null
410+
}
411+
382412
custom_tool_saved: {
383413
tool_id: string
384414
workspace_id: string

0 commit comments

Comments
 (0)