Skip to content

feat(F0AnalyticsDashboard): item-level filters#3715

Draft
siguenzaraul wants to merge 1 commit intomainfrom
feat/item-level-filters
Draft

feat(F0AnalyticsDashboard): item-level filters#3715
siguenzaraul wants to merge 1 commit intomainfrom
feat/item-level-filters

Conversation

@siguenzaraul
Copy link
Copy Markdown
Contributor

Summary

  • Add itemFilters support to dashboard items (charts, metrics, collections)
  • Collections render item filters as native filter bars within the table
  • Charts/metrics render them as inline controls in the card header
  • Item filters are independent of dashboard-level filters — they only affect their own item
  • Add showVisualMap option to heatmap charts
  • Refactor useDisplayDashboardAction for item filter state management
  • Add Storybook stories for item-level filters

Test plan

  • Verify Storybook WithItemFilters story renders correctly
  • Verify item filters on collections show native filter bar
  • Verify item filters on charts show inline controls
  • Verify item filters don't affect other dashboard items
  • Verify dashboard-level filters still work independently
  • pnpm build passes
  • pnpm test passes

Allow individual dashboard items (charts, metrics, collections) to declare
their own filters via `itemFilters`, independent of dashboard-level filters.
Collections render them as native filter bars; charts/metrics as inline
controls in the card header.

Also includes: heatmap showVisualMap option, useDisplayDashboardAction
refactor for item filter state management, and stories for the new feature.
Copilot AI review requested due to automatic review settings March 20, 2026 12:16
@github-actions github-actions bot added feat react Changes affect packages/react labels Mar 20, 2026
@github-actions
Copy link
Copy Markdown
Contributor

✅ No New Circular Dependencies

No new circular dependencies detected. Current count: 0

@github-actions
Copy link
Copy Markdown
Contributor

📦 Alpha Package Version Published

Use pnpm i github:factorialco/f0#npm/alpha-pr-3715 to install the package

Use pnpm i github:factorialco/f0#918af80f36079eec76263da90f502f855dc43fd5 to install this specific commit

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Visual review for your branch is published 🔍

Here are the links to:

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds item-level filter support to F0AnalyticsDashboard items (metrics, charts, collections) so each item can manage its own filter state independently of dashboard-level filters, and updates Storybook examples accordingly. It also refactors some Chat Dashboard types/mapping to reuse F0AnalyticsDashboard types.

Changes:

  • Extend DashboardItemBase with itemFilters / defaultItemFilters and wire item-level filtering into ChartItem, MetricItem, and CollectionItem.
  • Add dashboard card header support for rendering item filter controls/chips and provide Storybook stories + mock data demonstrating the feature.
  • Refactor chat-dashboard types to reuse MetricFormat / DashboardItemBase, and simplify chart-config mapping.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/react/src/sds/ai/F0ChatDashboard/types.ts Reuses F0AnalyticsDashboard types in chat dashboard payload types.
packages/react/src/sds/ai/F0ChatDashboard/stories/F0ChatDashboard.stories.tsx Updates chat dashboard heatmap story config.
packages/react/src/sds/ai/F0ChatDashboard/F0ChatDashboard.tsx Simplifies chat chart-config → dashboard chart-config mapping.
packages/react/src/sds/ai/F0AiChat/copilotActions/useDisplayDashboardAction.tsx Updates Copilot action parameter schema for dashboard items.
packages/react/src/components/F0DataChart/types.ts Updates heatmap prop typing (incl. heatmap legend-related fields).
packages/react/src/components/F0DataChart/components/HeatmapChart/useHeatmapChartOptions.ts Adjusts heatmap ECharts option generation (visualMap/grid behavior).
packages/react/src/components/F0DataChart/stories/Heatmap.stories.tsx Updates heatmap stories to match updated heatmap props.
packages/react/src/components/F0AnalyticsDashboard/types.ts Adds itemFilters / defaultItemFilters to item base types.
packages/react/src/components/F0AnalyticsDashboard/components/MetricItem/MetricItem.tsx Adds item-level filter UI + local filter state for metrics.
packages/react/src/components/F0AnalyticsDashboard/components/DashboardItem/DashboardItem.tsx Adds header/chips slots for item-level filter rendering.
packages/react/src/components/F0AnalyticsDashboard/components/CollectionItem/CollectionItem.tsx Injects item-level filters into OneDataCollection source definition.
packages/react/src/components/F0AnalyticsDashboard/components/ChartItem/ChartItem.tsx Adds item-level filter UI + local filter state for charts.
packages/react/src/components/F0AnalyticsDashboard/stories/mockDataMixed.ts Adds mock item filters + fetch functions demonstrating item-level filtering.
packages/react/src/components/F0AnalyticsDashboard/stories/index.stories.tsx Adds WithItemFilters Storybook story showcasing the feature.

