Skip to content

Commit 1060655

Browse files
Merge pull request #119 from codytodonnell/feature/explore-context
Refactor explore data state
2 parents ba606b7 + d95b168 commit 1060655

File tree

13 files changed

+171
-369
lines changed

13 files changed

+171
-369
lines changed

strudel-taskflows/src/components/FilterContext.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ export interface FilterState {
1212
expandedGroup: string | number | boolean;
1313
}
1414

15-
const FilterContextAPI = React.createContext<{state: FilterState; dispatch: React.Dispatch<FilterAction>} | undefined>(undefined);
15+
const FilterContextAPI = React.createContext<{
16+
activeFilters: FilterState['activeFilters'];
17+
expandedGroup: FilterState['expandedGroup'];
18+
dispatch: React.Dispatch<FilterAction>
19+
} | undefined>(undefined);
1620

1721
const initialState: FilterState = {
1822
activeFilters: [],
@@ -39,6 +43,7 @@ function filterReducer(state: FilterState, action: FilterAction): FilterState {
3943
} else if (filter.value) {
4044
activeFilters.push(filter);
4145
}
46+
console.log(activeFilters);
4247
return {
4348
...state,
4449
activeFilters
@@ -77,7 +82,11 @@ export const FilterContext: React.FC<FilterContextProps> = ({
7782
children
7883
}) => {
7984
const [state, dispatch] = useReducer(filterReducer, { ...initialState, activeFilters });
80-
const value = { state, dispatch };
85+
const value = {
86+
activeFilters: state.activeFilters,
87+
expandedGroup: state.expandedGroup,
88+
dispatch
89+
};
8190

8291
/**
8392
* Emit a change event when state.activeFilters changes
@@ -90,9 +99,9 @@ export const FilterContext: React.FC<FilterContextProps> = ({
9099
* If activeFilters is changed from outside the context (e.g. filters are reset)
91100
* then the new value should be dispatched.
92101
*/
93-
useEffect(() => {
94-
dispatch({ type: 'SET_ACTIVE_FILTERS', payload: activeFilters });
95-
}, [activeFilters]);
102+
// useEffect(() => {
103+
// dispatch({ type: 'SET_ACTIVE_FILTERS', payload: activeFilters });
104+
// }, [activeFilters]);
96105

97106
return (
98107
<FilterContextAPI.Provider value={value}>

strudel-taskflows/src/components/FilterField.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ export const FilterField: React.FC<FilterFieldProps> = ({
5656
filterProps,
5757
...rest
5858
}) => {
59-
const { state, dispatch } = useFilters();
59+
const { activeFilters, dispatch } = useFilters();
6060
const [value, setValue] = useState<FilterValue<typeof filterComponent>>(null);
61-
const currentFilter = state.activeFilters.find((filter) => filter.field === field);
61+
const currentFilter = activeFilters.find((filter) => filter.field === field);
6262
const isActive = hasValue(currentFilter?.value);
6363

6464
/**
@@ -133,7 +133,7 @@ export const FilterField: React.FC<FilterFieldProps> = ({
133133
);
134134
}
135135
case 'DateRange': {
136-
const currentDateRange = state.activeFilters.find((filter) => filter.field === filter.field)?.value;
136+
const currentDateRange = activeFilters.find((filter) => filter.field === filter.field)?.value;
137137
const hasValue = currentDateRange && Array.isArray(currentDateRange) && currentDateRange.length === 2;
138138
const currentMin = hasValue && Array.isArray(currentDateRange) ? currentDateRange[0] : null;
139139
const currentMax = hasValue && Array.isArray(currentDateRange) ? currentDateRange[1] : null;
@@ -202,7 +202,7 @@ export const FilterField: React.FC<FilterFieldProps> = ({
202202
} else if (hasValue(value)) {
203203
handleCancelFilter();
204204
}
205-
},[JSON.stringify(state.activeFilters)]);
205+
},[JSON.stringify(activeFilters)]);
206206

207207
return (
208208
<Stack
Lines changed: 55 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import CloseIcon from '@mui/icons-material/Close';
22
import { Box, Button, Chip, IconButton, Paper, PaperProps, Stack } from '@mui/material';
3-
import React, { useEffect, useState } from 'react';
4-
import { FilterContext, FilterState } from './FilterContext';
3+
import React from 'react';
4+
import { FilterState, useFilters } from './FilterContext';
55
import { hasValue } from './FilterField';
66

77
interface FilterPanelProps extends Omit<PaperProps, 'onChange'> {
@@ -26,7 +26,7 @@ export const Filters: React.FC<FilterPanelProps> = ({
2626
children,
2727
...rest
2828
}) => {
29-
const [activeFilters, setActiveFilters] = useState<any>([]);
29+
const { activeFilters, dispatch } = useFilters();
3030

3131
/**
3232
* Count the number of active filters in this group by using
@@ -44,74 +44,64 @@ export const Filters: React.FC<FilterPanelProps> = ({
4444
}
4545
})
4646

47-
const handleChange = (filters: FilterState['activeFilters']) => {
48-
setActiveFilters(filters);
49-
}
50-
5147
const handleReset = () => {
52-
setActiveFilters([]);
48+
dispatch({ type: 'SET_ACTIVE_FILTERS', payload: []})
5349
}
5450

55-
useEffect(() => {
56-
if (onChange) onChange(activeFilters);
57-
}, [activeFilters])
58-
5951
return (
60-
<FilterContext activeFilters={activeFilters} onChange={handleChange}>
61-
<Paper
62-
elevation={0}
63-
variant="outlined"
64-
{...rest}
65-
>
66-
<Stack spacing={0}>
67-
{header && (
68-
<Stack
69-
direction="row"
70-
spacing={0}
71-
alignItems="center"
52+
<Paper
53+
elevation={0}
54+
variant="outlined"
55+
{...rest}
56+
>
57+
<Stack spacing={0}>
58+
{header && (
59+
<Stack
60+
direction="row"
61+
spacing={0}
62+
alignItems="center"
63+
sx={{
64+
borderBottom: '1px solid',
65+
borderBottomColor: 'grey.300',
66+
paddingLeft: 2,
67+
paddingRight: 2,
68+
paddingTop: 1,
69+
paddingBottom: 1,
70+
}}
71+
>
72+
<Stack direction="row" spacing={2} flex={1}>
73+
<Box>{header}</Box>
74+
{activeChildren > 0 && (
75+
<Chip
76+
label={`${activeChildren} active`}
77+
color="primary"
78+
size="small"
79+
/>
80+
)}
81+
</Stack>
82+
<Button
83+
variant="outlined"
84+
onClick={handleReset}
7285
sx={{
73-
borderBottom: '1px solid',
74-
borderBottomColor: 'grey.300',
75-
paddingLeft: 2,
76-
paddingRight: 2,
77-
paddingTop: 1,
78-
paddingBottom: 1,
86+
marginRight: 1,
7987
}}
8088
>
81-
<Stack direction="row" spacing={2} flex={1}>
82-
<Box>{header}</Box>
83-
{activeChildren > 0 && (
84-
<Chip
85-
label={`${activeChildren} active`}
86-
color="primary"
87-
size="small"
88-
/>
89-
)}
90-
</Stack>
91-
<Button
92-
variant="outlined"
93-
onClick={handleReset}
94-
sx={{
95-
marginRight: 1,
96-
}}
97-
>
98-
Reset
99-
</Button>
100-
<IconButton onClick={onClose}><CloseIcon /></IconButton>
101-
</Stack>
102-
)}
103-
{grouped && (
104-
<Stack spacing={0}>
105-
{children}
106-
</Stack>
107-
)}
108-
{!grouped && (
109-
<Stack spacing={2} sx={{ padding: 2 }}>
110-
{children}
111-
</Stack>
112-
)}
113-
</Stack>
114-
</Paper>
115-
</FilterContext>
89+
Reset
90+
</Button>
91+
<IconButton onClick={onClose}><CloseIcon /></IconButton>
92+
</Stack>
93+
)}
94+
{grouped && (
95+
<Stack spacing={0}>
96+
{children}
97+
</Stack>
98+
)}
99+
{!grouped && (
100+
<Stack spacing={2} sx={{ padding: 2 }}>
101+
{children}
102+
</Stack>
103+
)}
104+
</Stack>
105+
</Paper>
116106
)
117107
}

strudel-taskflows/src/pages/explore-data/[id].tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@ import { Box, Container, Paper, Stack, Typography } from '@mui/material';
22
import React from 'react';
33
import { useParams } from 'react-router-dom';
44
import { PageHeader } from '../../components/PageHeader';
5-
import { useExploreData } from './_context/ContextProvider';
5+
import { taskflow } from './_config/taskflow.config';
66

77
/**
88
* Work in Progress:
99
*
1010
* Detail view for a selected row from the` <DataExplorer>` in the explore-data Task Flow.
1111
*/
1212
const DataDetailPage: React.FC = () => {
13-
const { state } = useExploreData();
1413
const params = useParams();
15-
const entity = state.data?.find((d) => {
14+
const dataIdField = taskflow.data.items.idField;
15+
const columns = taskflow.pages.index.tableColumns;
16+
const data: any[] = [];
17+
const entity = data?.find((d) => {
1618
if (params.id) {
17-
return d[state.dataIdField].toString() === params.id.toString();
19+
return d[dataIdField].toString() === params.id.toString();
1820
}
1921
});
20-
console.log(state);
21-
console.log(entity);
22-
const entityTitle = entity ? entity[state.columns[0].field] : 'Not Found';
22+
const entityTitle = entity ? entity[columns[0].field] : 'Not Found';
2323

2424
/**
2525
* Content to render on the page for this component
@@ -43,10 +43,10 @@ const DataDetailPage: React.FC = () => {
4343
>
4444
<Stack>
4545
<Typography fontWeight="bold">
46-
{state.columns[1].field}
46+
{columns[1].field}
4747
</Typography>
4848
<Typography>
49-
{entity && entity[state.columns[1].field]}
49+
{entity && entity[columns[1].field]}
5050
</Typography>
5151
</Stack>
5252
</Paper>

strudel-taskflows/src/pages/explore-data/_components/DataView.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@ import { SciDataGrid } from '../../../components/SciDataGrid';
66
import { filterData } from '../../../utils/filters.utils';
77
import { createFilterParams } from '../../../utils/queryParams.utils';
88
import { taskflow } from '../_config/taskflow.config';
9-
import { useExploreData } from '../_context/ContextProvider';
10-
import { setPreviewItem } from '../_context/actions';
9+
import { useFilters } from '../../../components/FilterContext';
1110

11+
interface DataViewProps {
12+
searchTerm: string;
13+
setPreviewItem: React.Dispatch<React.SetStateAction<any>>;
14+
}
1215
/**
1316
* Query the data rows and render as an interactive table
1417
*/
15-
export const DataView: React.FC = () => {
16-
const { state, dispatch } = useExploreData();
18+
export const DataView: React.FC<DataViewProps> = ({ searchTerm, setPreviewItem }) => {
19+
const { activeFilters } = useFilters();
1720
const [page, setPage] = useState(0);
1821
const [pageSize, setPageSize] = useState(25);
1922
const [offset, setOffest] = useState(page * pageSize);
2023
const dataSource = taskflow.data.items.source;
24+
const dataIdField = taskflow.data.items.idField;
25+
const columns = taskflow.pages.index.tableColumns;
2126
const filterConfigs = taskflow.pages.index.tableFilters;
2227
const queryMode = taskflow.data.items.queryMode;
2328
const staticParams = taskflow.data.items.staticParams;
@@ -26,7 +31,7 @@ export const DataView: React.FC = () => {
2631
queryParams = {
2732
limit: pageSize.toString(),
2833
offset: offset.toString(),
29-
...createFilterParams(state.activeFilters, state.filters)
34+
...createFilterParams(activeFilters, filterConfigs)
3035
}
3136
}
3237
const queryString = new URLSearchParams(queryParams).toString()
@@ -42,7 +47,7 @@ export const DataView: React.FC = () => {
4247
});
4348

4449
const handleRowClick = (rowData: any) => {
45-
dispatch(setPreviewItem(rowData.row));
50+
setPreviewItem(rowData.row);
4651
};
4752

4853
const handlePaginationModelChange = (model: GridPaginationModel) => {
@@ -88,13 +93,13 @@ export const DataView: React.FC = () => {
8893
<LinearProgress variant="indeterminate" />
8994
)}
9095
<SciDataGrid
91-
rows={queryMode === 'server' ? data.results : filterData(data, state.activeFilters, filterConfigs, state.searchTerm)}
96+
rows={queryMode === 'server' ? data.results : filterData(data, activeFilters, filterConfigs, searchTerm)}
9297
rowCount={queryMode === 'server' ? data.count : undefined}
9398
pagination
9499
paginationMode={queryMode}
95100
onPaginationModelChange={handlePaginationModelChange}
96-
getRowId={(row) => row[state.dataIdField]}
97-
columns={state.columns}
101+
getRowId={(row) => row[dataIdField]}
102+
columns={columns}
98103
disableColumnSelector
99104
autoHeight
100105
initialState={{

strudel-taskflows/src/pages/explore-data/_components/DataViewHeader.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import FilterListIcon from '@mui/icons-material/FilterList';
22
import { Button, Stack, TextField, Typography } from '@mui/material';
33
import React from 'react';
4-
import { useExploreData } from '../_context/ContextProvider';
5-
import { setSearch } from '../_context/actions';
64

75
interface DataViewHeaderProps {
6+
searchTerm: string;
7+
setSearchTerm: React.Dispatch<React.SetStateAction<string>>;
88
onToggleFiltersPanel: () => void;
99
}
1010

1111
/**
1212
* Data table header section with filters button and search bar
1313
*/
1414
export const DataViewHeader: React.FC<DataViewHeaderProps> = ({
15+
searchTerm,
16+
setSearchTerm,
1517
onToggleFiltersPanel,
1618
}) => {
17-
const { dispatch } = useExploreData();
18-
1919
const handleSearch: React.ChangeEventHandler<HTMLInputElement> = (evt) => {
20-
dispatch(setSearch(evt.target.value));
20+
setSearchTerm(evt.target.value);
2121
};
2222

2323
return (
@@ -40,6 +40,7 @@ export const DataViewHeader: React.FC<DataViewHeaderProps> = ({
4040
variant="outlined"
4141
label="Search"
4242
size="small"
43+
value={searchTerm}
4344
onChange={handleSearch}
4445
/>
4546
</Stack>

0 commit comments

Comments
 (0)