Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable box health filters on Dashboard #950

Merged
merged 9 commits into from
Nov 4, 2022
7 changes: 5 additions & 2 deletions assets/js/components/ClustersList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import Tags from './Tags';
import { addTagToCluster, removeTagFromCluster } from '@state/clusters';
import ClusterLink from '@components/ClusterLink';
import { ExecutionIcon } from '@components/ClusterDetails';
import { ComponentHealthSummary } from '@components/HealthSummary';
import { post, del } from '@lib/network';
import { useSearchParams } from 'react-router-dom';
import HealthSummary from './HealthSummary/HealthSummary';
import { getCounters } from './HealthSummary/summarySelection';

const getClusterTypeLabel = (type) => {
switch (type) {
Expand Down Expand Up @@ -132,9 +133,11 @@ const ClustersList = () => {
};
});

const counters = getCounters(data || []);

return (
<Fragment>
<ComponentHealthSummary data={data} />
<HealthSummary {...counters} className="mb-8" />
<Table
config={config}
data={data}
Expand Down
7 changes: 5 additions & 2 deletions assets/js/components/DatabasesOverview/DatabasesOverview.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import Tags from '@components/Tags';
import { addTagToDatabase, removeTagFromDatabase } from '@state/databases';

import { post, del } from '@lib/network';
import { ComponentHealthSummary } from '@components/HealthSummary';
import { getCounters } from '../HealthSummary/summarySelection';
import HealthSummary from '../HealthSummary/HealthSummary';

const byDatabase = (id) => (instance) => instance.sap_system_id === id;

Expand Down Expand Up @@ -141,11 +142,13 @@ const DatabasesOverview = () => {
};
});

const counters = getCounters(data || []);

