mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	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 <fredrik.no@gmail.com>
This commit is contained in:
		
							parent
							
								
									7406cbbaa7
								
							
						
					
					
						commit
						6fc30d3a79
					
				| @ -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", | ||||
|  | ||||
| @ -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)} | ||||
|         > | ||||
|             <span className={styles.listItemMetric}> | ||||
|                 <Progress | ||||
|                     strokeWidth={15} | ||||
|                     percentage={percent} | ||||
|                     isFallback={isStale} | ||||
|                 /> | ||||
|             </span> | ||||
|             <span className={styles.listItemToggle}> | ||||
|                 <ConditionallyRender | ||||
|                     condition={hasAccess(UPDATE_FEATURE, project)} | ||||
|                     show={ | ||||
|                         <Switch | ||||
|                             disabled={toggleFeature === undefined} | ||||
|                             title={`Toggle ${name}`} | ||||
|                             key="left-actions" | ||||
|                             onChange={() => toggleFeature(!enabled, name)} | ||||
|                             checked={enabled} | ||||
|                         /> | ||||
|                     } | ||||
|                     elseShow={ | ||||
|                         <Switch | ||||
|                             disabled | ||||
|                             title={`Toggle ${name}`} | ||||
|                             key="left-actions" | ||||
|                             checked={enabled} | ||||
|                         /> | ||||
|                     } | ||||
|                 /> | ||||
|                 <FeatureStatus lastSeenAt={lastSeenAt} /> | ||||
|             </span> | ||||
|             <span className={classnames(styles.listItemLink)}> | ||||
|                 <Link | ||||
|  | ||||
| @ -8,55 +8,33 @@ exports[`renders correctly with one feature 1`] = ` | ||||
|   <span | ||||
|     className="makeStyles-listItemMetric-2" | ||||
|   > | ||||
|     <svg | ||||
|       viewBox="0 0 24 24" | ||||
|     > | ||||
|       <path | ||||
|         d="M17.3,18C19,16.5 20,14.4 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12C4,14.4 5,16.5 6.7,18C8.2,16.7 10,16 12,16C14,16 15.9,16.7 17.3,18M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M7,9A1,1 0 0,1 8,10A1,1 0 0,1 7,11A1,1 0 0,1 6,10A1,1 0 0,1 7,9M10,6A1,1 0 0,1 11,7A1,1 0 0,1 10,8A1,1 0 0,1 9,7A1,1 0 0,1 10,6M17,9A1,1 0 0,1 18,10A1,1 0 0,1 17,11A1,1 0 0,1 16,10A1,1 0 0,1 17,9M14.4,6.1C14.9,6.3 15.1,6.9 15,7.4L13.6,10.8C13.8,11.1 14,11.5 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12C10,11 10.7,10.1 11.7,10L13.1,6.7C13.3,6.1 13.9,5.9 14.4,6.1Z" | ||||
|         fill="#E0E0E0" | ||||
|       /> | ||||
|     </svg> | ||||
|   </span> | ||||
|   <span> | ||||
|     <span | ||||
|       className="MuiSwitch-root" | ||||
|     <div | ||||
|       aria-describedby={null} | ||||
|       className="makeStyles-container-6" | ||||
|       onBlur={[Function]} | ||||
|       onFocus={[Function]} | ||||
|       onMouseLeave={[Function]} | ||||
|       onMouseOver={[Function]} | ||||
|       onTouchEnd={[Function]} | ||||
|       onTouchStart={[Function]} | ||||
|       style={ | ||||
|         Object { | ||||
|           "background": "#EDF0F1", | ||||
|           "fontSize": "0.8rem", | ||||
|         } | ||||
|       } | ||||
|       title="No usage reported" | ||||
|     > | ||||
|       <span | ||||
|         aria-disabled={false} | ||||
|         className="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-6 MuiSwitch-switchBase MuiSwitch-colorSecondary" | ||||
|         onBlur={[Function]} | ||||
|         onDragLeave={[Function]} | ||||
|         onFocus={[Function]} | ||||
|         onKeyDown={[Function]} | ||||
|         onKeyUp={[Function]} | ||||
|         onMouseDown={[Function]} | ||||
|         onMouseLeave={[Function]} | ||||
|         onMouseUp={[Function]} | ||||
|         onTouchEnd={[Function]} | ||||
|         onTouchMove={[Function]} | ||||
|         onTouchStart={[Function]} | ||||
|         tabIndex={null} | ||||
|         title="Toggle Another" | ||||
|         style={ | ||||
|           Object { | ||||
|             "fontSize": "1.4rem", | ||||
|           } | ||||
|         } | ||||
|       > | ||||
|         <span | ||||
|           className="MuiIconButton-label" | ||||
|         > | ||||
|           <input | ||||
|             checked={false} | ||||
|             className="PrivateSwitchBase-input-9 MuiSwitch-input" | ||||
|             disabled={false} | ||||
|             onChange={[Function]} | ||||
|             type="checkbox" | ||||
|           /> | ||||
|           <span | ||||
|             className="MuiSwitch-thumb" | ||||
|           /> | ||||
|         </span> | ||||
|         ⊕ | ||||
|       </span> | ||||
|       <span | ||||
|         className="MuiSwitch-track" | ||||
|       /> | ||||
|     </span> | ||||
|     </div> | ||||
|   </span> | ||||
|   <span | ||||
|     className="makeStyles-listItemLink-4" | ||||
| @ -105,58 +83,33 @@ exports[`renders correctly with one feature without permission 1`] = ` | ||||
|   <span | ||||
|     className="makeStyles-listItemMetric-2" | ||||
|   > | ||||
|     <svg | ||||
|       viewBox="0 0 24 24" | ||||
|     > | ||||
|       <path | ||||
|         d="M17.3,18C19,16.5 20,14.4 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12C4,14.4 5,16.5 6.7,18C8.2,16.7 10,16 12,16C14,16 15.9,16.7 17.3,18M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M7,9A1,1 0 0,1 8,10A1,1 0 0,1 7,11A1,1 0 0,1 6,10A1,1 0 0,1 7,9M10,6A1,1 0 0,1 11,7A1,1 0 0,1 10,8A1,1 0 0,1 9,7A1,1 0 0,1 10,6M17,9A1,1 0 0,1 18,10A1,1 0 0,1 17,11A1,1 0 0,1 16,10A1,1 0 0,1 17,9M14.4,6.1C14.9,6.3 15.1,6.9 15,7.4L13.6,10.8C13.8,11.1 14,11.5 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12C10,11 10.7,10.1 11.7,10L13.1,6.7C13.3,6.1 13.9,5.9 14.4,6.1Z" | ||||
|         fill="#E0E0E0" | ||||
|       /> | ||||
|     </svg> | ||||
|   </span> | ||||
|   <span> | ||||
|     <span | ||||
|       className="MuiSwitch-root" | ||||
|     <div | ||||
|       aria-describedby={null} | ||||
|       className="makeStyles-container-6" | ||||
|       onBlur={[Function]} | ||||
|       onFocus={[Function]} | ||||
|       onMouseLeave={[Function]} | ||||
|       onMouseOver={[Function]} | ||||
|       onTouchEnd={[Function]} | ||||
|       onTouchStart={[Function]} | ||||
|       style={ | ||||
|         Object { | ||||
|           "background": "#EDF0F1", | ||||
|           "fontSize": "0.8rem", | ||||
|         } | ||||
|       } | ||||
|       title="No usage reported" | ||||
|     > | ||||
|       <span | ||||
|         aria-disabled={false} | ||||
|         className="MuiButtonBase-root MuiIconButton-root PrivateSwitchBase-root-6 MuiSwitch-switchBase MuiSwitch-colorSecondary" | ||||
|         onBlur={[Function]} | ||||
|         onDragLeave={[Function]} | ||||
|         onFocus={[Function]} | ||||
|         onKeyDown={[Function]} | ||||
|         onKeyUp={[Function]} | ||||
|         onMouseDown={[Function]} | ||||
|         onMouseLeave={[Function]} | ||||
|         onMouseUp={[Function]} | ||||
|         onTouchEnd={[Function]} | ||||
|         onTouchMove={[Function]} | ||||
|         onTouchStart={[Function]} | ||||
|         tabIndex={null} | ||||
|         title="Toggle Another" | ||||
|         style={ | ||||
|           Object { | ||||
|             "fontSize": "1.4rem", | ||||
|           } | ||||
|         } | ||||
|       > | ||||
|         <span | ||||
|           className="MuiIconButton-label" | ||||
|         > | ||||
|           <input | ||||
|             checked={false} | ||||
|             className="PrivateSwitchBase-input-9 MuiSwitch-input" | ||||
|             disabled={false} | ||||
|             onChange={[Function]} | ||||
|             type="checkbox" | ||||
|           /> | ||||
|           <span | ||||
|             className="MuiSwitch-thumb" | ||||
|           /> | ||||
|         </span> | ||||
|         <span | ||||
|           className="MuiTouchRipple-root" | ||||
|         /> | ||||
|         ⊕ | ||||
|       </span> | ||||
|       <span | ||||
|         className="MuiSwitch-track" | ||||
|       /> | ||||
|     </span> | ||||
|     </div> | ||||
|   </span> | ||||
|   <span | ||||
|     className="makeStyles-listItemLink-4" | ||||
|  | ||||
| @ -19,20 +19,24 @@ export const useStyles = makeStyles(theme => ({ | ||||
|             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], | ||||
|     }, | ||||
| })); | ||||
|  | ||||
| @ -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 ( | ||||
|                 <FeatureToggleListNewItem | ||||
|                     key={feature.name} | ||||
| @ -65,6 +68,7 @@ const FeatureToggleListNew = ({ | ||||
|                     type={feature.type} | ||||
|                     environments={feature.environments} | ||||
|                     projectId={projectId} | ||||
|                     lastSeenAt={feature.lastSeenAt} | ||||
|                 /> | ||||
|             ); | ||||
|         }); | ||||
| @ -78,12 +82,12 @@ const FeatureToggleListNew = ({ | ||||
|                         <TableCell | ||||
|                             className={classnames( | ||||
|                                 styles.tableCell, | ||||
|                                 styles.tableCellName, | ||||
|                                 styles.tableCellStatus, | ||||
|                                 styles.tableCellHeader | ||||
|                             )} | ||||
|                             align="left" | ||||
|                         > | ||||
|                             <span data-loading>Name</span> | ||||
|                             <span data-loading>Status</span> | ||||
|                         </TableCell> | ||||
|                         <TableCell | ||||
|                             className={classnames( | ||||
| @ -91,10 +95,20 @@ const FeatureToggleListNew = ({ | ||||
|                                 styles.tableCellHeader, | ||||
|                                 styles.typeHeader | ||||
|                             )} | ||||
|                             align="left" | ||||
|                             align="center" | ||||
|                         > | ||||
|                             <span data-loading>Type</span> | ||||
|                         </TableCell> | ||||
|                         <TableCell | ||||
|                             className={classnames( | ||||
|                                 styles.tableCell, | ||||
|                                 styles.tableCellName, | ||||
|                                 styles.tableCellHeader | ||||
|                             )} | ||||
|                             align="left" | ||||
|                         > | ||||
|                             <span data-loading>Name</span> | ||||
|                         </TableCell> | ||||
|                         {getEnvironments().map((env: any) => { | ||||
|                             return ( | ||||
|                                 <TableCell | ||||
|  | ||||
| @ -3,6 +3,7 @@ import { | ||||
|     Switch, | ||||
|     TableCell, | ||||
|     TableRow, | ||||
|     Tooltip, | ||||
|     useMediaQuery, | ||||
|     useTheme, | ||||
| } from '@material-ui/core'; | ||||
| @ -16,16 +17,19 @@ import useToast from '../../../../hooks/useToast'; | ||||
| import { getTogglePath } from '../../../../utils/route-path-helpers'; | ||||
| import { SyntheticEvent } from 'react-router/node_modules/@types/react'; | ||||
| import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| import FeatureStatus from '../../FeatureView2/FeatureStatus/FeatureStatus'; | ||||
| 
 | ||||
| interface IFeatureToggleListNewItemProps { | ||||
|     name: string; | ||||
|     type: string; | ||||
|     environments: IEnvironments[]; | ||||
|     environments: IFeatureEnvironment[]; | ||||
|     projectId: string; | ||||
|     lastSeenAt?: Date; | ||||
| } | ||||
| 
 | ||||
| const FeatureToggleListNewItem = ({ | ||||
|     name, | ||||
|     lastSeenAt, | ||||
|     type, | ||||
|     environments, | ||||
|     projectId, | ||||
| @ -35,7 +39,7 @@ const FeatureToggleListNewItem = ({ | ||||
|     const smallScreen = useMediaQuery(theme.breakpoints.down('sm')); | ||||
|     const { toggleFeatureByEnvironment } = useToggleFeatureByEnv( | ||||
|         projectId, | ||||
|         name | ||||
|         name, | ||||
|     ); | ||||
|     const { uiConfig } = useUiConfig(); | ||||
|      | ||||
| @ -74,22 +78,25 @@ const FeatureToggleListNewItem = ({ | ||||
|         <> | ||||
|             <TableRow className={styles.tableRow}> | ||||
|                 <TableCell className={styles.tableCell} align="left" onClick={onClick}> | ||||
|                     <span data-loading>{name}</span> | ||||
|                     <FeatureStatus lastSeenAt={lastSeenAt} /> | ||||
|                 </TableCell> | ||||
|                 <ConditionallyRender | ||||
|                     condition={!smallScreen} | ||||
|                     show={ | ||||
|                         <TableCell className={styles.tableCell} align="left" onClick={onClick}> | ||||
|                             <div className={styles.tableCellType}> | ||||
|                         <TableCell className={styles.tableCell} align="center" onClick={onClick}> | ||||
|                             <Tooltip arrow placement="right" title={type}> | ||||
|                                 <IconComponent | ||||
|                                     data-loading | ||||
|                                     className={styles.icon} | ||||
|                                 />{' '} | ||||
|                                 <span data-loading>{type}</span> | ||||
|                             </div> | ||||
|                                 /> | ||||
|                             </Tooltip> | ||||
|                         </TableCell> | ||||
|                     } | ||||
|                 /> | ||||
|                 <TableCell className={styles.tableCell} align="left" onClick={onClick}> | ||||
|                     <span data-loading>{name}</span> | ||||
|                 </TableCell> | ||||
|                  | ||||
| 
 | ||||
|                 {environments.map((env: IEnvironments) => { | ||||
|                     return ( | ||||
|  | ||||
| @ -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', | ||||
|     }, | ||||
| })); | ||||
| @ -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 ( | ||||
|             <Tooltip title={props.toolTip} arrow placement="left"> | ||||
|                 <div | ||||
|                     className={styles.container} | ||||
|                     style={{ background: props.color, fontSize: '0.8rem' }} | ||||
|                 > | ||||
|                     {props.children} | ||||
|                 </div> | ||||
|             </Tooltip> | ||||
|         ); | ||||
|     }; | ||||
| 
 | ||||
|     return ( | ||||
|         <ConditionallyRender | ||||
|             condition={!!lastSeenAt} | ||||
|             show={ | ||||
|                 //@ts-ignore
 | ||||
|                 <TimeAgo | ||||
|                     date={lastSeenAt} | ||||
|                     title="" | ||||
|                     live={false} | ||||
|                     formatter={( | ||||
|                         value: number, | ||||
|                         unit: string, | ||||
|                         suffix: string | ||||
|                     ) => { | ||||
|                         return ( | ||||
|                             <Wrapper | ||||
|                                 toolTip={`Last usage reported ${value} ${unit} ${suffix}`} | ||||
|                                 color={getColor(unit)} | ||||
|                             > | ||||
|                                 {value} | ||||
|                                 {generateUnit(unit)} | ||||
|                             </Wrapper> | ||||
|                         ); | ||||
|                     }} | ||||
|                 /> | ||||
|             } | ||||
|             elseShow={ | ||||
|                 <Wrapper toolTip="No usage reported" color={getColor()}> | ||||
|                     <span style={{ fontSize: '1.4rem' }}>⊕</span> | ||||
|                 </Wrapper> | ||||
|             } | ||||
|         /> | ||||
|     ); | ||||
| }; | ||||
| 
 | ||||
| export default FeatureStatus; | ||||
| @ -8,6 +8,7 @@ export const useStyles = makeStyles(theme => ({ | ||||
|             flexDirection: 'column', | ||||
|         }, | ||||
|     }, | ||||
|     projectToggles: { width: '100%', minHeight: '100%' }, | ||||
|     header: { | ||||
|         backgroundColor: '#fff', | ||||
|         borderRadius: '10px', | ||||
|  | ||||
| @ -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', | ||||
|  | ||||
| @ -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%', | ||||
|  | ||||
| @ -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 = ({ | ||||
|         <aside> | ||||
|             <div className={styles.projectInfo}> | ||||
|                 <div className={styles.infoSection}> | ||||
|                     <div data-loading> | ||||
|                         <ProjectIcon className={styles.projectIcon} /> | ||||
|                     <div data-loading className={styles.percentageContainer}> | ||||
|                         <PercentageCircle percentage={health} /> | ||||
|                     </div> | ||||
|                     <p className={styles.subtitle} data-loading> | ||||
|                         Overall health rating | ||||
|  | ||||
| @ -7,7 +7,7 @@ interface ProjectOverviewProps { | ||||
|     projectId: string; | ||||
| } | ||||
| 
 | ||||
| const ProjectOverview = ({projectId}: ProjectOverviewProps) => { | ||||
| const ProjectOverview = ({ projectId }: ProjectOverviewProps) => { | ||||
|     const { project, loading } = useProject(projectId); | ||||
|     const { members, features, health } = project; | ||||
|     const styles = useStyles(); | ||||
| @ -21,9 +21,13 @@ const ProjectOverview = ({projectId}: ProjectOverviewProps) => { | ||||
|                     health={health} | ||||
|                     featureCount={features?.length} | ||||
|                 /> | ||||
|                 <ProjectFeatureToggles features={features} loading={loading} /> | ||||
|                 <div className={styles.projectToggles}> | ||||
|                     <ProjectFeatureToggles | ||||
|                         features={features} | ||||
|                         loading={loading} | ||||
|                     /> | ||||
|                 </div> | ||||
|             </div> | ||||
|              | ||||
|         </div> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| @ -8,7 +8,6 @@ export interface IFeatureToggleListItem { | ||||
| 
 | ||||
| export interface IEnvironments { | ||||
|     name: string; | ||||
|     displayName: string; | ||||
|     enabled: boolean; | ||||
| } | ||||
| 
 | ||||
| @ -16,7 +15,7 @@ export interface IFeatureToggle { | ||||
|     stale: boolean; | ||||
|     archived: boolean; | ||||
|     createdAt: string; | ||||
|     lastSeenAt: string; | ||||
|     lastSeenAt: Date; | ||||
|     description: string; | ||||
|     environments: IFeatureEnvironment[]; | ||||
|     name: string; | ||||
|  | ||||
| @ -2176,6 +2176,13 @@ | ||||
|     "@types/history" "*" | ||||
|     "@types/react" "*" | ||||
| 
 | ||||
| "@types/react-timeago@^4.1.3": | ||||
|   version "4.1.3" | ||||
|   resolved "https://registry.yarnpkg.com/@types/react-timeago/-/react-timeago-4.1.3.tgz#957baaa9f8ea98457ee63b6a57b57a616066ba35" | ||||
|   integrity sha512-XaaMBzuXLw7lxPPDs/fenlohcf3NDqM5qP4oOL/Meu+Hb1QChW4Igw/SruS1llEqch18RQB3wDTIwvqq4nivvw== | ||||
|   dependencies: | ||||
|     "@types/react" "*" | ||||
| 
 | ||||
| "@types/react-transition-group@^4.2.0": | ||||
|   version "4.4.1" | ||||
|   resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.1.tgz" | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user