Skip to content

Commit

Permalink
feat(ui/tables): save column filter state
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaim Lev-Ari committed May 5, 2024
1 parent ec4bf86 commit f9ad801
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export function withColumnFilters<D extends DefaultType>(
onColumnFiltersChange: (updater) => {
onChange(applySetStateAction(updater, filters));
},
initialState: {
...options.initialState,
columnFilters: filters,
},
};
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
} from '@@/datatables/ColumnVisibilityMenu';
import { TableSettingsProvider } from '@@/datatables/useTableSettings';
import { useTableState } from '@@/datatables/useTableState';
import { mergeOptions } from '@@/datatables/extend-options/mergeOptions';
import { withColumnFilters } from '@@/datatables/extend-options/withColumnFilters';

import { useContainers } from '../../queries/containers';

Expand Down Expand Up @@ -92,6 +94,12 @@ export function ContainersDatatable({
)}
dataset={containersQuery.data || []}
emptyContentLabel="No containers found"
extendTableOptions={mergeOptions(
withColumnFilters(
tableState.columnFilters,
tableState.setColumnFilters
)
)}
/>
</TableSettingsProvider>
</RowProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
refreshableSettings,
hiddenColumnsSettings,
createPersistedStore,
filteredColumnsSettings,
} from '@@/datatables/types';

