1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-17 01:17:29 +02:00
unleash.unleash/frontend/src/component/feature/FeatureToggleList/FeatureToggleList.jsx
2021-11-24 11:41:43 +01:00

237 lines
9.5 KiB
JavaScript

import { useContext, useLayoutEffect, useEffect } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { Link } from 'react-router-dom';
import { Button, List, Tooltip, IconButton, ListItem } from '@material-ui/core';
import useMediaQuery from '@material-ui/core/useMediaQuery';
import { Add } from '@material-ui/icons';
import FeatureToggleListItem from './FeatureToggleListItem';
import SearchField from '../../common/SearchField/SearchField';
import FeatureToggleListActions from './FeatureToggleListActions';
import ConditionallyRender from '../../common/ConditionallyRender/ConditionallyRender';
import PageContent from '../../common/PageContent/PageContent';
import HeaderTitle from '../../common/HeaderTitle';
import loadingFeatures from './loadingFeatures';
import { CREATE_FEATURE } from '../../providers/AccessProvider/permissions';
import AccessContext from '../../../contexts/AccessContext';
import { useStyles } from './styles';
import ListPlaceholder from '../../common/ListPlaceholder/ListPlaceholder';
import { getCreateTogglePath } from '../../../utils/route-path-helpers';
import { NAVIGATE_TO_CREATE_FEATURE } from '../../../testIds';
const FeatureToggleList = ({
fetcher,
features,
settings,
revive,
currentProjectId,
updateSetting,
featureMetrics,
toggleFeature,
archive,
loading,
flags,
}) => {
const { hasAccess } = useContext(AccessContext);
const styles = useStyles();
const smallScreen = useMediaQuery('(max-width:800px)');
const mobileView = useMediaQuery('(max-width:600px)');
useLayoutEffect(() => {
fetcher();
}, [fetcher]);
useEffect(() => {
updateSetting('filter', '');
/* eslint-disable-next-line */
}, []);
const toggleMetrics = () => {
updateSetting('showLastHour', !settings.showLastHour);
};
const setSort = v => {
updateSetting('sort', typeof v === 'string' ? v.trim() : '');
};
const createURL = getCreateTogglePath(currentProjectId, flags.E);
const renderFeatures = () => {
features.forEach(e => {
e.reviveName = e.name;
});
if (loading) {
return loadingFeatures.map(feature => (
<FeatureToggleListItem
key={feature.name}
settings={settings}
metricsLastHour={featureMetrics.lastHour[feature.name]}
metricsLastMinute={featureMetrics.lastMinute[feature.name]}
feature={feature}
toggleFeature={toggleFeature}
revive={revive}
hasAccess={hasAccess}
className={'skeleton'}
flags={flags}
/>
));
}
return (
<ConditionallyRender
condition={features.length > 0}
show={features.map(feature => (
<FeatureToggleListItem
key={feature.name}
settings={settings}
metricsLastHour={featureMetrics.lastHour[feature.name]}
metricsLastMinute={
featureMetrics.lastMinute[feature.name]
}
feature={feature}
toggleFeature={toggleFeature}
revive={revive}
hasAccess={hasAccess}
flags={flags}
/>
))}
elseShow={
<ConditionallyRender
condition={archive}
show={
<ListItem className={styles.emptyStateListItem}>
No archived features.
</ListItem>
}
elseShow={
<ListPlaceholder
text="No features available. Get started by adding a
new feature toggle."
link={createURL}
linkText="Add your first toggle"
/>
}
/>
}
/>
);
};
const headerTitle = archive ? 'Archived Features' : 'Features';
return (
<div className={styles.featureContainer}>
<div className={styles.searchBarContainer}>
<SearchField
updateValue={updateSetting.bind(this, 'filter')}
className={classnames(styles.searchBar, {
skeleton: loading,
})}
/>
<ConditionallyRender
condition={!mobileView && !archive}
show={<Link to="/archive">Archive</Link>}
/>
</div>
<PageContent
headerContent={
<HeaderTitle
loading={loading}
title={headerTitle}
actions={
<div className={styles.actionsContainer}>
<ConditionallyRender
condition={!smallScreen}
show={
<FeatureToggleListActions
settings={settings}
toggleMetrics={toggleMetrics}
setSort={setSort}
updateSetting={updateSetting}
loading={loading}
/>
}
/>
<ConditionallyRender
condition={!archive}
show={
<ConditionallyRender
condition={smallScreen}
show={
<Tooltip title="Create feature toggle">
<IconButton
component={Link}
to={createURL}
data-test={
NAVIGATE_TO_CREATE_FEATURE
}
disabled={
!hasAccess(
CREATE_FEATURE,
currentProjectId
)
}
>
<Add />
</IconButton>
</Tooltip>
}
elseShow={
<Button
to={createURL}
color="primary"
variant="contained"
component={Link}
data-test={
NAVIGATE_TO_CREATE_FEATURE
}
disabled={
!hasAccess(
CREATE_FEATURE,
currentProjectId
)
}
className={classnames({
skeleton: loading,
})}
>
Create feature toggle
</Button>
}
/>
}
/>
</div>
}
/>
}
>
<List>{renderFeatures()}</List>
</PageContent>
</div>
);
};
FeatureToggleList.propTypes = {
features: PropTypes.array.isRequired,
featureMetrics: PropTypes.object.isRequired,
fetcher: PropTypes.func,
revive: PropTypes.func,
updateSetting: PropTypes.func.isRequired,
toggleFeature: PropTypes.func,
settings: PropTypes.object,
history: PropTypes.object.isRequired,
loading: PropTypes.bool,
currentProjectId: PropTypes.string.isRequired,
flags: PropTypes.object,
};
export default FeatureToggleList;