feat: expand collapse

This commit is contained in:
cv
2021-05-20 08:34:03 +02:00
parent 34481b57c6
commit c912a61b57
6 changed files with 110 additions and 23 deletions
+60
View File
@@ -0,0 +1,60 @@
const { atom } = require('jotai');
const PATH = 'option-collapse';
// collapse options object, initialised from local storage
// REFRACT: When do we read from local storage?
// on every render?
export const collapseAtom = atom(JSON.parse(localStorage.getItem(PATH)) || {});
// get a single option, if it exists
export const SelectCollapse = (id) => {
return atom((get) => get(collapseAtom)[id]);
};
// change a single item in object
export const HandleCollapse = atom(null, (get, set, payload) => {
const updatedVal = {
...get(collapseAtom),
...payload,
};
set(collapseAtom, updatedVal);
localStorage.setItem(PATH, JSON.stringify(updatedVal));
});
// change collapsed in several items
export const BatchOperation = atom(null, (get, set, payload) => {
let prevOptions = get(collapseAtom);
let newOptions = {};
for (const item of payload.items) {
newOptions[item.id] = payload.isCollapsed;
}
if (payload.clear) {
// clear object
prevOptions = {};
// clear localstorage
localStorage.removeItem(PATH);
}
const options = { ...prevOptions, ...newOptions };
set(collapseAtom, options);
localStorage.setItem(PATH, JSON.stringify(options));
});
// change collapsed in all items
export const setAll = async (items, isCollapsed) => {
// clear storage
localStorage.removeItem(PATH);
// clear local object
console.log('debug collapse here', isCollapsed);
// call batch
BatchOperation({ items: items, isCollapsed: isCollapsed });
};
@@ -7,7 +7,7 @@ export default function CollapseBtn(props) {
<Button
size={props.size || 'xs'}
leftIcon={<FiChevronsUp />}
colorScheme='whiteAlpha'
colorScheme='white'
variant='outline'
onClick={clickhandler}
_focus={{ boxShadow: 'none' }}
@@ -7,7 +7,7 @@ export default function ExpandBtn(props) {
<Button
size={props.size || 'xs'}
leftIcon={<FiChevronsDown />}
colorScheme='whiteAlpha'
colorScheme='white'
variant='outline'
onClick={clickhandler}
_focus={{ boxShadow: 'none' }}
+30 -18
View File
@@ -1,6 +1,6 @@
import Icon from '@chakra-ui/icon';
import { FiChevronDown, FiChevronUp, FiMoreVertical } from 'react-icons/fi';
import { useState } from 'react';
import { useMemo } from 'react';
import { Draggable } from 'react-beautiful-dnd';
import EventTimes from 'common/components/eventTimes/EventTimes';
import EventTimesVertical from 'common/components/eventTimes/EventTimesVertical';
@@ -10,6 +10,8 @@ import VisibleIconBtn from 'common/components/buttons/VisibleIconBtn';
import DeleteIconBtn from 'common/components/buttons/DeleteIconBtn';
import { millisToMinutes } from 'common/dateConfig';
import style from './EventBlock.module.css';
import { SelectCollapse, HandleCollapse } from 'app/context/collapseAtom';
import { useAtom } from 'jotai';
const ExpandedBlock = (props) => {
const { provided, data, next, delay, delayValue, actionHandler } = props;
@@ -85,7 +87,7 @@ const ExpandedBlock = (props) => {
as={FiChevronUp}
marginTop='0.2em'
gridArea='more'
onClick={() => props.setExpanded(false)}
onClick={() => props.setCollapsed(true)}
/>
<div className={style.actionOverlay}>
<VisibleIconBtn actionHandler={actionHandler} active={data.isPublic} />
@@ -138,7 +140,7 @@ const CollapsedBlock = (props) => {
as={FiChevronDown}
marginTop='0.2em'
gridArea='more'
onClick={() => props.setExpanded(true)}
onClick={() => props.setCollapsed(false)}
/>
<div className={style.actionOverlay}>
<VisibleIconBtn actionHandler={actionHandler} active={data.isPublic} />
@@ -156,17 +158,27 @@ const CollapsedBlock = (props) => {
export default function EventBlock(props) {
const { data, selected, delay, index, actionHandler } = props;
const [expanded, setExpanded] = useState(true);
// const [collapsed, setCollapsed] = useState(checkLocalStorage(data.id));
// const collapsed = useSelector(itemsAtom, (state) => state === data.id);
const [collapsed] = useAtom(
useMemo(() => SelectCollapse(data.id), [data.id])
);
const [, setCollapsed] = useAtom(HandleCollapse);
// TODO: should this go inside useEffect()
// Would I then need to add this to state?
const isSelected = selected ? style.active : '';
const isExpanded = expanded ? style.expanded : style.collapsed;
const classSelect = `${style.event} ${isExpanded} ${isSelected}`;
const isCollapsed = collapsed ? style.collapsed : style.expanded;
const classSelect = `${style.event} ${isCollapsed} ${isSelected}`;
// Calculate delay in min
const delayValue = delay > 0 ? millisToMinutes(delay) : null;
const handleCollapse = (isCollapsed) => {
setCollapsed({ [data.id]: isCollapsed });
};
return (
<Draggable key={data.id} draggableId={data.id} index={index}>
{(provided) => (
@@ -175,17 +187,7 @@ export default function EventBlock(props) {
{...provided.draggableProps}
ref={provided.innerRef}
>
{expanded ? (
<ExpandedBlock
provided={provided}
data={data}
next={props.next}
delay={delay}
delayValue={delayValue}
actionHandler={actionHandler}
setExpanded={setExpanded}
/>
) : (
{collapsed ? (
<CollapsedBlock
provided={provided}
data={data}
@@ -193,7 +195,17 @@ export default function EventBlock(props) {
delay={delay}
delayValue={delayValue}
actionHandler={actionHandler}
setExpanded={setExpanded}
setCollapsed={handleCollapse}
/>
) : (
<ExpandedBlock
provided={provided}
data={data}
next={props.next}
delay={delay}
delayValue={delayValue}
actionHandler={actionHandler}
setCollapsed={handleCollapse}
/>
)}
</div>
@@ -15,8 +15,11 @@ import { showErrorToast } from 'common/helpers/toastManager';
import { useFetch } from 'app/hooks/useFetch.js';
import Empty from 'common/state/Empty';
import { EVENTS_TABLE } from 'app/api/apiConstants';
import { BatchOperation } from 'app/context/collapseAtom';
import { useAtom } from 'jotai';
export default function EventListWrapper() {
const [, setCollapsed] = useAtom(BatchOperation);
const queryClient = useQueryClient();
const { data, status, isError, refetch } = useFetch(
EVENTS_TABLE,
@@ -283,8 +286,17 @@ export default function EventListWrapper() {
}
}
console.log('debug m apply', Date.now() - t);
break;
case 'collapseall':
if (data == null) return;
setCollapsed({ clear: true, items: data, isCollapsed: true });
break;
case 'expandall':
if (data == null) return;
setCollapsed({ clear: true, items: data, isCollapsed: false });
break;
default:
showErrorToast('Unrecognised request', action);
break;
+5 -2
View File
@@ -73,8 +73,11 @@ const EventListMenu = ({ eventsHandler }) => {
</MenuList>
</Menu>
<CurrentBtn size='sm' />
<CollapseBtn size='sm' />
<ExpandBtn size='sm' />
<CollapseBtn
size='sm'
clickhandler={() => eventsHandler('collapseall')}
/>
<ExpandBtn size='sm' clickhandler={() => eventsHandler('expandall')} />
<MenuActionButtons actionHandler={actionHandler} size='sm' />
</div>
);