diff --git a/frontend/src/component/Reporting/ReportCard/ReportCard.jsx b/frontend/src/component/Reporting/ReportCard/ReportCard.tsx
similarity index 78%
rename from frontend/src/component/Reporting/ReportCard/ReportCard.jsx
rename to frontend/src/component/Reporting/ReportCard/ReportCard.tsx
index 26c3370c17..88a446efb3 100644
--- a/frontend/src/component/Reporting/ReportCard/ReportCard.jsx
+++ b/frontend/src/component/Reporting/ReportCard/ReportCard.tsx
@@ -1,23 +1,19 @@
import classnames from 'classnames';
import { Paper } from '@material-ui/core';
-import PropTypes from 'prop-types';
-
import CheckIcon from '@material-ui/icons/Check';
import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';
import ConditionallyRender from '../../common/ConditionallyRender/ConditionallyRender';
-
import styles from './ReportCard.module.scss';
import ReactTimeAgo from 'react-timeago';
+import { IProjectHealthReport } from "../../../interfaces/project";
-const ReportCard = ({
- health,
- activeCount,
- staleCount,
- potentiallyStaleCount,
- lastUpdate,
-}) => {
- const healthLessThan50 = health < 50;
- const healthLessThan75 = health < 75;
+interface IReportCardProps {
+ healthReport: IProjectHealthReport
+}
+
+export const ReportCard = ({ healthReport }: IReportCardProps) => {
+ const healthLessThan50 = healthReport.health < 50;
+ const healthLessThan75 = healthReport.health < 75;
const healthClasses = classnames(styles.reportCardHealthRating, {
[styles.healthWarning]: healthLessThan75,
@@ -27,21 +23,21 @@ const ReportCard = ({
const renderActiveToggles = () => (
<>
- {activeCount} active toggles
+ {healthReport.activeCount} active toggles
>
);
const renderStaleToggles = () => (
<>
- {staleCount} stale toggles
+ {healthReport.staleCount} stale toggles
>
);
const renderPotentiallyStaleToggles = () => (
<>
- {potentiallyStaleCount} potentially stale toggles
+ {healthReport.potentiallyStaleCount} potentially stale toggles
>
);
@@ -52,14 +48,14 @@ const ReportCard = ({
Health rating
-1}
+ condition={healthReport.health > -1}
show={
-
{health}%
+
{healthReport.health}%
Last updated:{' '}
@@ -73,12 +69,12 @@ const ReportCard = ({
-
Also includes potentially stale toggles.
@@ -88,7 +84,7 @@ const ReportCard = ({
-
@@ -101,13 +97,13 @@ const ReportCard = ({
Review your feature toggles and delete
@@ -126,9 +122,3 @@ const ReportCard = ({
);
};
-
-ReportCard.propTypes = {
- features: PropTypes.array.isRequired,
-};
-
-export default ReportCard;
diff --git a/frontend/src/component/Reporting/ReportCard/ReportCardContainer.jsx b/frontend/src/component/Reporting/ReportCard/ReportCardContainer.jsx
deleted file mode 100644
index fb1a1ccda3..0000000000
--- a/frontend/src/component/Reporting/ReportCard/ReportCardContainer.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { connect } from 'react-redux';
-
-import ReportCard from './ReportCard';
-import { filterByProject } from '../utils';
-
-const mapStateToProps = (state, ownProps) => {
- const features = state.features.toJS();
-
- const sameProject = filterByProject(ownProps.selectedProject);
- const featuresByProject = features.filter(sameProject);
-
- return {
- features: featuresByProject,
- };
-};
-
-const ReportCardContainer = connect(mapStateToProps, null)(ReportCard);
-
-export default ReportCardContainer;
diff --git a/frontend/src/component/Reporting/Reporting.jsx b/frontend/src/component/Reporting/Reporting.jsx
deleted file mode 100644
index d7465092db..0000000000
--- a/frontend/src/component/Reporting/Reporting.jsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import React, { useEffect, useState } from 'react';
-
-import PropTypes from 'prop-types';
-
-import Select from '../common/select';
-import ReportCardContainer from './ReportCard/ReportCardContainer';
-import ReportToggleList from './ReportToggleList/ReportToggleList';
-
-import ConditionallyRender from '../common/ConditionallyRender/ConditionallyRender';
-
-import { formatProjectOptions } from './utils';
-import { REPORTING_SELECT_ID } from '../../testIds';
-
-import styles from './Reporting.module.scss';
-import useHealthReport from '../../hooks/api/getters/useHealthReport/useHealthReport';
-import ApiError from '../common/ApiError/ApiError';
-import useQueryParams from '../../hooks/useQueryParams';
-
-const Reporting = ({ projects }) => {
- const [projectOptions, setProjectOptions] = useState([
- { key: 'default', label: 'Default' },
- ]);
- const [selectedProject, setSelectedProject] = useState('default');
- const { project, error, refetch } = useHealthReport(selectedProject);
-
- const params = useQueryParams();
- const projectId = params.get('project');
-
- useEffect(() => {
- if (projectId) {
- return setSelectedProject(projectId);
- }
- setSelectedProject(projects[0].id);
-
- /* eslint-disable-next-line */
- }, []);
-
- useEffect(() => {
- setProjectOptions(formatProjectOptions(projects));
- }, [projects]);
-
- const onChange = e => {
- const { value } = e.target;
-
- const selectedProject = projectOptions.find(
- option => option.key === value
- );
-
- setSelectedProject(selectedProject.key);
- };
-
- const renderSelect = () => (
-
-
Project
-
-
- );
-
- const multipleProjects = projects.length > 1;
-
- return (
-
-
-
-
- }
- />
-
-
-
- );
-};
-
-Reporting.propTypes = {
- fetchFeatureToggles: PropTypes.func.isRequired,
- projects: PropTypes.array.isRequired,
- features: PropTypes.array,
-};
-
-export default Reporting;
diff --git a/frontend/src/component/Reporting/Reporting.module.scss b/frontend/src/component/Reporting/Reporting.module.scss
deleted file mode 100644
index 0b8e7dbb12..0000000000
--- a/frontend/src/component/Reporting/Reporting.module.scss
+++ /dev/null
@@ -1,176 +0,0 @@
-.header {
- font-size: var(--h1-size);
- font-weight: 700;
- margin: 0 0 0.5rem 0;
-}
-
-.card {
- width: 100%;
- padding: var(--card-padding);
- margin: var(--card-margin-y) 0;
-}
-
-.projectSelector {
- margin-bottom: 1rem;
-}
-
-.select {
- background-color: #fff;
- border: none;
- padding: 0.5rem 1rem;
- position: static;
-}
-
-.select select {
- border: none;
- min-width: 120px;
-}
-
-.select select:active {
- border: none;
-}
-
-/** ReportCard **/
-
-.reportCardContainer {
- display: flex;
- justify-content: space-between;
-}
-
-.reportCardHealthInnerContainer {
- display: flex;
- align-items: center;
- justify-content: center;
- align-items: center;
- height: 80%;
-}
-
-.reportCardHealthRating {
- font-size: 2rem;
- font-weight: bold;
- color: var(--success);
-}
-
-.reportCardList {
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
-
-.reportCardList li {
- display: flex;
- align-items: center;
- margin: 0.5rem 0;
-}
-
-.reportCardList li span {
- margin: 0;
- padding: 0;
- margin-left: 0.5rem;
- font-size: var(--p-size);
-}
-
-.check,
-.danger {
- margin-right: 5px;
-}
-
-.check {
- color: var(--success);
-}
-
-.danger {
- color: var(--danger);
-}
-
-.reportCardActionContainer {
- display: flex;
- justify-content: center;
- flex-direction: column;
-}
-
-.reportCardActionText {
- max-width: 300px;
- font-size: var(--p-size);
-}
-
-.reportCardBtn {
- background-color: #f2f2f2;
-}
-
-.healthDanger {
- color: var(--danger);
-}
-
-.healthWarning {
- color: var(--warning);
-}
-
-/** ReportToggleList **/
-.reportToggleList {
- width: 100%;
- margin: var(--card-margin-y) 0;
-}
-
-.bulkAction {
- background-color: #f2f2f2;
- font-size: var(--p-size);
-}
-
-.sortIcon {
- margin-left: 8px;
- transform: translateY(6px);
-}
-
-.reportToggleListHeader {
- display: flex;
- justify-content: space-between;
- align-items: center;
- border-bottom: var(--default-border);
- padding: 1rem var(--card-padding-x);
-}
-
-.reportToggleListInnerContainer {
- padding: var(--card-padding);
-}
-
-.reportToggleListHeading {
- font-size: var(--h1-size);
- margin: 0;
- font-weight: 'bold';
-}
-
-.reportingToggleTable {
- width: 100%;
- border-spacing: 0 0.8rem;
-}
-
-.reportingToggleTable th {
- text-align: left;
-}
-
-.expired {
- color: var(--danger);
-}
-
-.active {
- color: var(--success);
-}
-
-.stale {
- color: var(--danger);
-}
-
-.reportStatus {
- display: flex;
- align-items: center;
-}
-
-.reportIcon {
- font-size: 1.5rem;
- margin-right: 5px;
-}
-
-.tableRow {
- cursor: pointer;
-}
diff --git a/frontend/src/component/Reporting/ReportingContainer.jsx b/frontend/src/component/Reporting/ReportingContainer.jsx
deleted file mode 100644
index cd0f52fd02..0000000000
--- a/frontend/src/component/Reporting/ReportingContainer.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { connect } from 'react-redux';
-import { fetchFeatureToggles } from '../../store/feature-toggle/actions';
-
-import Reporting from './Reporting.jsx';
-
-const mapStateToProps = state => ({
- projects: state.projects.toJS(),
-});
-
-const mapDispatchToProps = {
- fetchFeatureToggles,
-};
-
-const ReportingContainer = connect(
- mapStateToProps,
- mapDispatchToProps
-)(Reporting);
-
-export default ReportingContainer;
diff --git a/frontend/src/component/Reporting/utils.js b/frontend/src/component/Reporting/utils.js
index 6661f54fc5..30cded8956 100644
--- a/frontend/src/component/Reporting/utils.js
+++ b/frontend/src/component/Reporting/utils.js
@@ -177,10 +177,3 @@ export const getDates = dateString => {
export const filterByProject = selectedProject => feature =>
feature.project === selectedProject;
-
-export const isFeatureExpired = feature => {
- const [date, now] = getDates(feature.createdAt);
- const diff = getDiffInDays(date, now);
-
- return expired(diff, feature.type);
-};
diff --git a/frontend/src/component/project/Project/ProjectHealth/ProjectHealth.tsx b/frontend/src/component/project/Project/ProjectHealth/ProjectHealth.tsx
index 0424d2fdbb..99dd106dfa 100644
--- a/frontend/src/component/project/Project/ProjectHealth/ProjectHealth.tsx
+++ b/frontend/src/component/project/Project/ProjectHealth/ProjectHealth.tsx
@@ -1,40 +1,38 @@
-import useHealthReport from '../../../../hooks/api/getters/useHealthReport/useHealthReport';
+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 { ReportCard } from '../../../Reporting/ReportCard/ReportCard';
interface ProjectHealthProps {
projectId: string;
}
const ProjectHealth = ({ projectId }: ProjectHealthProps) => {
- const { project, error, refetch } = useHealthReport(projectId);
+ const { healthReport, refetchHealthReport, error } =
+ useHealthReport(projectId);
+
+ if (!healthReport) {
+ return null;
+ }
return (
}
/>
-
+
);
diff --git a/frontend/src/hooks/api/getters/useHealthReport/useHealthReport.ts b/frontend/src/hooks/api/getters/useHealthReport/useHealthReport.ts
index 9640f91a05..75c5229bbb 100644
--- a/frontend/src/hooks/api/getters/useHealthReport/useHealthReport.ts
+++ b/frontend/src/hooks/api/getters/useHealthReport/useHealthReport.ts
@@ -1,51 +1,42 @@
import useSWR, { mutate, SWRConfiguration } from 'swr';
-import { useState, useEffect } from 'react';
+import { useCallback } from 'react';
import { IProjectHealthReport } from '../../../../interfaces/project';
-import { fallbackProject } from '../useProject/fallbackProject';
-import useSort from '../../../useSort';
import { formatApiPath } from '../../../../utils/format-path';
import handleErrorResponses from '../httpErrorResponseHandler';
-const useHealthReport = (id: string, options: SWRConfiguration = {}) => {
- const KEY = `api/admin/projects/${id}/health-report`;
+interface IUseHealthReportOutput {
+ healthReport: IProjectHealthReport | undefined;
+ refetchHealthReport: () => void;
+ loading: boolean;
+ error?: Error;
+}
- const fetcher = () => {
- const path = formatApiPath(`api/admin/projects/${id}/health-report`);
- return fetch(path, {
- method: 'GET',
- })
- .then(handleErrorResponses('Health report'))
- .then(res => res.json());
- };
+export const useHealthReport = (
+ projectId: string,
+ options?: SWRConfiguration
+): IUseHealthReportOutput => {
+ const path = formatApiPath(`api/admin/projects/${projectId}/health-report`);
- const [sort] = useSort();
+ const { data, error } = useSWR(
+ path,
+ fetchHealthReport,
+ options
+ );
- const { data, error } = useSWR(KEY, fetcher, options);
- const [loading, setLoading] = useState(!error && !data);
-
- const refetch = () => {
- mutate(KEY);
- };
-
- useEffect(() => {
- setLoading(!error && !data);
- }, [data, error]);
-
- const sortedData = (
- data: IProjectHealthReport | undefined
- ): IProjectHealthReport => {
- if (data) {
- return { ...data, features: sort(data.features || []) };
- }
- return fallbackProject;
- };
+ const refetchHealthReport = useCallback(() => {
+ mutate(path).catch(console.warn);
+ }, [path]);
return {
- project: sortedData(data),
+ healthReport: data,
+ refetchHealthReport,
+ loading: !error && !data,
error,
- loading,
- refetch,
};
};
-export default useHealthReport;
+const fetchHealthReport = (path: string): Promise => {
+ return fetch(path)
+ .then(handleErrorResponses('Health report'))
+ .then(res => res.json());
+};
diff --git a/frontend/src/interfaces/project.ts b/frontend/src/interfaces/project.ts
index a915cd1996..835ba2845b 100644
--- a/frontend/src/interfaces/project.ts
+++ b/frontend/src/interfaces/project.ts
@@ -24,7 +24,7 @@ export interface IProjectHealthReport extends IProject {
staleCount: number;
potentiallyStaleCount: number;
activeCount: number;
- updatedAt: Date;
+ updatedAt: string;
}
export interface IPermission {