Comment on lines 114 to 124
export interface HeatmapChartConfig {
type: "heatmap"
/** Minimum value for the color scale */
min?: number
/** Maximum value for the color scale */
max?: number
/** Show value labels on each cell. @default false */
showLabels?: boolean
/** Show the visual map legend. @default false */
showVisualMap?: boolean
/** Format the value displayed in cells and tooltip */
valueFormatter?: (value: number) => string
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HeatmapChartConfig no longer exposes showVisualMap, which is a breaking API change and also conflicts with the PR description (“Add showVisualMap option to heatmap charts”). If the intent is to support toggling the legend, re-add showVisualMap?: boolean here (and plumb it through to F0DataChart). If the intent is to always hide it, the PR description (and any docs) should be updated and the removal should be called out explicitly as a breaking change.

Copilot uses AI. Check for mistakes.
Comment on lines 80 to 100
visualMap: {
min,
max,
calculable: false,
orient: "horizontal",
bottom: 0,
left: "center",
show: showVisualMap,
show: false,
inRange: {
color: [colors.borderSecondary, baseColor],
},
textStyle: {
color: colors.foregroundTertiary,
fontSize: theme.textStyle.fontSize,
},
formatter: valueFormatter
? (value: unknown) => valueFormatter(Number(value))
: undefined,
},
grid: buildGrid({ showLegend: showVisualMap }),
grid: buildGrid({ showLegend: false }),
series: [
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heatmap visual map is now hard-coded to show: false (and buildGrid({ showLegend: false })), so the legend/color scale can never be shown. This contradicts the PR description (adds showVisualMap option) and also makes any existing showVisualMap usage impossible. Either reintroduce a showVisualMap prop and use it here, or remove the dead visualMap config entirely and update docs/PR description accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines 81 to 87
export interface ChatDashboardHeatmapChartConfig {
type: "heatmap"
min?: number
max?: number
showLabels?: boolean
showVisualMap?: boolean
valueFormat?: FormatPreset
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ChatDashboardHeatmapChartConfig also dropped showVisualMap, which makes the chat-dashboard payload unable to request a visual map legend and conflicts with the PR description. If heatmaps should support toggling the legend, add showVisualMap?: boolean back and ensure the mapper (toDashboardChartConfig / heatmap options) respects it.

Copilot uses AI. Check for mistakes.
Comment on lines 183 to 193
const enabled = item.useDashboardFilters !== false
const mergedFilters = {
...(enabled ? filters : {}),
...localItemFilters,
} as FiltersState<Filters>

const { data, isLoading, error, retry } = useDashboardItemData<
Filters,
DashboardChartData
>(item.fetchData, filters, enabled)
>(item.fetchData, mergedFilters, true)

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mergedFilters includes item-level filter keys, but DashboardChartItem<Filters>.fetchData is still typed as receiving only FiltersState<Filters> (dashboard filters). The forced cast (as FiltersState<Filters>) hides this mismatch and can mislead consumers about what fetchData actually receives. Consider extending the item types with a second generic for ItemFilters (derived from itemFilters) and type fetchData as FiltersState<Filters & ItemFilters>, so callers can handle both sets without casts.

Copilot uses AI. Check for mistakes.
Comment on lines +89 to 103
const [localItemFilters, setLocalItemFilters] = useState<
FiltersState<FiltersDefinition>
>(() => item.defaultItemFilters ?? {})

const enabled = item.useDashboardFilters !== false
const mergedFilters = {
...(enabled ? filters : {}),
...localItemFilters,
} as FiltersState<Filters>

const { data, isLoading, error, retry } = useDashboardItemData<
Filters,
DashboardMetricData
>(item.fetchData, filters, enabled)
>(item.fetchData, mergedFilters, true)

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same typing issue as in ChartItem: item-level filters are merged into the object passed to fetchData, but the public type for DashboardMetricItem<Filters>.fetchData still says it only receives dashboard filters. The as FiltersState<Filters> cast papers over the mismatch. Updating the item types to model an ItemFilters generic (and typing fetchData to receive the merged state) would remove the need for casts and make the new feature safer to consume.

Copilot uses AI. Check for mistakes.
type: "object[]",
description: "Collection column definitions (id, label, width)",
required: false,
},
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The displayDashboard Copilot action parameter schema doesn’t expose the newly added item-level filter fields (itemFilters, defaultItemFilters). That means an agent can’t generate dashboards that use this new capability even though DashboardItemBase supports it. Add these fields to the items.attributes schema (and document their intended shape) so the tool contract matches the feature.

Suggested change
},
},
{
name: "itemFilters",
type: "object",
description:
"Item-level filter selections keyed by filter ID. Each key is a filter ID and each value is typically an array of filter value descriptors applied only to this item.",
required: false,
},
{
name: "defaultItemFilters",
type: "object",
description:
"Default item-level filter selections keyed by filter ID, used when no explicit itemFilters are provided for the item.",
required: false,
},

