1
0
Fork 0

chore: Further tweaks to pattern events

This commit is contained in:
Joost De Cock 2020-07-19 13:01:01 +02:00
parent 53e8274624
commit 4ac64e05cb
11 changed files with 2558 additions and 955 deletions

View file

@ -8,6 +8,22 @@ Unreleased:
- Workbench now includes events debug output and enables debug by default - Workbench now includes events debug output and enables debug by default
css-theme: css-theme:
- Added themeing for events - Added themeing for events
Fixed:
aaron:
- Set missing option `brianFitCollar` to `false`
bruce:
- Fixed a check for an undefined value in the store
carlton:
- Removed unused `hipsEase` code
hugo:
- Set missing option `brianFitCollar` to `false`
- Adding missing control point to front neck opening
simon:
- Set missing option `brianFitCollar` to `false`
simone:
- Set missing option `brianFitCollar` to `false`
sven:
- Avoided loading unset ribbingHeight from store
2.7.0: 2.7.0:
date: 2020-07-12 date: 2020-07-12

View file

@ -12,19 +12,20 @@
"@freesewing/mui-theme": "latest", "@freesewing/mui-theme": "latest",
"@freesewing/pattern-info": "latest", "@freesewing/pattern-info": "latest",
"@freesewing/plugin-bundle": "latest", "@freesewing/plugin-bundle": "latest",
"@freesewing/plugin-theme": "latest",
"@freesewing/plugin-i18n": "latest", "@freesewing/plugin-i18n": "latest",
"@freesewing/plugin-svgattr": "latest", "@freesewing/plugin-svgattr": "latest",
"@freesewing/plugin-theme": "latest",
"@freesewing/utils": "latest", "@freesewing/utils": "latest",
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1", "@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^v4.0.0-alpha.56", "@material-ui/lab": "^v4.0.0-alpha.56",
"file-saver": "^2.0.2",
"pattern": "link:..", "pattern": "link:..",
"prismjs": "1.20.0", "prismjs": "1.20.0",
"react": "^16.13", "react": "^16.13",
"react-dom": "^16.13", "react-dom": "^16.13",
"react-markdown": "^4.3.1",
"react-scripts": "^3.4.1", "react-scripts": "^3.4.1",
"file-saver": "^2.0.2",
"typeface-roboto-condensed": "latest" "typeface-roboto-condensed": "latest"
}, },
"scripts": { "scripts": {

File diff suppressed because it is too large Load diff

View file

@ -5,16 +5,68 @@ import WarningIcon from '@material-ui/icons/ErrorOutline'
import ErrorIcon from '@material-ui/icons/HighlightOff' import ErrorIcon from '@material-ui/icons/HighlightOff'
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
const Event = ({ type, event }) => ( const Event = ({ type, event }) => {
<div className={`draft-event ${type}`}> const formatError = (err) => (
<div className={`icon ${type}`}> <details>
{type === 'debug' && <DebugIcon fontSize="small" />} <summary>
{type === 'info' && <InfoIcon fontSize="small" />} <Markdown
{type === 'warning' && <WarningIcon fontSize="small" />} source={`
{type === 'error' && <ErrorIcon fontSize="small" />} \`\`\`js
${err.name}: ${err.message}
\`\`\`
`}
className="react-markdown dense"
/>
</summary>
<Markdown
source={`Error in \`${err.fileName}\` line \`${err.lineNumber}:${err.columnNumber}\``}
className="react-markdown"
/>
<Markdown
source={`
\`\`\`js
${err.stack}
\`\`\`
`}
className="react-markdown"
/>
</details>
)
const formatObject = (obj) => (
<Markdown
source={`
\`\`\`json
${JSON.stringify(obj, null, 2)}
\`\`\`
`}
className="react-markdown"
/>
)
const formatEvent = (e, data = false) => {
if (!data) data = []
if (typeof e === 'object') {
if (e instanceof Error === true) data.push(formatError(e))
else if (Array.isArray(e)) {
for (const subevent of e) data.concat(formatEvent(subevent, data))
} else data.push(formatObject(e))
} else data.push(<Markdown source={e} className="react-markdown" />)
return data
}
return (
<div className={`draft-event ${type}`}>
<div className={`icon ${type}`}>
{type === 'debug' && <DebugIcon fontSize="small" />}
{type === 'info' && <InfoIcon fontSize="small" />}
{type === 'warning' && <WarningIcon fontSize="small" />}
{type === 'error' && <ErrorIcon fontSize="small" />}
</div>
{formatEvent(event)}
</div> </div>
<Markdown source={event} /> )
</div> }
)
export default Event export default Event

View file

@ -75,12 +75,20 @@ Part.prototype.boundary = function () {
let topLeft = new Point(Infinity, Infinity) let topLeft = new Point(Infinity, Infinity)
let bottomRight = new Point(-Infinity, -Infinity) let bottomRight = new Point(-Infinity, -Infinity)
for (let key in this.paths) { for (let key in this.paths) {
let path = this.paths[key].boundary() try {
if (path.render) { let path = this.paths[key].boundary()
if (path.topLeft.x < topLeft.x) topLeft.x = path.topLeft.x if (path.render) {
if (path.topLeft.y < topLeft.y) topLeft.y = path.topLeft.y if (path.topLeft.x < topLeft.x) topLeft.x = path.topLeft.x
if (path.bottomRight.x > bottomRight.x) bottomRight.x = path.bottomRight.x if (path.topLeft.y < topLeft.y) topLeft.y = path.topLeft.y
if (path.bottomRight.y > bottomRight.y) bottomRight.y = path.bottomRight.y if (path.bottomRight.x > bottomRight.x) bottomRight.x = path.bottomRight.x
if (path.bottomRight.y > bottomRight.y) bottomRight.y = path.bottomRight.y
}
} catch (err) {
this.context.raise.error(`Could not calculate boundary of \`paths.${key}\``)
this.context.raise.debug(
`Since \`paths.${key}\` has no boundary, neither does \`parts.${this.name}\`. Ejecting part`
)
return false
} }
} }
for (let key in this.points) { for (let key in this.points) {
@ -190,19 +198,19 @@ Part.prototype.shorthand = function () {
// Wrap the Point constructor so objects can raise events // Wrap the Point constructor so objects can raise events
shorthand.Point = function (x, y) { shorthand.Point = function (x, y) {
Point.apply(this, [x, y, self.context.raise]) Point.apply(this, [x, y, true])
this.raise = self.context.raise this.raise = self.context.raise
} }
shorthand.Point.prototype = Object.create(Point.prototype) shorthand.Point.prototype = Object.create(Point.prototype)
// Wrap the Path constructor so objects can raise events // Wrap the Path constructor so objects can raise events
shorthand.Path = function () { shorthand.Path = function () {
Path.apply(this, [self.context.raise]) Path.apply(this, [true])
this.raise = self.context.raise this.raise = self.context.raise
} }
shorthand.Path.prototype = Object.create(Path.prototype) shorthand.Path.prototype = Object.create(Path.prototype)
// Wrap the Snippet constructor so objects can raise events // Wrap the Snippet constructor so objects can raise events
shorthand.Snippet = function (def, anchor) { shorthand.Snippet = function (def, anchor) {
Snippet.apply(this, [def, anchor, self.context.raise]) Snippet.apply(this, [def, anchor, true])
Snippet.apply(this, arguments) Snippet.apply(this, arguments)
shorthand.raise = self.context.raise shorthand.raise = self.context.raise
} }
@ -227,8 +235,12 @@ Part.prototype.shorthand = function () {
self.context.raise.warning( self.context.raise.warning(
`\`points.${name}\` was set with a \`y\` parameter that is not a \`number\`` `\`points.${name}\` was set with a \`y\` parameter that is not a \`number\``
) )
value.name = name try {
return (self.points[name] = value) value.name = name
} catch (err) {
self.context.raise.warning(`Could not set \`name\` property on \`points.${name}\``)
}
return (self.points[name] = value) || true
} }
} }
shorthand.points = new Proxy(this.points || {}, pointsProxy) shorthand.points = new Proxy(this.points || {}, pointsProxy)
@ -243,8 +255,12 @@ Part.prototype.shorthand = function () {
self.context.raise.warning( self.context.raise.warning(
`\`paths.${name}\` was set with a value that is not a \`Path\` object` `\`paths.${name}\` was set with a value that is not a \`Path\` object`
) )
value.name = name try {
return (self.paths[name] = value) value.name = name
} catch (err) {
self.context.raise.warning(`Could not set \`name\` property on \`paths.${name}\``)
}
return (self.paths[name] = value) || true
} }
} }
shorthand.paths = new Proxy(this.paths || {}, pathsProxy) shorthand.paths = new Proxy(this.paths || {}, pathsProxy)
@ -267,8 +283,12 @@ Part.prototype.shorthand = function () {
self.context.raise.warning( self.context.raise.warning(
`\`snippets.${name}\` was set with an \`anchor\` parameter that is not a \`Point\`` `\`snippets.${name}\` was set with an \`anchor\` parameter that is not a \`Point\``
) )
value.name = name try {
return (self.snippets[name] = value) value.name = name
} catch (err) {
self.context.raise.warning(`Could not set \`name\` property on \`snippets.${name}\``)
}
return (self.snippets[name] = value) || true
} }
} }
shorthand.snippets = new Proxy(this.snippets || {}, snippetsProxy) shorthand.snippets = new Proxy(this.snippets || {}, snippetsProxy)
@ -282,7 +302,7 @@ Part.prototype.shorthand = function () {
return Reflect.get(...arguments) return Reflect.get(...arguments)
}, },
set: (measurements, name, value) => { set: (measurements, name, value) => {
return (self.measurements[name] = value) return (self.measurements[name] = value) || true
} }
} }
shorthand.measurements = new Proxy(this.context.settings.measurements || {}, measurementsProxy) shorthand.measurements = new Proxy(this.context.settings.measurements || {}, measurementsProxy)
@ -294,7 +314,7 @@ Part.prototype.shorthand = function () {
return Reflect.get(...arguments) return Reflect.get(...arguments)
}, },
set: (options, name, value) => { set: (options, name, value) => {
return (self.options[name] = value) return (self.options[name] = value) || true
} }
} }
shorthand.options = new Proxy(this.context.settings.options || {}, optionsProxy) shorthand.options = new Proxy(this.context.settings.options || {}, optionsProxy)

