Files
backroad/app/react/docker/stacks/ListView/StacksDatatable/StacksDatatable.tsx
2024-02-14 19:50:20 -03:00

114 lines
3.2 KiB
TypeScript

import { Layers } from 'lucide-react';
import { Row } from '@tanstack/react-table';
import { useAuthorizations, useIsEdgeAdmin } from '@/react/hooks/useUser';
import { isBE } from '@/react/portainer/feature-flags/feature-flags.service';
import { Datatable } from '@@/datatables';
import { useTableState } from '@@/datatables/useTableState';
import { useRepeater } from '@@/datatables/useRepeater';
import { defaultGlobalFilterFn } from '@@/datatables/Datatable';
import { withGlobalFilter } from '@@/datatables/extend-options/withGlobalFilter';
import { isExternalStack, isOrphanedStack } from '../../view-models/utils';
import { TableActions } from './TableActions';
import { TableSettingsMenus } from './TableSettingsMenus';
import { createStore } from './store';
import { useColumns } from './columns';
import { DecoratedStack } from './types';
const tableKey = 'docker_stacks';
const settingsStore = createStore(tableKey);
export function StacksDatatable({
onRemove,
onReload,
isImageNotificationEnabled,
dataset,
}: {
onRemove: (items: Array<DecoratedStack>) => void;
onReload: () => void;
isImageNotificationEnabled: boolean;
dataset: Array<DecoratedStack>;
}) {
const tableState = useTableState(settingsStore, tableKey);
useRepeater(tableState.autoRefreshRate, onReload);
const isAdminQuery = useIsEdgeAdmin();
const canManageStacks = useAuthorizations([
'PortainerStackCreate',
'PortainerStackDelete',
]);
const columns = useColumns(isImageNotificationEnabled);
return (
<Datatable<DecoratedStack>
settingsManager={tableState}
title="Stacks"
titleIcon={Layers}
renderTableActions={(selectedRows) => (
<TableActions selectedItems={selectedRows} onRemove={onRemove} />
)}
renderTableSettings={(tableInstance) => (
<TableSettingsMenus
tableInstance={tableInstance}
tableState={tableState}
/>
)}
columns={columns}
dataset={dataset}
isRowSelectable={({ original: item }) =>
allowSelection(item, isAdminQuery.isAdmin, canManageStacks.authorized)
}
getRowId={(item) => item.Id.toString()}
initialTableState={{
globalFilter: {
showOrphanedStacks: tableState.showOrphanedStacks,
},
columnVisibility: Object.fromEntries(
tableState.hiddenColumns.map((col) => [col, false])
),
}}
extendTableOptions={withGlobalFilter(globalFilterFn)}
/>
);
}
function allowSelection(
item: DecoratedStack,
isAdmin: boolean,
canManageStacks: boolean
) {
if (isExternalStack(item)) {
return false;
}
if (isBE && isOrphanedStack(item) && !isAdmin) {
return false;
}
return isAdmin || canManageStacks;
}
function globalFilterFn(
row: Row<DecoratedStack>,
columnId: string,
filterValue: null | { showOrphanedStacks: boolean; search: string }
) {
return (
orphanedFilter(row, filterValue) &&
defaultGlobalFilterFn(row, columnId, filterValue)
);
}
function orphanedFilter(
row: Row<DecoratedStack>,
filterValue: null | { showOrphanedStacks: boolean; search: string }
) {
if (filterValue?.showOrphanedStacks) {
return true;
}
return !isOrphanedStack(row.original);
}