Skip to content

Commit

Permalink
finish adding example filters to device chart
Browse files Browse the repository at this point in the history
  • Loading branch information
levinmr committed Jan 14, 2025
1 parent 7e6833a commit 8451950
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 43 deletions.
48 changes: 31 additions & 17 deletions js/components/dashboard_content/DevicesChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,37 @@ import FilterSelect from "../select/FilterSelect";
* @returns {import('react').ReactElement} The rendered element
*/
function DevicesChart({ dataHrefBase }) {
const [dataFileName, setDataFileName] = useState('devices');
const [deviceData, setDeviceData] = useState(null);
const ref = useRef(null);
const chartBuilder = new ChartBuilder();
const reportFilters = [['30 Days', 'devices'], ['7 Days', 'devices-7-days'], ['90 Days', 'devices-90-days']]
const reportFilters = [
["30 Days", "devices"],
["7 Days", "devices-7-days"],
["90 Days", "devices-90-days"],
];
const [dataFileName, setDataFileName] = useState("devices");
const ref = useRef(null);

useEffect(() => {
const initDevicesChart = async () => {
if (deviceData == null && dataFileName) {
const data = await DataLoader.loadJSON(`${dataHrefBase}/${dataFileName}.json`);
await setDeviceData(data);
} else {
await buildChartForDeviceData();
if (dataFileName) {
let data;

try {
data = await DataLoader.loadJSON(
`${dataHrefBase}/${dataFileName}.json`,
);
} catch (e) {
data = { totals: {} };
}
await buildChartForDeviceData(data);
}
};
initDevicesChart().catch(console.error);
}, [deviceData, dataFileName]);
}, [dataFileName]);

