From 6fc30d3a791129a90920e7b3ae3f2bf1d4a289ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Fri, 8 Oct 2021 15:18:43 +0200 Subject: [PATCH] feat: add feature status (#403) * feat: add feature status * fix: use feature status in project feature list * fix: text size * fix: project view * fix: padding * fix: lint * fix: snapshots * fix: text size * fix: snapshots * fix: size * fix: revert size * fix: update snapshots Co-authored-by: Fredrik Oseberg --- frontend/package.json | 1 + .../FeatureToggleListItem.jsx | 56 +------ .../feature-list-item-component-test.jsx.snap | 139 ++++++------------ .../FeatureToggleListNew.styles.ts | 8 +- .../FeatureToggleListNew.tsx | 26 +++- .../FeatureToggleListNewItem.tsx | 23 ++- .../FeatureStatus/FeatureStatus.styles.ts | 16 ++ .../FeatureStatus/FeatureStatus.tsx | 105 +++++++++++++ .../project/Project/Project.styles.ts | 1 + .../ProjectFeatureToggles.styles.ts | 6 +- .../Project/ProjectInfo/ProjectInfo.styles.ts | 7 +- .../Project/ProjectInfo/ProjectInfo.tsx | 6 +- .../project/Project/ProjectOverview.tsx | 10 +- frontend/src/interfaces/featureToggle.ts | 3 +- frontend/yarn.lock | 7 + 15 files changed, 246 insertions(+), 168 deletions(-) create mode 100644 frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.styles.ts create mode 100644 frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.tsx diff --git a/frontend/package.json b/frontend/package.json index 767c382fd6..83fb5f6e54 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -49,6 +49,7 @@ "@types/react": "17.0.27", "@types/react-dom": "17.0.9", "@types/react-router-dom": "5.3.1", + "@types/react-timeago": "^4.1.3", "@welldone-software/why-did-you-render": "6.2.1", "array-move": "3.0.1", "classnames": "2.3.1", diff --git a/frontend/src/component/feature/FeatureToggleList/FeatureToggleListItem/FeatureToggleListItem.jsx b/frontend/src/component/feature/FeatureToggleList/FeatureToggleListItem/FeatureToggleListItem.jsx index d7011a884d..0e850a913e 100644 --- a/frontend/src/component/feature/FeatureToggleList/FeatureToggleListItem/FeatureToggleListItem.jsx +++ b/frontend/src/component/feature/FeatureToggleList/FeatureToggleListItem/FeatureToggleListItem.jsx @@ -3,20 +3,22 @@ import PropTypes from 'prop-types'; import classnames from 'classnames'; import { Link } from 'react-router-dom'; -import { Switch, IconButton, ListItem } from '@material-ui/core'; +import { IconButton, ListItem } from '@material-ui/core'; import { Undo } from '@material-ui/icons'; import TimeAgo from 'react-timeago'; -import Progress from '../../ProgressWheel'; import Status from '../../status-component'; import FeatureToggleListItemChip from './FeatureToggleListItemChip'; import ConditionallyRender from '../../../common/ConditionallyRender/ConditionallyRender'; import { UPDATE_FEATURE } from '../../../AccessProvider/permissions'; -import { calc, styles as commonStyles } from '../../../common'; +import { styles as commonStyles } from '../../../common'; import { useStyles } from './styles'; import { getTogglePath } from '../../../../utils/route-path-helpers'; +import FeatureStatus from '../../FeatureView2/FeatureStatus/FeatureStatus'; + + const FeatureToggleListItem = ({ feature, @@ -30,25 +32,9 @@ const FeatureToggleListItem = ({ }) => { const styles = useStyles(); - const { name, description, enabled, type, stale, createdAt, project } = + const { name, description, type, stale, createdAt, project, lastSeenAt } = feature; - const { showLastHour = false } = settings; - const isStale = showLastHour - ? metricsLastHour.isFallback - : metricsLastMinute.isFallback; - const percent = - 1 * - (showLastHour - ? calc( - metricsLastHour.yes, - metricsLastHour.yes + metricsLastHour.no, - 0 - ) - : calc( - metricsLastMinute.yes, - metricsLastMinute.yes + metricsLastMinute.no, - 0 - )); + const featureUrl = toggleFeature === undefined ? `/projects/${feature.project}/archived/${name}/metrics` @@ -60,33 +46,7 @@ const FeatureToggleListItem = ({ className={classnames(styles.listItem, rest.className)} > - - - - toggleFeature(!enabled, name)} - checked={enabled} - /> - } - elseShow={ - - } - /> + - - - - - - - - - - + ⊕ - - + - - - - - - - - - - - + ⊕ - - + ({ display: 'none', }, }, + tableCellStatus: { + width: '50px', + }, tableCellName: { width: '250px', + display: 'flex', }, tableCellEnv: { width: '20px', }, tableCellType: { - display: 'flex', + width: '32px', alignItems: 'center', [theme.breakpoints.down('sm')]: { display: 'none', }, }, icon: { - marginRight: '0.3rem', + color: theme.palette.grey[600], }, })); diff --git a/frontend/src/component/feature/FeatureToggleListNew/FeatureToggleListNew.tsx b/frontend/src/component/feature/FeatureToggleListNew/FeatureToggleListNew.tsx index 85ca027a87..1688b11ef5 100644 --- a/frontend/src/component/feature/FeatureToggleListNew/FeatureToggleListNew.tsx +++ b/frontend/src/component/feature/FeatureToggleListNew/FeatureToggleListNew.tsx @@ -11,7 +11,10 @@ import FeatureToggleListNewItem from './FeatureToggleListNewItem/FeatureToggleLi import usePagination from '../../../hooks/usePagination'; import loadingFeatures from './FeatureToggleListNewItem/loadingFeatures'; -import { IFeatureToggleListItem } from '../../../interfaces/featureToggle'; +import { + IFeatureToggle, + IFeatureToggleListItem, +} from '../../../interfaces/featureToggle'; import PaginateUI from '../../common/PaginateUI/PaginateUI'; interface IFeatureToggleListNewProps { features: IFeatureToggleListItem[]; @@ -26,7 +29,7 @@ const FeatureToggleListNew = ({ }: IFeatureToggleListNewProps) => { const styles = useStyles(); const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } = - usePagination(features, 9); + usePagination(features, 50); const getEnvironments = () => { if (features.length > 0) { @@ -57,7 +60,7 @@ const FeatureToggleListNew = ({ }); } - return page.map((feature: IFeatureToggleListItem) => { + return page.map((feature: IFeatureToggle) => { return ( ); }); @@ -78,12 +82,12 @@ const FeatureToggleListNew = ({ - Name + Status Type + + Name + {getEnvironments().map((env: any) => { return ( - {name} + -
+ + {' '} - {type} -
+ /> +
} /> + + {name} + + {environments.map((env: IEnvironments) => { return ( diff --git a/frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.styles.ts b/frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.styles.ts new file mode 100644 index 0000000000..c6a3a4a6af --- /dev/null +++ b/frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.styles.ts @@ -0,0 +1,16 @@ +import { makeStyles } from '@material-ui/core/styles'; + +export const useStyles = makeStyles(theme => ({ + container: { + width: '42px', + height: '42px', + fontSize: '0.7em', + background: 'gray', + borderRadius: '3px', + textAlign: 'center', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + padding: '13px 10px', + }, +})); diff --git a/frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.tsx b/frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.tsx new file mode 100644 index 0000000000..a7762c4008 --- /dev/null +++ b/frontend/src/component/feature/FeatureView2/FeatureStatus/FeatureStatus.tsx @@ -0,0 +1,105 @@ +import { useStyles } from './FeatureStatus.styles'; +import TimeAgo from 'react-timeago'; +import ConditionallyRender from '../../../common/ConditionallyRender'; +import { Tooltip } from '@material-ui/core'; + +function generateUnit(unit?: string): string { + switch (unit) { + case 'second': + return 's'; + case 'minute': + return 'm'; + case 'hour': + return 'h'; + case 'day': + return 'D'; + case 'week': + return 'W'; + case 'month': + return 'M'; + case 'year': + return 'Y'; + default: + return ''; + } +} + +function getColor(unit?: string): string { + switch (unit) { + case 'second': + return '#98E3AF'; + case 'minute': + return '#98E3AF'; + case 'hour': + return '#98E3AF'; + case 'day': + return '#98E3AF'; + case 'week': + return '#ECD875'; + case 'month': + return '#F5A69A'; + case 'year': + return '#F5A69A'; + default: + return '#EDF0F1'; + } +} + +interface FeatureStatusProps { + lastSeenAt?: Date; +} + +const FeatureStatus = ({ lastSeenAt }: FeatureStatusProps) => { + const styles = useStyles(); + + const Wrapper = ( + props: React.PropsWithChildren<{ color: string; toolTip: string }> + ) => { + return ( + +
+ {props.children} +
+
+ ); + }; + + return ( + { + return ( + + {value} + {generateUnit(unit)} + + ); + }} + /> + } + elseShow={ + + + + } + /> + ); +}; + +export default FeatureStatus; diff --git a/frontend/src/component/project/Project/Project.styles.ts b/frontend/src/component/project/Project/Project.styles.ts index b0b7067724..a285c6ca4e 100644 --- a/frontend/src/component/project/Project/Project.styles.ts +++ b/frontend/src/component/project/Project/Project.styles.ts @@ -8,6 +8,7 @@ export const useStyles = makeStyles(theme => ({ flexDirection: 'column', }, }, + projectToggles: { width: '100%', minHeight: '100%' }, header: { backgroundColor: '#fff', borderRadius: '10px', diff --git a/frontend/src/component/project/Project/ProjectFeatureToggles/ProjectFeatureToggles.styles.ts b/frontend/src/component/project/Project/ProjectFeatureToggles/ProjectFeatureToggles.styles.ts index 69f48f7efe..892da3ae12 100644 --- a/frontend/src/component/project/Project/ProjectFeatureToggles/ProjectFeatureToggles.styles.ts +++ b/frontend/src/component/project/Project/ProjectFeatureToggles/ProjectFeatureToggles.styles.ts @@ -3,9 +3,11 @@ import { makeStyles } from '@material-ui/core/styles'; export const useStyles = makeStyles(theme => ({ container: { boxShadow: 'none', - marginLeft: '2rem', - width: '100%', + marginLeft: '1rem', + minHeight: '100%', + width: 'calc(100% - 1rem)', position: 'relative', + paddingBottom: '4rem', [theme.breakpoints.down('sm')]: { marginLeft: '0', paddingBottom: '4rem', diff --git a/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.styles.ts b/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.styles.ts index 4090f7bb73..9a86279426 100644 --- a/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.styles.ts +++ b/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.styles.ts @@ -14,6 +14,11 @@ export const useStyles = makeStyles(theme => ({ marginBottom: '1rem', }, }, + percentageContainer: { + display: 'flex', + justifyContent: 'center', + margin: '1rem 0', + }, projectIcon: { margin: '2rem 0', [theme.breakpoints.down('sm')]: { @@ -35,7 +40,7 @@ export const useStyles = makeStyles(theme => ({ infoSection: { margin: '0', textAlign: 'center', - marginBottom: '1.5rem', + marginBottom: '1rem', backgroundColor: '#fff', borderRadius: '10px', width: '100%', diff --git a/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.tsx b/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.tsx index aa72a7e8c5..046dd8a291 100644 --- a/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.tsx +++ b/frontend/src/component/project/Project/ProjectInfo/ProjectInfo.tsx @@ -3,9 +3,9 @@ import { Link } from 'react-router-dom'; import ArrowForwardIcon from '@material-ui/icons/ArrowForward'; import classnames from 'classnames'; -import { ReactComponent as ProjectIcon } from '../../../../assets/icons/projectIcon.svg'; import { useCommonStyles } from '../../../../common.styles'; import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig'; +import PercentageCircle from '../../../common/PercentageCircle/PercentageCircle'; interface IProjectInfoProps { id: string; @@ -34,8 +34,8 @@ const ProjectInfo = ({