Skip to content

Commit

Permalink
Merge pull request #119 from codytodonnell/feature/explore-context
Browse files Browse the repository at this point in the history
Refactor explore data state
  • Loading branch information
codytodonnell authored Aug 26, 2024
2 parents ba606b7 + d95b168 commit 1060655
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 369 deletions.
19 changes: 14 additions & 5 deletions strudel-taskflows/src/components/FilterContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export interface FilterState {
expandedGroup: string | number | boolean;
}

const FilterContextAPI = React.createContext<{state: FilterState; dispatch: React.Dispatch<FilterAction>} | undefined>(undefined);
const FilterContextAPI = React.createContext<{
activeFilters: FilterState['activeFilters'];
expandedGroup: FilterState['expandedGroup'];
dispatch: React.Dispatch<FilterAction>
} | undefined>(undefined);

const initialState: FilterState = {
activeFilters: [],
Expand All @@ -39,6 +43,7 @@ function filterReducer(state: FilterState, action: FilterAction): FilterState {
} else if (filter.value) {
activeFilters.push(filter);
}
console.log(activeFilters);
return {
...state,
activeFilters
Expand Down Expand Up @@ -77,7 +82,11 @@ export const FilterContext: React.FC<FilterContextProps> = ({
children
}) => {
const [state, dispatch] = useReducer(filterReducer, { ...initialState, activeFilters });
const value = { state, dispatch };
const value = {
activeFilters: state.activeFilters,
expandedGroup: state.expandedGroup,
dispatch
};

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

return (
<FilterContextAPI.Provider value={value}>
Expand Down
8 changes: 4 additions & 4 deletions strudel-taskflows/src/components/FilterField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ export const FilterField: React.FC<FilterFieldProps> = ({
filterProps,
...rest
}) => {
const { state, dispatch } = useFilters();
const { activeFilters, dispatch } = useFilters();
const [value, setValue] = useState<FilterValue<typeof filterComponent>>(null);
const currentFilter = state.activeFilters.find((filter) => filter.field === field);
const currentFilter = activeFilters.find((filter) => filter.field === field);
const isActive = hasValue(currentFilter?.value);

/**
Expand Down Expand Up @@ -133,7 +133,7 @@ export const FilterField: React.FC<FilterFieldProps> = ({
);
}
case 'DateRange': {
const currentDateRange = state.activeFilters.find((filter) => filter.field === filter.field)?.value;
const currentDateRange = activeFilters.find((filter) => filter.field === filter.field)?.value;
const hasValue = currentDateRange && Array.isArray(currentDateRange) && currentDateRange.length === 2;
const currentMin = hasValue && Array.isArray(currentDateRange) ? currentDateRange[0] : null;
const currentMax = hasValue && Array.isArray(currentDateRange) ? currentDateRange[1] : null;
Expand Down Expand Up @@ -202,7 +202,7 @@ export const FilterField: React.FC<FilterFieldProps> = ({
} else if (hasValue(value)) {
handleCancelFilter();
}
},[JSON.stringify(state.activeFilters)]);
},[JSON.stringify(activeFilters)]);

return (
<Stack
Expand Down
120 changes: 55 additions & 65 deletions strudel-taskflows/src/components/Filters.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import CloseIcon from '@mui/icons-material/Close';
import { Box, Button, Chip, IconButton, Paper, PaperProps, Stack } from '@mui/material';
import React, { useEffect, useState } from 'react';
import { FilterContext, FilterState } from './FilterContext';
import React from 'react';
import { FilterState, useFilters } from './FilterContext';
import { hasValue } from './FilterField';

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

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

const handleChange = (filters: FilterState['activeFilters']) => {
setActiveFilters(filters);
}

const handleReset = () => {
setActiveFilters([]);
dispatch({ type: 'SET_ACTIVE_FILTERS', payload: []})
}

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

return (
<FilterContext activeFilters={activeFilters} onChange={handleChange}>
<Paper
elevation={0}
variant="outlined"
{...rest}
>
<Stack spacing={0}>
{header && (
<Stack
direction="row"
spacing={0}
alignItems="center"
<Paper
elevation={0}
variant="outlined"
{...rest}
>
<Stack spacing={0}>
{header && (
<Stack
direction="row"
spacing={0}
alignItems="center"
sx={{
borderBottom: '1px solid',
borderBottomColor: 'grey.300',
paddingLeft: 2,
paddingRight: 2,
paddingTop: 1,
paddingBottom: 1,
}}
>
<Stack direction="row" spacing={2} flex={1}>
<Box>{header}</Box>
{activeChildren > 0 && (
<Chip
label={`${activeChildren} active`}
color="primary"
size="small"
/>
)}
</Stack>
<Button
variant="outlined"
onClick={handleReset}
sx={{
borderBottom: '1px solid',
borderBottomColor: 'grey.300',
paddingLeft: 2,
paddingRight: 2,
paddingTop: 1,
paddingBottom: 1,
marginRight: 1,
}}
>
<Stack direction="row" spacing={2} flex={1}>
<Box>{header}</Box>
{activeChildren > 0 && (
<Chip
label={`${activeChildren} active`}
color="primary"
size="small"
/>
)}
</Stack>
<Button
variant="outlined"
onClick={handleReset}
sx={{
marginRight: 1,
}}
>
Reset
</Button>
<IconButton onClick={onClose}><CloseIcon /></IconButton>
</Stack>
)}
{grouped && (
<Stack spacing={0}>
{children}
</Stack>
)}
{!grouped && (
<Stack spacing={2} sx={{ padding: 2 }}>
{children}
</Stack>
)}
</Stack>
</Paper>
</FilterContext>
Reset
</Button>
<IconButton onClick={onClose}><CloseIcon /></IconButton>
</Stack>
)}
{grouped && (
<Stack spacing={0}>
{children}
</Stack>
)}
{!grouped && (
<Stack spacing={2} sx={{ padding: 2 }}>
{children}
</Stack>
)}
</Stack>
</Paper>
)
}
18 changes: 9 additions & 9 deletions strudel-taskflows/src/pages/explore-data/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,24 @@ import { Box, Container, Paper, Stack, Typography } from '@mui/material';
import React from 'react';
import { useParams } from 'react-router-dom';
import { PageHeader } from '../../components/PageHeader';
import { useExploreData } from './_context/ContextProvider';
import { taskflow } from './_config/taskflow.config';

/**
* Work in Progress:
*
* Detail view for a selected row from the` <DataExplorer>` in the explore-data Task Flow.
*/
const DataDetailPage: React.FC = () => {
const { state } = useExploreData();
const params = useParams();
const entity = state.data?.find((d) => {
const dataIdField = taskflow.data.items.idField;
const columns = taskflow.pages.index.tableColumns;
const data: any[] = [];
const entity = data?.find((d) => {
if (params.id) {
return d[state.dataIdField].toString() === params.id.toString();
return d[dataIdField].toString() === params.id.toString();
}
});
console.log(state);
console.log(entity);
const entityTitle = entity ? entity[state.columns[0].field] : 'Not Found';
const entityTitle = entity ? entity[columns[0].field] : 'Not Found';

/**
* Content to render on the page for this component
Expand All @@ -43,10 +43,10 @@ const DataDetailPage: React.FC = () => {
>
<Stack>
<Typography fontWeight="bold">
{state.columns[1].field}
{columns[1].field}
</Typography>
<Typography>
{entity && entity[state.columns[1].field]}
{entity && entity[columns[1].field]}
</Typography>
</Stack>
</Paper>
Expand Down
23 changes: 14 additions & 9 deletions strudel-taskflows/src/pages/explore-data/_components/DataView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@ import { SciDataGrid } from '../../../components/SciDataGrid';
import { filterData } from '../../../utils/filters.utils';
import { createFilterParams } from '../../../utils/queryParams.utils';
import { taskflow } from '../_config/taskflow.config';
import { useExploreData } from '../_context/ContextProvider';
import { setPreviewItem } from '../_context/actions';
import { useFilters } from '../../../components/FilterContext';

interface DataViewProps {
searchTerm: string;
setPreviewItem: React.Dispatch<React.SetStateAction<any>>;
}
/**
* Query the data rows and render as an interactive table
*/
export const DataView: React.FC = () => {
const { state, dispatch } = useExploreData();
export const DataView: React.FC<DataViewProps> = ({ searchTerm, setPreviewItem }) => {
const { activeFilters } = useFilters();
const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(25);
const [offset, setOffest] = useState(page * pageSize);
const dataSource = taskflow.data.items.source;
const dataIdField = taskflow.data.items.idField;
const columns = taskflow.pages.index.tableColumns;
const filterConfigs = taskflow.pages.index.tableFilters;
const queryMode = taskflow.data.items.queryMode;
const staticParams = taskflow.data.items.staticParams;
Expand All @@ -26,7 +31,7 @@ export const DataView: React.FC = () => {
queryParams = {
limit: pageSize.toString(),
offset: offset.toString(),
...createFilterParams(state.activeFilters, state.filters)
...createFilterParams(activeFilters, filterConfigs)
}
}
const queryString = new URLSearchParams(queryParams).toString()
Expand All @@ -42,7 +47,7 @@ export const DataView: React.FC = () => {
});

const handleRowClick = (rowData: any) => {
dispatch(setPreviewItem(rowData.row));
setPreviewItem(rowData.row);
};

const handlePaginationModelChange = (model: GridPaginationModel) => {
Expand Down Expand Up @@ -88,13 +93,13 @@ export const DataView: React.FC = () => {
<LinearProgress variant="indeterminate" />
)}
<SciDataGrid
rows={queryMode === 'server' ? data.results : filterData(data, state.activeFilters, filterConfigs, state.searchTerm)}
rows={queryMode === 'server' ? data.results : filterData(data, activeFilters, filterConfigs, searchTerm)}
rowCount={queryMode === 'server' ? data.count : undefined}
pagination
paginationMode={queryMode}
onPaginationModelChange={handlePaginationModelChange}
getRowId={(row) => row[state.dataIdField]}
columns={state.columns}
getRowId={(row) => row[dataIdField]}
columns={columns}
disableColumnSelector
autoHeight
initialState={{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import FilterListIcon from '@mui/icons-material/FilterList';
import { Button, Stack, TextField, Typography } from '@mui/material';
import React from 'react';
import { useExploreData } from '../_context/ContextProvider';
import { setSearch } from '../_context/actions';

interface DataViewHeaderProps {
searchTerm: string;
setSearchTerm: React.Dispatch<React.SetStateAction<string>>;
onToggleFiltersPanel: () => void;
}

/**
* Data table header section with filters button and search bar
*/
export const DataViewHeader: React.FC<DataViewHeaderProps> = ({
searchTerm,
setSearchTerm,
onToggleFiltersPanel,
}) => {
const { dispatch } = useExploreData();

const handleSearch: React.ChangeEventHandler<HTMLInputElement> = (evt) => {
dispatch(setSearch(evt.target.value));
setSearchTerm(evt.target.value);
};

return (
Expand All @@ -40,6 +40,7 @@ export const DataViewHeader: React.FC<DataViewHeaderProps> = ({
variant="outlined"
label="Search"
size="small"
value={searchTerm}
onChange={handleSearch}
/>
</Stack>
Expand Down
Loading

0 comments on commit 1060655

Please sign in to comment.