1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-23 00:22:19 +01:00

remove dead code

This commit is contained in:
andreas-unleash 2022-06-08 14:47:44 +03:00
parent 88f2bef1be
commit d50edfa294
4 changed files with 0 additions and 528 deletions

View File

@ -1,178 +0,0 @@
import { Dispatch, SetStateAction, useContext, VFC } from 'react';
import classnames from 'classnames';
import { Link } from 'react-router-dom';
import { List, ListItem } from '@mui/material';
import useMediaQuery from '@mui/material/useMediaQuery';
import { IFlags } from 'interfaces/uiConfig';
import { SearchField } from 'component/common/SearchField/SearchField';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import AccessContext from 'contexts/AccessContext';
import { IFeaturesFilter } from 'hooks/useFeaturesFilter';
import { FeatureToggleListItem } from './FeatureToggleListItem/FeatureToggleListItem';
import { FeatureToggleListActions } from './FeatureToggleListActions/FeatureToggleListActions';
import { CreateFeatureButton } from '../CreateFeatureButton/CreateFeatureButton';
import { IFeaturesSort } from 'hooks/useFeaturesSort';
import { FeatureSchema } from 'openapi';
import { useStyles } from './styles';
interface IFeatureToggleListProps {
features: FeatureSchema[];
loading?: boolean;
flags?: IFlags;
filter: IFeaturesFilter;
setFilter: Dispatch<SetStateAction<IFeaturesFilter>>;
sort: IFeaturesSort;
setSort: Dispatch<SetStateAction<IFeaturesSort>>;
onRevive?: (feature: string) => void;
inProject?: boolean;
isArchive?: boolean;
}
const loadingFeaturesPlaceholder: FeatureSchema[] = Array(10)
.fill({
createdAt: '2021-03-19T09:16:21.329Z',
description: ' ',
enabled: true,
lastSeenAt: '2021-03-24T10:46:38.036Z',
name: '',
project: 'default',
stale: true,
strategies: [],
variants: [],
type: 'release',
archived: false,
environments: [],
impressionData: false,
})
.map((feature, index) => ({ ...feature, name: `${index}` })); // ID for React key
export const FeatureToggleList: VFC<IFeatureToggleListProps> = ({
features,
onRevive,
inProject,
isArchive,
loading,
flags,
filter,
setFilter,
sort,
setSort,
}) => {
const { hasAccess } = useContext(AccessContext);
const { classes: styles } = useStyles();
const smallScreen = useMediaQuery('(max-width:800px)');
const mobileView = useMediaQuery('(max-width:600px)');
const setFilterQuery = (v: string) => {
const query = v && typeof v === 'string' ? v.trim() : '';
setFilter(prev => ({ ...prev, query }));
};
const renderFeatures = () => {
if (loading) {
return loadingFeaturesPlaceholder.map(feature => (
<FeatureToggleListItem
key={feature.name}
feature={feature}
onRevive={onRevive}
hasAccess={hasAccess}
className={'skeleton'}
flags={flags}
/>
));
}
return (
<ConditionallyRender
condition={features.length > 0}
show={features.map(feature => (
<FeatureToggleListItem
key={feature.name}
feature={feature}
onRevive={onRevive}
hasAccess={hasAccess}
flags={flags}
inProject={inProject}
/>
))}
elseShow={
<ListItem className={styles.emptyStateListItem}>
No archived features.
</ListItem>
}
/>
);
};
const searchResultsHeader = filter.query
? ` (${features.length} matches)`
: '';
const headerTitle = isArchive
? inProject
? `Project Archived Features ${searchResultsHeader}`
: `Archived Features ${searchResultsHeader}`
: `Features ${searchResultsHeader}`;
return (
<div>
<div
className={classnames(styles.searchBarContainer, {
dense: inProject,
})}
>
<SearchField
initialValue={filter.query}
updateValue={setFilterQuery}
showValueChip={!mobileView}
className={classnames(styles.searchBar, {
skeleton: loading,
})}
/>
<ConditionallyRender
condition={!mobileView && !isArchive}
show={<Link to="/archive">Archive</Link>}
/>
</div>
<PageContent
header={
<PageHeader
loading={loading}
title={headerTitle}
actions={
<div className={styles.actionsContainer}>
<ConditionallyRender
condition={!smallScreen}
show={
<FeatureToggleListActions
filter={filter}
setFilter={setFilter}
sort={sort}
setSort={setSort}
loading={loading}
inProject={inProject}
/>
}
/>
<ConditionallyRender
condition={!isArchive}
show={
<CreateFeatureButton
filter={filter}
loading={Boolean(loading)}
/>
}
/>
</div>
}
/>
}
>
<List>{renderFeatures()}</List>
</PageContent>
</div>
);
};