View file

@ -11,8 +11,8 @@ import {
round round
} from './utils' } from './utils'
function Path(raise = false) { function Path(debug = false) {
this.debug = raise ? true : false this.debug = debug
this.render = true this.render = true
this.topLeft = false this.topLeft = false
this.bottomRight = false this.bottomRight = false
@ -24,7 +24,7 @@ function Path(raise = false) {
Path.prototype.setRender = function (render = true) { Path.prototype.setRender = function (render = true) {
if (render) this.render = true if (render) this.render = true
else this.render = false else this.render = false
if (this.debug) this.raise('Setting `Path.render` to ' + render ? '`true`' : '`false`') if (this.debug) this.raise.debug('Setting `Path.render` to ' + render ? '`true`' : '`false`')
return this return this
} }
@ -387,7 +387,9 @@ function joinPaths(paths, closed = false) {
// We're using sitsRoughlyOn here to avoid miniscule line segments // We're using sitsRoughlyOn here to avoid miniscule line segments
if (current && !op.to.sitsRoughlyOn(current)) joint.line(op.to) if (current && !op.to.sitsRoughlyOn(current)) joint.line(op.to)
} else { } else {
throw new Error('Cannot join a closed paths with another') let err = 'Cannot join a closed path with another'
this.raise.error(err)
throw new Error(err)
} }
if (op.to) current = op.to if (op.to) current = op.to
} }