import { QuickAction, TableSettings } from './types';
Expand All @@ -12,6 +13,7 @@ export function createStore(storageKey: string) {
return createPersistedStore<TableSettings>(storageKey, 'name', (set) => ({
...hiddenColumnsSettings(set),
...refreshableSettings(set),
...filteredColumnsSettings(set),
truncateContainerName: TRUNCATE_LENGTH,
setTruncateContainerName(truncateContainerName: number) {
set({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
BasicTableSettings,
FilteredColumnsTableSettings,
RefreshableTableSettings,
SettableColumnsTableSettings,
} from '@@/datatables/types';
Expand All @@ -15,7 +16,8 @@ export interface TableSettings
extends BasicTableSettings,
SettableColumnsTableSettings,
SettableQuickActionsTableSettings<QuickAction>,
RefreshableTableSettings {
RefreshableTableSettings,
FilteredColumnsTableSettings {
truncateContainerName: number;
setTruncateContainerName: (value: number) => void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { Datatable, TableSettingsMenu } from '@@/datatables';
import {
BasicTableSettings,
createPersistedStore,
FilteredColumnsTableSettings,
filteredColumnsSettings,
refreshableSettings,
RefreshableTableSettings,
} from '@@/datatables/types';
Expand All @@ -18,6 +20,8 @@ import { AddButton, Button, ButtonGroup, LoadingButton } from '@@/buttons';
import { Link } from '@@/Link';
import { ButtonWithRef } from '@@/buttons/Button';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import { mergeOptions } from '@@/datatables/extend-options/mergeOptions';
import { withColumnFilters } from '@@/datatables/extend-options/withColumnFilters';

import { ImagesListResponse, useImages } from '../../queries/useImages';

Expand All @@ -28,13 +32,15 @@ const tableKey = 'images';

export interface TableSettings
extends BasicTableSettings,
RefreshableTableSettings {}
RefreshableTableSettings,
FilteredColumnsTableSettings {}

const settingsStore = createPersistedStore<TableSettings>(
tableKey,
'tags',
(set) => ({
...refreshableSettings(set),
...filteredColumnsSettings(set),
})
);

Expand Down Expand Up @@ -65,6 +71,9 @@ export function ImagesDatatable({
title="Images"
titleIcon={List}
data-cy="docker-images-datatable"
extendTableOptions={mergeOptions(
withColumnFilters(tableState.columnFilters, tableState.setColumnFilters)
)}
renderTableActions={(selectedItems) => (
<div className="flex items-center gap-2">
<RemoveButtonMenu selectedItems={selectedItems} onRemove={onRemove} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { List } from 'lucide-react';

import { Datatable } from '@@/datatables';
import { createPersistedStore } from '@@/datatables/types';
import { useTableState } from '@@/datatables/useTableState';
import {
BasicTableSettings,
type FilteredColumnsTableSettings,
filteredColumnsSettings,
} from '@@/datatables/types';
import { useTableStateWithStorage } from '@@/datatables/useTableState';
import { withMeta } from '@@/datatables/extend-options/withMeta';
import { mergeOptions } from '@@/datatables/extend-options/mergeOptions';
import { withColumnFilters } from '@@/datatables/extend-options/withColumnFilters';

import { useColumns } from './columns';
import { DecoratedTask } from './types';

const storageKey = 'docker-service-tasks';
const store = createPersistedStore(storageKey);

interface TableSettings
extends BasicTableSettings,
FilteredColumnsTableSettings {}

export function TasksDatatable({
dataset,
Expand All @@ -20,7 +29,13 @@ export function TasksDatatable({
isSlotColumnVisible: boolean;
serviceName: string;
}) {
const tableState = useTableState(store, storageKey);
const tableState = useTableStateWithStorage<TableSettings>(
storageKey,
undefined,
(set) => ({
...filteredColumnsSettings(set),
})
);
const columns = useColumns(isSlotColumnVisible);

return (
Expand All @@ -31,7 +46,11 @@ export function TasksDatatable({
columns={columns}
dataset={dataset}
emptyContentLabel="No task available."
extendTableOptions={withMeta({ table: 'tasks', serviceName })}
extendTableOptions={mergeOptions(
withMeta({ table: 'tasks', serviceName }),
withColumnFilters(tableState.columnFilters, tableState.setColumnFilters)
)}
disableSelect
data-cy="docker-service-tasks-datatable"
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export function StacksDatatable({
columnVisibility: Object.fromEntries(
tableState.hiddenColumns.map((col) => [col, false])
),
columnFilters: tableState.columnFilters,
}}
extendTableOptions={mergeOptions(
withGlobalFilter(globalFilterFn),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,34 @@ import { Datatable, TableSettingsMenu } from '@@/datatables';
import { TableSettingsMenuAutoRefresh } from '@@/datatables/TableSettingsMenuAutoRefresh';
import {
BasicTableSettings,
FilteredColumnsTableSettings,
filteredColumnsSettings,
RefreshableTableSettings,
createPersistedStore,
refreshableSettings,
} from '@@/datatables/types';
import { useRepeater } from '@@/datatables/useRepeater';
import { useTableState } from '@@/datatables/useTableState';
import { withMeta } from '@@/datatables/extend-options/withMeta';
import { withColumnFilters } from '@@/datatables/extend-options/withColumnFilters';

import { DecoratedVolume } from '../types';

import { TableActions } from './TableActions';
import { useColumns } from './columns';

interface TableSettings extends BasicTableSettings, RefreshableTableSettings {}
interface TableSettings
extends BasicTableSettings,
RefreshableTableSettings,
FilteredColumnsTableSettings {}

const storageKey = 'docker-volumes';
const store = createPersistedStore<TableSettings>(
storageKey,
undefined,
(set) => ({
...refreshableSettings(set),
...filteredColumnsSettings(set),
})
);

Expand Down Expand Up @@ -63,10 +70,16 @@ export function VolumesDatatable({
/>
</TableSettingsMenu>
)}
extendTableOptions={withMeta({
table: 'volumes',
isBrowseVisible,
})}
extendTableOptions={
(withMeta({
table: 'volumes',
isBrowseVisible,
}),
withColumnFilters(
tableState.columnFilters,
tableState.setColumnFilters
))
}
data-cy="docker-volumes-datatable"
/>
);
Expand Down
2 changes: 1 addition & 1 deletion app/react/hooks/useUnauthorizedRedirect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type AuthorizationOptions = {

type RedirectOptions = {
to: string;
params: Record<string, unknown>;
params?: Record<string, unknown>;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { CronJob, Job } from 'kubernetes-types/batch/v1';

import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { Authorized, useAuthorizations } from '@/react/hooks/useUser';
import { DefaultDatatableSettings } from '@/react/kubernetes/datatables/DefaultDatatableSettings';
import { createStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
import {
DefaultDatatableSettings,
TableSettings as KubeTableSettings,
} from '@/react/kubernetes/datatables/DefaultDatatableSettings';
import { useKubeStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
import { SystemResourceDescription } from '@/react/kubernetes/datatables/SystemResourceDescription';
import { pluralize } from '@/portainer/helpers/strings';
import { useNamespacesQuery } from '@/react/kubernetes/namespaces/queries/useNamespacesQuery';
Expand All @@ -17,9 +20,14 @@ import { useJobs } from '@/react/kubernetes/applications/useJobs';
import { useCronJobs } from '@/react/kubernetes/applications/useCronJobs';

import { Datatable, TableSettingsMenu } from '@@/datatables';
import { useTableState } from '@@/datatables/useTableState';
import { AddButton } from '@@/buttons';
import { DeleteButton } from '@@/buttons/DeleteButton';
import { AddButton } from '@@/buttons/AddButton';
import {
type FilteredColumnsTableSettings,
filteredColumnsSettings,
} from '@@/datatables/types';
import { mergeOptions } from '@@/datatables/extend-options/mergeOptions';
import { withColumnFilters } from '@@/datatables/extend-options/withColumnFilters';

import {
useConfigMapsForCluster,
Expand All @@ -31,11 +39,20 @@ import { getIsConfigMapInUse } from './utils';
import { ConfigMapRowData } from './types';
import { columns } from './columns';

interface TableSettings
extends KubeTableSettings,
FilteredColumnsTableSettings {}

const storageKey = 'k8sConfigMapsDatatable';
const settingsStore = createStore(storageKey);

export function ConfigMapsDatatable() {
const tableState = useTableState(settingsStore, storageKey);
const tableState = useKubeStore<TableSettings>(
storageKey,
undefined,
(set) => ({
...filteredColumnsSettings(set),
})
);
const { authorized: canWrite } = useAuthorizations(['K8sConfigMapsW']);
const readOnly = !canWrite;
const { authorized: canAccessSystemResources } = useAuthorizations(
Expand Down Expand Up @@ -109,6 +126,9 @@ export function ConfigMapsDatatable() {
/>
}
data-cy="k8s-configmaps-datatable"
extendTableOptions={mergeOptions(
withColumnFilters(tableState.columnFilters, tableState.setColumnFilters)
)}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { CronJob, Job } from 'kubernetes-types/batch/v1';

import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
import { Authorized, useAuthorizations } from '@/react/hooks/useUser';
import { DefaultDatatableSettings } from '@/react/kubernetes/datatables/DefaultDatatableSettings';
import { createStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
import {
DefaultDatatableSettings,
TableSettings as KubeTableSettings,
} from '@/react/kubernetes/datatables/DefaultDatatableSettings';
import { useKubeStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
import { SystemResourceDescription } from '@/react/kubernetes/datatables/SystemResourceDescription';
import { pluralize } from '@/portainer/helpers/strings';
import { useNamespacesQuery } from '@/react/kubernetes/namespaces/queries/useNamespacesQuery';
Expand All @@ -18,8 +21,13 @@ import { useCronJobs } from '@/react/kubernetes/applications/useCronJobs';

import { Datatable, TableSettingsMenu } from '@@/datatables';
import { AddButton } from '@@/buttons';
import { useTableState } from '@@/datatables/useTableState';
import { DeleteButton } from '@@/buttons/DeleteButton';
import {
type FilteredColumnsTableSettings,
filteredColumnsSettings,
} from '@@/datatables/types';
import { mergeOptions } from '@@/datatables/extend-options/mergeOptions';
import { withColumnFilters } from '@@/datatables/extend-options/withColumnFilters';

import {
useSecretsForCluster,
Expand All @@ -32,17 +40,26 @@ import { SecretRowData } from './types';
import { columns } from './columns';

const storageKey = 'k8sSecretsDatatable';
const settingsStore = createStore(storageKey);

interface TableSettings
extends KubeTableSettings,
FilteredColumnsTableSettings {}

export function SecretsDatatable() {
const tableState = useTableState(settingsStore, storageKey);
const tableState = useKubeStore<TableSettings>(
storageKey,
undefined,
(set) => ({
...filteredColumnsSettings(set),
})
);
const environmentId = useEnvironmentId();
const { authorized: canWrite } = useAuthorizations(['K8sSecretsW']);
const readOnly = !canWrite;
const { authorized: canAccessSystemResources } = useAuthorizations(
'K8sAccessSystemNamespaces'
);

const environmentId = useEnvironmentId();
const { data: namespaces, ...namespacesQuery } = useNamespacesQuery(
environmentId,
{
Expand Down Expand Up @@ -109,6 +126,9 @@ export function SecretsDatatable() {
/>
}
data-cy="k8s-secrets-datatable"
extendTableOptions={mergeOptions(
withColumnFilters(tableState.columnFilters, tableState.setColumnFilters)
)}
/>
);
}
Expand Down
Loading

0 comments on commit f9ad801

Please sign in to comment.