View File

@ -1,99 +0,0 @@
import { Dispatch, MouseEventHandler, SetStateAction, VFC } from 'react';
import { MenuItem, Typography } from '@mui/material';
import DropdownMenu from 'component/common/DropdownMenu/DropdownMenu';
import ProjectSelect from 'component/common/ProjectSelect/ProjectSelect';
import useLoading from 'hooks/useLoading';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import {
createFeaturesFilterSortOptions,
FeaturesSortType,
IFeaturesSort,
} from 'hooks/useFeaturesSort';
import { useStyles } from './styles';
import { IFeaturesFilter } from 'hooks/useFeaturesFilter';
let sortOptions = createFeaturesFilterSortOptions();
interface IFeatureToggleListActionsProps {
filter: IFeaturesFilter;
setFilter: Dispatch<SetStateAction<IFeaturesFilter>>;
sort: IFeaturesSort;
setSort: Dispatch<SetStateAction<IFeaturesSort>>;
loading?: boolean;
inProject?: boolean;
}
export const FeatureToggleListActions: VFC<IFeatureToggleListActionsProps> = ({
filter,
setFilter,
sort,
setSort,
loading = false,
inProject,
}) => {
const { classes: styles } = useStyles();
const { uiConfig } = useUiConfig();
const ref = useLoading(loading);
const handleSort: MouseEventHandler = e => {
const type = (e.target as Element)
.getAttribute('data-target')
?.trim() as FeaturesSortType;
if (type) {
setSort(prev => ({ ...prev, type }));
}
};
const selectedOption =
sortOptions.find(o => o.type === sort.type) || sortOptions[0];
if (inProject) {
sortOptions = sortOptions.filter(option => option.type !== 'project');
}
const renderSortingOptions = () =>
sortOptions.map(option => (
<MenuItem
style={{ fontSize: '14px' }}
key={option.type}
disabled={option.type === sort.type}
data-target={option.type}
>
{option.name}
</MenuItem>
));
return (
<div className={styles.actions} ref={ref}>
<Typography variant="body2" data-loading>
Sorted by:
</Typography>
<DropdownMenu
id={'sorting'}
label={`By ${selectedOption.name}`}
callback={handleSort}
renderOptions={renderSortingOptions}
title="Sort by"
style={{ textTransform: 'lowercase', fontWeight: 'normal' }}
data-loading
/>
<ConditionallyRender
condition={uiConfig.flags.P && !inProject}
show={
<ProjectSelect
currentProjectId={filter.project}
updateCurrentProject={project =>
setFilter(prev => ({ ...prev, project }))
}
style={{
textTransform: 'lowercase',
fontWeight: 'normal',
}}
data-loading
/>
}
/>
</div>
);
};

View File

@ -1,12 +0,0 @@
import { makeStyles } from 'tss-react/mui';
export const useStyles = makeStyles()({
actions: {
'& > *': {
margin: '0 0.25rem',
},
marginRight: '0.25rem',
display: 'flex',
alignItems: 'center',
},
});

View File

