Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions table/schemas/table.cue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ spec: close({
defaultColumnHidden?: bool
pagination?: bool
enableFiltering?: bool
enableSorting?: bool
columnSettings?: [...#columnSettings]
cellSettings?: [...#cellSettings]
transforms?: [...common.#transform]
Expand Down
8 changes: 8 additions & 0 deletions table/schemas/tests/valid/table-enable-sorting.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"kind": "Table",
"spec": {
"density": "standard",
"enableSorting": true,
"enableFiltering": true
}
}
7 changes: 7 additions & 0 deletions table/sdk/go/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ func WithEnableFiltering(enabled bool) Option {
}
}

func WithEnableSorting(enabled bool) Option {
return func(builder *Builder) error {
builder.EnableSorting = enabled
return nil
}
}

func WithColumnSettings(settings []ColumnSettings) Option {
return func(builder *Builder) error {
builder.ColumnSettings = settings
Expand Down
1 change: 1 addition & 0 deletions table/sdk/go/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ type PluginSpec struct {
DefaultColumnHidden bool `json:"defaultColumnHidden,omitempty" yaml:"defaultColumnHidden,omitempty"`
Pagination bool `json:"pagination,omitempty" yaml:"pagination,omitempty"`
EnableFiltering bool `json:"enableFiltering,omitempty" yaml:"enableFiltering,omitempty"`
EnableSorting bool `json:"enableSorting,omitempty" yaml:"enableSorting,omitempty"`
ColumnSettings []ColumnSettings `json:"columnSettings,omitempty" yaml:"columnSettings,omitempty"`
CellSettings []CellSettings `json:"cellSettings,omitempty" yaml:"cellSettings,omitempty"`
Transforms []common.Transform `json:"transforms,omitempty" yaml:"transforms,omitempty"`
Expand Down
33 changes: 25 additions & 8 deletions table/src/components/ColumnsEditor/ColumnEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,30 @@ type OmittedMuiProps = 'children' | 'value' | 'onChange';
export interface ColumnEditorProps extends Omit<StackProps, OmittedMuiProps> {
column: ColumnSettings;
onChange: (column: ColumnSettings) => void;
defaultEnableSorting?: boolean;
}

export function ColumnEditor({ column, onChange, ...others }: ColumnEditorProps): ReactElement {
export function ColumnEditor({
column,
onChange,
defaultEnableSorting = false,
...others
}: ColumnEditorProps): ReactElement {
const [width, setWidth] = useState<number>(
column.width === undefined || column.width === 'auto' ? 100 : column.width
);

const enableSorting = column.enableSorting ?? defaultEnableSorting;

function handleEnableSortingChange(checked: boolean): void {
if (checked === defaultEnableSorting) {
const { enableSorting: _ignored, ...rest } = column;
onChange(rest);
return;
}
onChange({ ...column, enableSorting: checked });
}

return (
<Stack {...others}>
<OptionsEditorGrid>
Expand Down Expand Up @@ -95,14 +112,14 @@ export function ColumnEditor({ column, onChange, ...others }: ColumnEditorProps)
/>
<OptionsEditorControl
label="Enable sorting"
control={
<Switch
checked={column.enableSorting ?? false}
onChange={(e) => onChange({ ...column, enableSorting: e.target.checked })}
/>
}
control={<Switch checked={enableSorting} onChange={(e) => handleEnableSortingChange(e.target.checked)} />}
/>
{column.enableSorting && (
{column.enableSorting === undefined && (
<Typography variant="caption" color="text.secondary">
Inherits from General Settings
</Typography>
)}
{enableSorting && (
<OptionsEditorControl
label="Default Sort"
control={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export function ColumnEditorContainer({
onDelete,
onMoveUp,
onMoveDown,
defaultEnableSorting,
}: ColumnEditorContainerProps): ReactElement {
function handleHideColumn(): void {
onChange({ ...column, hide: !column.hide });
Expand Down Expand Up @@ -104,7 +105,7 @@ export function ColumnEditorContainer({
{/* When a <Grid> is inside a <Stack> with gap, the negative margin of the grid is not applied. Therefore, let's wrap it in a div. */}
{!isCollapsed && (
<div>
<ColumnEditor column={column} onChange={onChange} />
<ColumnEditor column={column} onChange={onChange} defaultEnableSorting={defaultEnableSorting} />
</div>
)}
</DragAndDropElement>
Expand Down
4 changes: 3 additions & 1 deletion table/src/components/ColumnsEditor/ColumnsEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ import { ColumnEditorContainer } from './ColumnEditorContainer';
export interface ColumnsEditorProps {
columnSettings: ColumnSettings[];
onChange: (columnOptions: ColumnSettings[]) => void;
defaultEnableSorting?: boolean;
}

export function ColumnsEditor({ columnSettings, onChange }: ColumnsEditorProps): ReactElement {
export function ColumnsEditor({ columnSettings, onChange, defaultEnableSorting }: ColumnsEditorProps): ReactElement {
const [columnsCollapsed, setColumnsCollapsed] = useState(columnSettings.map(() => true));

function handleColumnChange(index: number, column: ColumnSettings): void {
Expand Down Expand Up @@ -73,6 +74,7 @@ export function ColumnsEditor({ columnSettings, onChange }: ColumnsEditorProps):
key={i}
column={column}
isCollapsed={columnsCollapsed[i] ?? true}
defaultEnableSorting={defaultEnableSorting}
onChange={(updatedColumn: ColumnSettings) => handleColumnChange(i, updatedColumn)}
onDelete={() => handleColumnDelete(i)}
onCollapse={(collapsed) => handleColumnCollapseExpand(i, collapsed)}
Expand Down
8 changes: 7 additions & 1 deletion table/src/components/TableColumnsEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,11 @@ export function TableColumnsEditor({ onChange, value }: TableColumnsEditorProps)
onChange({ ...value, columnSettings: columns });
}

return <ColumnsEditor columnSettings={value.columnSettings ?? []} onChange={handleColumnsChange} />;
return (
<ColumnsEditor
columnSettings={value.columnSettings ?? []}
onChange={handleColumnsChange}
defaultEnableSorting={value.enableSorting}
/>
);
}
21 changes: 21 additions & 0 deletions table/src/components/TablePanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,27 @@ describe('TablePanel', () => {
TEST_TIMEOUT
);

it(
'should enable sorting on all columns when enableSorting is set in general settings',
async () => {
renderPanel(MOCK_TIME_SERIES_DATA_SINGLEVALUE, {
enableSorting: true,
// column settings without an explicit enableSorting inherit the general default
columnSettings: [
{ name: 'value', header: 'Value' },
{ name: 'env', enableSorting: false },
],
});

const valueHeaderCell = await screen.findByRole('columnheader', { name: /Value/i });
expect(await within(valueHeaderCell).findByTestId('ArrowDownwardIcon')).toBeInTheDocument();

const envHeaderCell = await screen.findByRole('columnheader', { name: 'env' });
expect(within(envHeaderCell).queryByTestId('ArrowDownwardIcon')).not.toBeInTheDocument();
},
TEST_TIMEOUT
);

it('should apply transforms', async () => {
renderPanel(MOCK_TIME_SERIES_DATA_SINGLEVALUE, {
transforms: [
Expand Down
22 changes: 17 additions & 5 deletions table/src/components/TablePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ function generateColumnConfig(
columnSettings: ColumnSettings[],
allVariables: VariableStateMap,
gaugeRangeByColumn: Record<string, GaugeRange>,
globalCellSettings: CellSettings[] = []
globalCellSettings: CellSettings[] = [],
defaultEnableSorting = false
): TableColumnConfig<unknown> | undefined {
for (const column of columnSettings) {
if (column.name === name) {
Expand All @@ -360,7 +361,7 @@ function generateColumnConfig(
accessorKey: name,
header: header ?? name,
headerDescription,
enableSorting,
enableSorting: enableSorting ?? defaultEnableSorting,
width,
align,
dataLink: modifiedDataLink,
Expand All @@ -372,6 +373,7 @@ function generateColumnConfig(
return {
accessorKey: name,
header: name,
enableSorting: defaultEnableSorting,
};
}

Expand Down Expand Up @@ -544,7 +546,8 @@ export function TablePanel({ contentDimensions, spec, queryResults }: TableProps
spec.columnSettings ?? [],
allVariables,
gaugeRangeByColumn,
spec.cellSettings ?? []
spec.cellSettings ?? [],
spec.enableSorting ?? false
);
if (columnConfig !== undefined) {
columns.push(columnConfig);
Expand All @@ -561,7 +564,8 @@ export function TablePanel({ contentDimensions, spec, queryResults }: TableProps
spec.columnSettings ?? [],
allVariables,
gaugeRangeByColumn,
spec.cellSettings ?? []
spec.cellSettings ?? [],
spec.enableSorting ?? false
);
if (columnConfig !== undefined) {
columns.push(columnConfig);
Expand All @@ -571,7 +575,15 @@ export function TablePanel({ contentDimensions, spec, queryResults }: TableProps
}

return columns;
}, [keys, spec.columnSettings, spec.defaultColumnHidden, allVariables, gaugeRangeByColumn, spec.cellSettings]);
}, [
keys,
spec.columnSettings,
spec.defaultColumnHidden,
spec.enableSorting,
allVariables,
gaugeRangeByColumn,
spec.cellSettings,
]);

// Filtering state — declared before cellConfigs so filteredData is available for cell config evaluation
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
Expand Down
12 changes: 12 additions & 0 deletions table/src/components/TableSettingsEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ export function TableSettingsEditor({ onChange, value }: TableSettingsEditorProp
onChange({ ...value, enableFiltering: checked });
}

function handleEnableSortingChange(_event: ChangeEvent, checked: boolean): void {
onChange({
...value,
enableSorting: checked,
columnSettings: value.columnSettings?.map(({ enableSorting: _ignored, ...column }) => column),
});
}

return (
<OptionsEditorGrid>
<OptionsEditorColumn>
Expand All @@ -110,6 +118,10 @@ export function TableSettingsEditor({ onChange, value }: TableSettingsEditorProp
label="Enable Column Filtering"
control={<Switch checked={!!value.enableFiltering} onChange={handleEnableFilteringChange} />}
/>
<OptionsEditorControl
label="Enable Sorting"
control={<Switch checked={!!value.enableSorting} onChange={handleEnableSortingChange} />}
/>

<DefaultColumnsDimensionsControl
label="Width"
Expand Down
3 changes: 3 additions & 0 deletions table/src/models/table-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export interface ColumnSettings {
align?: 'left' | 'center' | 'right';

// When `true`, the column will be sortable.
// When unset, inherits TableOptions.enableSorting from General Settings.
enableSorting?: boolean;

// Default sort order for the column.
Expand Down Expand Up @@ -138,6 +139,8 @@ export interface TableOptions {
pagination?: boolean;
// Enable filtering for individual columns.
enableFiltering?: boolean;
// When true, columns are sortable by default unless overridden in columnSettings.
enableSorting?: boolean;
// Enable row selection.
selection?: SelectionOptions;
// Customize actions available for selected rows.
Expand Down
Loading