mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-21 19:25:57 +00:00
Register column picker template governance
This commit is contained in:
@@ -2421,6 +2421,11 @@ Chart visibility display actions are registry-backed too.
|
||||
pressed-state, title, icon, and toolbar action styling for summary-bearing
|
||||
filter surfaces. Pages must compose that primitive instead of recreating local
|
||||
chart visibility buttons or one-option segmented controls.
|
||||
Column visibility controls are registry-backed too. `ColumnPicker` owns the
|
||||
column chooser trigger, panel title, reset action, empty-state copy, hidden
|
||||
count badge, dropdown width, and outside-click lifecycle through the shared
|
||||
shell/state/model split. Table surfaces must compose that primitive instead of
|
||||
recreating local column chooser buttons or panels.
|
||||
Grouped/list table-mode controls are registry-backed as well.
|
||||
`GroupedTableModeSegmentedControl` owns the shared `Group by` label,
|
||||
`Grouped` / `List` labels, tooltip titles, and icons for table mode switching.
|
||||
|
||||
@@ -255,6 +255,24 @@
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "column-picker-shell",
|
||||
"category": "column-picker",
|
||||
"summary": "Table column visibility controls must compose ColumnPicker instead of recreating column chooser trigger, panel, reset, or hidden-count chrome locally.",
|
||||
"canonical": {
|
||||
"path": "src/components/shared/ColumnPicker.tsx",
|
||||
"export": "ColumnPicker"
|
||||
},
|
||||
"requiredConsumers": [
|
||||
{ "path": "src/components/Workloads/WorkloadsFilter.tsx" },
|
||||
{ "path": "src/features/standalone/AgentsMachinesTable.tsx" }
|
||||
],
|
||||
"proof": [
|
||||
"src/components/shared/SharedPrimitives.guardrails.test.ts",
|
||||
"src/components/shared/ColumnPicker.test.tsx",
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "grouped-table-mode-segmented-control",
|
||||
"category": "table-mode-control",
|
||||
@@ -387,6 +405,25 @@
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "column-picker-local-column-chooser",
|
||||
"category": "column-picker",
|
||||
"summary": "Table surfaces must not copy the column chooser title and panel copy owned by ColumnPicker.",
|
||||
"canonical": {
|
||||
"path": "src/components/shared/ColumnPicker.tsx",
|
||||
"export": "ColumnPicker"
|
||||
},
|
||||
"scopes": ["src/components", "src/features", "src/pages"],
|
||||
"extensions": [".tsx"],
|
||||
"allPatterns": ["Choose which columns to display", "Show Columns"],
|
||||
"legacyReason": "Retired migration debt. Table column visibility controls must use ColumnPicker; local column chooser copies are not allowed.",
|
||||
"allowedPaths": [],
|
||||
"ignoredPaths": ["src/components/shared/ColumnPicker.test.tsx"],
|
||||
"proof": [
|
||||
"src/components/shared/SharedPrimitives.guardrails.test.ts",
|
||||
"scripts/shared-template-audit.mjs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "grouped-table-mode-local-segmented-control",
|
||||
"category": "table-mode-control",
|
||||
|
||||
@@ -778,8 +778,48 @@ describe('shared primitive guardrails', () => {
|
||||
});
|
||||
|
||||
it('keeps column picker on shell, runtime, and model owners', () => {
|
||||
const registry = JSON.parse(sharedTemplateRegistrySource) as {
|
||||
rules?: Array<{
|
||||
id: string;
|
||||
canonical?: { path?: string; export?: string };
|
||||
requiredConsumers?: Array<{ path?: string }>;
|
||||
}>;
|
||||
patternGuards?: Array<{
|
||||
id: string;
|
||||
canonical?: { path?: string; export?: string };
|
||||
allPatterns?: string[];
|
||||
scopes?: string[];
|
||||
allowedPaths?: string[];
|
||||
ignoredPaths?: string[];
|
||||
}>;
|
||||
};
|
||||
const registeredRule = registry.rules?.find((rule) => rule.id === 'column-picker-shell');
|
||||
const registeredGuard = registry.patternGuards?.find(
|
||||
(guard) => guard.id === 'column-picker-local-column-chooser',
|
||||
);
|
||||
|
||||
expect(registeredRule?.canonical?.path).toBe('src/components/shared/ColumnPicker.tsx');
|
||||
expect(registeredRule?.canonical?.export).toBe('ColumnPicker');
|
||||
expect(registeredRule?.requiredConsumers?.map((consumer) => consumer.path)).toEqual([
|
||||
'src/components/Workloads/WorkloadsFilter.tsx',
|
||||
'src/features/standalone/AgentsMachinesTable.tsx',
|
||||
]);
|
||||
expect(registeredGuard?.canonical?.path).toBe('src/components/shared/ColumnPicker.tsx');
|
||||
expect(registeredGuard?.canonical?.export).toBe('ColumnPicker');
|
||||
expect(registeredGuard?.allPatterns).toEqual([
|
||||
'Choose which columns to display',
|
||||
'Show Columns',
|
||||
]);
|
||||
expect(registeredGuard?.allowedPaths ?? []).toHaveLength(0);
|
||||
expect(registeredGuard?.ignoredPaths).toEqual(['src/components/shared/ColumnPicker.test.tsx']);
|
||||
expect(registeredGuard?.scopes).toEqual(
|
||||
expect.arrayContaining(['src/components', 'src/features', 'src/pages']),
|
||||
);
|
||||
|
||||
expect(columnPickerSource).toContain('useColumnPickerState');
|
||||
expect(columnPickerSource).toContain('COLUMN_PICKER_PANEL_TITLE');
|
||||
expect(columnPickerSource).toContain('COLUMN_PICKER_BUTTON_TITLE');
|
||||
expect(columnPickerSource).toContain('filterUtilityBadgeClass');
|
||||
expect(columnPickerSource).not.toContain('createSignal');
|
||||
expect(columnPickerSource).not.toContain('createEffect');
|
||||
expect(columnPickerSource).not.toContain('document.addEventListener');
|
||||
@@ -793,10 +833,19 @@ describe('shared primitive guardrails', () => {
|
||||
expect(columnPickerStateSource).toContain('hiddenCount');
|
||||
|
||||
expect(columnPickerModelSource).toContain('COLUMN_PICKER_BUTTON_LABEL');
|
||||
expect(columnPickerModelSource).toContain('COLUMN_PICKER_BUTTON_TITLE');
|
||||
expect(columnPickerModelSource).toContain('COLUMN_PICKER_PANEL_TITLE');
|
||||
expect(columnPickerModelSource).toContain('COLUMN_PICKER_RESET_LABEL');
|
||||
expect(columnPickerModelSource).toContain('COLUMN_PICKER_EMPTY_LABEL');
|
||||
expect(columnPickerModelSource).toContain('getHiddenColumnCount');
|
||||
expect(columnPickerModelSource).toContain('shouldShowColumnPickerReset');
|
||||
expect(columnPickerModelSource).toContain('getColumnPickerOptionTextClass');
|
||||
|
||||
for (const source of [workloadsFilterSource, agentsMachinesTableSource]) {
|
||||
expect(source).toContain('ColumnPicker');
|
||||
expect(source).not.toContain('Choose which columns to display');
|
||||
expect(source).not.toContain('Show Columns');
|
||||
}
|
||||
});
|
||||
|
||||
it('keeps tag input on shell, runtime, and model owners', () => {
|
||||
|
||||
Reference in New Issue
Block a user