mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-18 01:18:23 +02:00
* refactor: improve ChangePassword types * refactor: improve usePagination types * refactor: improve UsersList types
295 lines
10 KiB
TypeScript
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;
|