return loading ? (
'Loading HANA Databases...'
) : (
<Fragment>
<ComponentHealthSummary data={data} />
<HealthSummary {...counters} className="mb-8" />
<Table
config={config}
data={data}
Expand Down
10 changes: 0 additions & 10 deletions assets/js/components/HealthSummary/ComponentHealthSummary.jsx

This file was deleted.

74 changes: 33 additions & 41 deletions assets/js/components/HealthSummary/HealthSummary.jsx
Original file line number Diff line number Diff line change
@@ -1,51 +1,43 @@
import classNames from 'classnames';
import React from 'react';
import HealthSummaryBox from './HealthSummaryBox';

const any = (predicate, label) =>
Object.keys(predicate).reduce((accumulator, key) => {
if (accumulator) {
return true;
}
return predicate[key] === label;
}, false);

const getCounters = (data) => {
const defaultCounter = { critical: 0, warning: 0, passing: 0, unknown: 0 };

if (!data || 0 === data.length) {
return defaultCounter;
}

return data.reduce((accumulator, element) => {
if (any(element, 'critical')) {
return { ...accumulator, critical: accumulator.critical + 1 };
}

if (any(element, 'warning')) {
return { ...accumulator, warning: accumulator.warning + 1 };
}

if (any(element, 'unknown')) {
return { ...accumulator, unknown: accumulator.unknown + 1 };
}

if (any(element, 'passing')) {
return { ...accumulator, passing: accumulator.passing + 1 };
}
return accumulator;
}, defaultCounter);
};

const HealthSummary = ({ data }) => {
const { passing, warning, critical } = getCounters(data);

const HealthSummary = ({
passing,
critical,
warning,
className,
onFilterChange,
activeFilters = {
passing: false,
critical: false,
warning: false,
},
}) => {
return (
<div className="tn-health-container flex flex-row justify-between">
<HealthSummaryBox health="passing" value={passing} />
<HealthSummaryBox health="warning" value={warning} />
<div
className={classNames(
className,
'tn-health-container flex flex-row justify-between'
)}
>
<HealthSummaryBox
health="passing"
value={passing}
selected={activeFilters.passing}
onClick={onFilterChange}
/>
<HealthSummaryBox
health="warning"
value={warning}
selected={activeFilters.warning}
onClick={onFilterChange}
/>
<HealthSummaryBox
style={{ marginRight: 0 }}
health="critical"
selected={activeFilters.critical}
onClick={onFilterChange}
value={critical}
/>
</div>
Expand Down
32 changes: 26 additions & 6 deletions assets/js/components/HealthSummary/HealthSummaryBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,51 @@ import React from 'react';

const iconByHealth = {
passing: () => (
<EOS_CHECK_CIRCLE_OUTLINED size={40} className="fill-green-600" />
<EOS_CHECK_CIRCLE_OUTLINED
size={40}
className="fill-green-600"
style={{ opacity: 1 }}
/>
),
warning: () => (
<EOS_WARNING_OUTLINED
size={40}
className="fill-yellow-400"
style={{ opacity: 1 }}
/>
),
critical: () => (
<EOS_ERROR_OUTLINED
size={40}
className="fill-red-600"
style={{ opacity: 1 }}
/>
),
warning: () => <EOS_WARNING_OUTLINED size={40} className="fill-yellow-400" />,
critical: () => <EOS_ERROR_OUTLINED size={40} className="fill-red-600" />,
};

const styleByHealth = {
passing: (selected) =>
classNames(
'tn-health-passing w-1/3 px-5 shadow rounded-lg my-2 mr-10 bg-white',
{
'bg-jungle-green-500 border-green-600 text-white': selected,
'bg-jungle-green-500 border-green-600 text-white hover:opacity-75':
selected,
'text-jungle-green-500': !selected,
}
),
warning: (selected) =>
classNames(
'tn-health-warning w-1/3 px-5 shadow rounded-lg my-2 mr-10 bg-white',
{
'bg-yellow-400 border-yellow-400 text-white': selected,
'bg-yellow-400 border-yellow-400 text-white hover:opacity-75': selected,
'text-yellow-400': !selected,
}
),
critical: (selected) =>
classNames(
'tn-health-critical w-1/3 px-5 shadow rounded-lg my-2 mr-10 bg-white',
{
'bg-red-600 border-red-600 text-white': selected,
'bg-red-600 border-red-600 text-white hover:opacity-75': selected,
'text-red-600': !selected,
}
),
Expand All @@ -59,6 +76,9 @@ const HealthSummaryBox = ({
return (
<div
style={style}
data-testid={`health-box-${health}-${
selected ? 'selected' : 'not-selected'
}`}
className={styleByHealth[health](selected)}
role={onClick === defaultOnClick ? null : 'button'}
onClick={() => onClick(health)}
Expand Down
79 changes: 62 additions & 17 deletions assets/js/components/HealthSummary/HomeHealthSummary.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { Fragment } from 'react';
import React, { useState, useEffect } from 'react';
import Table from '@components/Table';
import HealthIcon from '../Health/HealthIcon';
import HealthIcon from '@components/Health/HealthIcon';
import { Link } from 'react-router-dom';
import { useSelector } from 'react-redux';
import HealthSummary from '@components/HealthSummary';
import useQueryStringValues from '@hooks/useQueryStringValues';
import { getCounters, isMostRelevantPrio } from './summarySelection';

const healthSummaryTableConfig = {
usePadding: false,
Expand Down Expand Up @@ -68,28 +70,71 @@ const healthSummaryTableConfig = {
],
};

const GlobalHealth = ({ data }) => {
return (
<Fragment>
<h1 className="text-2xl font-semibold">At a glance</h1>
<hr className="my-3" />
<h5 className="text-xl">Global Health</h5>
<HealthSummary data={data} />
</Fragment>
);
};

export const HomeHealthSummary = () => {
const { loading, sapSystemsHealth } = useSelector(
(state) => state.sapSystemsHealthSummary
);

const {
extractedParams: { health: healthFilters = [] },
setQueryValues,
} = useQueryStringValues(['health']);

const [counters, setCounters] = useState({
warning: 0,
critical: 0,
passing: 0,
});

const [summaryData, setSummaryData] = useState([]);
const [activeFilters, setActiveFilters] = useState({});

useEffect(() => {
setCounters(getCounters(sapSystemsHealth));
setSummaryData(sapSystemsHealth);
}, [sapSystemsHealth]);

useEffect(() => {
setActiveFilters(
healthFilters.reduce((acc, curr) => ({ ...acc, [curr]: true }), {})
);
if (healthFilters.length === 0) {
setSummaryData(sapSystemsHealth);
return;
}
setSummaryData(
sapSystemsHealth.filter((e) => {
let result = false;

healthFilters.forEach((f) => {
result = result || isMostRelevantPrio(e, f);
});
return result;
})
);
}, [healthFilters]);

const onFiltersChange = (filterValue) => {
const newFilters = healthFilters.includes(filterValue)
? healthFilters.filter((f) => f !== filterValue)
: [...healthFilters, filterValue];
setQueryValues({ health: newFilters });
};

return loading ? (
<div>Loading...</div>
) : (
<Fragment>
<GlobalHealth data={sapSystemsHealth} />
<Table config={healthSummaryTableConfig} data={sapSystemsHealth} />
</Fragment>
<div data-testid="home-health-summary">
<h1 className="text-2xl font-semibold">At a glance</h1>
<hr className="my-3" />
<h5 className="text-xl">Global Health</h5>

<HealthSummary
{...counters}
onFilterChange={onFiltersChange}
activeFilters={activeFilters}
/>
<Table config={healthSummaryTableConfig} data={summaryData} />
</div>
);
};
Loading