1
0
Fork 0

wip(lab): Moved draft to wrapper

This commit is contained in:
Joost De Cock 2022-01-30 15:14:44 +01:00
parent e62a862559
commit 153bff0536
11 changed files with 208 additions and 80 deletions

View file

@ -7,7 +7,7 @@ const Error = props => (
<h1>{props.app.t('errors.something')}</h1> <h1>{props.app.t('errors.something')}</h1>
<div className="max-w-96"><Robot pose='fail' embed/></div> <div className="max-w-96"><Robot pose='fail' embed/></div>
</div> </div>
<Events events={props.patternInstance.events} /> <Events events={props.draft.events} />
</div> </div>
) )

View file

@ -1,7 +1,5 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import SvgWrapper from './svg-wrapper' import SvgWrapper from './svg-wrapper'
import theme from 'pkgs/plugin-theme/src/index.js'
import Robot from 'shared/components/robot/index.js'
import Error from './error.js' import Error from './error.js'
import Events from './events.js' import Events from './events.js'
import Json from 'shared/components/json.js' import Json from 'shared/components/json.js'
@ -17,37 +15,28 @@ const tabClasses = active => `
const Wrap = props => <div className="max-w-screen-xl m-auto">{props.children}</div> const Wrap = props => <div className="max-w-screen-xl m-auto">{props.children}</div>
const LabDraft = props => { const LabDraft = props => {
const { app, pattern, gist, updateGist, unsetGist } = props const { app, draft, pattern, gist, updateGist, unsetGist } = props
if (!draft) return null
const [tab, setTab] = useState(props.pattern.config.name) const [tab, setTab] = useState(props.pattern.config.name)
const patternInstance = new pattern(gist) if (gist?.renderer === 'svg') {
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'} />
}
// Render as SVG // Render as SVG
let svg let svg
try { svg = patternInstance.render() } try { svg = draft.render() }
catch(error) { catch(error) {
console.log('Failed to render pattern', error) console.log('Failed to render pattern', error)
return <Error error={error} {...eprops} /> return <Error error={error} {...props} />
} }
if (gist?.renderer === 'svg')
return <div dangerouslySetInnerHTML={{ __html: svg }} /> return <div dangerouslySetInnerHTML={{ __html: svg }} />
}
// Render as React // Render as React
let patternProps = {} let patternProps = {}
try { patternProps = patternInstance.draft().getRenderProps() } try { patternProps = draft.draft().getRenderProps() }
catch(error) { catch(error) {
console.log('Failed to get render props for pattern', error) console.log('Failed to get render props for pattern', error)
return <Error error={error} {...eprops} /> return <Error error={error} {...props} />
} }
return ( return (
@ -59,11 +48,11 @@ const LabDraft = props => {
className={tabClasses(tab === name)} className={tabClasses(tab === name)}
>{name}</button>)} >{name}</button>)}
</div> </div>
{tab === 'events' && <Wrap><Events events={patternInstance.events} /></Wrap>} {tab === 'events' && <Wrap><Events events={draft.events} /></Wrap>}
{tab === 'json' && <Wrap><Json>{JSON.stringify(props.gist, null, 2)}</Json></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 === 'yaml' && <Wrap><Yaml json={JSON.stringify(props.gist, null, 2)} /></Wrap>}
{tab === props.pattern.config.name && <SvgWrapper {tab === props.pattern.config.name && <SvgWrapper
patternInstance={patternInstance} draft={draft}
patternProps={patternProps} patternProps={patternProps}
gist={gist} gist={gist}
updateGist={updateGist} updateGist={updateGist}

View file

@ -41,7 +41,7 @@ const Part = props => {
{props.gist?.xray?.reveal?.[partName] && <XrayPart {...props} />} {props.gist?.xray?.reveal?.[partName] && <XrayPart {...props} />}
{Object.keys(part.paths).map((pathName) => ( {Object.keys(part.paths).map((pathName) => (
<Path <Path
key={name} key={pathName}
pathName={pathName} pathName={pathName}
path={part.paths[pathName]} path={part.paths[pathName]}
topLeft={props.part.topLeft} topLeft={props.part.topLeft}
@ -49,11 +49,11 @@ const Part = props => {
{...props} {...props}
/> />
))} ))}
{Object.keys(props.part.points).map((name) => ( {Object.keys(props.part.points).map((pointName) => (
<Point <Point
key={name} key={pointName}
pointName={name} pointName={pointName}
point={props.part.points[name]} point={props.part.points[pointName]}
topLeft={props.part.topLeft} topLeft={props.part.topLeft}
bottomRight={props.part.bottomRight} bottomRight={props.part.bottomRight}
{...props} {...props}
@ -61,7 +61,7 @@ const Part = props => {
))} ))}
{Object.keys(props.part.snippets).map((snippetName) => ( {Object.keys(props.part.snippets).map((snippetName) => (
<Snippet <Snippet
key={name} key={snippetName}
snippetName={snippetName} snippetName={snippetName}
snippet={props.part.snippets[snippetName]} snippet={props.part.snippets[snippetName]}
{...props} {...props}

View file

@ -6,10 +6,10 @@ const XrayPath = props => (
<path <path
d={props.path.asPathstring()} d={props.path.asPathstring()}
{...getProps(props.path)} {...getProps(props.path)}
className="opacity-0 stroke-4xl stroke-contrast hover:opacity-25 hover:cursor-pointer" className="opacity-0 stroke-3xl stroke-contrast hover:opacity-25 hover:cursor-pointer"
onClick={() => props.updateGist( onClick={() => props.updateGist(
['xray', 'parts', props.partName, 'paths', props.pathName], ['xray', 'parts', props.partName, 'paths', props.pathName],
props.path 1
)} )}
/> />
</g> </g>

View file

@ -1,5 +1,6 @@
import Text from '../text' import Text from '../text'
import Circle from '../circle' import Circle from '../circle'
import { round, formatMm } from 'shared/utils.js'
const RevealPoint = props => { const RevealPoint = props => {
const r = 15 * props.gist.scale const r = 15 * props.gist.scale
@ -22,9 +23,89 @@ const RevealPoint = props => {
m ${2*r} 0 L ${bottomRight.x} ${y}`} className={classes} /> m ${2*r} 0 L ${bottomRight.x} ${y}`} className={classes} />
</g> </g>
) )
}
// Length for the indicators
const lead = 20
// Length for the text on indicators
// this is longer to prevent text from being cropped
const longLead = 40
const Coord = ({id, val, pointName}) => (
<text>
<textPath xlinkHref={`#${id}`} startOffset="50%">
<tspan className="center fill-note text-sm" dy={0}>
{round(val)}
</tspan>
</textPath>
<textPath xlinkHref={`#${id}`} startOffset="50%">
<tspan className="center fill-note text-xs" dy={5}>
{pointName}
</tspan>
</textPath>
</text>
)
const PosX = ({ id, point, scale, pointName }) => (
<g>
<path id={id+'_x'} d={`
M ${point.x - (point.x < 0 ? 0 : lead*scale)} ${point.y}
l ${lead * scale} 0
`}
className="stroke-note stroke-sm"
markerStart={point.x < 0 ? "url(#grainlineFrom)" : ''}
markerEnd={point.x < 0 ? '' : "url(#grainlineTo)"}
/>
<path id={id+'_xlong'} d={`
M ${point.x - (point.x < 0 ? longLead/2.4*scale : longLead*scale)} ${point.y}
l ${longLead * scale * 1.4} 0
`}
className="hidden"
/>
<Coord id={`${id}_xlong`} val={point.x} pointName={pointName}/>
</g>
)
const PosY = ({ id, point, scale, pointName }) => (
<g>
<path id={id+'_y'} d={`
M ${point.x} ${point.y + (point.y < 0 ? lead*scale : 0)}
l 0 ${lead * scale * -1}
`}
className="stroke-note stroke-sm"
markerStart={point.y < 0 ? '' : "url(#grainlineFrom)"}
markerEnd={point.y < 0 ? "url(#grainlineTo)" : ''}
/>
<path id={id+'_ylong'} d={`
M ${point.x} ${point.y + (point.y < 0 ? longLead/1.25*scale : longLead*scale/5)}
l 0 ${longLead * scale * -1}
`}
className="hidden"
/>
<Coord id={`${id}_ylong`} val={point.y} pointName={pointName} />
</g>
)
const ActiveXrayPoint = props => {
const id = `${props.partName}_${props.pointName}_xray_point`
const r = 15 * props.gist.scale
const { x, y } = props.point
const { topLeft, bottomRight } = props.part
const i = Object.keys(props.gist.xray.parts[props.partName].points).indexOf(props.pointName)%10
const classes = `stroke-sm stroke-color-${i} stroke-dashed`
const posProps = {
id,
point: props.point,
pointName: props.pointName,
scale: props.gist.scale,
} }
const XrayPoint = props => ( return <g><PosX {...posProps} /><PosY {...posProps} /></g>
}
const PassiveXrayPoint = props => (
<g> <g>
<circle <circle
cx={props.point.x} cx={props.point.x}
@ -36,10 +117,15 @@ const XrayPoint = props => (
cy={props.point.y} cy={props.point.y}
r={7.5 * props.gist.scale} r={7.5 * props.gist.scale}
className="opacity-0 stroke-lining fill-lining hover:opacity-25 hover:cursor-pointer" className="opacity-0 stroke-lining fill-lining hover:opacity-25 hover:cursor-pointer"
onClick={() => props.updateGist( onClick={props.gist?.xray?.parts?.[props.partName]?.points?.[props.pointName]
? () => props.unsetGist(
['xray', 'parts', props.partName, 'points', props.pointName]
)
: () => props.updateGist(
['xray', 'parts', props.partName, 'points', props.pointName], ['xray', 'parts', props.partName, 'points', props.pointName],
props.point 1
)} )
}
/> />
</g> </g>
) )
@ -48,11 +134,18 @@ const XrayPoint = props => (
const Point = props => { const Point = props => {
const { point, pointName, partName, gist } = props const { point, pointName, partName, gist } = props
const output = [] const output = []
if (gist.xray) output.push(<XrayPoint {...props} key={'xp-' + pointName} />) // Passive indication for points
if (gist.xray) output.push(<PassiveXrayPoint {...props} key={'xp-' + pointName} />)
// Active indication for points (point that have been clicked on)
if (gist.xray?.parts?.[partName]?.points?.[pointName])
output.push(<ActiveXrayPoint {...props} key={'rp-' + pointName} />)
// Reveal (based on clicking the seach icon in sidebar
if (gist.xray?.reveal?.[partName]?.points?.[pointName]) if (gist.xray?.reveal?.[partName]?.points?.[pointName])
output.push(<RevealPoint {...props} key={'rp-' + pointName} />) output.push(<RevealPoint {...props} key={'rp-' + pointName} />)
// Render text
if (point.attributes && point.attributes.get('data-text')) if (point.attributes && point.attributes.get('data-text'))
output.push(<Text {...props} key={'point-' + pointName} />) output.push(<Text {...props} key={'point-' + pointName} />)
// Render circle
if (point.attributes && point.attributes.get('data-circle')) if (point.attributes && point.attributes.get('data-circle'))
output.push(<Circle point={point} key={'circle-' + pointName} />) output.push(<Circle point={point} key={'circle-' + pointName} />)

View file

@ -2,7 +2,7 @@ import { Chevron } from 'shared/components/navigation/primary.js'
import { Ul, Li, Details, Summary, SumDiv, NoSumDiv, Deg } from 'shared/components/workbench/menu' import { Ul, Li, Details, Summary, SumDiv, NoSumDiv, Deg } from 'shared/components/workbench/menu'
import { round } from 'shared/utils.js' import { round } from 'shared/utils.js'
const XrayAttributes = ({ attr=false }) => { const XrayAttributes = ({ attr=false, t }) => {
if (!attr || !attr.list || Object.keys(attr.list).length < 1) return null if (!attr || !attr.list || Object.keys(attr.list).length < 1) return null
return ( return (
@ -17,7 +17,7 @@ const XrayAttributes = ({ attr=false }) => {
</Summary> </Summary>
<Ul> <Ul>
{Object.keys(attr.list).map(at => ( {Object.keys(attr.list).map(at => (
<Li> <Li key={at}>
<Details> <Details>
<Summary> <Summary>
<SumDiv> <SumDiv>
@ -31,7 +31,10 @@ const XrayAttributes = ({ attr=false }) => {
<Li key={val}> <Li key={val}>
<NoSumDiv> <NoSumDiv>
<Deg /> <Deg />
<span>{val}</span> <span>{val === true
? t('app.yes')
: val
}</span>
</NoSumDiv> </NoSumDiv>
</Li> </Li>
))} ))}

View file

@ -107,8 +107,19 @@ const XrayList = props => {
</button> </button>
<Chevron /> <Chevron />
</Summary> </Summary>
{type === 'paths' && <Path path={part.paths[id]} />} {type === 'paths' && <Path
{type === 'points' && <Point point={part.points[id]} />} pathName={id}
partName={props.partName}
draft={props.draft}
t={props.app.t}
units={props.gist.units}
/>}
{type === 'points' && <Point
pointName={id}
partName={props.partName}
draft={props.draft}
t={props.app.t}
/>}
</Details> </Details>
</Li> </Li>
)) ))

View file

@ -61,7 +61,7 @@ const XrayPathOps = ({ ops=false }) => {
<Summary> <Summary>
<SumDiv> <SumDiv>
<Deg /> <Deg />
PathOps <span className="font-bold">path.ops</span>
</SumDiv> </SumDiv>
<Chevron /> <Chevron />
</Summary> </Summary>

View file

@ -1,25 +1,33 @@
import { Ul, Li, Details, Summary, NoSumDiv, Deg } from 'shared/components/workbench/menu' import { Ul, Li, Details, Summary, NoSumDiv, Deg } from 'shared/components/workbench/menu'
import { formatMm } from 'shared/utils.js'
import Attributes from './attributes.js' import Attributes from './attributes.js'
import Ops from './path-ops.js' import Ops from './path-ops.js'
/*
* Things to add
*
* ops
*/
const XrayPath = ({ pathName, partName, draft, t, units }) => {
const path = draft?.parts?.[partName]?.paths?.[pathName]
const XrayPath = ({ path }) => ( return (
<Ul> <Ul>
<Attributes attr={path.attributes} />
<Li> <Li>
<NoSumDiv> <NoSumDiv>
<Deg /> <Deg />
<span className="font-bold mr-2">Render =</span> <span className="font-bold mr-2">path.render =</span>
<span>{JSON.stringify(path.render)}</span> <span>{JSON.stringify(path.render)}</span>
</NoSumDiv> </NoSumDiv>
</Li> </Li>
<Attributes attr={path.attributes} /> <Li>
<NoSumDiv>
<Deg />
<span className="font-bold mr-2">path.length() =</span>
<span dangerouslySetInnerHTML={{
__html: formatMm(path.length(), units)
}} />
</NoSumDiv>
</Li>
<Ops ops={path.ops} /> <Ops ops={path.ops} />
</Ul> </Ul>
) )
}
export default XrayPath export default XrayPath

View file

@ -2,7 +2,11 @@ import { Ul, Li, Details, Summary, NoSumDiv, Deg } from 'shared/components/workb
import { round } from 'shared/utils.js' import { round } from 'shared/utils.js'
import Attributes from './attributes.js' import Attributes from './attributes.js'
const XrayPoint = ({ point }) => ( const XrayPoint = ({ pointName, partName, draft, t }) => {
const point = draft?.parts?.[partName]?.points?.[pointName]
return point
? (
<Ul> <Ul>
{['x', 'y'].map(coord => ( {['x', 'y'].map(coord => (
<Li key={coord}> <Li key={coord}>
@ -13,8 +17,9 @@ const XrayPoint = ({ point }) => (
</NoSumDiv> </NoSumDiv>
</Li> </Li>
))} ))}
<Attributes attr={point.attributes} /> <Attributes attr={point.attributes} t={t} />
</Ul> </Ul>
) ) : null
}
export default XrayPoint export default XrayPoint

View file

@ -7,6 +7,8 @@ import LabDraft from 'shared/components/workbench/draft/index.js'
import set from 'lodash.set' import set from 'lodash.set'
import unset from 'lodash.unset' import unset from 'lodash.unset'
import defaultSettings from 'shared/components/workbench/default-settings.js' import defaultSettings from 'shared/components/workbench/default-settings.js'
import DraftError from 'shared/components/workbench/draft/error.js'
import theme from 'pkgs/plugin-theme/src/index.js'
// Generates a default pattern gist to start from // Generates a default pattern gist to start from
@ -66,6 +68,18 @@ const WorkbenchWrapper = ({ app, pattern }) => {
setGist(newGist) setGist(newGist)
} }
// Generate the draft here so we can pass it to both Menu
// and LabDraft
let draft = false
if (mode === 'draft') {
draft = new pattern(gist)
if (gist?.renderer === 'svg') patternInstance.use(theme)
try { draft.draft() }
catch(error) {
console.log('Failed to draft pattern', error)
return <DraftError error={error} app={app} draft={draft} at={'draft'} />
}
}
// Required props for layout // Required props for layout
const layoutProps = { const layoutProps = {
@ -81,9 +95,12 @@ const WorkbenchWrapper = ({ app, pattern }) => {
updateGist={updateGist} updateGist={updateGist}
unsetGist={unsetGist} unsetGist={unsetGist}
setGist={setGist} setGist={setGist}
draft={draft}
/> />
} }
return ( return (
<Layout {...layoutProps}> <Layout {...layoutProps}>
{mode === 'measurements' && ( {mode === 'measurements' && (
@ -98,8 +115,10 @@ const WorkbenchWrapper = ({ app, pattern }) => {
<LabDraft <LabDraft
app={app} app={app}
pattern={pattern} pattern={pattern}
draft={draft}
gist={gist} gist={gist}
updateGist={updateGist} updateGist={updateGist}
unsetGist={unsetGist}
/> />
)} )}
</Layout> </Layout>