Skip to content
This repository has been archived by the owner on Sep 12, 2024. It is now read-only.

Subdim filter fe #1002

Merged
merged 6 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions frontend/src/assets/images/subdim_filter.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 19 additions & 4 deletions frontend/src/components/Anomaly/anomaly.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
width: 170px !important;
}
.option-selections {
background: $white;
border: 1px solid rgba(34, 34, 34, 0.12);
background: #f5f5f5;
border: 1px solid #f5f5f5;
box-sizing: border-box;
border-radius: 6px;
padding: 4px;
Expand All @@ -16,18 +16,33 @@
justify-content: center;
span {
padding: 8px;
cursor: pointer;
font-weight: $font-weight-400;
font-size: $font-size-14;
line-height: $line-height-16;
color: $grey_variation-3;
color: #222222;
&.active {
color: $green;
font-weight: $font-weight-500;
background: $green_variation-2;
border-radius: 6px;
}
}
.clear-filter {
font-size: 12px;
line-height: 16px;
font-weight: 500;
color: #0597f2;
cursor: pointer;
}
}
}
.filter-container {
display: flex;
justify-content: space-evenly;
align-items: center;
.selectcategory__control {
border: 1px solid #bdbdbd !important;
background: #ffffff !important;
}
}
.ddgif_parent_container {
Expand Down
233 changes: 156 additions & 77 deletions frontend/src/components/Anomaly/index.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useEffect, useState, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { useHistory } from 'react-router-dom';

import { useHistory, useLocation } from 'react-router-dom';
import Select from 'react-select';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import highchartsMore from 'highcharts/highcharts-more';
Expand All @@ -15,6 +15,7 @@ import AnomalyEmptyState from '../AnomalyEmptyState';
import EmptyAnomalyDrilldown from '../EmptyDrillDown';
import { formatDateTime, getTimezone } from '../../utils/date-helper';
import { HRNumbers } from '../../utils/Formatting/Numbers/humanReadableNumberFormatter';
import subdimFilterImage from '../../assets/images/subdim_filter.svg';
import './anomaly.scss';

import deepDrillGif from '../../assets/Animations/PH_Animation.gif';
Expand All @@ -26,7 +27,6 @@ import {
setRetrain
} from '../../redux/actions';
import store from '../../redux/store';
import SubdimensionEmpty from '../SubdimensionEmpty';

import { useToast } from 'react-toast-wnm';
import { CustomContent, CustomActions } from '../../utils/toast-helper';
Expand All @@ -52,22 +52,105 @@ const RESET_CSV = {
type: 'RESET_CSV'
};

const customStyles = {
container: (provided) => ({
...provided,
width: 140
})
};

const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
const location = useLocation();
const query = new URLSearchParams(location.search);
const dispatch = useDispatch();
const history = useHistory();
const toast = useToast();
const [chartData, setChartData] = useState([]);
const [subDimLoading, setSubDimloading] = useState(true);
const [retrainOn, setRetrainOn] = useState(false);
const [subDimList, setSubDimList] = useState([]);
const [drilldownCollapse, setDrilldownCollapse] = useState(true);
const [anomalStatusInfo, setAnomalyStatusInfo] = useState(false);
const [kpiTab, setKPITab] = useState('Overall KPI');
const [dimension, setDimension] = useState(
query.getAll('dimension')?.length > 0
? {
value: query.getAll('dimension')[0],
label: query.getAll('dimension')[0]
}
: null
);
const [value, setValue] = useState(
query.getAll('value')?.length > 0
? { value: query.getAll('value')[0], label: query.getAll('value')[0] }
: null
);
const [dimensionOptions, setDimensionOptions] = useState([]);
const [valueOptions, setValueOptions] = useState([]);

const idRef = useRef(0);
const isFirstRun = useRef(true);

const KPITabs = [{ name: 'Overall KPI' }, { name: 'Sub-dimensions' }];
const handleRetrain = () => {
dispatch(setRetrain(kpi));
};

const handleDownloadClick = () => {
dispatch(anomalyDownloadCsv(kpi));
};

const handleDimensionChange = (e) => {
let params = new URLSearchParams();
params.append('dimension', e.value);
history.push({
pathname: kpi,
search: '?' + params.toString()
});
setDimension(e);
if (anomalyDetectionData && anomalyDetectionData.dimensions_values) {
const dimensionIndex = anomalyDetectionData.dimensions_values?.findIndex(
(dimensionItem) => {
return e.value.toString() === dimensionItem.value.toString();
}
);
if (dimensionIndex >= 0) {
setValueOptions(
anomalyDetectionData.dimensions_values[dimensionIndex]
.subdim_value_options
);
}
}
setValue(null);
};

const handleValueChange = (e) => {
setValue(e);
let params = new URLSearchParams();
params.append('dimension', dimension?.value);
params.append('value', e.value);
history.push({
pathname: kpi,
search: '?' + params.toString()
});
store.dispatch(RESET_ACTION);
let dimFilterObj = undefined;
if (dimension && e) {
dimFilterObj = { dimension: dimension.value, value: e.value };
}
dispatch(anomalyDetection(kpi, dimFilterObj));
};

const clearSubdimFilters = () => {
setDimension(null);
setValue(null);
setValueOptions(null);
const params = new URLSearchParams(location.search);
params?.delete('dimension');
params?.delete('value');
history.push({
pathname: kpi,
search: params?.toString()
});

store.dispatch(RESET_ACTION);
dispatch(anomalyDetection(kpi, null));
};

const {
anomalyDetectionData,
Expand Down Expand Up @@ -104,7 +187,11 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {

useEffect(() => {
store.dispatch(RESET_ACTION);
getAnomaly(kpiTab);
let dimFilterObj = undefined;
if (dimension && value) {
dimFilterObj = { dimension: dimension.value, value: value.value };
}
dispatch(anomalyDetection(kpi, dimFilterObj));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [kpi]);

Expand All @@ -118,39 +205,24 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
}, [retrain]);

useEffect(() => {
if (isFirstRun.current) {
isFirstRun.current = false;
return;
}
store.dispatch(RESET_ACTION);
getAnomaly(kpiTab);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [kpiTab]);

const getAnomaly = (tab) => {
if (tab === 'Sub-dimensions') {
setSubDimloading(true);
}
dispatch(anomalyDetection(kpi, tab));
};

useEffect(() => {
let subDimesionList = [];
if (kpiTab === 'Overall KPI') {
if (anomalyDetectionData) {
idRef.current = anomalyDetectionData?.data?.base_anomaly_id;
renderChart(anomalyDetectionData?.data?.chart_data);
handleDataQuality(anomalyDetectionData?.data?.base_anomaly_id);
}
} else if (kpiTab === 'Sub-dimensions') {
setSubDimloading(false);
if (anomalyDetectionData) {
subDimesionList =
anomalyDetectionData?.data?.length &&
anomalyDetectionData?.data?.map((anomaly) => (
<Anomalygraph key={`dl-${anomaly.title}`} drilldown={anomaly} />
));
setSubDimList(subDimesionList);
if (anomalyDetectionData) {
idRef.current = anomalyDetectionData?.data?.base_anomaly_id;
renderChart(anomalyDetectionData?.data?.chart_data);
handleDataQuality(anomalyDetectionData?.data?.base_anomaly_id);
setDimensionOptions(anomalyDetectionData?.dimensions_values);
if (dimension?.value) {
const dimensionIndex =
anomalyDetectionData.dimensions_values?.findIndex((dimensionItem) => {
return (
dimension.value.toString() === dimensionItem.value.toString()
);
});
if (dimensionIndex >= 0) {
setValueOptions(
anomalyDetectionData.dimensions_values[dimensionIndex]
.subdim_value_options
);
}
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
Expand Down Expand Up @@ -446,14 +518,6 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
}
};

const handleRetrain = () => {
dispatch(setRetrain(kpi));
};

const handleDownloadClick = () => {
dispatch(anomalyDownloadCsv(kpi));
};

const customToast = (data) => {
const { type, header, description } = data;
toast({
Expand Down Expand Up @@ -481,7 +545,6 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
)
});
};

return (
<>
{retrainOn === true || anomalStatusInfo === true ? (
Expand Down Expand Up @@ -520,19 +583,42 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
<div className="option-selections-container">
<div className="download-container">
<div className="option-selections">
{KPITabs?.length &&
KPITabs.map(function (tab, i) {
return (
<span
onClick={() => setKPITab(tab.name)}
className={
tab.name === kpiTab ? 'active' : 'inactive'
}
key={i}>
{tab.name}
</span>
);
})}
<div className="filter-container">
<img src={subdimFilterImage} alt="filter" />
</div>
<div className="filter-container">
<span>Dimension =</span>
<Select
value={dimension}
placeholder="select"
styles={customStyles}
classNamePrefix="selectcategory"
isSearchable={false}
options={dimensionOptions}
onChange={(e) => handleDimensionChange(e)}
/>
</div>
<div className="filter-container">
<span>Value =</span>
<Select
value={value}
placeholder="select"
styles={customStyles}
classNamePrefix="selectcategory"
isSearchable={false}
options={valueOptions}
onChange={(e) => handleValueChange(e)}
/>
</div>
{(dimension || value) && (
<div className="filter-container">
<span
class="clear-filter"
onClick={() => clearSubdimFilters()}>
Clear filter
</span>
</div>
)}
</div>
<div
className="download-icon"
Expand All @@ -542,23 +628,15 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
</div>
</div>
</div>

{kpiTab === 'Overall KPI' &&
chartData &&
chartData.length !== 0 ? (
{chartData && Object.keys(chartData)?.length && (
<HighchartsReact
containerProps={{ className: 'chartContainer' }}
highcharts={Highcharts}
options={chartData}
/>
) : subDimLoading ? null : subDimList && subDimList.length ? (
subDimList
) : (
<div className="dashboard-layout setup-layout-empty">
<SubdimensionEmpty />
</div>
)}
{kpiTab === 'Overall KPI' && (

{anomalyDetectionData?.is_overall && (
<div className="retrain-button-container">
<div
className="retrain-button"
Expand All @@ -570,7 +648,8 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
)}
</div>
</div>
{kpiTab === 'Overall KPI' ? (

{anomalyDetectionData?.is_overall && (
<div className="dashboard-layout">
<div
className={
Expand Down Expand Up @@ -632,7 +711,7 @@ const Anomaly = ({ kpi, anomalystatus, dashboard }) => {
</>
) : null}
</div>
) : null}
)}
</>
) : (
anomalyDetectionData !== '' && <Noresult title="Anomaly" />
Expand Down
Loading