@ -1,239 +0,0 @@
import React, { useMemo } from 'react';
import { basePath } from 'utils/formatPath';
import { createPersistentGlobalStateHook } from './usePersistentGlobalState';
import {
expired,
getDiffInDays,
toggleExpiryByTypeMap,
} from 'component/Reporting/utils';
import { FeatureSchema } from 'openapi';
export type FeaturesSortType =
| 'name'
| 'expired'
| 'type'
| 'enabled'
| 'stale'
| 'created'
| 'archived'
| 'last-seen'
| 'status'
| 'project';
export interface IFeaturesSort {
type: FeaturesSortType;
desc?: boolean;
}
export interface IFeaturesSortOutput {
sort: IFeaturesSort;
sorted: FeatureSchema[];
setSort: React.Dispatch<React.SetStateAction<IFeaturesSort>>;
}
export interface IFeaturesFilterSortOption {
type: FeaturesSortType;
name: string;
}
// Store the features sort state globally, and in localStorage.
// When changing the format of IFeaturesSort, change the version as well.
const useFeaturesSortState = createPersistentGlobalStateHook<IFeaturesSort>(
`${basePath}:useFeaturesSort:v1`,
{ type: 'name' }
);
export const useFeaturesSort = (
features: FeatureSchema[]
): IFeaturesSortOutput => {
const [sort, setSort] = useFeaturesSortState();
const sorted = useMemo(() => {
return sortFeatures(features, sort);
}, [features, sort]);
return {
setSort,
sort,
sorted,
};
};
export const createFeaturesFilterSortOptions =
(): IFeaturesFilterSortOption[] => {
return [
{ type: 'name', name: 'Name' },
{ type: 'type', name: 'Type' },
{ type: 'enabled', name: 'Enabled' },
{ type: 'stale', name: 'Stale' },
{ type: 'status', name: 'Status' },
{ type: 'created', name: 'Created' },
{ type: 'archived', name: 'Archived' },
{ type: 'last-seen', name: 'Last seen' },
{ type: 'project', name: 'Project' },
];
};
const sortAscendingFeatures = (
features: FeatureSchema[],
sort: IFeaturesSort
): FeatureSchema[] => {
switch (sort.type) {
case 'enabled':
return sortByEnabled(features);
case 'stale':
return sortByStale(features);
case 'created':
return sortByCreated(features);
case 'archived':
return sortByArchived(features);
case 'last-seen':
return sortByLastSeen(features);
case 'name':
return sortByName(features);
case 'project':
return sortByProject(features);
case 'type':
return sortByType(features);
case 'expired':
return sortByExpired(features);
case 'status':
return sortByStatus(features);
default:
console.error(`Unknown feature sort type: ${sort.type}`);
return features;
}
};
const sortFeatures = (
features: FeatureSchema[],
sort: IFeaturesSort
): FeatureSchema[] => {
const sorted = sortAscendingFeatures(features, sort);
if (sort.desc) {
return [...sorted].reverse();
}
return sorted;
};
const sortByEnabled = (
features: Readonly<FeatureSchema[]>
): FeatureSchema[] => {
return [...features].sort((a, b) =>
a.enabled === b.enabled ? 0 : a.enabled ? -1 : 1
);
};
const sortByStale = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
return [...features].sort((a, b) =>
a.stale === b.stale ? 0 : a.stale ? -1 : 1
);
};
const sortByLastSeen = (
features: Readonly<FeatureSchema[]>
): FeatureSchema[] => {
return [...features].sort((a, b) =>
a.lastSeenAt && b.lastSeenAt
? compareNullableDates(b.lastSeenAt, a.lastSeenAt)
: a.lastSeenAt
? -1
: b.lastSeenAt
? 1
: compareNullableDates(b.createdAt, a.createdAt)
);
};
const sortByCreated = (
features: Readonly<FeatureSchema[]>
): FeatureSchema[] => {
return [...features].sort((a, b) =>
compareNullableDates(b.createdAt, a.createdAt)
);
};
const sortByArchived = (
features: Readonly<FeatureSchema[]>
): FeatureSchema[] => {
return [...features].sort((a, b) =>
compareNullableDates(b.archivedAt, a.archivedAt)
);
};
const sortByName = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
return [...features].sort((a, b) => a.name.localeCompare(b.name));
};
const sortByProject = (
features: Readonly<FeatureSchema[]>
): FeatureSchema[] => {
return [...features].sort((a, b) =>
a.project && b.project
? a.project.localeCompare(b.project)
: a.project
? 1
: b.project
? -1
: 0
);
};
const sortByType = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
return [...features].sort((a, b) =>
a.type && b.type
? a.type.localeCompare(b.type)
: a.type
? 1
: b.type
? -1
: 0
);
};
const compareNullableDates = (
a: Date | null | undefined,
b: Date | null | undefined
): number => {
return a && b ? a?.getTime?.() - b?.getTime?.() : a ? 1 : b ? -1 : 0;
};
const sortByExpired = (
features: Readonly<FeatureSchema[]>
): FeatureSchema[] => {
return [...features].sort((a, b) => {
const now = new Date();
const dateA = a.createdAt!;
const dateB = b.createdAt!;
const diffA = getDiffInDays(dateA, now);
const diffB = getDiffInDays(dateB, now);
if (!expired(diffA, a.type!) && expired(diffB, b.type!)) {
return 1;
}
if (expired(diffA, a.type!) && !expired(diffB, b.type!)) {
return -1;
}
const expiration = toggleExpiryByTypeMap as Record<string, number>;
const expiredByA = a.type ? diffA - expiration[a.type] : 0;
const expiredByB = b.type ? diffB - expiration[b.type] : 0;
return expiredByB - expiredByA;
});
};
const sortByStatus = (features: Readonly<FeatureSchema[]>): FeatureSchema[] => {
return [...features].sort((a, b) => {
if (a.stale) {
return 1;
} else if (b.stale) {
return -1;
} else {
return 0;
}
});
};