1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-18 01:18:23 +02:00
unleash.unleash/frontend/src/component/feature/FeatureToggleListNew/FeatureToggleListNew.tsx
olav 7b60ef2aa6 refactor: misc type improvements (#945)
* refactor: improve ChangePassword types

* refactor: improve usePagination types

* refactor: improve UsersList types
2022-05-04 08:14:49 +02:00

295 lines
10 KiB
TypeScript

import { useState, useEffect, useContext } from 'react';
import {
Table,
TableBody,
TableCell,
TableHead,
TableRow,
} from '@mui/material';
import classnames from 'classnames';
import { useStyles } from './FeatureToggleListNew.styles';
import FeatureToggleListNewItem from './FeatureToggleListNewItem/FeatureToggleListNewItem';
import usePagination from 'hooks/usePagination';
import loadingFeatures from './FeatureToggleListNewItem/loadingFeatures';
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
import PaginateUI from 'component/common/PaginateUI/PaginateUI';
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
import { createGlobalStateHook } from 'hooks/useGlobalState';
import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext';
interface IFeatureToggleListNewProps {
features: IFeatureToggleListItem[];
loading: boolean;
projectId: string;
}
// @ts-expect-error
const sortList = (list, sortOpt) => {
if (!list) {
return list;
}
if (!sortOpt.field) {
return list;
}
if (sortOpt.type === 'string') {
// @ts-expect-error
return list.sort((a, b) => {
const fieldA = a[sortOpt.field]?.toUpperCase();
const fieldB = b[sortOpt.field]?.toUpperCase();
const direction = sortOpt.direction;
if (fieldA < fieldB) {
return direction === 0 ? -1 : 1;
}
if (fieldA > fieldB) {
return direction === 0 ? 1 : -1;
}
return 0;
});
}
if (sortOpt.type === 'date') {
// @ts-expect-error
return list.sort((a, b) => {
const fieldA = new Date(a[sortOpt.field]);
const fieldB = new Date(b[sortOpt.field]);
if (fieldA < fieldB) {
return sortOpt.direction === 0 ? 1 : -1;
}
if (fieldA > fieldB) {
return sortOpt.direction === 0 ? -1 : 1;
}
return 0;
});
}
return list;
};
interface ISortedState {
field: string;
type: string;
direction: number;
}
const useFeatureToggLeProjectSort = createGlobalStateHook<ISortedState>(
'useFeatureToggLeProjectSort',
{ field: 'name', type: 'string', direction: 0 }
);
const FeatureToggleListNew = ({
features,
loading,
projectId,
}: IFeatureToggleListNewProps) => {
const { classes: styles } = useStyles();
const { setAnnouncement } = useContext(AnnouncerContext);
const [sortOpt, setSortOpt] = useFeatureToggLeProjectSort();
const [sortedFeatures, setSortedFeatures] = useState<
IFeatureToggleListItem[]
>(sortList([...features], sortOpt));
const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
usePagination(sortedFeatures, 50);
useEffect(() => {
setSortedFeatures(sortList([...features], sortOpt));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [features]);
const updateSort = (field: string) => {
let newSortOpt;
if (field === sortOpt.field) {
newSortOpt = { ...sortOpt, direction: (sortOpt.direction + 1) % 2 };
} else if (['createdAt', 'lastSeenAt'].includes(field)) {
newSortOpt = {
field,
type: 'date',
direction: 0,
};
} else {
newSortOpt = {
field,
type: 'string',
direction: 0,
};
}
setSortOpt(newSortOpt);
setSortedFeatures(sortList([...features], newSortOpt));
setPageIndex(0);
setAnnouncement(
`Sorted table by ${field}, ${
sortOpt.direction ? 'ascending' : 'descending'
}`
);
};
const getEnvironments = () => {
if (features.length > 0) {
const envs = features[0].environments || [];
return envs;
}
return [
{
name: 'default',
enabled: false,
},
];
};
const renderFeatures = () => {
if (loading) {
return loadingFeatures.map((feature: IFeatureToggleListItem) => {
return (
<FeatureToggleListNewItem
key={feature.name}
name={feature.name}
type={feature.type}
environments={feature.environments}
projectId={projectId}
createdAt={new Date().toISOString()}
/>
);
});
}
return page.map((feature: IFeatureToggleListItem) => {
return (
<FeatureToggleListNewItem
key={feature.name}
name={feature.name}
type={feature.type}
environments={feature.environments}
projectId={projectId}
lastSeenAt={feature.lastSeenAt}
createdAt={feature.createdAt}
/>
);
});
};
const ariaSort = (field: string) => {
return field === sortOpt.field
? sortOpt.direction
? 'ascending'
: 'descending'
: undefined;
};
return (
<>
<Table>
<TableHead>
<TableRow>
<TableCell
className={classnames(
styles.tableCell,
styles.tableCellStatus,
styles.tableCellHeader,
styles.tableCellHeaderSortable
)}
align="left"
aria-sort={ariaSort('lastSeenAt')}
>
<button
data-loading
onClick={() => updateSort('lastSeenAt')}
className={styles.sortButton}
>
Last use
</button>
</TableCell>
<TableCell
className={classnames(
styles.tableCell,
styles.tableCellType,
styles.tableCellHeader,
styles.tableCellHeaderSortable
)}
align="center"
aria-sort={ariaSort('type')}
>
<button
data-loading
onClick={() => updateSort('type')}
className={styles.sortButton}
>
Type
</button>
</TableCell>
<TableCell
className={classnames(
styles.tableCell,
styles.tableCellName,
styles.tableCellHeader,
styles.tableCellHeaderSortable
)}
align="left"
aria-sort={ariaSort('name')}
>
<button
data-loading
onClick={() => updateSort('name')}
className={styles.sortButton}
>
Name
</button>
</TableCell>
<TableCell
className={classnames(
styles.tableCell,
styles.tableCellCreated,
styles.tableCellHeader,
styles.tableCellHeaderSortable
)}
align="left"
aria-sort={ariaSort('createdAt')}
>
<button
data-loading
onClick={() => updateSort('createdAt')}
className={styles.sortButton}
>
Created
</button>
</TableCell>
{getEnvironments().map((env: any) => {
return (
<TableCell
key={env.name}
className={classnames(
styles.tableCell,
styles.tableCellEnv,
styles.tableCellHeader,
styles.tableCellHeaderSortable
)}
align="center"
>
<StringTruncator
text={env.name}
maxLength={15}
maxWidth="90"
data-loading
/>
</TableCell>
);
})}
</TableRow>
</TableHead>
<TableBody>{renderFeatures()}</TableBody>
</Table>
<PaginateUI
pages={pages}
pageIndex={pageIndex}
setPageIndex={setPageIndex}
nextPage={nextPage}
prevPage={prevPage}
/>
</>
);
};
export default FeatureToggleListNew;