feat(lab): Draft view pretty ok now
This commit is contained in:
parent
73163f5676
commit
929822b249
15 changed files with 327 additions and 29 deletions
|
@ -0,0 +1,15 @@
|
|||
import Robot from 'shared/components/robot/index.js'
|
||||
import Events from './events.js'
|
||||
|
||||
const Error = props => (
|
||||
<div className="mt-12">
|
||||
<div className="flex flex-row items-center justify-around">
|
||||
<h1>{props.app.t('errors.something')}</h1>
|
||||
<div className="max-w-96"><Robot pose='fail' embed/></div>
|
||||
</div>
|
||||
<Events events={props.patternInstance.events} />
|
||||
</div>
|
||||
)
|
||||
|
||||
export default Error
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import Markdown from 'react-markdown'
|
||||
import { linkClasses } from 'shared/components/navigation/primary.js'
|
||||
|
||||
const eventBlock = events => events.join(" \n")
|
||||
|
||||
const EventGroup = ({ type='info', events=[] }) => events.length > 0 ? (
|
||||
<div className="">
|
||||
<h3 className="capitalize" id={`events-${type}`}>{type}</h3>
|
||||
<div className="mdx">
|
||||
<Markdown>{eventBlock(events)}</Markdown>
|
||||
</div>
|
||||
</div>
|
||||
) : null
|
||||
|
||||
const order = [
|
||||
'error',
|
||||
'warning',
|
||||
'info',
|
||||
'debug'
|
||||
]
|
||||
|
||||
const Events = props => (
|
||||
<div className="flex flex-col">
|
||||
<ul className="flex flex-row row-wrap">
|
||||
{order.map(type => (
|
||||
<li key={type} className="">
|
||||
<a href={`#events-${type}`} className={`text-secondary font-bold capitalize text-xl`}>{type}</a>
|
||||
{type === 'debug' ? '' : <span className="px-2 font-bold">|</span>}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
{order.map(type => <EventGroup type={type} events={props.events[type]} />)}
|
||||
</div>
|
||||
)
|
||||
|
||||
export default Events
|
|
@ -3,35 +3,86 @@ import Svg from './svg'
|
|||
import Defs from './defs'
|
||||
import Part from './part'
|
||||
import theme from 'pkgs/plugin-theme/src/index.js'
|
||||
import Robot from 'shared/components/robot/index.js'
|
||||
import Error from './error.js'
|
||||
import Events from './events.js'
|
||||
import Json from 'shared/components/json.js'
|
||||
import Yaml from 'shared/components/yaml.js'
|
||||
import { capitalize } from 'shared/utils.js'
|
||||
|
||||
const LabDraft = ({ app, pattern, gist, updateGist }) => {
|
||||
const tabClasses = active => `
|
||||
tab tab-bordered font-bold text-4xl pb-12 capitalize
|
||||
${active && 'text-base-content tab-active'}
|
||||
`
|
||||
|
||||
const Wrap = props => <div className="max-w-screen-xl m-auto">{props.children}</div>
|
||||
|
||||
const LabDraft = props => {
|
||||
const { app, pattern, gist, updateGist } = props
|
||||
|
||||
const [tab, setTab] = useState(props.pattern.config.name)
|
||||
|
||||
const patternInstance = new pattern(gist)
|
||||
if (gist?.renderer === 'svg') return <div
|
||||
dangerouslySetInnerHTML={{ __html: patternInstance.use(theme).draft().render()}} />
|
||||
const eprops = { ...props, patternInstance }
|
||||
if (gist?.renderer === 'svg') patternInstance.use(theme)
|
||||
// Catch errors
|
||||
try { patternInstance.draft() }
|
||||
catch(error) {
|
||||
console.log('Failed to draft pattern', error)
|
||||
return <Error error={error} {...eprops} at={'draft'} />
|
||||
}
|
||||
|
||||
const patternProps = patternInstance.draft().getRenderProps()
|
||||
console.log(patternProps)
|
||||
// Render as SVG
|
||||
let svg
|
||||
try { svg = patternInstance.render() }
|
||||
catch(error) {
|
||||
console.log('Failed to render pattern', error)
|
||||
return <Error error={error} {...eprops} />
|
||||
}
|
||||
|
||||
if (gist?.renderer === 'svg')
|
||||
return <div dangerouslySetInnerHTML={{ __html: svg }} />
|
||||
|
||||
// Render as React
|
||||
let patternProps = {}
|
||||
try { patternProps = patternInstance.draft().getRenderProps() }
|
||||
catch(error) {
|
||||
console.log('Failed to get render props for pattern', error)
|
||||
return <Error error={error} {...eprops} />
|
||||
}
|
||||
|
||||
return (
|
||||
<Svg {...patternProps}>
|
||||
<Defs {...patternProps} />
|
||||
<style>{`:root { --pattern-scale: ${gist.scale || 1}}`}</style>
|
||||
<g>
|
||||
{Object.keys(patternProps.parts).map((name) => (
|
||||
<Part
|
||||
key={name}
|
||||
part={patternProps.parts[name]}
|
||||
locale={gist.locale}
|
||||
paperless={gist.paperless}
|
||||
units={gist.units}
|
||||
name={name}
|
||||
app={app}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
</Svg>
|
||||
<div>
|
||||
<div className="tabs my-8 mx-auto justify-center">
|
||||
{[props.pattern.config.name, 'events', 'yaml', 'json'].map(name => <button
|
||||
key={name}
|
||||
onClick={() => setTab(name)}
|
||||
className={tabClasses(tab === name)}
|
||||
>{name}</button>)}
|
||||
</div>
|
||||
{tab === 'events' && <Wrap><Events events={patternInstance.events} /></Wrap>}
|
||||
{tab === 'json' && <Wrap><Json>{JSON.stringify(props.gist, null, 2)}</Json></Wrap>}
|
||||
{tab === 'yaml' && <Wrap><Yaml json={JSON.stringify(props.gist, null, 2)} /></Wrap>}
|
||||
{tab === props.pattern.config.name && (
|
||||
<Svg {...patternProps}>
|
||||
<Defs {...patternProps} />
|
||||
<style>{`:root { --pattern-scale: ${gist.scale || 1}}`}</style>
|
||||
<g>
|
||||
{Object.keys(patternProps.parts).map((name) => (
|
||||
<Part
|
||||
key={name}
|
||||
part={patternProps.parts[name]}
|
||||
locale={gist.locale}
|
||||
paperless={gist.paperless}
|
||||
units={gist.units}
|
||||
name={name}
|
||||
app={app}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
</Svg>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import ClearIcon from 'shared/components/icons/clear.js'
|
||||
import orderBy from 'lodash.orderby'
|
||||
|
||||
const CoreSettingOnly = props => {
|
||||
const list = props.pattern.config.draftOrder
|
||||
const partNames = list.map(part => ({ id: part, name: props.app.t(`parts.${part}`, props.app.locale) }))
|
||||
|
||||
const togglePart = part => {
|
||||
const parts = props.gist.only || []
|
||||
const newParts = new Set(parts)
|
||||
if (newParts.has(part)) newParts.delete(part)
|
||||
else newParts.add(part)
|
||||
if (newParts.size < 1) reset()
|
||||
else props.updateGist(['only'], [...newParts])
|
||||
}
|
||||
|
||||
const reset = () => {
|
||||
props.unsetGist(['only'])
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="py-4 mx-6 border-l-2 pl-2">
|
||||
<p className="m-0 p-0 px-2 mb-2 text-neutral-content opacity-60 italic">
|
||||
{props.app.t(`settings.only.description`)}
|
||||
</p>
|
||||
<div className="flex flex-row">
|
||||
<div className="grow">
|
||||
{orderBy(partNames, ['name'], ['asc']).map(part => (
|
||||
<button
|
||||
key={part.id}
|
||||
onClick={() => togglePart(part.id)}
|
||||
className={`
|
||||
mr-1 mb-1 text-left text-lg w-full hover:text-secondary-focus px-2
|
||||
${props.gist?.only && props.gist.only.indexOf(part.id) !== -1 && 'font-bold text-secondary'}
|
||||
`}
|
||||
>
|
||||
<span className={`
|
||||
text-3xl mr-2 inline-block p-0 leading-3
|
||||
translate-y-3
|
||||
`}>
|
||||
<>°</>
|
||||
</span>
|
||||
{part.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row-reverse">
|
||||
<button
|
||||
title={props.app.t('app.reset')}
|
||||
className="btn btn-ghost btn-xs text-accent"
|
||||
disabled={!props.gist.only || props.gist.only.length < 1}
|
||||
onClick={reset}
|
||||
>
|
||||
<ClearIcon />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default CoreSettingOnly
|
||||
|
||||
|
|
@ -17,6 +17,7 @@ const settings = {
|
|||
complete: {
|
||||
dflt: false,
|
||||
},
|
||||
only: { },
|
||||
locale: {
|
||||
list: ['de', 'en', 'es', 'fr', 'nl'],
|
||||
},
|
||||
|
@ -35,6 +36,9 @@ const settings = {
|
|||
svg: '@freesewing/core (SVG)'
|
||||
}
|
||||
},
|
||||
debug: {
|
||||
dflt: false,
|
||||
},
|
||||
}
|
||||
|
||||
const CoreSettings = props => {
|
||||
|
|
|
@ -2,6 +2,7 @@ import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
|
|||
import PctDegOption from 'shared/components/workbench/inputs/design-option-pct-deg'
|
||||
import CountOption from 'shared/components/workbench/inputs/design-option-count'
|
||||
import ListSetting from './core-setting-list'
|
||||
import OnlySetting from './core-setting-only'
|
||||
import MmSetting from './core-setting-mm'
|
||||
import BoolSetting from './core-setting-bool.js'
|
||||
import SaBoolSetting from './core-setting-sa-bool.js'
|
||||
|
@ -23,6 +24,13 @@ const settings = {
|
|||
</span>
|
||||
)
|
||||
},
|
||||
debug: props => {
|
||||
return (
|
||||
<span className="text-secondary">
|
||||
{props.app.t(`app.${props.gist.debug ? 'yes' : 'no'}`)}
|
||||
</span>
|
||||
)
|
||||
},
|
||||
locale: props => {
|
||||
return (
|
||||
<span className="text-secondary">
|
||||
|
@ -56,6 +64,9 @@ const settings = {
|
|||
{props.config.titles[props.gist.renderer]}
|
||||
</span>
|
||||
),
|
||||
only: props => (props.gist?.only && props.gist.only.lenght > 0)
|
||||
? <span>{props.gist.only.length}</span>
|
||||
: <span>fixme</span>
|
||||
}
|
||||
|
||||
const inputs = {
|
||||
|
@ -82,13 +93,14 @@ const inputs = {
|
|||
title: props.config.titles[key]
|
||||
}))}
|
||||
/>,
|
||||
only: props => <OnlySetting {...props} />
|
||||
}
|
||||
|
||||
const Setting = props => {
|
||||
|
||||
if (props.setting === 'saBool')
|
||||
return <SaBoolSetting {...props} {...props.config} />
|
||||
if (['paperless', 'complete'].indexOf(props.setting) !== -1)
|
||||
if (['paperless', 'complete', 'debug'].indexOf(props.setting) !== -1)
|
||||
return <BoolSetting {...props} {...props.config} />
|
||||
|
||||
const Input = inputs[props.setting]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue