diff --git a/features/show_hide_columns.feature b/features/show_hide_columns.feature index 84b1bd30..1d3ac6e0 100644 --- a/features/show_hide_columns.feature +++ b/features/show_hide_columns.feature @@ -1,6 +1,6 @@ Feature: Show/hide a forecast column - Scenario: Clicking the NAC column hide link hides the NAC column - Given the user wants to hide the NAC column - When the user clicks the hide NAC column - Then the NAC column is hidden + Scenario: Clicking the NAC code column hide link hides the NAC code column + Given the user wants to hide the NAC code column + When the user clicks the hide NAC code column + Then the NAC code column is hidden diff --git a/features/steps/show_hide_columns.py b/features/steps/show_hide_columns.py index 0d571bbd..1d378971 100644 --- a/features/steps/show_hide_columns.py +++ b/features/steps/show_hide_columns.py @@ -7,13 +7,13 @@ from features.environment import TEST_COST_CENTRE_CODE, create_test_user -@given("the user wants to hide the NAC column") +@given("the user wants to hide the NAC code column") def step_impl(context): create_test_user(context) context.browser.get(f"{context.base_url}/forecast/edit/{TEST_COST_CENTRE_CODE}/") -@when("the user clicks the hide NAC column") +@when("the user clicks the hide NAC code column") def step_impl(context): filter_switch_button = WebDriverWait(context.browser, 500).until( ec.presence_of_element_located((By.ID, "action-bar-switch")) @@ -21,13 +21,13 @@ def step_impl(context): filter_switch_button.click() - show_hide_nac = WebDriverWait(context.browser, 500).until( - ec.presence_of_element_located((By.ID, "show_hide_nac")) + show_hide_nac_code = WebDriverWait(context.browser, 500).until( + ec.presence_of_element_located((By.ID, "show_hide_nac_code")) ) - show_hide_nac.click() + show_hide_nac_code.click() -@then("the NAC column is hidden") +@then("the NAC code column is hidden") def step_impl(context): header_hidden = False diff --git a/front_end/src/Components/ActualsHeaderRow/index.jsx b/front_end/src/Components/ActualsHeaderRow/index.jsx index f99ce4b2..a0b828d7 100644 --- a/front_end/src/Components/ActualsHeaderRow/index.jsx +++ b/front_end/src/Components/ActualsHeaderRow/index.jsx @@ -1,14 +1,24 @@ import React, { useEffect, useState } from "react"; +import { useSelector } from "react-redux"; const ActualsHeaderRow = () => { - const [numActuals, setNumActuals] = useState(0); + const [actualsCount, setActualsCount] = useState(0); + + const hiddenColsCount = useSelector( + (state) => state.hiddenCols.hiddenCols.length, + ); + + // Number of columns from Select All to Budget + const colsBeforeMonths = 9; + // Number of columns from Apr to Variance % + const forecastColCount = 18; useEffect(() => { const timer = () => { setTimeout(() => { if (window.actuals) { if (window.actuals.length > 0) { - setNumActuals(window.actuals.length); + setActualsCount(window.actuals.length); } } else { timer(); @@ -20,17 +30,23 @@ const ActualsHeaderRow = () => { return ( - - {numActuals > 0 && ( + + {actualsCount > 0 && ( Actuals )} - + Forecast diff --git a/front_end/src/Components/Common/CheckboxItem/index.jsx b/front_end/src/Components/Common/CheckboxItem/index.jsx new file mode 100644 index 00000000..882fc1e5 --- /dev/null +++ b/front_end/src/Components/Common/CheckboxItem/index.jsx @@ -0,0 +1,17 @@ +export default function CheckboxItem({ onChange, checked, name, label }) { + return ( +
+ + +
+ ); +} diff --git a/front_end/src/Components/EditActionBar/index.jsx b/front_end/src/Components/EditActionBar/index.jsx index 93e4b190..c8a65d48 100644 --- a/front_end/src/Components/EditActionBar/index.jsx +++ b/front_end/src/Components/EditActionBar/index.jsx @@ -3,6 +3,7 @@ import ReactDOM from "react-dom"; import { useSelector, useDispatch } from "react-redux"; import { TOGGLE_ITEM, TOGGLE_SHOW_ALL } from "../../Reducers/HiddenCols"; import { TOGGLE_FILTER } from "../../Reducers/Filter"; +import CheckboxItem from "../Common/CheckboxItem"; const EditActionBar = () => { const dispatch = useDispatch(); @@ -42,8 +43,8 @@ const EditActionBar = () => {
-

Show/hide columns

-
+

Show/hide columns

+
{
-

Individual columns

-
-
- { - dispatch(TOGGLE_ITEM("natural_account_code")); - }} - /> - -
-
- { - dispatch(TOGGLE_ITEM("programme")); - }} - /> - -
-
- { - dispatch(TOGGLE_ITEM("analysis1_code")); - }} - /> - -
-
- { - dispatch(TOGGLE_ITEM("analysis2_code")); - }} - /> - -
-
- { - dispatch(TOGGLE_ITEM("project_code")); - }} - /> - -
+

Individual columns

+
+ dispatch(TOGGLE_ITEM("programme_code"))} + checked={hiddenCols.indexOf("programme_code") === -1} + name={"programme_code"} + label={"Programme code"} + /> + + dispatch(TOGGLE_ITEM("programme_description")) + } + checked={hiddenCols.indexOf("programme_description") === -1} + name={"programme_description"} + label={"Programme description"} + /> + dispatch(TOGGLE_ITEM("nac_code"))} + checked={hiddenCols.indexOf("nac_code") === -1} + name={"nac_code"} + label={"NAC code"} + /> + dispatch(TOGGLE_ITEM("nac_description"))} + checked={hiddenCols.indexOf("nac_description") === -1} + name={"nac_description"} + label={"NAC description"} + /> + dispatch(TOGGLE_ITEM("analysis1_code"))} + checked={hiddenCols.indexOf("analysis1_code") === -1} + name={"analysis1_code"} + label={"Analysis 1"} + /> + dispatch(TOGGLE_ITEM("analysis2_code"))} + checked={hiddenCols.indexOf("analysis2_code") === -1} + name={"analysis2_code"} + label={"Analysis 2"} + /> + dispatch(TOGGLE_ITEM("project_code"))} + checked={hiddenCols.indexOf("project_code") === -1} + name={"project_code"} + label={"Project code"} + />
diff --git a/front_end/src/Components/Table/index.jsx b/front_end/src/Components/Table/index.jsx index 245574fb..c0fe245b 100644 --- a/front_end/src/Components/Table/index.jsx +++ b/front_end/src/Components/Table/index.jsx @@ -15,7 +15,7 @@ import OverspendUnderspend from "../../Components/OverspendUnderspend/index"; import TotalOverspendUnderspend from "../../Components/TotalOverspendUnderspend/index"; import TotalVariancePercentage from "../../Components/TotalVariancePercentage/index"; import ActualsHeaderRow from "../../Components/ActualsHeaderRow/index"; -import { getCellId } from "../../Util"; +import { getCellId, monthsToTitleCase } from "../../Util"; import { SET_EDITING_CELL } from "../../Reducers/Edit"; import { @@ -64,35 +64,27 @@ function Table({ rowData, sheetUpdating, payrollData }) { )} - Programme code - Programme description - - NAC code + Programme code + + Programme description - - NAC description + + NAC code + NAC description Contract Reconciliation Markets Project Code Budget - Apr - May - Jun - Jul - Aug - Sep - Oct - Nov - Dec - Jan - Feb - Mar + {monthsToTitleCase.map((month) => { + return ( + + {month} + + ); + })} {window.period_display && window.period_display.includes(13) && ( Adj 1 )} @@ -149,31 +141,28 @@ function Table({ rowData, sheetUpdating, payrollData }) { )} - + - + - + - + @@ -237,10 +226,13 @@ function Table({ rowData, sheetUpdating, payrollData }) { })} Totals - - - - + + + + diff --git a/front_end/src/Reducers/HiddenCols.js b/front_end/src/Reducers/HiddenCols.js index b1707ef9..3a774a48 100644 --- a/front_end/src/Reducers/HiddenCols.js +++ b/front_end/src/Reducers/HiddenCols.js @@ -1,13 +1,25 @@ import { createSlice } from "@reduxjs/toolkit"; -// Use of this lib guarentees no state mutatation +// Use of this lib guarantees no state mutation + +const defaultState = { + hiddenCols: [], + showAll: true, +}; + +const loadState = () => { + const serializedState = localStorage.getItem("editForecast.hiddenCols"); + return serializedState ? JSON.parse(serializedState) : defaultState; +}; + +const saveState = (state) => { + const serializedState = JSON.stringify(state); + localStorage.setItem("editForecast.hiddenCols", serializedState); +}; const hiddenCols = createSlice({ name: "hiddenCols", slice: "hidden", - initialState: { - hiddenCols: [], - showAll: true, - }, + initialState: loadState(), reducers: { TOGGLE_ITEM: (state, action) => { let index = state.hiddenCols.indexOf(action.payload); @@ -17,13 +29,16 @@ const hiddenCols = createSlice({ state.showAll = false; state.hiddenCols.push(action.payload); } + saveState(state); }, TOGGLE_SHOW_ALL: (state, action) => { if (state.showAll) { state.showAll = false; state.hiddenCols = [ - "natural_account_code", - "programme", + "nac_code", + "nac_description", + "programme_code", + "programme_description", "analysis1_code", "analysis2_code", "project_code", @@ -33,6 +48,7 @@ const hiddenCols = createSlice({ // Turn on all cols state.hiddenCols = []; } + saveState(state); }, }, }); diff --git a/front_end/styles/action-bar.scss b/front_end/styles/action-bar.scss index 1f531120..3ed70d1d 100644 --- a/front_end/styles/action-bar.scss +++ b/front_end/styles/action-bar.scss @@ -26,6 +26,7 @@ } .action-bar-content { + display: grid; border: 16px solid govuk-colour("mid-grey"); border-top-width: 0; background-color: govuk-colour("light-grey");