Skip to content

Commit

Permalink
Check results filtering (#799)
Browse files Browse the repository at this point in the history
* Style the "back to cluster button" in ChecksResult view

The style of back to cluster CTA changes

* Add filters to ChecksResult screen
  • Loading branch information
CDimonaco authored Sep 7, 2022
1 parent bb49d59 commit 5a390c4
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 12 deletions.
2 changes: 2 additions & 0 deletions assets/js/components/Button/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const getSizeClasses = (size) => {

const getButtonClasses = (type) => {
switch (type) {
case 'transparent':
return 'bg-transparent hover:opacity-75 focus:outline-none w-full transition ease-in duration-200 font-semibold';
case 'secondary':
return 'bg-persimmon hover:opacity-75 focus:outline-none text-gray-800 w-full transition ease-in duration-200 text-center font-semibold rounded shadow';
default:
Expand Down
81 changes: 81 additions & 0 deletions assets/js/components/ClusterDetails/ChecksResultFilters.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React, { useState, useEffect } from 'react';
import Filter from '@components/Table/Filter';

export const RESULT_FILTER_FIELD = 'result';

export const useFilteredChecks = (cluster) => {
const [filtersPredicates, setFiltersPredicates] = useState([]);
const [filteredChecks, setFilteredChecks] = useState([]);

const filterChecks = (checks, predicates) => {
if (predicates.length === 0) return checks;

return checks.filter((check) =>
predicates.some((predicate) => predicate(check))
);
};

const checksForHost = (hostID) =>
filteredChecks
.filter((result) => result.host_id === hostID)
.map((result) => result.check_id);

useEffect(() => {
if (cluster?.checks_results.length > 0) {
const selectedCheckResults = cluster?.checks_results.filter((result) =>
cluster?.selected_checks.includes(result?.check_id)
);

setFilteredChecks(filterChecks(selectedCheckResults, filtersPredicates));
}
}, [cluster?.checks_results, cluster?.selected_checks, filtersPredicates]);

return {
setFiltersPredicates,
filteredChecksyByHost: checksForHost,
};
};

const ChecksResultFilters = ({ onChange }) => {
const [filtersForField, setFiltersForField] = useState({});

// This structure is the foundation for a multi field filters
// we can reuse later this structure in other parts of the application

useEffect(() => {
if (Object.keys(filtersForField).length >= 0) {
const filtersToApply = Object.keys(filtersForField).reduce(
(acc, curr) => {
return [...acc, ...filtersForField[curr].predicates];
},
[]
);

onChange(filtersToApply);
}
}, [filtersForField]);

return (
<div className="flex">
<Filter
key={RESULT_FILTER_FIELD}
title={'checks result'}
options={['passing', 'warning', 'critical', 'unknown']}
value={filtersForField[RESULT_FILTER_FIELD]?.values || []}
onChange={(list) => {
setFiltersForField((existingFilters) => ({
...existingFilters,
[RESULT_FILTER_FIELD]: {
predicates: list.map(
(value) => (checks) => checks[RESULT_FILTER_FIELD] === value
),
values: list,
},
}));
}}
/>
</div>
);
};

export default ChecksResultFilters;
39 changes: 27 additions & 12 deletions assets/js/components/ClusterDetails/ChecksResults.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import {
} from './ClusterDetails';
import { ExecutionIcon } from './ExecutionIcon';
import { getClusterName } from '@components/ClusterLink';
import ChecksResultFilters, {
useFilteredChecks,
} from '@components/ClusterDetails/ChecksResultFilters';

import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
Expand Down Expand Up @@ -86,6 +89,9 @@ export const ChecksResults = () => {

const hostname = getHostname(useSelector((state) => state.hostsList.hosts));

const { filteredChecksyByHost, setFiltersPredicates } =
useFilteredChecks(cluster);

useEffect(() => {
cluster?.provider && dispatchUpdateCatalog();
}, [cluster?.provider]);
Expand Down Expand Up @@ -136,6 +142,7 @@ export const ChecksResults = () => {
);
} else {
const lastExecution = sortHosts(cluster?.hosts_executions.slice());

pageContent = lastExecution.map(
({ _cluster_id, host_id, reachable, msg }, idx) => (
<div key={idx} className="flex flex-col">
Expand Down Expand Up @@ -179,7 +186,7 @@ export const ChecksResults = () => {
</tr>
</thead>
<tbody className="bg-white divide-y divide-gray-200">
{sortChecks(cluster?.selected_checks.slice()).map(
{sortChecks(filteredChecksyByHost(host_id)).map(
(checkId) => (
<tr
key={checkId}
Expand Down Expand Up @@ -234,24 +241,32 @@ export const ChecksResults = () => {
{findCheckDataByID(selectedCheck)?.remediation}
</ReactMarkdown>
</Modal>
<div className="flex mb-4">
<h1 className="text-3xl w-3/5">
<span className="font-medium">Checks Results for cluster</span>{' '}
<span className={`font-bold ${truncatedClusterNameClasses}`}>
{getClusterName(cluster)}
</span>
</h1>
<div className="flex w-2/5 justify-end text-white">
<div className="flex mb-8">
<div className="flex w-2/5">
<Button
className="w-1/3 bg-waterhole-blue text-white"
className="w-2/3 text-jungle-green-500 text-left py-0 px-0"
size="small"
type="transparent"
onClick={() => navigate(`/clusters/${cluster.id}`)}
>
<EOS_ARROW_BACK className="inline-block fill-white" /> Back to
Cluster
<EOS_ARROW_BACK className="inline-block fill-jungle-green-500" />{' '}
Back to Cluster Details
</Button>
</div>
</div>
<div className="flex mb-4 justify-between">
<h1 className="text-3xl w-3/5">
<span className="font-medium">Checks Results for cluster</span>{' '}
<span className={`font-bold ${truncatedClusterNameClasses}`}>
{getClusterName(cluster)}
</span>
</h1>
<ChecksResultFilters
onChange={(filtersPredicates) =>
setFiltersPredicates(filtersPredicates)
}
/>
</div>
{pageContent}
</div>
);
Expand Down

0 comments on commit 5a390c4

Please sign in to comment.