Copilot uses AI. Check for mistakes.
Comment on lines 75 to 88
function toDashboardChartConfig(
chatChart: ChatDashboardChartConfig
): DashboardChartConfig {
const valueFormatter = buildFormatter(
"valueFormat" in chatChart ? chatChart.valueFormat : undefined
)

switch (chatChart.type) {
case "bar": {
const { valueFormat: _, ...rest } = chatChart
return { ...rest, ...(valueFormatter ? { valueFormatter } : {}) }
}
case "line": {
const { valueFormat: _, ...rest } = chatChart
return { ...rest, ...(valueFormatter ? { valueFormatter } : {}) }
}
case "funnel": {
const { valueFormat: _, ...rest } = chatChart
return { ...rest, ...(valueFormatter ? { valueFormatter } : {}) }
}
case "radar": {
const { valueFormat: _, ...rest } = chatChart
return { ...rest, ...(valueFormatter ? { valueFormatter } : {}) }
}
case "pie": {
const { valueFormat: _, ...rest } = chatChart
return { ...rest, ...(valueFormatter ? { valueFormatter } : {}) }
}
case "gauge": {
const { valueFormat: _, ...rest } = chatChart
return { ...rest, ...(valueFormatter ? { valueFormatter } : {}) }
}
case "heatmap": {
const { valueFormat: _, ...rest } = chatChart
return { ...rest, ...(valueFormatter ? { valueFormatter } : {}) }
}
const { valueFormat: _, ...rest } = chatChart as ChatDashboardChartConfig & {
valueFormat?: FormatPreset
}
return {
...rest,
...(valueFormatter ? { valueFormatter } : {}),
} as DashboardChartConfig
}
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toDashboardChartConfig now relies on as ... casts when stripping valueFormat and returning DashboardChartConfig. This reduces type-safety (it can hide accidental shape drift between chat chart configs and dashboard chart configs). Prefer returning a properly typed object without assertions (e.g., by destructuring valueFormat with a type guard per chart type or by using a helper that omits valueFormat in a type-safe way).

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat react Changes affect packages/react

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants