add reset_all and undo buttons to error boundary. no styling
This commit is contained in:
parent
00953e9189
commit
9bcfa4f39b
10 changed files with 93 additions and 28 deletions
|
@ -1,9 +1,5 @@
|
|||
---
|
||||
title: Dart position
|
||||
title: "Dart position"
|
||||
---
|
||||
|
||||
Controls whether to split at the shoulder or armhole
|
||||
|
||||
|
||||
## Effect of this option on the pattern
|
||||

|
||||
The **Dart position** option controls whether to create the princess seam at the shoulder or armhole.
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
import ResetButtons from './reset-buttons'
|
||||
|
||||
class ErrorBoundary extends React.Component {
|
||||
constructor(props) {
|
||||
|
@ -25,7 +26,11 @@ class ErrorBoundary extends React.Component {
|
|||
render() {
|
||||
if (this.state.hasError) {
|
||||
// You can render any custom fallback UI
|
||||
return this.props.errorView || (<h1>Something went wrong.</h1>);
|
||||
return (<div>
|
||||
{this.props.errorView || (<h1>Something went wrong.</h1>)}
|
||||
<ResetButtons undoGist={this.props.undoGist} resetGist={this.props.resetGist} />
|
||||
</div>)
|
||||
return ;
|
||||
}
|
||||
|
||||
try {
|
10
sites/shared/components/error/reset-buttons.js
Normal file
10
sites/shared/components/error/reset-buttons.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
export default function ({resetGist, undoGist}) {
|
||||
const {t} = useTranslation(['app'])
|
||||
|
||||
return (<>
|
||||
<button className="btn btn-primary" onClick={undoGist}>{t('undo')}</button>
|
||||
<button className="btn btn-primary" onClick={resetGist}>{t('reset_all')}</button>
|
||||
</>
|
||||
)}
|
|
@ -18,14 +18,14 @@ const Draft = props => {
|
|||
...patternProps.autoLayout,
|
||||
width: patternProps.width,
|
||||
height: patternProps.height
|
||||
})
|
||||
}, false, false)
|
||||
}
|
||||
}, [layout])
|
||||
|
||||
if (!patternProps || !layout) return null
|
||||
|
||||
// Helper method to update part layout and re-calculate width * height
|
||||
const updateLayout = (name, config) => {
|
||||
const updateLayout = (name, config, history=true) => {
|
||||
// Start creating new layout
|
||||
const newLayout = {...layout}
|
||||
newLayout.parts[name] = config
|
||||
|
@ -49,7 +49,7 @@ const Draft = props => {
|
|||
newLayout.height = bottomRight.y - topLeft.y
|
||||
newLayout.bottomRight = bottomRight
|
||||
newLayout.topLeft = topLeft
|
||||
updateGist(['layout'], newLayout)
|
||||
updateGist(['layout'], newLayout, false, history)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ const Part = props => {
|
|||
|
||||
// update the layout on mount
|
||||
useEffect(() => {
|
||||
if (partRef.current) updateLayout()
|
||||
if (partRef.current) updateLayout(false)
|
||||
}, [partRef])
|
||||
|
||||
// Initialize drag handler
|
||||
|
@ -168,7 +168,7 @@ const Part = props => {
|
|||
updateLayout()
|
||||
setRotate(!rotate)
|
||||
}
|
||||
const updateLayout = () => {
|
||||
const updateLayout = (history=true) => {
|
||||
const partRect = partRef.current.getBoundingClientRect();
|
||||
const matrix = partRef.current.ownerSVGElement.getScreenCTM().inverse();
|
||||
|
||||
|
@ -188,7 +188,7 @@ const Part = props => {
|
|||
flipY,
|
||||
tl,
|
||||
br
|
||||
})
|
||||
}, history)
|
||||
}
|
||||
|
||||
// Method to flip (mirror) the part along the X or Y axis
|
||||
|
|
|
@ -4,7 +4,6 @@ import DesignOptions from './design-options'
|
|||
import CoreSettings from './core-settings'
|
||||
import Xray from './xray'
|
||||
import TestDesignOptions from './test-design-options'
|
||||
import ErrorBoundary from 'shared/components/error-boundary'
|
||||
|
||||
export const Ul = props => <ul className="pl-5 list-inside">{props.children}</ul>
|
||||
export const Li = props => (
|
||||
|
@ -87,7 +86,6 @@ const WorkbenchMenu = props => {
|
|||
return (
|
||||
<nav className="grow mb-12">
|
||||
<ViewMenu {...props} />
|
||||
<ErrorBoundary>
|
||||
{props.gist?._state?.view === 'draft' && (
|
||||
<>
|
||||
<DesignOptions {...props} />
|
||||
|
@ -96,7 +94,6 @@ const WorkbenchMenu = props => {
|
|||
</>
|
||||
)}
|
||||
{props.gist?._state?.view === 'test' && <TestDesignOptions {...props} />}
|
||||
</ErrorBoundary>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import DraftEvents from 'shared/components/workbench/events.js'
|
|||
import CutLayout from 'shared/components/workbench/layout/cut'
|
||||
import PrintLayout from 'shared/components/workbench/layout/print'
|
||||
|
||||
import ErrorBoundary from 'shared/components/error-boundary';
|
||||
import ErrorBoundary from 'shared/components/error/error-boundary';
|
||||
|
||||
const views = {
|
||||
measurements: Measurements,
|
||||
|
@ -57,7 +57,7 @@ const doPreload = async (preload, from, design, gist, setGist, setPreloaded) =>
|
|||
const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false }) => {
|
||||
|
||||
// State for gist
|
||||
const {gist, setGist, unsetGist, updateGist, gistReady} = useGist(design, app);
|
||||
const {gist, setGist, unsetGist, updateGist, gistReady, undoGist, resetGist} = useGist(design, app);
|
||||
const [messages, setMessages] = useState([])
|
||||
const [popup, setPopup] = useState(false)
|
||||
const [preloaded, setPreloaded] = useState(false)
|
||||
|
@ -87,8 +87,8 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
|||
}, [preload, preloaded, from, design])
|
||||
|
||||
// Helper methods to manage the gist state
|
||||
const updateWBGist = useMemo(() => (path, value, closeNav=false) => {
|
||||
updateGist(path, value)
|
||||
const updateWBGist = useMemo(() => (path, value, closeNav=false, addToHistory=true) => {
|
||||
updateGist(path, value, addToHistory)
|
||||
// Force close of menu on mobile if it is open
|
||||
if (closeNav && app.primaryMenu) app.setPrimaryMenu(false)
|
||||
}, [app])
|
||||
|
@ -142,6 +142,12 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
|||
showInfo: setPopup,
|
||||
}
|
||||
|
||||
const errorProps = {
|
||||
undoGist,
|
||||
resetGist,
|
||||
gist
|
||||
}
|
||||
|
||||
// Layout to use
|
||||
const LayoutComponent = layout
|
||||
? layout
|
||||
|
@ -153,7 +159,7 @@ const WorkbenchWrapper = ({ app, design, preload=false, from=false, layout=false
|
|||
|
||||
return <LayoutComponent {...layoutProps}>
|
||||
{messages}
|
||||
<ErrorBoundary gist={gist}>
|
||||
<ErrorBoundary {...errorProps}>
|
||||
<Component {...componentProps} />
|
||||
{popup && <Modal cancel={() => setPopup(false)}>{popup}</Modal>}
|
||||
</ErrorBoundary>
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import useLocalStorage from './useLocalStorage';
|
||||
import set from 'lodash.set'
|
||||
import unset from 'lodash.unset'
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
import defaultSettings from 'shared/components/workbench/default-settings.js'
|
||||
import {useState, useEffect} from 'react'
|
||||
|
||||
// Generates a default design gist to start from
|
||||
export const defaultGist = (design, locale='en') => {
|
||||
|
@ -19,25 +21,68 @@ export const defaultGist = (design, locale='en') => {
|
|||
// generate the gist state and its handlers
|
||||
export function useGist(design, app) {
|
||||
// get the localstorage state and setter
|
||||
const [gist, setGist, gistReady] = useLocalStorage(`${design.config.name}_gist`, defaultGist(design, app.locale));
|
||||
const [gist, _setGist, gistReady] = useLocalStorage(`${design.config.name}_gist`, defaultGist(design, app.locale));
|
||||
const [gistHistory, setGistHistory] = useState([]);
|
||||
const [gistFuture, setGistFuture] = useState([]);
|
||||
|
||||
const setGist = (newGist, addToHistory=true) => {
|
||||
let oldGist
|
||||
_setGist((gistState) => {
|
||||
// have to clone it or nested objects will be referenced instead of copied, which defeats the purpose
|
||||
oldGist = cloneDeep(gistState);
|
||||
return typeof newGist === 'function' ? newGist(cloneDeep(gistState)) : newGist
|
||||
})
|
||||
|
||||
if (addToHistory) {
|
||||
setGistHistory((history) => {
|
||||
return [...history, oldGist]
|
||||
})
|
||||
setGistFuture([])
|
||||
}
|
||||
}
|
||||
|
||||
/** update a single gist value */
|
||||
const updateGist = (path, value) => {
|
||||
const updateGist = (path, value, addToHistory=true) => {
|
||||
setGist((gistState) => {
|
||||
const newGist = {...gistState};
|
||||
set(newGist, path, value);
|
||||
return newGist;
|
||||
})
|
||||
}, addToHistory)
|
||||
}
|
||||
|
||||
/** unset a single gist value */
|
||||
const unsetGist = (path) => {
|
||||
const unsetGist = (path, addToHistory=true) => {
|
||||
setGist((gistState) => {
|
||||
const newGist = {... gistState};
|
||||
const newGist = {...gistState};
|
||||
unset(newGist, path);
|
||||
return newGist;
|
||||
}, addToHistory)
|
||||
}
|
||||
|
||||
const undoGist = () => {
|
||||
_setGist((gistState) => {
|
||||
let prevGist;
|
||||
setGistHistory((history) => {
|
||||
const newHistory = [...history]
|
||||
prevGist = newHistory.pop() || defaultGist(design, app.locale);
|
||||
return newHistory;
|
||||
})
|
||||
setGistFuture((future) => [gistState, ...future]);
|
||||
|
||||
return {...prevGist}
|
||||
})
|
||||
}
|
||||
|
||||
return {gist, setGist, unsetGist, gistReady, updateGist};
|
||||
const redoGist = () => {
|
||||
const newHistory = [...gistHistory, gist]
|
||||
const newFuture = [...gistFuture]
|
||||
const newGist = newFuture.shift()
|
||||
setGistHistory(newHistory)
|
||||
setGistFuture(newFuture)
|
||||
_setGist(newGist)
|
||||
}
|
||||
|
||||
const resetGist = () => setGist(defaultGist(design, app.locale))
|
||||
|
||||
return {gist, setGist, unsetGist, gistReady, updateGist, undoGist, redoGist, resetGist};
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
"file-saver": "^2.0.5",
|
||||
"front-matter": "^4.0.2",
|
||||
"highlight.js": "^11.4.0",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"lodash.orderby": "^4.6.0",
|
||||
"lodash.unset": "^4.5.2",
|
||||
"mdast-util-toc": "^6.1.0",
|
||||
|
|
|
@ -13805,6 +13805,11 @@ lodash.castarray@^4.4.0:
|
|||
resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
|
||||
integrity sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=
|
||||
|
||||
lodash.clonedeep@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
||||
integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
|
||||
|
||||
lodash.debounce@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue