diff --git a/frontend/src/actions/commonActions.js b/frontend/src/actions/commonActions.js index ad95bbf8..77b09fb9 100644 --- a/frontend/src/actions/commonActions.js +++ b/frontend/src/actions/commonActions.js @@ -1,9 +1,10 @@ import * as TYPES from "@/actions/types.js"; +import { setCatFilters, sliceTableRows } from "./homeActions"; import { setOCPCatFilters, sliceOCPTableRows } from "./ocpActions"; import { DEFAULT_PER_PAGE } from "@/assets/constants/paginationConstants"; -import { sliceTableRows } from "./homeActions"; +import { cloneDeep } from "lodash"; const getSortableRowValues = (result, tableColumns) => { const tableKeys = tableColumns.map((item) => item.value); @@ -75,7 +76,8 @@ export const calculateMetrics = (results) => { }; export const buildFilterData = (currState) => (dispatch, getState) => { - const results = [...getState()[currState].results]; + const results = [...getState()[currState].filteredResults]; + const categoryFilterValue = getState()[currState].categoryFilterValue; const tableFilters = [...getState()[currState].tableFilters]; @@ -85,11 +87,19 @@ export const buildFilterData = (currState) => (dispatch, getState) => { let obj = { name: filter.name, key, - value: [...new Set(results.map((item) => item[key]))], + value: [ + ...new Set(results.map((item) => item[key]?.toString()?.toLowerCase())), + ], }; filterData.push(obj); } - dispatch(setFilterData(filterData, currState, tableFilters[0].name)); + dispatch( + setFilterData( + filterData, + currState, + categoryFilterValue || tableFilters[0].name + ) + ); }; const setFilterData = (filterData, currState, activeFilter) => (dispatch) => { @@ -99,6 +109,12 @@ const setFilterData = (filterData, currState, activeFilter) => (dispatch) => { payload: filterData, }); dispatch(setOCPCatFilters(activeFilter)); + } else if (currState === "cpt") { + dispatch({ + type: TYPES.SET_CPT_FILTER_DATA, + payload: filterData, + }); + dispatch(setCatFilters(activeFilter)); } }; @@ -124,15 +140,35 @@ export const getFilteredData = (appliedFilters, results) => { return filtered; }; -export const getAppliedFilters = - (currState, selectedOption) => (dispatch, getState) => { - const { categoryFilterValue, filterData } = getState()[currState]; - const appliedFilters = { ...getState()[currState].appliedFilters }; +export const deleteAppliedFilters = + (filterKey, filterValue, currState) => (dispatch, getState) => { + const appliedFilters = cloneDeep(getState()[currState].appliedFilters); + + const index = appliedFilters[filterKey].indexOf( + filterValue?.toString()?.toLowerCase() + ); + if (index >= 0) { + appliedFilters[filterKey].splice(index, 1); + if (appliedFilters[filterKey].length === 0) { + delete appliedFilters[filterKey]; + } + } + return appliedFilters; + }; - const category = filterData.filter( - (item) => item.name === categoryFilterValue - )[0].key; - appliedFilters[category] = selectedOption; +export const getSelectedFilter = + (selectedCategory, selectedOption, currState) => (dispatch, getState) => { + const selectedFilters = cloneDeep(getState()[currState].selectedFilters); - return appliedFilters; + const obj = selectedFilters.find((i) => i.name === selectedCategory); + selectedOption = selectedOption?.toString()?.toLowerCase(); + const objValue = obj.value.map((i) => i?.toString()?.toLowerCase()); + + if (objValue.includes(selectedOption)) { + const arr = objValue.filter((selection) => selection !== selectedOption); + obj.value = arr; + } else { + obj.value = [...obj.value, selectedOption]; + } + return selectedFilters; }; diff --git a/frontend/src/actions/homeActions.js b/frontend/src/actions/homeActions.js index 45ccad65..28433344 100644 --- a/frontend/src/actions/homeActions.js +++ b/frontend/src/actions/homeActions.js @@ -6,7 +6,14 @@ import { START_PAGE, } from "@/assets/constants/paginationConstants"; import { appendDateFilter, appendQueryString } from "@/utils/helper"; -import { calculateMetrics, getFilteredData, sortTable } from "./commonActions"; +import { + buildFilterData, + calculateMetrics, + deleteAppliedFilters, + getFilteredData, + getSelectedFilter, + sortTable, +} from "./commonActions"; import API from "@/utils/axiosInstance"; import { cloneDeep } from "lodash"; @@ -21,8 +28,6 @@ export const fetchOCPJobsData = () => async (dispatch, getState) => { pretty: true, ...(start_date && { start_date }), ...(end_date && { end_date }), - // start_date: "2024-04-21", - // end_date: "2024-04-22", }, }); if (response?.data?.results?.length > 0) { @@ -44,10 +49,7 @@ export const fetchOCPJobsData = () => async (dispatch, getState) => { }); dispatch(applyFilters()); dispatch(sortTable("cpt")); - dispatch(getCPTSummary()); - dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); - dispatch(sliceTableRows(0, DEFAULT_PER_PAGE)); - // dispatch(buildFilterData()); + dispatch(tableReCalcValues()); } } catch (error) { dispatch(showFailureToast()); @@ -74,29 +76,6 @@ export const sliceTableRows = (startIdx, endIdx) => (dispatch, getState) => { }); }; -export const buildFilterData = () => (dispatch, getState) => { - const results = [...getState().cpt.filteredResults]; - - const tableFilters = [...getState().cpt.tableFilters]; - - const filterData = []; - for (const filter of tableFilters) { - const key = filter.value; - let obj = { - name: filter.name, - key, - value: [...new Set(results.map((item) => item[key]?.toLowerCase()))], - }; - filterData.push(obj); - } - - dispatch({ - type: TYPES.SET_CPT_FILTER_DATA, - payload: filterData, - }); - dispatch(setCatFilters(tableFilters[0].name)); -}; - export const setCatFilters = (category) => (dispatch, getState) => { const filterData = [...getState().cpt.filterData]; const options = filterData.filter((item) => item.name === category)[0].value; @@ -123,19 +102,10 @@ export const setSelectedFilterFromUrl = (params) => (dispatch, getState) => { }); }; export const setSelectedFilter = - (selectedCategory, selectedOption) => (dispatch, getState) => { - const selectedFilters = cloneDeep(getState().cpt.selectedFilters); - - const obj = selectedFilters.find((i) => i.name === selectedCategory); - selectedOption = selectedOption?.toString()?.toLowerCase(); - const objValue = obj.value.map((i) => i?.toString()?.toLowerCase()); - - if (objValue.includes(selectedOption)) { - const arr = objValue.filter((selection) => selection !== selectedOption); - obj.value = arr; - } else { - obj.value = [...obj.value, selectedOption]; - } + (selectedCategory, selectedOption) => (dispatch) => { + const selectedFilters = dispatch( + getSelectedFilter(selectedCategory, selectedOption, "cpt") + ); dispatch({ type: TYPES.SET_SELECTED_FILTERS, payload: selectedFilters, @@ -170,25 +140,16 @@ export const setOtherSummaryFilter = () => (dispatch, getState) => { type: TYPES.SET_FILTERED_DATA, payload: data, }); - dispatch(getCPTSummary()); - dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); - dispatch(sliceTableRows(0, DEFAULT_PER_PAGE)); + dispatch(tableReCalcValues()); }; export const removeAppliedFilters = (filterKey, filterValue, navigate) => (dispatch, getState) => { - const appliedFilters = cloneDeep(getState().cpt.appliedFilters); const { start_date, end_date } = getState().cpt; - const index = appliedFilters[filterKey] - ?.toString() - ?.toLowerCase() - .indexOf(filterValue); - if (index >= 0) { - appliedFilters[filterKey].splice(index, 1); - if (appliedFilters[filterKey].length === 0) { - delete appliedFilters[filterKey]; - } - } + const appliedFilters = dispatch( + deleteAppliedFilters(filterKey, filterValue, "cpt") + ); + dispatch({ type: TYPES.SET_APPLIED_FILTERS, payload: appliedFilters, @@ -212,12 +173,10 @@ export const applyFilters = () => (dispatch, getState) => { dispatch({ type: TYPES.SET_FILTERED_DATA, - payload: isFilterApplied ? filtered : results, + payload: filtered, }); - dispatch(getCPTSummary()); - dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); - dispatch(sliceTableRows(0, DEFAULT_PER_PAGE)); - dispatch(buildFilterData()); + dispatch(tableReCalcValues()); + dispatch(buildFilterData("cpt")); }; export const setFilterFromURL = (searchParams) => ({ @@ -261,3 +220,9 @@ export const getCPTSummary = () => (dispatch, getState) => { payload: countObj, }); }; + +export const tableReCalcValues = () => (dispatch) => { + dispatch(getCPTSummary()); + dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); + dispatch(sliceTableRows(0, DEFAULT_PER_PAGE)); +}; diff --git a/frontend/src/actions/ocpActions.js b/frontend/src/actions/ocpActions.js index eff9cfa9..d37b185b 100644 --- a/frontend/src/actions/ocpActions.js +++ b/frontend/src/actions/ocpActions.js @@ -1,5 +1,5 @@ import * as API_ROUTES from "@/utils/apiConstants"; -import * as TYPES from "@/actions/types.js"; +import * as TYPES from "./types.js"; import { DEFAULT_PER_PAGE, @@ -9,13 +9,15 @@ import { appendDateFilter, appendQueryString } from "@/utils/helper.js"; import { buildFilterData, calculateMetrics, + deleteAppliedFilters, getFilteredData, + getSelectedFilter, sortTable, -} from "@/actions/commonActions.js"; +} from "./commonActions"; import API from "@/utils/axiosInstance"; -import { getAppliedFilters } from "./commonActions"; -import { showFailureToast } from "@/actions/toastActions"; +import { cloneDeep } from "lodash"; +import { showFailureToast } from "./toastActions"; export const fetchOCPJobs = () => async (dispatch, getState) => { try { @@ -26,8 +28,6 @@ export const fetchOCPJobs = () => async (dispatch, getState) => { pretty: true, ...(start_date && { start_date }), ...(end_date && { end_date }), - // start_date: "2024-04-21", - // end_date: "2024-04-22", }, }); if (response?.data?.results?.length > 0) { @@ -48,10 +48,7 @@ export const fetchOCPJobs = () => async (dispatch, getState) => { }); dispatch(applyFilters()); dispatch(sortTable("ocp")); - dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); - dispatch(sliceOCPTableRows(0, DEFAULT_PER_PAGE)); - dispatch(buildFilterData("ocp")); - dispatch(getOCPSummary()); + dispatch(tableReCalcValues()); } } catch (error) { dispatch(showFailureToast()); @@ -112,42 +109,66 @@ export const applyFilters = () => (dispatch, getState) => { Object.keys(appliedFilters).length > 0 && !Object.values(appliedFilters).includes(""); - const filtered = getFilteredData(appliedFilters, results); + const filtered = isFilterApplied + ? getFilteredData(appliedFilters, results) + : results; dispatch({ type: TYPES.SET_OCP_FILTERED_DATA, - payload: isFilterApplied ? filtered : results, + payload: filtered, }); - dispatch(getOCPSummary()); - dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); - dispatch(sliceOCPTableRows(0, DEFAULT_PER_PAGE)); + dispatch(tableReCalcValues()); + dispatch(buildFilterData("ocp")); }; -export const setAppliedFilters = - (selectedOption, navigate) => (dispatch, getState) => { - const appliedFilters = dispatch(getAppliedFilters("ocp", selectedOption)); - const { start_date, end_date } = getState().ocp; +export const setSelectedFilterFromUrl = (params) => (dispatch, getState) => { + const selectedFilters = cloneDeep(getState().ocp.selectedFilters); + for (const key in params) { + selectedFilters.find((i) => i.name === key).value = params[key].split(","); + } + dispatch({ + type: TYPES.SET_SELECTED_OCP_FILTERS, + payload: selectedFilters, + }); +}; +export const setSelectedFilter = + (selectedCategory, selectedOption) => (dispatch) => { + const selectedFilters = dispatch( + getSelectedFilter(selectedCategory, selectedOption, "ocp") + ); dispatch({ - type: TYPES.SET_OCP_APPLIED_FILTERS, - payload: appliedFilters, + type: TYPES.SET_SELECTED_OCP_FILTERS, + payload: selectedFilters, }); - appendQueryString({ ...appliedFilters, start_date, end_date }, navigate); - dispatch(applyFilters()); }; +export const setAppliedFilters = (navigate) => (dispatch, getState) => { + const { start_date, end_date, selectedFilters } = getState().ocp; + const appliedFilterArr = selectedFilters.filter((i) => i.value.length > 0); + + const appliedFilters = {}; + appliedFilterArr.forEach((item) => { + appliedFilters[item["name"]] = item.value; + }); + + dispatch({ + type: TYPES.SET_OCP_APPLIED_FILTERS, + payload: appliedFilters, + }); + appendQueryString({ ...appliedFilters, start_date, end_date }, navigate); + dispatch(applyFilters()); +}; export const removeAppliedFilters = - (filterKey, navigate) => (dispatch, getState) => { - const appliedFilters = { ...getState().ocp.appliedFilters }; + (filterKey, filterValue, navigate) => (dispatch, getState) => { + const appliedFilters = dispatch( + deleteAppliedFilters(filterKey, filterValue, "ocp") + ); const { start_date, end_date } = getState().ocp; - const name = filterKey; - // eslint-disable-next-line no-unused-vars - const { [name]: removedProperty, ...remainingObject } = appliedFilters; - dispatch({ type: TYPES.SET_OCP_APPLIED_FILTERS, - payload: remainingObject, + payload: appliedFilters, }); - appendQueryString({ ...remainingObject, start_date, end_date }, navigate); + appendQueryString({ ...appliedFilters, start_date, end_date }, navigate); dispatch(applyFilters()); }; @@ -173,32 +194,17 @@ export const setFilterFromURL = (searchParams) => ({ payload: searchParams, }); -export const filterFromSummary = - (category, value, navigate) => (dispatch, getState) => { - const { start_date, end_date } = getState().ocp; - const appliedFilters = { ...getState().ocp.appliedFilters }; - appliedFilters[category] = value; - dispatch({ - type: TYPES.SET_OCP_APPLIED_FILTERS, - payload: appliedFilters, - }); - appendQueryString({ ...appliedFilters, start_date, end_date }, navigate); - dispatch(applyFilters()); - }; - export const setOtherSummaryFilter = () => (dispatch, getState) => { const filteredResults = [...getState().ocp.filteredResults]; - const keyWordArr = ["SUCCESS", "FAILURE"]; + const keyWordArr = ["success", "failure"]; const data = filteredResults.filter( - (item) => !keyWordArr.includes(item.jobStatus) + (item) => !keyWordArr.includes(item.jobStatus?.toLowerCase()) ); dispatch({ type: TYPES.SET_OCP_FILTERED_DATA, payload: data, }); - dispatch(getOCPSummary()); - dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); - dispatch(sliceOCPTableRows(0, DEFAULT_PER_PAGE)); + dispatch(tableReCalcValues()); }; export const getOCPSummary = () => (dispatch, getState) => { @@ -249,3 +255,8 @@ export const setTableColumns = (key, isAdding) => (dispatch, getState) => { payload: tableColumns, }); }; +export const tableReCalcValues = () => (dispatch) => { + dispatch(getOCPSummary()); + dispatch(setPageOptions(START_PAGE, DEFAULT_PER_PAGE)); + dispatch(sliceOCPTableRows(0, DEFAULT_PER_PAGE)); +}; diff --git a/frontend/src/actions/types.js b/frontend/src/actions/types.js index f1663eda..77db108b 100644 --- a/frontend/src/actions/types.js +++ b/frontend/src/actions/types.js @@ -42,3 +42,4 @@ export const SET_OCP_FILTERED_DATA = "SET_OCP_FILTERED_DATA"; export const SET_OCP_APPLIED_FILTERS = "SET_OCP_APPLIED_FILTERS"; export const SET_OCP_GRAPH_DATA = "SET_OCP_GRAPH_DATA"; export const SET_OCP_COLUMNS = "SET_OCP_COLUMNS"; +export const SET_SELECTED_OCP_FILTERS = "SET_SELECTED_OCP_FILTERS"; diff --git a/frontend/src/components/templates/OCP/index.jsx b/frontend/src/components/templates/OCP/index.jsx index 9b6b33b8..6c7739a4 100644 --- a/frontend/src/components/templates/OCP/index.jsx +++ b/frontend/src/components/templates/OCP/index.jsx @@ -1,7 +1,6 @@ import { fetchGraphData, fetchOCPJobs, - filterFromSummary, removeAppliedFilters, setAppliedFilters, setDateFilter, @@ -12,9 +11,11 @@ import { setOtherSummaryFilter, setPage, setPageOptions, + setSelectedFilter, + setSelectedFilterFromUrl, setTableColumns, sliceOCPTableRows, -} from "../../../actions/ocpActions"; +} from "@/actions/ocpActions"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate, useSearchParams } from "react-router-dom"; @@ -45,6 +46,7 @@ const OCP = () => { start_date, end_date, graphData, + selectedFilters, } = useSelector((state) => state.ocp); const modifidedTableFilters = useMemo( @@ -63,7 +65,12 @@ const OCP = () => { searchParams.delete("start_date"); searchParams.delete("end_date"); const params = Object.fromEntries(searchParams); - dispatch(setFilterFromURL(params)); + const obj = {}; + for (const key in params) { + obj[key] = params[key].split(","); + } + dispatch(setFilterFromURL(obj)); + dispatch(setSelectedFilterFromUrl(params)); dispatch(setDateFilter(startDate, endDate, navigate)); } }, []); @@ -102,26 +109,39 @@ const OCP = () => { // Pagination helper /* Summary Tab Filter*/ const removeStatusFilter = () => { - dispatch(removeAppliedFilters("jobStatus", navigate)); + if ( + Array.isArray(appliedFilters["jobStatus"]) && + appliedFilters["jobStatus"].length > 0 + ) { + appliedFilters["jobStatus"].forEach((element) => { + updateSelectedFilter("jobStatus", element); + dispatch(removeAppliedFilters("jobStatus", element, navigate)); + }); + } }; const applyStatusFilter = (value) => { - dispatch(filterFromSummary("jobStatus", value, navigate)); + updateSelectedFilter("jobStatus", value); + dispatch(setAppliedFilters(navigate)); }; const applyOtherFilter = () => { - dispatch(removeAppliedFilters("jobStatus", navigate)); + removeStatusFilter(); dispatch(setOtherSummaryFilter()); }; + const updateSelectedFilter = (category, value) => { + dispatch(setSelectedFilter(category, value)); + }; /* Filter helper */ const onCategoryChange = (_event, value) => { dispatch(setOCPCatFilters(value)); }; - const onOptionsChange = (_event, value) => { - dispatch(setAppliedFilters(value, navigate)); + const onOptionsChange = () => { + dispatch(setAppliedFilters(navigate)); }; - const deleteItem = (key) => { - dispatch(removeAppliedFilters(key, navigate)); + const deleteItem = (key, value) => { + dispatch(removeAppliedFilters(key, value, navigate)); + updateSelectedFilter(key, value); }; const startDateChangeHandler = (date, key) => { dispatch(setDateFilter(date, key, navigate)); @@ -160,25 +180,25 @@ const OCP = () => { applyOtherFilter={applyOtherFilter} /> - {tableFilters?.length > 0 && filterOptions?.length > 0 && ( - - )} + { return { ...state, graphData: [...state.graphData, payload] }; case TYPES.SET_OCP_COLUMNS: return { ...state, tableColumns: payload }; - case TYPES.SET_SELECTED_FILTERS: + case TYPES.SET_SELECTED_OCP_FILTERS: return { ...state, selectedFilters: payload }; default: return state;