mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(tables): add PostHog events for table-workflow run/stop gestures (#4839)
* feat(tables): add PostHog events for table-workflow run/stop gestures * fix(tables): pass run source from action-bar play/refresh dispatchers
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useCallback, useMemo, useReducer, useRef, useState } from 'react'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { useParams, useRouter } from 'next/navigation'
|
||||
import { usePostHog } from 'posthog-js/react'
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
} from '@/components/emcn'
|
||||
import { Download, Pencil, Table as TableIcon, Trash, Upload } from '@/components/emcn/icons'
|
||||
import type { RunLimit, RunMode } from '@/lib/api/contracts/tables'
|
||||
import { captureEvent } from '@/lib/posthog/client'
|
||||
import type { ColumnDefinition, Filter, TableRow as TableRowType, WorkflowGroup } from '@/lib/table'
|
||||
import {
|
||||
type ColumnOption,
|
||||
@@ -123,6 +125,10 @@ export function Table({
|
||||
const workspaceId = propWorkspaceId || (params.workspaceId as string)
|
||||
const tableId = propTableId || (params.tableId as string)
|
||||
|
||||
const posthog = usePostHog()
|
||||
const posthogRef = useRef(posthog)
|
||||
posthogRef.current = posthog
|
||||
|
||||
useTableEventStream({ tableId, workspaceId })
|
||||
|
||||
const [slideout, dispatch] = useReducer(slideoutReducer, { kind: 'none' })
|
||||
@@ -225,24 +231,40 @@ export function Table({
|
||||
// gutter, action-bar Play/Refresh, right-click context menu) reduces to a
|
||||
// (groupIds, rowIds?, runMode) triple. Empty groupIds = no-op.
|
||||
const runScope = useCallback(
|
||||
(args: { groupIds: string[]; rowIds?: string[]; runMode: RunMode; limit?: RunLimit }) => {
|
||||
if (args.groupIds.length === 0) return
|
||||
if (args.rowIds && args.rowIds.length === 0) return
|
||||
runColumnMutate(args)
|
||||
(args: {
|
||||
groupIds: string[]
|
||||
rowIds?: string[]
|
||||
runMode: RunMode
|
||||
limit?: RunLimit
|
||||
source: 'row' | 'rows' | 'column'
|
||||
}) => {
|
||||
const { source, ...mutateArgs } = args
|
||||
if (mutateArgs.groupIds.length === 0) return
|
||||
if (mutateArgs.rowIds && mutateArgs.rowIds.length === 0) return
|
||||
runColumnMutate(mutateArgs)
|
||||
captureEvent(posthogRef.current, 'table_workflow_run', {
|
||||
table_id: tableId,
|
||||
workspace_id: workspaceId,
|
||||
source,
|
||||
run_mode: mutateArgs.runMode,
|
||||
group_count: mutateArgs.groupIds.length,
|
||||
row_count: mutateArgs.rowIds?.length ?? null,
|
||||
has_limit: mutateArgs.limit != null,
|
||||
})
|
||||
},
|
||||
[runColumnMutate]
|
||||
[runColumnMutate, tableId, workspaceId]
|
||||
)
|
||||
|
||||
const onRunColumn = useCallback(
|
||||
(groupId: string, runMode: RunMode, rowIds?: string[], limit?: RunLimit) => {
|
||||
runScope({ groupIds: [groupId], rowIds, runMode, limit })
|
||||
runScope({ groupIds: [groupId], rowIds, runMode, limit, source: 'column' })
|
||||
},
|
||||
[runScope]
|
||||
)
|
||||
|
||||
const onRunRows = useCallback(
|
||||
(rowIds: string[], runMode: RunMode) => {
|
||||
runScope({ groupIds: tableWorkflowGroups.map((g) => g.id), rowIds, runMode })
|
||||
runScope({ groupIds: tableWorkflowGroups.map((g) => g.id), rowIds, runMode, source: 'rows' })
|
||||
},
|
||||
[runScope, tableWorkflowGroups]
|
||||
)
|
||||
@@ -253,6 +275,7 @@ export function Table({
|
||||
groupIds: tableWorkflowGroups.map((g) => g.id),
|
||||
rowIds: [rowId],
|
||||
runMode: 'incomplete',
|
||||
source: 'row',
|
||||
})
|
||||
},
|
||||
[runScope, tableWorkflowGroups]
|
||||
@@ -263,8 +286,14 @@ export function Table({
|
||||
const onStopRow = useCallback(
|
||||
(rowId: string) => {
|
||||
cancelRunsMutate({ scope: 'row', rowId })
|
||||
captureEvent(posthogRef.current, 'table_workflow_stopped', {
|
||||
table_id: tableId,
|
||||
workspace_id: workspaceId,
|
||||
scope: 'row',
|
||||
row_count: 1,
|
||||
})
|
||||
},
|
||||
[cancelRunsMutate]
|
||||
[cancelRunsMutate, tableId, workspaceId]
|
||||
)
|
||||
|
||||
const onStopRows = (rowIds: string[]) => {
|
||||
@@ -272,12 +301,24 @@ export function Table({
|
||||
for (const rowId of rowIds) {
|
||||
cancelRunsMutate({ scope: 'row', rowId })
|
||||
}
|
||||
captureEvent(posthogRef.current, 'table_workflow_stopped', {
|
||||
table_id: tableId,
|
||||
workspace_id: workspaceId,
|
||||
scope: 'rows',
|
||||
row_count: rowIds.length,
|
||||
})
|
||||
}
|
||||
|
||||
// useCallback because <RunStatusControl> is memo-wrapped.
|
||||
const onStopAll = useCallback(() => {
|
||||
cancelRunsMutate({ scope: 'all' })
|
||||
}, [cancelRunsMutate])
|
||||
captureEvent(posthogRef.current, 'table_workflow_stopped', {
|
||||
table_id: tableId,
|
||||
workspace_id: workspaceId,
|
||||
scope: 'all',
|
||||
row_count: null,
|
||||
})
|
||||
}, [cancelRunsMutate, tableId, workspaceId])
|
||||
|
||||
const onSelectionChange = (next: SelectionSnapshot) => {
|
||||
setSelection(next)
|
||||
@@ -547,6 +588,7 @@ export function Table({
|
||||
groupIds: scope.groupIds,
|
||||
rowIds: scope.allRows ? undefined : scope.rowIds,
|
||||
runMode: 'incomplete',
|
||||
source: 'rows',
|
||||
})
|
||||
}}
|
||||
onRefresh={() => {
|
||||
@@ -556,6 +598,7 @@ export function Table({
|
||||
groupIds: scope.groupIds,
|
||||
rowIds: scope.allRows ? undefined : scope.rowIds,
|
||||
runMode: 'all',
|
||||
source: 'rows',
|
||||
})
|
||||
}}
|
||||
onStopWorkflows={() => {
|
||||
|
||||
@@ -379,6 +379,36 @@ export interface PostHogEventMap {
|
||||
workspace_id: string
|
||||
}
|
||||
|
||||
/**
|
||||
* A table-workflow run was dispatched from the grid.
|
||||
* `source` distinguishes the gesture: a single row's gutter Play (`row`),
|
||||
* a multi-row selection across every workflow column (`rows`), or a single
|
||||
* workflow column header / column-scoped selection (`column`).
|
||||
*/
|
||||
table_workflow_run: {
|
||||
table_id: string
|
||||
workspace_id: string
|
||||
source: 'row' | 'rows' | 'column'
|
||||
run_mode: 'all' | 'incomplete'
|
||||
group_count: number
|
||||
/** Number of explicitly targeted rows; `null` when the run targets all rows in scope. */
|
||||
row_count: number | null
|
||||
has_limit: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Running table workflows were cancelled.
|
||||
* `scope` is `all` (every running row), `row` (one row's gutter Stop), or
|
||||
* `rows` (a multi-row selection).
|
||||
*/
|
||||
table_workflow_stopped: {
|
||||
table_id: string
|
||||
workspace_id: string
|
||||
scope: 'all' | 'row' | 'rows'
|
||||
/** Number of rows targeted; `null` for the `all` scope. */
|
||||
row_count: number | null
|
||||
}
|
||||
|
||||
custom_tool_saved: {
|
||||
tool_id: string
|
||||
workspace_id: string
|
||||
|
||||
Reference in New Issue
Block a user