mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: update health report (#541)
* fix: align styling with other pages * feat: add last updat to heath report * add feature status to last seen in health overview * fix: add mobile style * fix:add background color on table hover Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
This commit is contained in:
		
							parent
							
								
									bb38df5293
								
							
						
					
					
						commit
						31d88da08b
					
				@ -1,4 +1,3 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import classnames from 'classnames';
 | 
			
		||||
import { Paper } from '@material-ui/core';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
@ -8,12 +7,14 @@ import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined'
 | 
			
		||||
import ConditionallyRender from '../../common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
 | 
			
		||||
import styles from './ReportCard.module.scss';
 | 
			
		||||
import ReactTimeAgo from 'react-timeago';
 | 
			
		||||
 | 
			
		||||
const ReportCard = ({
 | 
			
		||||
    health,
 | 
			
		||||
    activeCount,
 | 
			
		||||
    staleCount,
 | 
			
		||||
    potentiallyStaleCount,
 | 
			
		||||
    lastUpdate,
 | 
			
		||||
}) => {
 | 
			
		||||
    const healthLessThan50 = health < 50;
 | 
			
		||||
    const healthLessThan75 = health < 75;
 | 
			
		||||
@ -52,11 +53,22 @@ const ReportCard = ({
 | 
			
		||||
                    <div className={styles.reportCardHealthInnerContainer}>
 | 
			
		||||
                        <ConditionallyRender
 | 
			
		||||
                            condition={health > -1}
 | 
			
		||||
                            show={<p className={healthClasses}>{health}%</p>}
 | 
			
		||||
                            show={
 | 
			
		||||
                                <div>
 | 
			
		||||
                                    <p className={healthClasses}>{health}%</p>
 | 
			
		||||
                                    <p className={styles.lastUpdate}>
 | 
			
		||||
                                        Last updated:{' '}
 | 
			
		||||
                                        <ReactTimeAgo
 | 
			
		||||
                                            date={lastUpdate}
 | 
			
		||||
                                            live={false}
 | 
			
		||||
                                        />
 | 
			
		||||
                                    </p>
 | 
			
		||||
                                </div>
 | 
			
		||||
                            }
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div className={styles.reportCardListContainer}>
 | 
			
		||||
                <div className={styles.reportCardToggle}>
 | 
			
		||||
                    <h2 className={styles.header}>Toggle report</h2>
 | 
			
		||||
                    <ul className={styles.reportCardList}>
 | 
			
		||||
                        <li>
 | 
			
		||||
@ -65,28 +77,49 @@ const ReportCard = ({
 | 
			
		||||
                                show={renderActiveToggles}
 | 
			
		||||
                            />
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <ConditionallyRender
 | 
			
		||||
                            condition={activeCount}
 | 
			
		||||
                            show={
 | 
			
		||||
                                <p className={styles.reportCardActionText}>
 | 
			
		||||
                                    Also includes potentially stale toggles.
 | 
			
		||||
                                </p>
 | 
			
		||||
                            }
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <ConditionallyRender
 | 
			
		||||
                                condition={staleCount}
 | 
			
		||||
                                show={renderStaleToggles}
 | 
			
		||||
                            />
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <ConditionallyRender
 | 
			
		||||
                                condition={potentiallyStaleCount}
 | 
			
		||||
                                show={renderPotentiallyStaleToggles}
 | 
			
		||||
                            />
 | 
			
		||||
                        </li>
 | 
			
		||||
                    </ul>
 | 
			
		||||
                </div>
 | 
			
		||||
 | 
			
		||||
                <div className={styles.reportCardAction}>
 | 
			
		||||
                    <h2 className={styles.header}>Potential actions</h2>
 | 
			
		||||
                    <div className={styles.reportCardActionContainer}>
 | 
			
		||||
                        <p className={styles.reportCardActionText}>
 | 
			
		||||
                            Review your feature toggles and delete unused
 | 
			
		||||
                            toggles.
 | 
			
		||||
                        </p>
 | 
			
		||||
                        <ul className={styles.reportCardList}>
 | 
			
		||||
                            <li>
 | 
			
		||||
                                <ConditionallyRender
 | 
			
		||||
                                    condition={potentiallyStaleCount}
 | 
			
		||||
                                    show={renderPotentiallyStaleToggles}
 | 
			
		||||
                                />
 | 
			
		||||
                            </li>
 | 
			
		||||
                        </ul>
 | 
			
		||||
                        <ConditionallyRender
 | 
			
		||||
                            condition={potentiallyStaleCount}
 | 
			
		||||
                            show={
 | 
			
		||||
                                <p className={styles.reportCardActionText}>
 | 
			
		||||
                                    Review your feature toggles and delete
 | 
			
		||||
                                    unused toggles.
 | 
			
		||||
                                </p>
 | 
			
		||||
                            }
 | 
			
		||||
                            elseShow={
 | 
			
		||||
                                <p className={styles.reportCardNoActionText}>
 | 
			
		||||
                                    No action is required
 | 
			
		||||
                                </p>
 | 
			
		||||
                            }
 | 
			
		||||
                        />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,8 @@
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    padding: var(--card-padding);
 | 
			
		||||
    margin: var(--card-margin-y) 0;
 | 
			
		||||
    border-radius: 10px;
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.header {
 | 
			
		||||
@ -14,9 +16,19 @@
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
.reportCardHealth {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
}
 | 
			
		||||
.reportCardAction {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
}
 | 
			
		||||
.reportCardToggle {
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.reportCardHealthInnerContainer {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
@ -70,6 +82,12 @@
 | 
			
		||||
.reportCardActionText {
 | 
			
		||||
    max-width: 300px;
 | 
			
		||||
    font-size: var(--p-size);
 | 
			
		||||
    margin-left: 35px;
 | 
			
		||||
}
 | 
			
		||||
.reportCardNoActionText {
 | 
			
		||||
    max-width: 300px;
 | 
			
		||||
    font-size: var(--p-size);
 | 
			
		||||
    margin-left: 15px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.reportCardBtn {
 | 
			
		||||
@ -83,3 +101,16 @@
 | 
			
		||||
.healthWarning {
 | 
			
		||||
    color: var(--warning);
 | 
			
		||||
}
 | 
			
		||||
.lastUpdate {
 | 
			
		||||
    color: #585858;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (max-width: 600px) {
 | 
			
		||||
    .reportCardContainer {
 | 
			
		||||
        flex-wrap: wrap;
 | 
			
		||||
    }
 | 
			
		||||
    .reportCardToggle {
 | 
			
		||||
        margin: 10px 5px;
 | 
			
		||||
        flex-basis: 100%;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,8 @@
 | 
			
		||||
.reportToggleList {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    margin: var(--card-margin-y) 0;
 | 
			
		||||
    border-radius: 10px;
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bulkAction {
 | 
			
		||||
@ -65,7 +67,31 @@
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.tableRow:hover {
 | 
			
		||||
    background-color: #eeeeee;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.checkbox {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media only screen and (max-width: 800px) {
 | 
			
		||||
    .hideColumn {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
    th {
 | 
			
		||||
        min-width: 120px;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@media only screen and (max-width: 550px) {
 | 
			
		||||
    .hideColumnStatus {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media only screen and (max-width: 425px) {
 | 
			
		||||
    .hideColumnLastSeen {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -5,11 +5,23 @@ import PropTypes from 'prop-types';
 | 
			
		||||
 | 
			
		||||
import ConditionallyRender from '../../../common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
 | 
			
		||||
import { NAME, LAST_SEEN, CREATED, EXPIRED, STATUS, REPORT } from '../../constants';
 | 
			
		||||
import {
 | 
			
		||||
    NAME,
 | 
			
		||||
    LAST_SEEN,
 | 
			
		||||
    CREATED,
 | 
			
		||||
    EXPIRED,
 | 
			
		||||
    STATUS,
 | 
			
		||||
    REPORT,
 | 
			
		||||
} from '../../constants';
 | 
			
		||||
 | 
			
		||||
import styles from '../ReportToggleList.module.scss';
 | 
			
		||||
 | 
			
		||||
const ReportToggleListHeader = ({ handleCheckAll, checkAll, setSortData, bulkActionsOn }) => {
 | 
			
		||||
const ReportToggleListHeader = ({
 | 
			
		||||
    handleCheckAll,
 | 
			
		||||
    checkAll,
 | 
			
		||||
    setSortData,
 | 
			
		||||
    bulkActionsOn,
 | 
			
		||||
}) => {
 | 
			
		||||
    const handleSort = type => {
 | 
			
		||||
        setSortData(prev => ({
 | 
			
		||||
            sortKey: type,
 | 
			
		||||
@ -34,27 +46,56 @@ const ReportToggleListHeader = ({ handleCheckAll, checkAll, setSortData, bulkAct
 | 
			
		||||
                    }
 | 
			
		||||
                />
 | 
			
		||||
 | 
			
		||||
                <th role="button" tabIndex={0} style={{ width: '150px' }} onClick={() => handleSort(NAME)}>
 | 
			
		||||
                <th
 | 
			
		||||
                    role="button"
 | 
			
		||||
                    tabIndex={0}
 | 
			
		||||
                    style={{ width: '150px' }}
 | 
			
		||||
                    onClick={() => handleSort(NAME)}
 | 
			
		||||
                >
 | 
			
		||||
                    Name
 | 
			
		||||
                    <UnfoldMoreOutlinedIcon className={styles.sortIcon} />
 | 
			
		||||
                </th>
 | 
			
		||||
                <th role="button" tabIndex={0} onClick={() => handleSort(LAST_SEEN)}>
 | 
			
		||||
                <th
 | 
			
		||||
                    role="button"
 | 
			
		||||
                    className={styles.hideColumnLastSeen}
 | 
			
		||||
                    tabIndex={0}
 | 
			
		||||
                    onClick={() => handleSort(LAST_SEEN)}
 | 
			
		||||
                >
 | 
			
		||||
                    Last seen
 | 
			
		||||
                    <UnfoldMoreOutlinedIcon className={styles.sortIcon} />
 | 
			
		||||
                </th>
 | 
			
		||||
                <th role="button" tabIndex={0} onClick={() => handleSort(CREATED)}>
 | 
			
		||||
                <th
 | 
			
		||||
                    role="button"
 | 
			
		||||
                    tabIndex={0}
 | 
			
		||||
                    className={styles.hideColumn}
 | 
			
		||||
                    onClick={() => handleSort(CREATED)}
 | 
			
		||||
                >
 | 
			
		||||
                    Created
 | 
			
		||||
                    <UnfoldMoreOutlinedIcon className={styles.sortIcon} />
 | 
			
		||||
                </th>
 | 
			
		||||
                <th role="button" tabIndex={0} onClick={() => handleSort(EXPIRED)}>
 | 
			
		||||
                <th
 | 
			
		||||
                    role="button"
 | 
			
		||||
                    tabIndex={0}
 | 
			
		||||
                    className={styles.hideColumn}
 | 
			
		||||
                    onClick={() => handleSort(EXPIRED)}
 | 
			
		||||
                >
 | 
			
		||||
                    Expired
 | 
			
		||||
                    <UnfoldMoreOutlinedIcon className={styles.sortIcon} />
 | 
			
		||||
                </th>
 | 
			
		||||
                <th role="button" tabIndex={0} onClick={() => handleSort(STATUS)}>
 | 
			
		||||
                <th
 | 
			
		||||
                    role="button"
 | 
			
		||||
                    tabIndex={0}
 | 
			
		||||
                    className={styles.hideColumnStatus}
 | 
			
		||||
                    onClick={() => handleSort(STATUS)}
 | 
			
		||||
                >
 | 
			
		||||
                    Status
 | 
			
		||||
                    <UnfoldMoreOutlinedIcon className={styles.sortIcon} />
 | 
			
		||||
                </th>
 | 
			
		||||
                <th role="button" tabIndex={0} onClick={() => handleSort(REPORT)}>
 | 
			
		||||
                <th
 | 
			
		||||
                    role="button"
 | 
			
		||||
                    tabIndex={0}
 | 
			
		||||
                    onClick={() => handleSort(REPORT)}
 | 
			
		||||
                >
 | 
			
		||||
                    Report
 | 
			
		||||
                    <UnfoldMoreOutlinedIcon className={styles.sortIcon} />
 | 
			
		||||
                </th>
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import { Checkbox } from '@material-ui/core';
 | 
			
		||||
import CheckIcon from '@material-ui/icons/Check';
 | 
			
		||||
import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';
 | 
			
		||||
import ConditionallyRender from '../../../common/ConditionallyRender/ConditionallyRender';
 | 
			
		||||
import FeatureStatus from '../../../feature/FeatureView2/FeatureStatus/FeatureStatus';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    pluralize,
 | 
			
		||||
@ -75,20 +76,13 @@ const ReportToggleListItem = ({
 | 
			
		||||
 | 
			
		||||
            return pluralize(result, 'day');
 | 
			
		||||
        }
 | 
			
		||||
        return 'N/A';
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const formatLastSeenAt = () => {
 | 
			
		||||
        if (!lastSeenAt) return 'Never';
 | 
			
		||||
 | 
			
		||||
        const [date, now] = getDates(lastSeenAt);
 | 
			
		||||
        const diff = getDiffInDays(date, now);
 | 
			
		||||
        if (diff === 0) return '1 day';
 | 
			
		||||
 | 
			
		||||
        if (diff) {
 | 
			
		||||
            return pluralize(diff, 'day');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return '1 day';
 | 
			
		||||
        return (
 | 
			
		||||
            <FeatureStatus lastSeenAt={lastSeenAt} tooltipPlacement="bottom" />
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const renderStatus = (icon, text) => (
 | 
			
		||||
@ -126,7 +120,7 @@ const ReportToggleListItem = ({
 | 
			
		||||
        history.push(getTogglePath(project, name));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    const statusClasses = classnames(styles.active, {
 | 
			
		||||
    const statusClasses = classnames(styles.active, styles.hideColumnStatus, {
 | 
			
		||||
        [styles.stale]: stale,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@ -151,9 +145,11 @@ const ReportToggleListItem = ({
 | 
			
		||||
                }
 | 
			
		||||
            />
 | 
			
		||||
            <td>{name}</td>
 | 
			
		||||
            <td>{formatLastSeenAt()}</td>
 | 
			
		||||
            <td>{formatCreatedAt()}</td>
 | 
			
		||||
            <td className={styles.expired}>{formatExpiredAt()}</td>
 | 
			
		||||
            <td className={styles.hideColumnLastSeen}>{formatLastSeenAt()}</td>
 | 
			
		||||
            <td className={styles.hideColumn}>{formatCreatedAt()}</td>
 | 
			
		||||
            <td className={`${styles.expired} ${styles.hideColumn}`}>
 | 
			
		||||
                {formatExpiredAt()}
 | 
			
		||||
            </td>
 | 
			
		||||
            <td className={statusClasses}>{stale ? 'Stale' : 'Active'}</td>
 | 
			
		||||
            <td>{formatReportStatus()}</td>
 | 
			
		||||
        </tr>
 | 
			
		||||
 | 
			
		||||
@ -58,7 +58,10 @@ const FeatureToggleListItem = ({
 | 
			
		||||
            className={classnames(styles.listItem, rest.className)}
 | 
			
		||||
        >
 | 
			
		||||
            <span className={styles.listItemMetric}>
 | 
			
		||||
                <FeatureStatus lastSeenAt={lastSeenAt} />
 | 
			
		||||
                <FeatureStatus
 | 
			
		||||
                    lastSeenAt={lastSeenAt}
 | 
			
		||||
                    tooltipPlacement="left"
 | 
			
		||||
                />
 | 
			
		||||
            </span>
 | 
			
		||||
            <span
 | 
			
		||||
                className={classnames(
 | 
			
		||||
 | 
			
		||||
@ -83,7 +83,10 @@ const FeatureToggleListNewItem = ({
 | 
			
		||||
                    align="left"
 | 
			
		||||
                    onClick={onClick}
 | 
			
		||||
                >
 | 
			
		||||
                    <FeatureStatus lastSeenAt={lastSeenAt} />
 | 
			
		||||
                    <FeatureStatus
 | 
			
		||||
                        lastSeenAt={lastSeenAt}
 | 
			
		||||
                        tooltipPlacement="left"
 | 
			
		||||
                    />
 | 
			
		||||
                </TableCell>
 | 
			
		||||
                <TableCell
 | 
			
		||||
                    className={classNames(
 | 
			
		||||
 | 
			
		||||
@ -47,16 +47,20 @@ function getColor(unit?: string): string {
 | 
			
		||||
 | 
			
		||||
interface FeatureStatusProps {
 | 
			
		||||
    lastSeenAt?: Date;
 | 
			
		||||
    tooltipPlacement?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const FeatureStatus = ({ lastSeenAt }: FeatureStatusProps) => {
 | 
			
		||||
const FeatureStatus = ({
 | 
			
		||||
    lastSeenAt,
 | 
			
		||||
    tooltipPlacement,
 | 
			
		||||
}: FeatureStatusProps) => {
 | 
			
		||||
    const styles = useStyles();
 | 
			
		||||
 | 
			
		||||
    const Wrapper = (
 | 
			
		||||
        props: React.PropsWithChildren<{ color: string; toolTip: string }>
 | 
			
		||||
    ) => {
 | 
			
		||||
        return (
 | 
			
		||||
            <Tooltip title={props.toolTip} arrow placement="left">
 | 
			
		||||
            <Tooltip title={props.toolTip} arrow placement={tooltipPlacement}>
 | 
			
		||||
                <div
 | 
			
		||||
                    className={styles.container}
 | 
			
		||||
                    style={{ background: props.color, fontSize: '0.8rem' }}
 | 
			
		||||
@ -83,7 +87,9 @@ const FeatureStatus = ({ lastSeenAt }: FeatureStatusProps) => {
 | 
			
		||||
                    ) => {
 | 
			
		||||
                        return (
 | 
			
		||||
                            <Wrapper
 | 
			
		||||
                                toolTip={`Last usage reported ${value} ${unit}${value !== 1 ? 's' : ''} ${suffix}`}
 | 
			
		||||
                                toolTip={`Last usage reported ${value} ${unit}${
 | 
			
		||||
                                    value !== 1 ? 's' : ''
 | 
			
		||||
                                } ${suffix}`}
 | 
			
		||||
                                color={getColor(unit)}
 | 
			
		||||
                            >
 | 
			
		||||
                                {value}
 | 
			
		||||
@ -94,7 +100,10 @@ const FeatureStatus = ({ lastSeenAt }: FeatureStatusProps) => {
 | 
			
		||||
                />
 | 
			
		||||
            }
 | 
			
		||||
            elseShow={
 | 
			
		||||
                <Wrapper toolTip="No usage reported from connected applications" color={getColor()}>
 | 
			
		||||
                <Wrapper
 | 
			
		||||
                    toolTip="No usage reported from connected applications"
 | 
			
		||||
                    color={getColor()}
 | 
			
		||||
                >
 | 
			
		||||
                    <span style={{ fontSize: '1.4rem' }}>⊕</span>
 | 
			
		||||
                </Wrapper>
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import useHealthReport from '../../../../hooks/api/getters/useHealthReport/useHealthReport';
 | 
			
		||||
import ApiError from '../../../common/ApiError/ApiError';
 | 
			
		||||
import ConditionallyRender from '../../../common/ConditionallyRender';
 | 
			
		||||
import ReportCardContainer from '../../../Reporting/ReportCard/ReportCardContainer'
 | 
			
		||||
import ReportToggleList from '../../../Reporting/ReportToggleList/ReportToggleList'
 | 
			
		||||
import ReportCardContainer from '../../../Reporting/ReportCard/ReportCardContainer';
 | 
			
		||||
import ReportToggleList from '../../../Reporting/ReportToggleList/ReportToggleList';
 | 
			
		||||
 | 
			
		||||
interface ProjectHealthProps {
 | 
			
		||||
    projectId: string;
 | 
			
		||||
@ -25,18 +25,19 @@ const ProjectHealth = ({ projectId }: ProjectHealthProps) => {
 | 
			
		||||
                }
 | 
			
		||||
            />
 | 
			
		||||
            <ReportCardContainer
 | 
			
		||||
                    health={project?.health}
 | 
			
		||||
                    staleCount={project?.staleCount}
 | 
			
		||||
                    activeCount={project?.activeCount}
 | 
			
		||||
                    potentiallyStaleCount={project?.potentiallyStaleCount}
 | 
			
		||||
                    selectedProject={project.name}
 | 
			
		||||
                health={project?.health}
 | 
			
		||||
                staleCount={project?.staleCount}
 | 
			
		||||
                activeCount={project?.activeCount}
 | 
			
		||||
                potentiallyStaleCount={project?.potentiallyStaleCount}
 | 
			
		||||
                selectedProject={project.name}
 | 
			
		||||
                lastUpdate={project.updatedAt}
 | 
			
		||||
            />
 | 
			
		||||
            <ReportToggleList
 | 
			
		||||
                features={project.features}
 | 
			
		||||
                selectedProject={projectId}
 | 
			
		||||
            />
 | 
			
		||||
        </div>
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default ProjectHealth;
 | 
			
		||||
export default ProjectHealth;
 | 
			
		||||
 | 
			
		||||
@ -24,4 +24,5 @@ export interface IProjectHealthReport extends IProject {
 | 
			
		||||
    staleCount: number;
 | 
			
		||||
    potentiallyStaleCount: number;
 | 
			
		||||
    activeCount: number;
 | 
			
		||||
    updatedAt: Date;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user