function buildChartForDeviceData() {
function buildChartForDeviceData(data) {
return chartBuilder
.setElement(ref.current)
.setData(deviceData)
.setData(data)
.setTransformer((d) => {
const devices = transformers.listify(d.totals.by_device);
devices.forEach((device) => {
Expand All @@ -61,11 +70,9 @@ function DevicesChart({ dataHrefBase }) {
}

async function dataFileChangeHandler(fileName) {
if (!deviceData) return;
if (!fileName) return;

console.log(fileName)
await setDataFileName(fileName);
await setDeviceData({});
}

return (
Expand All @@ -79,7 +86,10 @@ function DevicesChart({ dataHrefBase }) {
Devices
</Tooltip>
</a>
<a href={`${dataHrefBase}/${dataFileName}.csv`} aria-label={`${dataHrefBase}/${dataFileName}.csv`}>
<a
href={`${dataHrefBase}/${dataFileName}.csv`}
aria-label={`${dataHrefBase}/${dataFileName}.csv`}
>
<svg
className="usa-icon margin-bottom-neg-05 margin-left-05"
aria-hidden="true"
Expand All @@ -93,7 +103,11 @@ function DevicesChart({ dataHrefBase }) {
<figure id="chart_device_types" ref={ref}>
<div className="data chart__bar-chart text--capitalize margin-top-2"></div>
</figure>
<FilterSelect filters={reportFilters} defaultFilter={dataFileName || ''} onChange={dataFileChangeHandler} />
<FilterSelect
filters={reportFilters}
defaultFilterValue={dataFileName || ""}
onChange={dataFileChangeHandler}
/>
</>
);
}
Expand Down
12 changes: 4 additions & 8 deletions js/components/dashboard_content/__tests__/DevicesChart.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe("DevicesChart", () => {
return Promise.resolve(null);
});
component = render(
<DevicesChart dataHrefBase="http://www.example.com/data/" />,
<DevicesChart dataHrefBase="http://www.example.com/data" />,
);
});

Expand Down Expand Up @@ -55,7 +55,7 @@ describe("DevicesChart", () => {
return Promise.resolve(data);
});
component = render(
<DevicesChart dataHrefBase="http://www.example.com/data/" />,
<DevicesChart dataHrefBase="http://www.example.com/data" />,
);
await waitFor(() => screen.getByText("mobile"));
// Wait for barchart transition animation to complete (200 ms, set in
Expand All @@ -77,16 +77,12 @@ describe("DevicesChart", () => {
return Promise.reject(error);
});
component = render(
<DevicesChart dataHrefBase="http://www.example.com/data/" />,
<DevicesChart dataHrefBase="http://www.example.com/data" />,
);
});

it("renders a component in error state", () => {
it("renders a component with an empty chart", () => {
expect(component.asFragment()).toMatchSnapshot();
});

it("logs the error to console", () => {
expect(console.error).toHaveBeenCalledWith(error);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ exports[`DeviceDemographics renders 1`] = `
</span>
</a>
<a
aria-label="devices.csv"
aria-label="http://www.example.com/data//devices.csv"
href="http://www.example.com/data//devices.csv"
>
<svg
Expand All @@ -59,6 +59,25 @@ exports[`DeviceDemographics renders 1`] = `
class="data chart__bar-chart text--capitalize margin-top-2"
/>
</figure>
<select
class="usa-select"
>
<option
value="devices"
>
30 Days
</option>
<option
value="devices-7-days"
>
7 Days
</option>
<option
value="devices-90-days"
>
90 Days
</option>
</select>
<div
class="chart__title desktop:padding-top-2"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ exports[`DevicesChart when data is loaded renders a component with data loaded 1
</span>
</a>
<a
aria-label="devices.csv"
href="http://www.example.com/data//devices.csv"
aria-label="http://www.example.com/data/devices.csv"
href="http://www.example.com/data/devices.csv"
>
<svg
aria-hidden="true"
Expand Down Expand Up @@ -143,6 +143,25 @@ exports[`DevicesChart when data is loaded renders a component with data loaded 1
</div>
</div>
</figure>
<select
class="usa-select"
>
<option
value="devices"
>
30 Days
</option>
<option
value="devices-7-days"
>
7 Days
</option>
<option
value="devices-90-days"
>
90 Days
</option>
</select>
</DocumentFragment>
`;

Expand Down Expand Up @@ -176,8 +195,8 @@ exports[`DevicesChart when data is not loaded renders a component in loading sta
</span>
</a>
<a
aria-label="devices.csv"
href="http://www.example.com/data//devices.csv"
aria-label="http://www.example.com/data/devices.csv"
href="http://www.example.com/data/devices.csv"
>
<svg
aria-hidden="true"
Expand All @@ -198,10 +217,29 @@ exports[`DevicesChart when data is not loaded renders a component in loading sta
class="data chart__bar-chart text--capitalize margin-top-2"
/>
</figure>
<select
class="usa-select"
>
<option
value="devices"
>
30 Days
</option>
<option
value="devices-7-days"
>
7 Days
</option>
<option
value="devices-90-days"
>
90 Days
</option>
</select>
</DocumentFragment>
`;

exports[`DevicesChart when data loading has an error renders a component in error state 1`] = `
exports[`DevicesChart when data loading has an error renders a component with an empty chart 1`] = `
<DocumentFragment>
<div
class="chart__title"
Expand Down Expand Up @@ -231,8 +269,8 @@ exports[`DevicesChart when data loading has an error renders a component in erro
</span>
</a>
<a
aria-label="devices.csv"
href="http://www.example.com/data//devices.csv"
aria-label="http://www.example.com/data/devices.csv"
href="http://www.example.com/data/devices.csv"
>
<svg
aria-hidden="true"
Expand All @@ -253,5 +291,24 @@ exports[`DevicesChart when data loading has an error renders a component in erro
class="data chart__bar-chart text--capitalize margin-top-2"
/>
</figure>
<select
class="usa-select"
>
<option
value="devices"
>
30 Days
</option>
<option
value="devices-7-days"
>
7 Days
</option>
<option
value="devices-90-days"
>
90 Days
</option>
</select>
</DocumentFragment>
`;
18 changes: 8 additions & 10 deletions js/components/select/FilterSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import PropTypes from "prop-types";
*
* @param {object} props the properties for the component
* @param {string[][]} props.filters the name and value of each filter option.
* @param {string} props.defaultFilter the name of the option which should be
* selected by default.
* @param {function} props.onChange a function to call when the selected option
* @param {string} props.defaultFilterValue the value of the option which should
* be selected by default.
* @param {Function} props.onChange a function to call when the selected option
* is changed.
* @returns {import('react').ReactElement} The rendered element
*/
Expand All @@ -19,22 +19,21 @@ function FilterSelect({ filters, defaultFilterValue, onChange }) {
// Sort by display name, which is array index 0
if (a[0] < b[0]) {
return -1;
}
else if (a[0] > b[0]) {
} else if (a[0] > b[0]) {
return 1;
}
return 0;
})
});

useEffect(() => {
onChange(selectedFilter);
}, [selectedFilter])
}, [selectedFilter]);

return (
<select
className="usa-select"
value={selectedFilter}
onChange={e => setSelectedFilter(e.target.value)}
onChange={(e) => setSelectedFilter(e.target.value)}
>
{sortedFilters.map((filter, index) => {
return (
Expand All @@ -45,12 +44,11 @@ function FilterSelect({ filters, defaultFilterValue, onChange }) {
})}
</select>
);

}

FilterSelect.propTypes = {
filters: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.string)).isRequired,
defaultFilter: PropTypes.string.isRequired,
defaultFilterValue: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
};

Expand Down

0 comments on commit 8451950

Please sign in to comment.