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) => void; onReload: () => void; isImageNotificationEnabled: boolean; dataset: Array; }) { const tableState = useTableState(settingsStore, tableKey); useRepeater(tableState.autoRefreshRate, onReload); const isAdminQuery = useIsEdgeAdmin(); const canManageStacks = useAuthorizations([ 'PortainerStackCreate', 'PortainerStackDelete', ]); const columns = useColumns(isImageNotificationEnabled); return ( settingsManager={tableState} title="Stacks" titleIcon={Layers} renderTableActions={(selectedRows) => ( )} renderTableSettings={(tableInstance) => ( )} 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, columnId: string, filterValue: null | { showOrphanedStacks: boolean; search: string } ) { return ( orphanedFilter(row, filterValue) && defaultGlobalFilterFn(row, columnId, filterValue) ); } function orphanedFilter( row: Row, filterValue: null | { showOrphanedStacks: boolean; search: string } ) { if (filterValue?.showOrphanedStacks) { return true; } return !isOrphanedStack(row.original); }