Skip to content

Instantly share code, notes, and snippets.

@casdidier
Created February 24, 2021 13:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save casdidier/5b83b8e26a82dd63c9d2ff9b196f07ed to your computer and use it in GitHub Desktop.
Save casdidier/5b83b8e26a82dd63c9d2ff9b196f07ed to your computer and use it in GitHub Desktop.
import React, { useState, useContext } from 'react';
import PropTypes from 'prop-types';
import {
Grid,
List,
ListItem,
ListItemIcon,
ListItemText,
Collapse,
Typography,
Checkbox,
} from '@material-ui/core';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import gql from 'graphql-tag';
import { useQuery } from '@apollo/client';
import { makeStyles } from '@material-ui/core/styles';
import TreeView from '@material-ui/lab/TreeView';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import ArrowRightIcon from '@material-ui/icons/ArrowRight';
import withTreeForm from './withTreeForm';
import StyledTreeItem from './StyledTreeItem';
import ParentStyledTreeItem from './ParentStyledTreeItem';
import ParentContainer from './ParentContainer';
import ParentFilterContext from './ParentFilterContext';
function Filters(props) {
const { categoryChange, parentCategoryChange } = props;
const classes = useStyles();
const context = useContext(ParentFilterContext);
const GET_COLLECTIONS = gql`
{ collections
{ id,
label,
multipleSelection,
position
entries {
id,
label
subEntries {
id,
label
}
}
}
}
`;
function IsTree(collection) {
let isTree = false;
if (collection.entries) {
collection.entries.map((entry) => {
if (entry.subEntries) {
entry.subEntries.map((subentry) => {
isTree = true;
return isTree;
});
}
});
}
return isTree;
}
const [dataCollections, setDataCollections] = useState({});
// console.log('dataCollections', dataCollections);
const {
loading: loadingCollections,
error: errorCollections,
} = useQuery(GET_COLLECTIONS, {
fetchPolicy: 'network-only',
onCompleted: (data) => {
setDataCollections(data);
},
});
if (loadingCollections) return 'Loading...';
if (errorCollections) return `Error! ${errorCollections.message}`;
// const TreeParentContainer = withTreeForm(ParentContainer);
return (
<Grid item xs={2}>
{dataCollections.collections && dataCollections.collections.map((collection) => {
// const [display, setDisplay] = useState(false);
return (
<div>
<Typography
className={classes.collectionLabel}
// onClick={setDisplay(!display)}
>
{collection.label}
</Typography>
{ // display &&
IsTree(collection) && (
collection.entries && collection.entries.map((entry, index) => {
return (
<TreeView
className={classes.root}
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
defaultEndIcon={<div style={{ width: 24 }} />}
>
<ParentContainer
entry={entry}
subEntries={entry.subEntries}
categoryChange={categoryChange}
parentCategoryChange={parentCategoryChange}
/>
</TreeView>
);
})
)
}
{!IsTree(collection) && (
<List>
{collection.entries && collection.entries.map((entry) => {
return (
<ListItem
key={entry.id}
role={undefined}
dense
>
<ListItemText primary={entry.label} />
<Checkbox
edge="start"
tabIndex={-1}
disableRipple
onChange={categoryChange}
name="{categoryChange.id}"
value={entry.id}
onClick={(e) => (e.stopPropagation())}
/>
</ListItem>
);
})}
</List>
)}
</div>
);
})}
</Grid>
);
}
Filters.propTypes = {
categoryChange: PropTypes.func.isRequired,
parentCategoryChange: PropTypes.func.isRequired,
};
export default Filters;
import React, { useState, useEffect } from 'react';
import {
Grid,
List,
ListItem,
ListItemIcon,
ListItemText,
Collapse,
Typography,
Checkbox,
} from '@material-ui/core';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import ArrowRightIcon from '@material-ui/icons/ArrowRight';
import TreeView from '@material-ui/lab/TreeView';
import { makeStyles } from '@material-ui/core/styles';
import ParentFilterContext from './ParentFilterContext';
import StyledTreeItem from './StyledTreeItem';
const useStyles = makeStyles({
root: {
height: 264,
flexGrow: 1,
maxWidth: 400,
},
collectionLabel: {
textAlign: 'center',
color: '#bf083e',
},
});
function ParentContainer(props) {
const classes = useStyles();
const {
labelText, color, bgColor, categoryChange, checked, entry, subEntries, parentCategoryChange, ...other
} = props;
const [parentCheckboxChecked, setParentCheckboxChecked] = useState(false);
const [status, setStatus] = useState('status checked OK');
const [checkboxes, setCheckboxes] = useState([]);
/* update the checkboxes children */
useEffect(() => {
const newCheckboxesState = [];
subEntries.map((subEntry) => {
newCheckboxesState.push({ id: subEntry.id, label: subEntry.label, checked: false });
});
setCheckboxes(newCheckboxesState);
}, []);
// console.log(checkboxes);
const handleCheckboxgroupChange = (updatedUsecaseCBState) => {
setCheckboxes(updatedUsecaseCBState);
};
const handleParentCheckboxChange = (isChecked) => {
const newCheckState = checkboxes.map((aCheckbox) => ({
...aCheckbox,
checked: isChecked,
}));
handleCheckboxgroupChange(newCheckState);
};
const updateParentWithChildren = (props) => {
let allChecked = false;
for (let i = 0; i < checkboxes.length; i += 1) {
if (checkboxes[i].checked) {
allChecked = true;
} else {
allChecked = false;
break;
}
}
setParentCheckboxChecked({ allChecked });
};
const handleChildCheckboxChange = (isChecked, index) => {
console.log('isChecked', isChecked, 'index', index);
// const { onCheckboxGroupChange } = this.props;
const newCheckState = checkboxes.map(
(aCheckbox, i) => (index === i ? { ...aCheckbox, checked: isChecked } : aCheckbox),
);
handleCheckboxgroupChange(newCheckState);
};
return (
// <ParentFilterContext.Provider value={
// {
// doSomething: status,
// checked: false,
// handleParentCheckboxChange,
// updateParentWithChildren,
// handleChildCheckboxChange,
// }
// }
// >
<StyledTreeItem
key={entry.id}
nodeId={entry.id}
labelText={entry.label}
categoryChange={parentCategoryChange}
>
{checkboxes && checkboxes.map((subEntry) => {
// console.log(entry);
// console.log(entry.subEntries);
return (
<StyledTreeItem
key={subEntry.id}
nodeId={subEntry.id}
labelText={subEntry.label}
categoryChange={categoryChange}
/>
);
})}
</StyledTreeItem>
// </ParentFilterContext.Provider>
);
}
export default ParentContainer;
export const MyContext = React.createContext();
import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import { Checkbox } from '@material-ui/core';
import TreeItem from '@material-ui/lab/TreeItem';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
import ParentFilterContext from './ParentFilterContext';
const useTreeItemStyles = makeStyles((theme) => ({
root: {
color: theme.palette.text.secondary,
'&:hover > $content': {
backgroundColor: theme.palette.action.hover,
},
'&:focus > $content, &$selected > $content': {
backgroundColor: `var(--tree-view-bg-color, ${theme.palette.grey[400]})`,
color: 'var(--tree-view-color)',
},
'&:focus > $content $label, &:hover > $content $label, &$selected > $content $label': {
backgroundColor: 'transparent',
},
},
content: {
color: theme.palette.text.secondary,
borderTopRightRadius: theme.spacing(2),
borderBottomRightRadius: theme.spacing(2),
paddingRight: theme.spacing(1),
fontWeight: theme.typography.fontWeightMedium,
'$expanded > &': {
fontWeight: theme.typography.fontWeightRegular,
},
},
group: {
marginLeft: 0,
'& $content': {
paddingLeft: theme.spacing(2),
},
},
expanded: {},
selected: {},
label: {
fontWeight: 'inherit',
color: 'inherit',
},
labelRoot: {
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0.5, 0),
},
labelText: {
fontWeight: 'inherit',
flexGrow: 1,
},
}));
function StyledTreeItem(props) {
const classes = useTreeItemStyles();
const {
labelText, color, bgColor, categoryChange, checked, handleChildCheckboxChange, key, nodeId, ...other
} = props;
const context = useContext(ParentFilterContext);
return (
<TreeItem
label={(
<div className={classes.labelRoot}>
<Typography variant="body2" className={classes.labelText}>
{labelText}
</Typography>
<Checkbox
edge="start"
tabIndex={-1}
disableRipple
checked={checked}
name="categories"
value={other.nodeId}
onChange={handleCheckboxChange}
onClick={(e) => (e.stopPropagation())}
// checkboxChangeCallback={(checkStatus) => handleChildCheckboxChange(checkStatus, nodeId)}
/>
</div>
)}
style={{
'--tree-view-color': color,
'--tree-view-bg-color': bgColor,
}}
classes={{
root: classes.root,
content: classes.content,
expanded: classes.expanded,
selected: classes.selected,
group: classes.group,
label: classes.label,
}}
{...other}
/>
);
}
StyledTreeItem.propTypes = {
bgColor: PropTypes.string,
color: PropTypes.string,
labelText: PropTypes.string.isRequired,
categoryChange: PropTypes.func,
checked: PropTypes.boolean,
};
export default StyledTreeItem;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment