[react] feat: Improved error handling when pattern drafting fails (#205)
If drafting a part fails, the logs store contains an array [message, stacktrace] instead of a simple string. Handle this in the LogView. Also display an error message in the DraftView when there were errors during drafting.  after clicking the button:  (could also display the stack traces, but they're quite unhelpful and you can find them in the browser console anyway, the code for that is commented out) Closes #163 Reviewed-on: https://codeberg.org/freesewing/freesewing/pulls/205 Reviewed-by: Joost De Cock <joostdecock@noreply.codeberg.org> Co-authored-by: Jonathan Haas <haasjona@gmail.com> Co-committed-by: Jonathan Haas <haasjona@gmail.com>
This commit is contained in:
parent
40eb75ce43
commit
b4a5393290
6 changed files with 96 additions and 15 deletions
|
@ -0,0 +1,59 @@
|
|||
// Dependencies
|
||||
import React, { useState } from 'react'
|
||||
import { Popout } from '../../../Popout/index.mjs'
|
||||
import { CloseIcon, ExpandIcon } from '../../../Icon/index.mjs'
|
||||
import { Link } from '../../../Link/index.mjs'
|
||||
import { LogEntry } from './LogEntry.mjs'
|
||||
|
||||
export const DraftErrorHandler = ({ failure, errors }) => {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const [hidden, setHidden] = useState(false)
|
||||
|
||||
if (hidden || (!failure && errors.length === 0)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Popout error>
|
||||
<p>
|
||||
Sorry, there were problems drafting your pattern with the given measurements and options.
|
||||
</p>
|
||||
<p>
|
||||
Please double check your measurements according to{' '}
|
||||
<Link href="/docs/measurements/">our documentation</Link>. Also check{' '}
|
||||
<Link href="https://v4.freesewing.org/docs/about/faq/measurements-issues/">
|
||||
our common measurement issues FAQ entry
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
<p>
|
||||
If you believe your measurements are correct and/or if you'd like further assistance, you
|
||||
can ask for help <Link href="https://forum.freesewing.eu">on our forum</Link>,{' '}
|
||||
<Link href="https://discord.freesewing.org">our Discord server</Link>, or{' '}
|
||||
<Link href="https://codeberg.org/freesewing/freesewing/issues">report an issue</Link>.
|
||||
</p>
|
||||
|
||||
<div className={'tw-mt-4'}>
|
||||
<button
|
||||
className={`tw-daisy-btn tw-daisy-btn-primary`}
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
>
|
||||
<ExpandIcon />
|
||||
Show error details
|
||||
</button>
|
||||
<button className={`tw-daisy-btn tw-ml-4`} onClick={() => setHidden(true)}>
|
||||
<CloseIcon />
|
||||
Hide
|
||||
</button>
|
||||
</div>
|
||||
{expanded ? (
|
||||
<div className={'tw-mt-8'}>
|
||||
{failure ? <LogEntry key="failure" logEntry={failure} /> : null}
|
||||
{errors.map((line, i) => (
|
||||
<LogEntry key={i} logEntry={line} />
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</Popout>
|
||||
)
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
// Dependencies
|
||||
import React from 'react'
|
||||
import { draft, missingMeasurements, bundlePatternTranslations } from '../../lib/index.mjs'
|
||||
import { bundlePatternTranslations, draft, missingMeasurements } from '../../lib/index.mjs'
|
||||
// Components
|
||||
import { Null } from '@freesewing/react/components/Null'
|
||||
import { ZoomablePattern } from '../ZoomablePattern.mjs'
|
||||
import { PatternLayout } from '../PatternLayout.mjs'
|
||||
import { DraftErrorHandler } from './DraftErrorHandler.mjs'
|
||||
|
||||
/**
|
||||
* The draft view allows users to tweak their pattern
|
||||
|
@ -38,7 +39,7 @@ export const DraftView = ({ Design, state, update, config, plugins = [], PluginO
|
|||
/*
|
||||
* First, attempt to draft
|
||||
*/
|
||||
const { pattern } = draft(Design, state.settings, plugins)
|
||||
const { pattern, failure, errors } = draft(Design, state.settings, plugins)
|
||||
|
||||
/*
|
||||
* Create object holding strings for translation
|
||||
|
@ -52,6 +53,7 @@ export const DraftView = ({ Design, state, update, config, plugins = [], PluginO
|
|||
const __html = pattern.render()
|
||||
output = (
|
||||
<>
|
||||
<DraftErrorHandler {...{ failure, errors }} />
|
||||
<PluginOutput {...{ pattern, Design, state, update, config }} />
|
||||
<ZoomablePattern update={update}>
|
||||
<div className="tw-w-full tw-h-full" dangerouslySetInnerHTML={{ __html }} />
|
||||
|
@ -65,6 +67,7 @@ export const DraftView = ({ Design, state, update, config, plugins = [], PluginO
|
|||
renderProps = pattern.getRenderProps()
|
||||
output = (
|
||||
<>
|
||||
<DraftErrorHandler {...{ failure, errors }} />
|
||||
<PluginOutput {...{ pattern, Design, state, update, config, strings }} />
|
||||
<ZoomablePattern
|
||||
renderProps={renderProps}
|
||||
|
|
|
@ -9,6 +9,7 @@ import { Null } from '@freesewing/react/components/Null'
|
|||
import { ZoomablePattern } from '../ZoomablePattern.mjs'
|
||||
import { PatternLayout } from '../PatternLayout.mjs'
|
||||
import { Xray } from '@freesewing/react/components/Xray'
|
||||
import { DraftErrorHandler } from './DraftErrorHandler.mjs'
|
||||
|
||||
/**
|
||||
* The inspect view allows users to inspect their pattern
|
||||
|
@ -47,7 +48,7 @@ export const InspectView = ({ Design, state, update, config }) => {
|
|||
/*
|
||||
* First, attempt to draft
|
||||
*/
|
||||
const { pattern } = draft(Design, state.settings)
|
||||
const { pattern, failure, errors } = draft(Design, state.settings, plugins)
|
||||
|
||||
/*
|
||||
* Create object holding strings for translation
|
||||
|
@ -57,6 +58,7 @@ export const InspectView = ({ Design, state, update, config }) => {
|
|||
const renderProps = pattern.getRenderProps()
|
||||
const output = (
|
||||
<>
|
||||
<DraftErrorHandler {...{ failure, errors }} />
|
||||
<ZoomablePattern
|
||||
renderProps={renderProps}
|
||||
patternLocale={state.locale || 'en'}
|
||||
|
|
|
@ -7,6 +7,7 @@ import { draft } from '../../lib/index.mjs'
|
|||
// Components
|
||||
import { PatternLayout } from '../PatternLayout.mjs'
|
||||
import { MovablePattern } from '../MovablePattern.mjs'
|
||||
import { DraftErrorHandler } from './DraftErrorHandler.mjs'
|
||||
|
||||
export const LayoutView = (props) => {
|
||||
const { config, state, update, Design } = props
|
||||
|
@ -23,9 +24,10 @@ export const LayoutView = (props) => {
|
|||
* Now draft the pattern
|
||||
*/
|
||||
const { pattern, failure, errors } = draft(Design, settings, [tilerPlugin(pageSettings)])
|
||||
if (failure) return <p>Draft failed. FIXME: Handle this gracefully.</p>
|
||||
|
||||
const output = (
|
||||
<>
|
||||
<DraftErrorHandler {...{ failure, errors }} />
|
||||
<MovablePattern
|
||||
{...{
|
||||
update,
|
||||
|
@ -34,6 +36,7 @@ export const LayoutView = (props) => {
|
|||
state,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
return <PatternLayout {...{ update, Design, output, state, pattern, config }} />
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import React from 'react'
|
||||
import Markdown from 'react-markdown'
|
||||
|
||||
export const LogEntry = ({ logEntry }) => (
|
||||
<>
|
||||
<div className="log-entry tw-mb-2">
|
||||
<Markdown>{Array.isArray(logEntry) ? logEntry[0] : logEntry}</Markdown>
|
||||
</div>
|
||||
{/* uncomment to enable stacktrace view
|
||||
Array.isArray(logEntry) && logEntry[1].stack ? (
|
||||
<Highlight title="Stacktrace" raw={logEntry[1]?.stack} />
|
||||
) : null */}
|
||||
</>
|
||||
)
|
|
@ -3,10 +3,10 @@ import { draft } from '../../lib/index.mjs'
|
|||
// Hooks
|
||||
import React from 'react'
|
||||
// Components
|
||||
import Markdown from 'react-markdown'
|
||||
import { H1, H3 } from '@freesewing/react/components/Heading'
|
||||
import { HeaderMenu } from '../HeaderMenu.mjs'
|
||||
import { Tabs, Tab } from '@freesewing/react/components/Tab'
|
||||
import { LogEntry } from './LogEntry.mjs'
|
||||
|
||||
// The log levels
|
||||
const levels = ['error', 'warn', 'info', 'debug']
|
||||
|
@ -36,7 +36,7 @@ export const LogView = (props) => {
|
|||
<>
|
||||
<H3>{level}</H3>
|
||||
{pattern.setStores[0].logs[level].map((line, i) => (
|
||||
<Markdown key={i}>{line}</Markdown>
|
||||
<LogEntry key={i} logEntry={line} />
|
||||
))}
|
||||
</>
|
||||
) : null}
|
||||
|
@ -50,7 +50,7 @@ export const LogView = (props) => {
|
|||
<>
|
||||
<H3>{level}</H3>
|
||||
{pattern.store.logs[level].map((line, i) => (
|
||||
<Markdown key={i}>{line}</Markdown>
|
||||
<LogEntry key={i} logEntry={line} />
|
||||
))}
|
||||
</>
|
||||
) : null}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue