diff --git a/.gitignore b/.gitignore index db47040fd..caa6f98fa 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,4 @@ yarn.lock package.json package-lock.json db.json +server/db backup.json diff --git a/client/src/App.css b/client/src/App.css index edce8e121..b28937f73 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -3,8 +3,10 @@ -moz-osx-font-smoothing: grayscale; } +body, +html, .App { margin: 0px auto; overflow: hidden; height: 100vh; -} \ No newline at end of file +} diff --git a/client/src/app/context/collapseAtom.js b/client/src/app/context/collapseAtom.js index 30d1e18de..57ee2a9e4 100644 --- a/client/src/app/context/collapseAtom.js +++ b/client/src/app/context/collapseAtom.js @@ -1,12 +1,24 @@ const { atom } = require('jotai'); const PATH = 'option-collapse'; +const initialValue = {}; // 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)) || {}); +export const collapseAtom = atom( + (get) => { + const storedOptions = localStorage.getItem(PATH); + if (storedOptions == null) return initialValue; + + return JSON.parse(storedOptions); + }, + (get, set, newValues) => { + set(collapseAtom, newValues); + localStorage.setItem(PATH, JSON.stringify(newValues)); + } +); // get a single option, if it exists export const SelectCollapse = (id) => { @@ -52,9 +64,6 @@ 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 }); }; diff --git a/client/src/features/editors/list/EventListWrapper.jsx b/client/src/features/editors/list/EventListWrapper.jsx index 700a717c3..c7f28f705 100644 --- a/client/src/features/editors/list/EventListWrapper.jsx +++ b/client/src/features/editors/list/EventListWrapper.jsx @@ -206,102 +206,105 @@ export default function EventListWrapper() { }, [isError]); // Events API - const eventsHandler = useCallback(async (action, payload) => { - switch (action) { - case 'add': - try { - let t = Date.now(); - await addEvent.mutateAsync(payload); - console.log('debug m add', Date.now() - t); - } catch (error) { - showErrorToast('Error creating event', error.message); - } - break; - case 'update': - try { - let t = Date.now(); - await updateEvent.mutateAsync(payload); - console.log('debug m update', Date.now() - t); - } catch (error) { - showErrorToast('Error updating event', error.message); - } - break; - case 'patch': - try { - let t = Date.now(); - await patchEvent.mutateAsync(payload); - console.log('debug m patch', Date.now() - t); - } catch (error) { - showErrorToast('Error updating event', error.message); - } - break; - case 'delete': - try { - let t = Date.now(); - await deleteEvent.mutateAsync(payload); - console.log('debug m delete', Date.now() - t); - } catch (error) { - showErrorToast('Error deleting event', error.message); - } - break; - case 'reorder': - try { - let t = Date.now(); - await reorderEvent.mutateAsync(payload); - console.log('debug m reorder', Date.now() - t); - } catch (error) { - showErrorToast('Error reordering event', error.message); - } - break; - case 'applyDelay': - let t = Date.now(); - - // if delay <= 0 delete delay and next block - if (payload.duration <= 0) { + const eventsHandler = useCallback( + async (action, payload) => { + switch (action) { + case 'add': try { - // look for block after - let afterId = false; - let blockAfter = null; - for (const d of data) { - if (d.id === payload.id) afterId = true; - if (afterId && d.type === 'block') { - blockAfter = d.id; - break; + let t = Date.now(); + await addEvent.mutateAsync(payload); + console.log('debug m add', Date.now() - t); + } catch (error) { + showErrorToast('Error creating event', error.message); + } + break; + case 'update': + try { + let t = Date.now(); + await updateEvent.mutateAsync(payload); + console.log('debug m update', Date.now() - t); + } catch (error) { + showErrorToast('Error updating event', error.message); + } + break; + case 'patch': + try { + let t = Date.now(); + await patchEvent.mutateAsync(payload); + console.log('debug m patch', Date.now() - t); + } catch (error) { + showErrorToast('Error updating event', error.message); + } + break; + case 'delete': + try { + let t = Date.now(); + await deleteEvent.mutateAsync(payload); + console.log('debug m delete', Date.now() - t); + } catch (error) { + showErrorToast('Error deleting event', error.message); + } + break; + case 'reorder': + try { + let t = Date.now(); + await reorderEvent.mutateAsync(payload); + console.log('debug m reorder', Date.now() - t); + } catch (error) { + showErrorToast('Error reordering event', error.message); + } + break; + case 'applyDelay': + let t = Date.now(); + + // if delay <= 0 delete delay and next block + if (payload.duration <= 0) { + try { + // look for block after + let afterId = false; + let blockAfter = null; + for (const d of data) { + if (d.id === payload.id) afterId = true; + if (afterId && d.type === 'block') { + blockAfter = d.id; + break; + } } + + // delete delay + await deleteEvent.mutateAsync(payload.id); + // delete block after, if any + if (blockAfter) await deleteEvent.mutateAsync(blockAfter); + } catch (error) { + showErrorToast('Error applying delay', error.message); + } + } else { + console.log('debug applydelay', payload.id); + try { + await applyDelay.mutateAsync(payload.id); + } catch (error) { + showErrorToast('Error applying delay', error.message); } - - // delete delay - await deleteEvent.mutateAsync(payload.id); - // delete block after, if any - if (blockAfter) await deleteEvent.mutateAsync(blockAfter); - } catch (error) { - showErrorToast('Error applying delay', error.message); } - } else { - console.log('debug applydelay', payload.id); - try { - await applyDelay.mutateAsync(payload.id); - } catch (error) { - showErrorToast('Error applying delay', error.message); - } - } - console.log('debug m apply', Date.now() - t); - break; + 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; + 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; - } - }, []); + default: + showErrorToast('Unrecognised request', action); + break; + } + }, + [data] + ); return ( <> diff --git a/client/src/features/editors/list/MenuActionButtons.jsx b/client/src/features/menu/MenuActionButtons.jsx similarity index 92% rename from client/src/features/editors/list/MenuActionButtons.jsx rename to client/src/features/menu/MenuActionButtons.jsx index 24eb63ce2..f506be7be 100644 --- a/client/src/features/editors/list/MenuActionButtons.jsx +++ b/client/src/features/menu/MenuActionButtons.jsx @@ -1,7 +1,6 @@ import { Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/menu'; import { IconButton } from '@chakra-ui/button'; import { FiZap, FiPlus, FiClock, FiMinusCircle } from 'react-icons/fi'; -import { useEffect } from 'react'; export default function MenuActionButtons(props) { const { actionHandler } = props; @@ -10,10 +9,6 @@ export default function MenuActionButtons(props) { backgroundColor: 'rgba(255,255,255,1)', }; - useEffect(() =>{ - console.log('debug action button render') - }) - return (