1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-12 01:17:04 +02:00

refactor: port some things to TS (#843)

* refactor: port useSort to TS

* refactor: port loadingFeatures to TS

* refactor: port admin index to TS

* refactor: port TagTypeList to TS

* refactor: merge route interfaces

* refactor: port common utils to TS

* refactor: fix snapshot date typo

* refactor: port Reporting utils to TS

* refactor: improve PermissionIconButton prop types
This commit is contained in:
olav 2022-04-06 12:22:24 +02:00 committed by GitHub
parent 73652b66e9
commit a088866124
24 changed files with 172 additions and 128 deletions

View File

@ -9,15 +9,17 @@ import {
sortFeaturesByExpiredAtDescending,
sortFeaturesByStatusAscending,
sortFeaturesByStatusDescending,
} from './utils';
} from 'component/Reporting/utils';
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
const getTestData = () => [
const getTestData = (): IFeatureToggleListItem[] => [
{
name: 'abe',
createdAt: '2021-02-14T02:42:34.515Z',
lastSeenAt: '2021-02-21T19:34:21.830Z',
type: 'release',
stale: false,
environments: [],
},
{
name: 'bet',
@ -25,6 +27,7 @@ const getTestData = () => [
lastSeenAt: '2021-02-19T19:34:21.830Z',
type: 'release',
stale: false,
environments: [],
},
{
name: 'cat',
@ -32,6 +35,7 @@ const getTestData = () => [
lastSeenAt: '2021-02-18T19:34:21.830Z',
type: 'experiment',
stale: true,
environments: [],
},
];

View File

@ -4,38 +4,54 @@ import differenceInDays from 'date-fns/differenceInDays';
import { EXPERIMENT, OPERATIONAL, RELEASE } from 'constants/featureToggleTypes';
import { FOURTYDAYS, SEVENDAYS } from './constants';
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
export const toggleExpiryByTypeMap = {
export const toggleExpiryByTypeMap: Record<string, number> = {
[EXPERIMENT]: FOURTYDAYS,
[RELEASE]: FOURTYDAYS,
[OPERATIONAL]: SEVENDAYS,
};
export const applyCheckedToFeatures = (features, checkedState) =>
features.map(feature => ({ ...feature, checked: checkedState }));
export interface IFeatureToggleListItemCheck extends IFeatureToggleListItem {
checked: boolean;
}
export const getCheckedState = (name, features) => {
export const applyCheckedToFeatures = (
features: IFeatureToggleListItem[],
checkedState: boolean
): IFeatureToggleListItemCheck[] => {
return features.map(feature => ({
...feature,
checked: checkedState,
}));
};
export const getCheckedState = (
name: string,
features: IFeatureToggleListItemCheck[]
) => {
const feature = features.find(feature => feature.name === name);
if (feature) {
return feature.checked ? feature.checked : false;
return feature.checked;
}
return false;
};
export const getDiffInDays = (date, now) =>
export const getDiffInDays = (date: Date, now: Date) =>
Math.abs(differenceInDays(date, now));
export const formatProjectOptions = projects =>
projects.map(project => ({ key: project.id, label: project.name }));
export const expired = (diff, type) => {
export const expired = (diff: number, type: string) => {
if (diff >= toggleExpiryByTypeMap[type]) return true;
return false;
};
export const getObjectProperties = (target, ...keys) => {
const newObject = {};
export const getObjectProperties = <T extends object>(
target: T,
...keys: (keyof T)[]
): Partial<T> => {
const newObject: Partial<T> = {};
keys.forEach(key => {
if (target[key] !== undefined) {
@ -46,7 +62,9 @@ export const getObjectProperties = (target, ...keys) => {
return newObject;
};
export const sortFeaturesByNameAscending = features => {
export const sortFeaturesByNameAscending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] => {
const sorted = [...features];
sorted.sort((a, b) => {
if (a.name < b.name) {
@ -60,10 +78,14 @@ export const sortFeaturesByNameAscending = features => {
return sorted;
};
export const sortFeaturesByNameDescending = features =>
export const sortFeaturesByNameDescending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] =>
sortFeaturesByNameAscending([...features]).reverse();
export const sortFeaturesByLastSeenAscending = features => {
export const sortFeaturesByLastSeenAscending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] => {
const sorted = [...features];
sorted.sort((a, b) => {
if (!a.lastSeenAt) return -1;
@ -77,10 +99,14 @@ export const sortFeaturesByLastSeenAscending = features => {
return sorted;
};
export const sortFeaturesByLastSeenDescending = features =>
export const sortFeaturesByLastSeenDescending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] =>
sortFeaturesByLastSeenAscending([...features]).reverse();
export const sortFeaturesByCreatedAtAscending = features => {
export const sortFeaturesByCreatedAtAscending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] => {
const sorted = [...features];
sorted.sort((a, b) => {
const dateA = parseISO(a.createdAt);
@ -91,10 +117,14 @@ export const sortFeaturesByCreatedAtAscending = features => {
return sorted;
};
export const sortFeaturesByCreatedAtDescending = features =>
export const sortFeaturesByCreatedAtDescending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] =>
sortFeaturesByCreatedAtAscending([...features]).reverse();
export const sortFeaturesByExpiredAtAscending = features => {
export const sortFeaturesByExpiredAtAscending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] => {
const sorted = [...features];
sorted.sort((a, b) => {
const now = new Date();
@ -120,7 +150,9 @@ export const sortFeaturesByExpiredAtAscending = features => {
return sorted;
};
export const sortFeaturesByExpiredAtDescending = features => {
export const sortFeaturesByExpiredAtDescending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] => {
const sorted = [...features];
const now = new Date();
sorted.sort((a, b) => {
@ -146,7 +178,9 @@ export const sortFeaturesByExpiredAtDescending = features => {
return sorted;
};
export const sortFeaturesByStatusAscending = features => {
export const sortFeaturesByStatusAscending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] => {
const sorted = [...features];
sorted.sort((a, b) => {
if (a.stale) return 1;
@ -156,15 +190,17 @@ export const sortFeaturesByStatusAscending = features => {
return sorted;
};
export const sortFeaturesByStatusDescending = features =>
export const sortFeaturesByStatusDescending = (
features: IFeatureToggleListItem[]
): IFeatureToggleListItem[] =>
sortFeaturesByStatusAscending([...features]).reverse();
export const pluralize = (items, word) => {
export const pluralize = (items: number, word: string): string => {
if (items === 1) return `${items} ${word}`;
return `${items} ${word}s`;
};
export const getDates = dateString => {
export const getDates = (dateString: string): [Date, Date] => {
const date = parseISO(dateString);
const now = new Date();

View File

@ -69,7 +69,7 @@ const Constraint = ({
show={
<div className={styles.btnContainer}>
<PermissionIconButton
onClick={editCallback}
onClick={editCallback!}
permission={UPDATE_FEATURE}
projectId={projectId}
disabled={disabledEdit}
@ -78,7 +78,7 @@ const Constraint = ({
</PermissionIconButton>
<PermissionIconButton
onClick={deleteCallback}
onClick={deleteCallback!}
permission={UPDATE_FEATURE}
projectId={projectId}
>

View File

@ -100,7 +100,7 @@ export const ConstraintAccordionViewHeader = ({
condition={Boolean(onEditClick)}
show={
<PermissionIconButton
onClick={onEditClick}
onClick={onEditClick!}
permission={UPDATE_FEATURE_STRATEGY}
projectId={projectId}
environmentId={environmentId}
@ -114,7 +114,7 @@ export const ConstraintAccordionViewHeader = ({
condition={Boolean(onDeleteClick)}
show={
<PermissionIconButton
onClick={onDeleteClick}
onClick={onDeleteClick!}
permission={UPDATE_FEATURE_STRATEGY}
projectId={projectId}
environmentId={environmentId}

View File

@ -1,26 +1,37 @@
import { IconButton, Tooltip, IconButtonProps } from '@material-ui/core';
import React, { useContext } from 'react';
import React, { useContext, ReactNode } from 'react';
import AccessContext from 'contexts/AccessContext';
import { Link } from 'react-router-dom';
interface IPermissionIconButtonProps extends IconButtonProps {
interface IPermissionIconButtonProps {
permission: string;
Icon?: React.ElementType;
onClick?: (e: any) => void;
projectId?: string;
environmentId?: string;
className?: string;
title?: string;
children?: ReactNode;
disabled?: boolean;
hidden?: boolean;
type?: 'button';
edge?: IconButtonProps['edge'];
}
const PermissionIconButton: React.FC<IPermissionIconButtonProps> = ({
interface IButtonProps extends IPermissionIconButtonProps {
onClick: (event: React.SyntheticEvent) => void;
}
interface ILinkProps extends IPermissionIconButtonProps {
component: typeof Link;
to: string;
}
const PermissionIconButton = ({
permission,
Icon,
onClick,
projectId,
children,
environmentId,
...rest
}) => {
}: IButtonProps | ILinkProps) => {
const { hasAccess } = useContext(AccessContext);
let access;
@ -39,7 +50,7 @@ const PermissionIconButton: React.FC<IPermissionIconButtonProps> = ({
return (
<Tooltip title={tooltipText} arrow>
<span>
<IconButton onClick={onClick} disabled={!access} {...rest}>
<IconButton disabled={!access} {...rest}>
{children}
</IconButton>
</span>

View File

@ -1,17 +1,21 @@
import { weightTypes } from '../feature/FeatureView/FeatureVariants/FeatureVariantsList/AddFeatureVariant/enums';
import { IFlags } from 'interfaces/uiConfig';
import { IRoute } from 'interfaces/route';
import { IFeatureVariant } from 'interfaces/featureToggle';
export const filterByFlags = flags => r => {
if (r.flag && !flags[r.flag]) {
return false;
export const filterByFlags = (flags: IFlags) => (r: IRoute) => {
if (!r.flag) {
return true;
}
return true;
return (flags as unknown as Record<string, boolean>)[r.flag];
};
export const scrollToTop = () => {
window.scrollTo(0, 0);
};
export const trim = value => {
export const trim = (value: string): string => {
if (value && value.trim) {
return value.trim();
} else {
@ -19,7 +23,7 @@ export const trim = value => {
}
};
export function updateWeight(variants, totalWeight) {
export function updateWeight(variants: IFeatureVariant[], totalWeight: number) {
if (variants.length === 0) {
return [];
}
@ -48,7 +52,9 @@ export function updateWeight(variants, totalWeight) {
throw new Error('There must be at least one variable variant');
}
const percentage = parseInt(remainingPercentage / variableVariantCount);
const percentage = parseInt(
String(remainingPercentage / variableVariantCount)
);
return variants.map(variant => {
if (variant.weightType !== weightTypes.FIX) {

View File

@ -1,4 +1,6 @@
const loadingFeatures = [
import { IFeatureToggle } from 'interfaces/featureToggle';
const loadingFeatures: Partial<IFeatureToggle>[] = [
{
createdAt: '2021-03-19T09:16:21.329Z',
description: '',
@ -6,7 +8,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'one',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -19,7 +20,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'two',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -32,7 +32,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'three',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -45,7 +44,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'four',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -58,7 +56,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'five',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -71,7 +68,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'six',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -84,7 +80,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'seven',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -97,7 +92,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'eight',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -110,7 +104,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'nine',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],
@ -123,7 +116,6 @@ const loadingFeatures = [
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: 'ten',
project: 'default',
reviveName: 'cool-thing',
stale: true,
strategies: [],
variants: [],

View File

@ -1,11 +1,13 @@
const loadingFeatures = [
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
const loadingFeatures: IFeatureToggleListItem[] = [
{
type: 'release',
name: 'loading1',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -13,10 +15,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'loadg2',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -24,10 +26,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'loading3',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -35,10 +37,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'loadi4',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -46,10 +48,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'loadi5',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -57,10 +59,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'loadg6',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -68,10 +70,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'loading7',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -79,10 +81,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'ln8',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],
@ -90,10 +92,10 @@ const loadingFeatures = [
{
type: 'release',
name: 'load9',
createdAt: '2006-01-02T15:04:05Z',
environments: [
{
name: ':global:',
displayName: 'Across all environments',
enabled: true,
},
],

View File

@ -51,7 +51,6 @@ const FeatureOverviewEnvironmentStrategy = ({
permission={UPDATE_FEATURE_STRATEGY}
environmentId={environmentId}
projectId={projectId}
// @ts-expect-error
component={Link}
to={editStrategyPath}
>

View File

@ -49,7 +49,6 @@ const FeatureOverviewMetaData = () => {
<PermissionIconButton
projectId={projectId}
permission={UPDATE_FEATURE}
// @ts-expect-error
component={Link}
to={`/projects/${projectId}/features/${featureId}/settings`}
>
@ -65,7 +64,6 @@ const FeatureOverviewMetaData = () => {
<PermissionIconButton
projectId={projectId}
permission={UPDATE_FEATURE}
// @ts-expect-error
component={Link}
to={`/projects/${projectId}/features/${featureId}/settings`}
>

View File

@ -141,7 +141,6 @@ export const FeatureView = () => {
permission={CREATE_FEATURE}
projectId={projectId}
data-loading
// @ts-expect-error
component={Link}
to={`/projects/${projectId}/features/${featureId}/strategies/copy`}
>

View File

@ -50,26 +50,9 @@ import { CreateUnleashContextPage } from 'component/context/CreateUnleashContext
import { CreateSegment } from 'component/segments/CreateSegment/CreateSegment';
import { EditSegment } from 'component/segments/EditSegment/EditSegment';
import { SegmentsList } from 'component/segments/SegmentList/SegmentList';
import { FunctionComponent } from 'react';
import { IRoute } from 'interfaces/route';
interface Route {
path: string;
title: string;
type: string;
layout?: string;
parent?: string;
flag?: string;
hidden?: Boolean;
component: FunctionComponent;
menu: {
mobile?: boolean;
advanced?: boolean;
adminSettings?: boolean;
};
}
export const routes: Route[] = [
export const routes: IRoute[] = [
// Splash
{
path: '/splash/:splashId',

View File

@ -52,7 +52,6 @@ const ProjectInfo = ({
<PermissionIconButton
permission={UPDATE_PROJECT}
projectId={id}
// @ts-expect-error
component={Link}
className={permissionButtonClass}
data-loading

View File

@ -27,10 +27,14 @@ import useTagTypes from 'hooks/api/getters/useTagTypes/useTagTypes';
import useToast from 'hooks/useToast';
import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
import { formatUnknownError } from 'utils/formatUnknownError';
import { ITagType } from 'interfaces/tags';
export const TagTypeList = () => {
const { hasAccess } = useContext(AccessContext);
const [deletion, setDeletion] = useState({ open: false });
const [deletion, setDeletion] = useState<{
open: boolean;
name?: string;
}>({ open: false });
const history = useHistory();
const smallScreen = useMediaQuery('(max-width:700px)');
const { deleteTagType } = useTagTypesApi();
@ -39,14 +43,16 @@ export const TagTypeList = () => {
const deleteTag = async () => {
try {
await deleteTagType(deletion.name);
refetch();
setDeletion({ open: false });
setToastData({
type: 'success',
show: true,
text: 'Successfully deleted tag type.',
});
if (deletion.name) {
await deleteTagType(deletion.name);
refetch();
setDeletion({ open: false });
setToastData({
type: 'success',
show: true,
title: 'Successfully deleted tag type.',
});
}
} catch (error) {
setToastApiError(formatUnknownError(error));
}
@ -91,7 +97,7 @@ export const TagTypeList = () => {
/>
);
const renderTagType = tagType => {
const renderTagType = (tagType: ITagType) => {
let link = (
<Link to={`/tag-types/edit/${tagType.name}`}>
<strong>{tagType.name}</strong>
@ -126,7 +132,7 @@ export const TagTypeList = () => {
component={Link}
to={`/tag-types/edit/${tagType.name}`}
>
<Edit className={styles.icon} />
<Edit className={styles.icon} titleAccess="Edit tag type" />
</PermissionIconButton>
<ConditionallyRender
condition={hasAccess(DELETE_TAG_TYPE)}

View File

@ -1,5 +1,5 @@
import React from 'react';
import { TagTypeList } from '../TagTypeList';
import { TagTypeList } from 'component/tags/TagTypeList/TagTypeList';
import renderer from 'react-test-renderer';
import { MemoryRouter } from 'react-router-dom';
import { ThemeProvider } from '@material-ui/styles';

View File

@ -9,7 +9,7 @@ Object {
"filtered": Array [
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],
@ -81,7 +81,7 @@ Object {
"filtered": Array [
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],
@ -96,7 +96,7 @@ Object {
},
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],
@ -111,7 +111,7 @@ Object {
},
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],
@ -137,7 +137,7 @@ Object {
"filtered": Array [
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],
@ -152,7 +152,7 @@ Object {
},
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],
@ -179,7 +179,7 @@ Object {
"filtered": Array [
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],
@ -194,7 +194,7 @@ Object {
},
Object {
"archived": false,
"createdAt": "22006-01-02T15:04:05Z",
"createdAt": "2006-01-02T15:04:05Z",
"description": "1",
"enabled": false,
"environments": Array [],

View File

@ -102,7 +102,7 @@ const mockFeatureToggle = (
strategies: [],
variants: [],
environments: [],
createdAt: '22006-01-02T15:04:05Z',
createdAt: '2006-01-02T15:04:05Z',
lastSeenAt: '2006-01-02T15:04:05Z',
...overrides,
};

View File

@ -10,7 +10,7 @@ import {
sortFeaturesByExpiredAtDescending,
sortFeaturesByStatusAscending,
sortFeaturesByStatusDescending,
} from '../component/Reporting/utils';
} from 'component/Reporting/utils';
import {
LAST_SEEN,
@ -19,7 +19,8 @@ import {
EXPIRED,
STATUS,
REPORT,
} from '../component/Reporting/constants';
} from 'component/Reporting/constants';
import { IFeatureToggleListItem } from 'interfaces/featureToggle';
const useSort = () => {
const [sortData, setSortData] = useState({
@ -27,7 +28,7 @@ const useSort = () => {
ascending: true,
});
const handleSortName = features => {
const handleSortName = (features: IFeatureToggleListItem[]) => {
if (sortData.ascending) {
return sortFeaturesByNameAscending(features);
}
@ -35,35 +36,35 @@ const useSort = () => {
return sortFeaturesByNameDescending(features);
};
const handleSortLastSeen = features => {
const handleSortLastSeen = (features: IFeatureToggleListItem[]) => {
if (sortData.ascending) {
return sortFeaturesByLastSeenAscending(features);
}
return sortFeaturesByLastSeenDescending(features);
};
const handleSortCreatedAt = features => {
const handleSortCreatedAt = (features: IFeatureToggleListItem[]) => {
if (sortData.ascending) {
return sortFeaturesByCreatedAtAscending(features);
}
return sortFeaturesByCreatedAtDescending(features);
};
const handleSortExpiredAt = features => {
const handleSortExpiredAt = (features: IFeatureToggleListItem[]) => {
if (sortData.ascending) {
return sortFeaturesByExpiredAtAscending(features);
}
return sortFeaturesByExpiredAtDescending(features);
};
const handleSortStatus = features => {
const handleSortStatus = (features: IFeatureToggleListItem[]) => {
if (sortData.ascending) {
return sortFeaturesByStatusAscending(features);
}
return sortFeaturesByStatusDescending(features);
};
const sort = features => {
const sort = (features: IFeatureToggleListItem[]) => {
switch (sortData.sortKey) {
case NAME:
return handleSortName(features);

View File

@ -3,6 +3,9 @@ import { IFeatureStrategy } from './strategy';
export interface IFeatureToggleListItem {
type: string;
name: string;
stale?: boolean;
lastSeenAt?: string;
createdAt: string;
environments: IEnvironments[];
}

View File

@ -1,14 +1,19 @@
import React from 'react';
import { FunctionComponent } from 'react';
interface IRoute {
export interface IRoute {
path: string;
icon?: string;
title?: string;
component: React.ComponentType;
title: string;
type: string;
hidden?: boolean;
flag?: string;
layout?: string;
parent?: string;
flag?: string;
hidden?: boolean;
component: FunctionComponent;
menu: IRouteMenu;
}
export default IRoute;
interface IRouteMenu {
mobile?: boolean;
advanced?: boolean;
adminSettings?: boolean;
}