import { useEffect, useMemo, useState, VFC } from 'react'; import { Link, useMediaQuery, useTheme } from '@mui/material'; import { Link as RouterLink, useSearchParams } from 'react-router-dom'; import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table'; import { Table, SortableTableHeader, TableBody, TableCell, TableRow, TablePlaceholder, } from 'component/common/Table'; import { useFeatures } from 'hooks/api/getters/useFeatures/useFeatures'; import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext'; import { DateCell } from 'component/common/Table/cells/DateCell/DateCell'; import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell'; import { FeatureSeenCell } from 'component/common/Table/cells/FeatureSeenCell/FeatureSeenCell'; import { FeatureTypeCell } from 'component/common/Table/cells/FeatureTypeCell/FeatureTypeCell'; import { FeatureNameCell } from 'component/common/Table/cells/FeatureNameCell/FeatureNameCell'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { PageContent } from 'component/common/PageContent/PageContent'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import { sortTypes } from 'utils/sortTypes'; import { createLocalStorage } from 'utils/createLocalStorage'; import { useVirtualizedRange } from 'hooks/useVirtualizedRange'; import { FeatureSchema } from 'openapi'; import { CreateFeatureButton } from '../CreateFeatureButton/CreateFeatureButton'; import { FeatureStaleCell } from './FeatureStaleCell/FeatureStaleCell'; import { useStyles } from './styles'; import { useSearch } from 'hooks/useSearch'; import { Search } from 'component/common/Search/Search'; export const featuresPlaceholder: FeatureSchema[] = Array(15).fill({ name: 'Name of the feature', description: 'Short description of the feature', type: '-', createdAt: new Date(2022, 1, 1), project: 'projectID', }); export type PageQueryType = Partial< Record<'sort' | 'order' | 'search', string> >; const columns = [ { Header: 'Seen', accessor: 'lastSeenAt', Cell: FeatureSeenCell, sortType: 'date', align: 'center', maxWidth: 85, }, { Header: 'Type', accessor: 'type', Cell: FeatureTypeCell, align: 'center', maxWidth: 85, }, { Header: 'Name', accessor: 'name', minWidth: 150, Cell: FeatureNameCell, sortType: 'alphanumeric', searchable: true, }, { Header: 'Created', accessor: 'createdAt', Cell: DateCell, sortType: 'date', maxWidth: 150, }, { Header: 'Project ID', accessor: 'project', Cell: ({ value }: { value: string }) => ( ), sortType: 'alphanumeric', maxWidth: 150, filterName: 'project', searchable: true, }, { Header: 'State', accessor: 'stale', Cell: FeatureStaleCell, sortType: 'boolean', maxWidth: 120, filterName: 'state', filterParsing: (value: any) => (value ? 'stale' : 'active'), }, // Always hidden -- for search { accessor: 'description', }, ]; const defaultSort: SortingRule = { id: 'createdAt', desc: true }; const { value: storedParams, setValue: setStoredParams } = createLocalStorage( 'FeatureToggleListTable:v1', defaultSort ); export const FeatureToggleListTable: VFC = () => { const theme = useTheme(); const rowHeight = theme.shape.tableRowHeight; const { classes } = useStyles(); const isSmallScreen = useMediaQuery(theme.breakpoints.down('md')); const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg')); const { features = [], loading } = useFeatures(); const [searchParams, setSearchParams] = useSearchParams(); const [initialState] = useState(() => ({ sortBy: [ { id: searchParams.get('sort') || storedParams.id, desc: searchParams.has('order') ? searchParams.get('order') === 'desc' : storedParams.desc, }, ], hiddenColumns: ['description'], globalFilter: searchParams.get('search') || '', })); const [searchValue, setSearchValue] = useState(initialState.globalFilter); const { data: searchedData, getSearchText, getSearchContext, } = useSearch(columns, searchValue, features); const data = useMemo( () => searchedData?.length === 0 && loading ? featuresPlaceholder : searchedData, [searchedData, loading] ); const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow, state: { sortBy }, setHiddenColumns, } = useTable( { columns, data, initialState, sortTypes, autoResetSortBy: false, disableSortRemove: true, disableMultiSort: true, }, useSortBy, useFlexLayout ); useEffect(() => { const hiddenColumns = ['description']; if (isMediumScreen) { hiddenColumns.push('lastSeenAt', 'stale'); } if (isSmallScreen) { hiddenColumns.push('type', 'createdAt'); } setHiddenColumns(hiddenColumns); }, [setHiddenColumns, isSmallScreen, isMediumScreen]); useEffect(() => { const tableState: PageQueryType = {}; tableState.sort = sortBy[0].id; if (sortBy[0].desc) { tableState.order = 'desc'; } if (searchValue) { tableState.search = searchValue; } setSearchParams(tableState, { replace: true, }); setStoredParams({ id: sortBy[0].id, desc: sortBy[0].desc || false }); }, [sortBy, searchValue, setSearchParams]); const [firstRenderedIndex, lastRenderedIndex] = useVirtualizedRange(rowHeight); const tableHeight = rowHeight * rows.length + theme.shape.tableRowHeightCompact; return ( } /> View archive } > } /> } > {rows.map((row, index) => { const top = index * rowHeight + theme.shape.tableRowHeightCompact; const isVirtual = index < firstRenderedIndex || index > lastRenderedIndex; if (isVirtual) { return null; } prepareRow(row); return ( {row.cells.map(cell => ( {cell.render('Cell')} ))} ); })}
0} show={ No feature toggles found matching “ {searchValue} ” } elseShow={ No feature toggles available. Get started by adding a new feature toggle. } /> } />
); };