View file

@ -31,7 +31,6 @@ export default function Pattern(config = { options: {} }) {
}, },
debug: function (data) { debug: function (data) {
events.debug.push(data) events.debug.push(data)
console.log(data)
} }
} }
this.raise.debug( this.raise.debug(
@ -80,7 +79,11 @@ export default function Pattern(config = { options: {} }) {
else if (typeof option.count !== 'undefined') this.settings.options[i] = option.count else if (typeof option.count !== 'undefined') this.settings.options[i] = option.count
else if (typeof option.bool !== 'undefined') this.settings.options[i] = option.bool else if (typeof option.bool !== 'undefined') this.settings.options[i] = option.bool
else if (typeof option.dflt !== 'undefined') this.settings.options[i] = option.dflt else if (typeof option.dflt !== 'undefined') this.settings.options[i] = option.dflt
else throw new Error('Unknown option type: ' + JSON.stringify(option)) else {
let err = 'Unknown option type: ' + JSON.stringify(option)
this.raise.error(err)
throw new Error(err)
}
} else { } else {
this.settings.options[i] = option this.settings.options[i] = option
} }
@ -129,11 +132,7 @@ Pattern.prototype.apply = function (settings) {
} }
} else this.settings[key] = settings[key] } else this.settings[key] = settings[key]
} }
if (this.settings.debug) this.raise.debug('Debug enabled') if (!this.settings.debug) this.debug = false
else {
this.raise.debug('Debug disabled')
this.debug = false
}
return this return this
} }
@ -166,7 +165,14 @@ Pattern.prototype.draft = function () {
this.raise.debug( this.raise.debug(
`Injecting part \`${this.config.inject[partName]}\` into part \`${partName}\`` `Injecting part \`${this.config.inject[partName]}\` into part \`${partName}\``
) )
this.parts[partName].inject(this.parts[this.config.inject[partName]]) try {
this.parts[partName].inject(this.parts[this.config.inject[partName]])
} catch (err) {
this.raise.error([
`Could not inject part \`${this.config.inject[partName]}\` into part \`${partName}\``,
err
])
}
} }
if (this.needs(partName)) { if (this.needs(partName)) {
let method = 'draft' + capitalize(partName) let method = 'draft' + capitalize(partName)
@ -174,17 +180,22 @@ Pattern.prototype.draft = function () {
this.raise.error(`Method \`pattern.${method}\` is callable`) this.raise.error(`Method \`pattern.${method}\` is callable`)
throw new Error('Method "' + method + '" on pattern object is not callable') throw new Error('Method "' + method + '" on pattern object is not callable')
} }
this.parts[partName] = this[method](this.parts[partName]) try {
this.parts[partName] = this[method](this.parts[partName])
} catch (err) {
this.raise.error([`Unable to draft part \`${partName}\``, err])
}
if (typeof this.parts[partName] === 'undefined') { if (typeof this.parts[partName] === 'undefined') {
this.raise.error( this.raise.error(
`Result of \`pattern.${method}\` was \`undefined\`. Did you forget to return the \`Part\` object?` `Result of \`pattern.${method}\` was \`undefined\`. Did you forget to return the \`Part\` object?`
) )
throw new Error(
'Result of ' + method + '() was undefined. Did you forget to return the Part object?'
)
} }
this.parts[partName].render = try {
this.parts[partName].render === false ? false : this.wants(partName) this.parts[partName].render =
this.parts[partName].render === false ? false : this.wants(partName)
} catch (err) {
this.raise.error([`Unable to set \`render\` property on part \`${partName}\``, err])
}
} else { } else {
if (this.debug) if (this.debug)
this.raise.debug( this.raise.debug(
@ -323,7 +334,7 @@ Pattern.prototype.sampleMeasurement = function (measurementName) {
let parts = this.sampleParts() let parts = this.sampleParts()
let val = this.settings.measurements[measurementName] let val = this.settings.measurements[measurementName]
if (val === undefined) if (val === undefined)
throw new Error('Cannot sample a measurement that is undefined: ' + measurementName) this.raise.error(`Cannot sample measurement \`${measurementName}\` because it's \`undefined\``)
let step = val / 50 let step = val / 50
val = val * 0.9 val = val * 0.9
for (let run = 1; run < 11; run++) { for (let run = 1; run < 11; run++) {
@ -410,6 +421,10 @@ Pattern.prototype.macro = function (key, method) {
/** Packs parts in a 2D space and sets pattern size */ /** Packs parts in a 2D space and sets pattern size */
Pattern.prototype.pack = function () { Pattern.prototype.pack = function () {
if (this.events.error.length > 0) {
this.raise.warning(`One or more errors occured. Not packing pattern parts`)
return this
}
let bins = [] let bins = []
for (let key in this.parts) { for (let key in this.parts) {
let part = this.parts[key] let part = this.parts[key]
@ -531,7 +546,10 @@ Pattern.prototype.resolveDependencies = function (graph = this.config.dependenci
else if (Array.isArray(this.config.dependencies[i])) { else if (Array.isArray(this.config.dependencies[i])) {
if (this.config.dependencies[i].indexOf(dependency) === -1) if (this.config.dependencies[i].indexOf(dependency) === -1)
this.config.dependencies[i].push(dependency) this.config.dependencies[i].push(dependency)
} else throw new Error('Part dependencies should be a string or an array of strings') } else {
this.raise.error('Part dependencies should be a string or an array of strings')
throw new Error('Part dependencies should be a string or an array of strings')
}
} }
// Parts both in the parts and dependencies array trip up the dependency resolver // Parts both in the parts and dependencies array trip up the dependency resolver
if (Array.isArray(this.config.parts)) { if (Array.isArray(this.config.parts)) {

View file

@ -1,8 +1,8 @@
import Attributes from './attributes' import Attributes from './attributes'
import { round } from './utils' import { round } from './utils'
function Point(x, y, raise = false) { function Point(x, y, debug = false) {
this.debug = raise ? true : false this.debug = debug
if (this.debug) { if (this.debug) {
if (typeof x !== 'number') raise.warning('Called `new Point(x,y)` but `x` is not a number') if (typeof x !== 'number') raise.warning('Called `new Point(x,y)` but `x` is not a number')
if (typeof y !== 'number') raise.warning('Called `new Point(x,y)` but `y` is not a number') if (typeof y !== 'number') raise.warning('Called `new Point(x,y)` but `y` is not a number')

View file

@ -1,8 +1,8 @@
import Attributes from './attributes' import Attributes from './attributes'
import Point from './point' import Point from './point'
function Snippet(def, anchor, raise = false) { function Snippet(def, anchor, debug = false) {
this.debug = raise ? true : false this.debug = debug
if (this.debug) { if (this.debug) {
if (typeof def !== 'string') if (typeof def !== 'string')
raise.warning('Called `new Snippet(def, anchor)` but `def` is not a string') raise.warning('Called `new Snippet(def, anchor)` but `def` is not a string')

View file

@ -3,13 +3,11 @@ div.draft-events {
max-width: 900px; max-width: 900px;
div.draft-event { div.draft-event {
margin: 0.5rem auto; margin: 0.5rem auto;
line-height: 1.1;
font-size: 85%; font-size: 85%;
padding: 0.5rem; padding: 0.5rem;
border: 1px dotted black; border: 1px dotted black;
border-radius: 3px; border-radius: 3px;
position: relative; position: relative;
padding-left: 36px;
div.icon { div.icon {
position: absolute; position: absolute;
top: 0; top: 0;
@ -38,6 +36,7 @@ div.draft-events {
} }
p:first-of-type { p:first-of-type {
margin-top: 0; margin-top: 0;
padding-left: 32px;
} }
p:last-of-type { p:last-of-type {
margin-bottom: 0; margin-bottom: 0;
@ -55,4 +54,11 @@ div.draft-events {
div.draft-event.error { div.draft-event.error {
border-color: $oc-red-6; border-color: $oc-red-6;
} }
div.draft-event details summary {
margin-left: 1rem;
list-style-position: outside;
}
div.draft-event details summary:hover {
cursor: help;
}
} }

View file

@ -2,14 +2,14 @@ code[class*='language-'],
pre[class*='language-'] { pre[class*='language-'] {
text-shadow: none; text-shadow: none;
} }
.workbench.theme-wrapper.light code, .workbench.theme-wrapper.light :not(pre) > code,
.theme-wrapper.light :not(pre) > code[class*='language-'] { .theme-wrapper.light :not(pre) > code[class*='language-'] {
padding: 0.1rem 0.25rem; padding: 0.1rem 0.25rem;
background: $oc-yellow-0; background: $oc-yellow-0;
border: 1px $oc-yellow-2 solid; border: 1px $oc-yellow-2 solid;
color: $oc-gray-9; color: $oc-gray-9;
} }
.workbench.theme-wrapper.dark code, .workbench.theme-wrapper.dark :not(pre) > code,
.theme-wrapper.dark :not(pre) > code[class*='language-'] { .theme-wrapper.dark :not(pre) > code[class*='language-'] {
padding: 0.125rem 0.5rem; padding: 0.125rem 0.5rem;
background: $oc-gray-9; background: $oc-gray-9;
@ -20,9 +20,14 @@ pre[class*='language-'] {
div.gatsby-highlight { div.gatsby-highlight {
position: relative; position: relative;
} }
div.react-markdown pre,
div.gatsby-highlight pre { div.gatsby-highlight pre {
padding: 1.5rem 1rem; padding: 1.5rem 1rem;
} }
div.react-markdown.dense pre,
div.gatsby-highlight.dense pre {
padding: 0.5rem 1rem;
}
pre.language-yaml:before, pre.language-yaml:before,
pre.language-js:before, pre.language-js:before,
@ -81,6 +86,14 @@ pre[class*='language-'] {
.theme-wrapper.dark pre[class*='language-'] { .theme-wrapper.dark pre[class*='language-'] {
border: 1px solid $oc-gray-8; border: 1px solid $oc-gray-8;
} }
div.react-markdown pre[class*='language-'],
div.react-markdown pre code[class*='language-'] {
margin: 0.5rem 0;
}
div.react-markdown pre[class*='language-']:before {
display: none;
}
@include xs-screen { @include xs-screen {
pre code[class*='language-'], pre code[class*='language-'],
pre[class*='language-'] { pre[class*='language-'] {