1
0
Fork 0

refactor(components): Removed prop-types dependency

This commit is contained in:
Joost De Cock 2020-04-25 19:09:02 +02:00
parent 8cf8424437
commit cda9b03713
44 changed files with 559 additions and 1026 deletions

View file

@ -1,49 +1,36 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import Radio from '@material-ui/core/Radio' import Radio from '@material-ui/core/Radio'
import RadioGroup from '@material-ui/core/RadioGroup' import RadioGroup from '@material-ui/core/RadioGroup'
import FormControlLabel from '@material-ui/core/FormControlLabel' import FormControlLabel from '@material-ui/core/FormControlLabel'
const Bool = props => { const Bool = ({ dflt = false, labels = ['false', 'true'], value, name, updateValue }) => {
const [value, setValue] = useState(props.dflt) const [val, setVal] = useState(dflt)
useEffect(() => { useEffect(() => {
if (props.value !== value) setValue(props.value) if (value !== val) setVal(value)
}, [props.value]) }, [value])
const toggle = () => { const toggle = () => {
props.updateValue(props.name, !value) updateValue(name, !val)
setValue(!value) setVal(!val)
} }
return ( return (
<RadioGroup onChange={toggle} value={JSON.stringify(value)}> <RadioGroup onChange={toggle} value={JSON.stringify(val)}>
<FormControlLabel <FormControlLabel
control={<Radio color="primary" />} control={<Radio color="primary" />}
value="false" value="false"
checked={value === 'true' || value === true || value === 1 ? false : true} checked={val === 'true' || val === true || val === 1 ? false : true}
label={props.labels[0]} label={labels[0]}
className="po-list-item" className="po-list-item"
/> />
<FormControlLabel <FormControlLabel
control={<Radio color="primary" />} control={<Radio color="primary" />}
value="true" value="true"
checked={value === 'true' || value === true || value === 1 ? true : false} checked={val === 'true' || val === true || val === 1 ? true : false}
label={props.labels[1]} label={labels[1]}
className="po-list-item" className="po-list-item"
/> />
</RadioGroup> </RadioGroup>
) )
} }
Bool.propTypes = {
dflt: PropTypes.bool,
labels: PropTypes.array,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired
}
Bool.defaultProps = {
dflt: false,
labels: ['false', 'true']
}
export default Bool export default Bool

View file

@ -1,24 +1,23 @@
import React, { useState } from "react"; import React, { useState } from 'react'
import PropTypes from "prop-types"; import FormGroup from '@material-ui/core/FormGroup'
import FormGroup from "@material-ui/core/FormGroup"; import FormControlLabel from '@material-ui/core/FormControlLabel'
import FormControlLabel from "@material-ui/core/FormControlLabel"; import Checkbox from '@material-ui/core/Checkbox'
import Checkbox from "@material-ui/core/Checkbox";
const FormFieldChecks = props => { const FormFieldChecks = (props) => {
const [value, setValue] = useState(props.dflt ? props.dflt : []); const [value, setValue] = useState(props.dflt ? props.dflt : [])
const toggle = part => { const toggle = (part) => {
let parts = value.slice(0); let parts = value.slice(0)
let index = parts.indexOf(part); let index = parts.indexOf(part)
if (index === -1) parts.push(part); if (index === -1) parts.push(part)
else parts.splice(index, 1); else parts.splice(index, 1)
setValue(parts); setValue(parts)
props.updateValue(props.name, parts); props.updateValue(props.name, parts)
}; }
return ( return (
<FormGroup> <FormGroup>
{Object.keys(props.checks).map(i => { {Object.keys(props.checks).map((i) => {
return ( return (
<FormControlLabel <FormControlLabel
control={ control={
@ -32,17 +31,10 @@ const FormFieldChecks = props => {
key={i} key={i}
className="po-list-item" className="po-list-item"
/> />
); )
})} })}
</FormGroup> </FormGroup>
); )
}; }
FormFieldChecks.propTypes = { export default FormFieldChecks
dflt: PropTypes.array,
checks: PropTypes.object,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired
};
export default FormFieldChecks;

View file

@ -1,15 +1,14 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import Radio from '@material-ui/core/Radio' import Radio from '@material-ui/core/Radio'
import RadioGroup from '@material-ui/core/RadioGroup' import RadioGroup from '@material-ui/core/RadioGroup'
import FormControlLabel from '@material-ui/core/FormControlLabel' import FormControlLabel from '@material-ui/core/FormControlLabel'
const FormFieldList = props => { const FormFieldList = (props) => {
const [value, setValue] = useState(props.dflt) const [value, setValue] = useState(props.dflt)
useEffect(() => { useEffect(() => {
if (props.value !== value) setValue(props.value) if (props.value !== value) setValue(props.value)
}, [props.value]) }, [props.value])
const update = evt => { const update = (evt) => {
props.updateValue(props.name, evt.target.value) props.updateValue(props.name, evt.target.value)
setValue(evt.target.value) setValue(evt.target.value)
} }
@ -30,15 +29,4 @@ const FormFieldList = props => {
) )
} }
FormFieldList.propTypes = {
dflt: PropTypes.oneOfType([
PropTypes.number.isRequired,
PropTypes.string.isRequired,
PropTypes.bool.isRequired
]),
list: PropTypes.object,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired
}
export default FormFieldList export default FormFieldList

View file

@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import TextField from '@material-ui/core/TextField' import TextField from '@material-ui/core/TextField'
import IconButton from '@material-ui/core/IconButton' import IconButton from '@material-ui/core/IconButton'
import InvalidIcon from '@material-ui/icons/Warning' import InvalidIcon from '@material-ui/icons/Warning'
@ -47,13 +46,4 @@ const FormFieldMeasurement = (props) => {
) )
} }
FormFieldMeasurement.propTypes = {
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
units: PropTypes.oneOf(['metric', 'imperial'])
}
FormFieldMeasurement.defaultProps = {}
export default injectIntl(FormFieldMeasurement) export default injectIntl(FormFieldMeasurement)

View file

@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import Slider from '@material-ui/core/Slider' import Slider from '@material-ui/core/Slider'
import { withStyles } from '@material-ui/core/styles' import { withStyles } from '@material-ui/core/styles'
@ -11,48 +10,32 @@ const PaddedSlider = withStyles({
thumb: { width: '16px', height: '16px' } thumb: { width: '16px', height: '16px' }
})(Slider) })(Slider)
const FormFieldSlider = props => { const FormFieldSlider = ({ min = 0, max = 100, step = 0.1, label = false, updateValue, name }) => {
const [value, setValue] = useState(props.value) const [val, setVal] = useState(value)
useEffect(() => { useEffect(() => {
if (props.value !== value) setValue(props.value) if (value !== val) setVal(value)
}, [props.value]) }, [value])
const update = (evt, newValue) => { const update = (evt, newValue) => {
props.updateValue(props.name, newValue, evt) updateValue(name, newValue, evt)
setValue(newValue) setVal(newValue)
} }
return ( return (
<PaddedSlider <PaddedSlider
value={value} value={val}
min={props.min} min={min}
max={props.max} max={max}
step={props.step} step={step}
onChange={update} onChange={update}
onChangeCommitted={update} onChangeCommitted={update}
classes={{ classes={{
track: 'slider-track', track: 'slider-track',
thumb: 'slider-thumb' thumb: 'slider-thumb'
}} }}
aria-labelledby={props.label} aria-labelledby={label}
/> />
) )
} }
FormFieldSlider.propTypes = {
min: PropTypes.number,
max: PropTypes.number,
step: PropTypes.number,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.oneOf([false])])
}
FormFieldSlider.defaultProps = {
min: 0,
max: 100,
step: 0.1,
label: false
}
export default FormFieldSlider export default FormFieldSlider

View file

@ -1,26 +1,16 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import Icon from '../Icon' import Icon from '../Icon'
const Blockquote = props => { const Blockquote = (props) => {
const attr = Object.assign({}, props) const attr = Object.assign({}, props)
delete attr.type delete attr.type
delete attr.children delete attr.children
return ( return (
<blockquote className={props.type} {...attr}> <blockquote className={props.type || 'note'} {...attr}>
{props.children} {props.children || null}
{props.type === 'fixme' ? null : <Icon icon={props.type} className={'icon ' + props.type} />} {props.type !== 'fixme' && <Icon icon={props.type} className={'icon ' + props.type} />}
</blockquote> </blockquote>
) )
} }
Blockquote.propTypes = {
type: PropTypes.string.isRequired,
children: PropTypes.node
}
Blockquote.defaultProps = {
type: 'note',
children: null
}
export default Blockquote export default Blockquote

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
const Circle = (props) => ( const Circle = (props) => (
<circle <circle
@ -10,8 +9,4 @@ const Circle = (props) => (
/> />
) )
Circle.propTypes = {
point: PropTypes.object.isRequired
}
export default Circle export default Circle

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import Path from '../Path' import Path from '../Path'
import Point from '../Point' import Point from '../Point'
import Snippet from '../Snippet' import Snippet from '../Snippet'
@ -136,12 +135,4 @@ const Part = (props) => {
) )
} }
Part.propTypes = {
part: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
language: PropTypes.string.isRequired,
paperless: PropTypes.bool.isRequired,
design: PropTypes.bool.isRequired
}
export default Part export default Part

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import TextOnPath from '../TextOnPath' import TextOnPath from '../TextOnPath'
import DesignPath from '../DesignPath' import DesignPath from '../DesignPath'
import { getProps } from '../utils' import { getProps } from '../utils'
@ -18,10 +17,4 @@ const Path = (props) => {
return output return output
} }
Path.propTypes = {
path: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
language: PropTypes.string.isRequired
}
export default Path export default Path

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import DesignPoint from '../DesignPoint' import DesignPoint from '../DesignPoint'
import Text from '../Text' import Text from '../Text'
import Circle from '../Circle' import Circle from '../Circle'
@ -12,14 +11,8 @@ const Point = (props) => {
output.push(<Text {...props} key={'point-' + props.name} />) output.push(<Text {...props} key={'point-' + props.name} />)
if (props.point.attributes.get('data-circle')) if (props.point.attributes.get('data-circle'))
output.push(<Circle point={props.point} key={'circle-' + props.name} />) output.push(<Circle point={props.point} key={'circle-' + props.name} />)
if (output.length < 1) return null
else return output
}
Point.propTypes = { return output.length < 1 ? null : output
point: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
language: PropTypes.string.isRequired
} }
export default Point export default Point

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import { getProps } from '../utils' import { getProps } from '../utils'
const Snippet = (props) => { const Snippet = (props) => {
@ -25,8 +24,4 @@ const Snippet = (props) => {
return <use {...snippetProps} {...getProps(props.snippet)} /> return <use {...snippetProps} {...getProps(props.snippet)} />
} }
Snippet.propTypes = {
snippet: PropTypes.object.isRequired
}
export default Snippet export default Snippet

View file

@ -1,40 +1,33 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
const Svg = (props) => { const Svg = ({
embed = true,
design = false,
language = 'en',
className = 'freesewing draft',
style = {},
viewBox = false,
width,
height,
children
}) => {
let attributes = { let attributes = {
xmlns: 'http://www.w3.org/2000/svg', xmlns: 'http://www.w3.org/2000/svg',
'xmlns:svg': 'http://www.w3.org/2000/svg', 'xmlns:svg': 'http://www.w3.org/2000/svg',
xmlnsXlink: 'http://www.w3.org/1999/xlink', xmlnsXlink: 'http://www.w3.org/1999/xlink',
xmlLang: props.language, xmlLang: language,
viewBox: props.viewBox || `0 0 ${props.width} ${props.height}`, viewBox: viewBox || `0 0 ${width} ${height}`,
className: props.className, className,
style: props.style style
} }
if (!props.embed) { if (!embed) {
attributes.width = props.width + 'mm' attributes.width = width + 'mm'
attributes.height = props.height + 'mm' attributes.height = height + 'mm'
} }
if (props.design) attributes.className += ' design' if (design) attributes.className += ' design'
return <svg {...attributes}>{props.children}</svg> return <svg {...attributes}>{children}</svg>
}
Svg.propTypes = {
embed: PropTypes.bool,
className: PropTypes.string,
language: PropTypes.string,
design: PropTypes.bool
}
Svg.defaultProps = {
embed: true,
design: false,
language: 'en',
className: 'freesewing draft',
style: {},
viewBox: false
} }
export default Svg export default Svg

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import { strings } from '@freesewing/i18n' import { strings } from '@freesewing/i18n'
const Text = (props) => { const Text = (props) => {
@ -30,6 +29,7 @@ const Text = (props) => {
) )
} }
} else text.push(<tspan key="tspan-1">{translated}</tspan>) } else text.push(<tspan key="tspan-1">{translated}</tspan>)
return ( return (
<text <text
x={props.point.x} x={props.point.x}
@ -41,9 +41,4 @@ const Text = (props) => {
) )
} }
Text.propTypes = {
point: PropTypes.object.isRequired,
language: PropTypes.string.isRequired
}
export default Text export default Text

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import { strings } from '@freesewing/i18n' import { strings } from '@freesewing/i18n'
const TextOnPath = (props) => { const TextOnPath = (props) => {
@ -29,9 +28,4 @@ const TextOnPath = (props) => {
) )
} }
TextOnPath.propTypes = {
path: PropTypes.object.isRequired,
language: PropTypes.string.isRequired
}
export default TextOnPath export default TextOnPath

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import Svg from './Svg' import Svg from './Svg'
import Defs from './Defs' import Defs from './Defs'
import Part from './Part' import Part from './Part'
@ -11,8 +10,8 @@ const Draft = (props) => (
height={props.height} height={props.height}
language={props.settings.locale} language={props.settings.locale}
id={props.settings.idPrefix + 'svg'} id={props.settings.idPrefix + 'svg'}
design={props.design} design={props.design || false}
style={props.style} style={props.style || {}}
viewBox={props.viewBox} viewBox={props.viewBox}
className={props.className || 'freesewing draft'} className={props.className || 'freesewing draft'}
> >
@ -20,7 +19,7 @@ const Draft = (props) => (
units={props.settings.units} units={props.settings.units}
parts={props.parts} parts={props.parts}
paperless={props.settings.paperless} paperless={props.settings.paperless}
design={props.design} design={props.design || false}
/> />
<g> <g>
{Object.keys(props.parts).map((name) => ( {Object.keys(props.parts).map((name) => (
@ -31,8 +30,8 @@ const Draft = (props) => (
units={props.settings.units} units={props.settings.units}
key={name} key={name}
name={name} name={name}
focus={props.focus} focus={props.focus || false}
design={props.design} design={props.design || false}
raiseEvent={props.raiseEvent} raiseEvent={props.raiseEvent}
/> />
))} ))}
@ -40,16 +39,4 @@ const Draft = (props) => (
</Svg> </Svg>
) )
Draft.propTypes = {
parts: PropTypes.object.isRequired,
settings: PropTypes.object.isRequired,
design: PropTypes.bool
}
Draft.defaultProps = {
design: false,
focus: false,
style: {}
}
export default Draft export default Draft

View file

@ -1,11 +1,10 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import FormFieldList from '../../.form/FormFieldList' import FormFieldList from '../../.form/FormFieldList'
import OptionPreamble from '../OptionPreamble' import OptionPreamble from '../OptionPreamble'
import { injectIntl } from 'react-intl' import { injectIntl } from 'react-intl'
import { languages } from '@freesewing/i18n' import { languages } from '@freesewing/i18n'
const DraftSettingLanguage = props => { const DraftSettingLanguage = (props) => {
const [value, setValue] = useState(props.value === null ? props.intl.locale : props.value) const [value, setValue] = useState(props.value === null ? props.intl.locale : props.value)
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
@ -64,12 +63,4 @@ const DraftSettingLanguage = props => {
) )
} }
DraftSettingLanguage.propTypes = {
raiseEvent: PropTypes.func.isRequired,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired
}
export default injectIntl(DraftSettingLanguage) export default injectIntl(DraftSettingLanguage)

View file

@ -1,12 +1,11 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import FormFieldSlider from '../../.form/FormFieldSlider' import FormFieldSlider from '../../.form/FormFieldSlider'
import formatMm from '@freesewing/utils/formatMm' import formatMm from '@freesewing/utils/formatMm'
import roundMm from '@freesewing/utils/roundMm' import roundMm from '@freesewing/utils/roundMm'
import sliderStep from '@freesewing/utils/sliderStep' import sliderStep from '@freesewing/utils/sliderStep'
import OptionPreamble from '../OptionPreamble' import OptionPreamble from '../OptionPreamble'
const DraftSettingMargin = props => { const DraftSettingMargin = (props) => {
const [value, setValue] = useState(props.value === null ? props.dflt : props.value) const [value, setValue] = useState(props.value === null ? props.dflt : props.value)
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
@ -77,16 +76,4 @@ const DraftSettingMargin = props => {
) )
} }
DraftSettingMargin.propTypes = {
raiseEvent: PropTypes.func.isRequired,
updateValue: PropTypes.func.isRequired,
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired,
units: PropTypes.oneOf(['metric', 'imperial']).isRequired
}
DraftSettingMargin.defaultProps = {
// FIXME
}
export default DraftSettingMargin export default DraftSettingMargin

View file

@ -1,5 +1,4 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import FormFieldList from '../../.form/FormFieldList' import FormFieldList from '../../.form/FormFieldList'
import FormFieldSlider from '../../.form/FormFieldSlider' import FormFieldSlider from '../../.form/FormFieldSlider'
import formatMm from '@freesewing/utils/formatMm' import formatMm from '@freesewing/utils/formatMm'
@ -8,7 +7,7 @@ import defaultSa from '@freesewing/utils/defaultSa'
import sliderStep from '@freesewing/utils/sliderStep' import sliderStep from '@freesewing/utils/sliderStep'
import OptionPreamble from '../OptionPreamble' import OptionPreamble from '../OptionPreamble'
const DraftSettingSa = props => { const DraftSettingSa = (props) => {
const [value, setValue] = useState( const [value, setValue] = useState(
props.value === defaultSa[props.units] ? 'dflt' : props.value === 0 ? 'none' : 'custom' props.value === defaultSa[props.units] ? 'dflt' : props.value === 0 ? 'none' : 'custom'
) )
@ -131,16 +130,4 @@ const DraftSettingSa = props => {
) )
} }
DraftSettingSa.propTypes = {
updateValue: PropTypes.func.isRequired,
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired,
units: PropTypes.oneOf(['metric', 'imperial']).isRequired,
labels: PropTypes.object
}
DraftSettingSa.defaultProps = {
// FIXME
}
export default DraftSettingSa export default DraftSettingSa

View file

@ -1,5 +1,4 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import DraftSettingSa from '../DraftSettingSa' import DraftSettingSa from '../DraftSettingSa'
import DraftSettingMargin from '../DraftSettingMargin' import DraftSettingMargin from '../DraftSettingMargin'
@ -11,9 +10,41 @@ import DraftSettingLanguage from '../DraftSettingLanguage'
import DraftSettingOnly from '../DraftSettingOnly' import DraftSettingOnly from '../DraftSettingOnly'
import RightIcon from '@material-ui/icons/KeyboardArrowRight' import RightIcon from '@material-ui/icons/KeyboardArrowRight'
const DraftSettings = props => { const DraftSettings = ({
units = 'metric',
raiseEvent,
updateValue,
noDocs,
pattern,
config,
data = { settings: {} }
}) => {
// State
const [expanded, setExpanded] = useState([]) const [expanded, setExpanded] = useState([])
const toggleGroup = group => {
// Building blocks
const noyes = [<FormattedMessage id="app.no" />, <FormattedMessage id="app.yes" />]
const hideshow = [<FormattedMessage id="app.hide" />, <FormattedMessage id="app.show" />]
const metricimperial = {
metric: <FormattedMessage id="app.metricUnits" />,
imperial: <FormattedMessage id="app.imperialUnits" />
}
const labels = {
sa: {
none: <FormattedMessage id="app.noSeamAllowance" />,
dflt: <FormattedMessage id="app.standardSeamAllowance" />,
custom: <FormattedMessage id="app.customSeamAllowance" />
},
only: {
dflt: <FormattedMessage id="app.default" />,
custom: <FormattedMessage id="app.custom" />
},
paperless: noyes,
advanced: hideshow,
complete: hideshow
}
// Methods
const toggleGroup = (group) => {
let shown = expanded.slice(0) let shown = expanded.slice(0)
let index = shown.indexOf(group) let index = shown.indexOf(group)
if (index === -1) shown.push(group) if (index === -1) shown.push(group)
@ -33,42 +64,21 @@ const DraftSettings = props => {
case 'margin': case 'margin':
return 2 return 2
case 'units': case 'units':
return props.units return units
default: default:
return false return false
} }
} }
const addProps = (setting) => {
let noyes = [<FormattedMessage id="app.no" />, <FormattedMessage id="app.yes" />]
let hideshow = [<FormattedMessage id="app.hide" />, <FormattedMessage id="app.show" />]
let units = {
metric: <FormattedMessage id="app.metricUnits" />,
imperial: <FormattedMessage id="app.imperialUnits" />
}
const addProps = setting => {
const labels = {
sa: {
none: <FormattedMessage id="app.noSeamAllowance" />,
dflt: <FormattedMessage id="app.standardSeamAllowance" />,
custom: <FormattedMessage id="app.customSeamAllowance" />
},
only: {
dflt: <FormattedMessage id="app.default" />,
custom: <FormattedMessage id="app.custom" />
},
paperless: noyes,
advanced: hideshow,
complete: hideshow
}
let childProps = { let childProps = {
raiseEvent: props.raiseEvent, raiseEvent,
updateValue: props.updateValue, updateValue,
units: props.units, units,
key: setting, key: setting,
name: setting, name: setting,
labels: labels[setting], labels: labels[setting],
noDocs: props.noDocs, noDocs,
dflt: getDefault(setting, props.pattern), dflt: getDefault(setting, pattern),
designDflt: getDefault(setting) designDflt: getDefault(setting)
} }
childProps.title = <FormattedMessage id={'settings.' + setting + '.title'} /> childProps.title = <FormattedMessage id={'settings.' + setting + '.title'} />
@ -76,26 +86,21 @@ const DraftSettings = props => {
if (setting === 'only') { if (setting === 'only') {
childProps.customDflt = [] childProps.customDflt = []
childProps.parts = {} childProps.parts = {}
if (props.config.draftOrder) { if (config.draftOrder) {
for (let part of props.config.draftOrder) for (let part of config.draftOrder)
childProps.parts[part] = <FormattedMessage id={'parts.' + part} /> childProps.parts[part] = <FormattedMessage id={'parts.' + part} />
} }
} }
if ( if (typeof data.settings[setting] !== 'undefined') childProps.value = data.settings[setting]
typeof props.data !== 'undefined' &&
typeof props.data.settings !== 'undefined' &&
typeof props.data.settings[setting] !== 'undefined'
)
childProps.value = props.data.settings[setting]
else childProps.value = null else childProps.value = null
return childProps return childProps
} }
let groups = { const groups = {
advanced: [ advanced: [
<DraftSettingLanguage {...addProps('locale')} />, <DraftSettingLanguage {...addProps('locale')} />,
<DraftSettingUnits {...addProps('units')} list={units} />, <DraftSettingUnits {...addProps('units')} list={metricimperial} />,
<DraftSettingComplete {...addProps('complete')} />, <DraftSettingComplete {...addProps('complete')} />,
<DraftSettingMargin {...addProps('margin')} />, <DraftSettingMargin {...addProps('margin')} />,
<DraftSettingOnly {...addProps('only')} /> <DraftSettingOnly {...addProps('only')} />
@ -103,19 +108,19 @@ const DraftSettings = props => {
} }
return ( return (
<React.Fragment> <>
<ul className="config l2 nogroups"> <ul className="config l2 nogroups">
<DraftSettingSa {...addProps('sa')} /> <DraftSettingSa {...addProps('sa')} />
<DraftSettingPaperless {...addProps('paperless')} /> <DraftSettingPaperless {...addProps('paperless')} />
<DraftSettingAdvanced {...addProps('advanced')} /> <DraftSettingAdvanced {...addProps('advanced')} />
</ul> </ul>
{props.data.settings.advanced ? ( {data.settings.advanced && (
<ul className="config l2"> <ul className="config l2">
{Object.keys(groups).map(group => { {Object.keys(groups).map((group) => {
let open = true let open = true
if (expanded.indexOf(group) === -1) open = false if (expanded.indexOf(group) === -1) open = false
let children = null let children = null
if (open) children = groups[group].map(component => component) if (open) children = groups[group].map((component) => component)
return ( return (
<React.Fragment key={group}> <React.Fragment key={group}>
<li className={open ? 'expanded' : 'collapsed'} key={group + '-ghead'}> <li className={open ? 'expanded' : 'collapsed'} key={group + '-ghead'}>
@ -129,15 +134,9 @@ const DraftSettings = props => {
) )
})} })}
</ul> </ul>
) : null} )}
</React.Fragment> </>
) )
} }
DraftSettings.propTypes = {
config: PropTypes.object.isRequired
}
DraftSettings.defaultProps = {}
export default DraftSettings export default DraftSettings

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import Pct from '../PatternOptionPercentage' import Pct from '../PatternOptionPercentage'
import Deg from '../PatternOptionDegree' import Deg from '../PatternOptionDegree'
import Mm from '../PatternOptionMillimeter' import Mm from '../PatternOptionMillimeter'
@ -12,7 +11,7 @@ import { FormattedMessage } from 'react-intl'
import { injectIntl } from 'react-intl' import { injectIntl } from 'react-intl'
import RightIcon from '@material-ui/icons/KeyboardArrowRight' import RightIcon from '@material-ui/icons/KeyboardArrowRight'
const OptionGroup = props => { const OptionGroup = (props) => {
const renderOption = (name, sub = false) => { const renderOption = (name, sub = false) => {
let option = props.config.options[name] let option = props.config.options[name]
let type = optionType(option) let type = optionType(option)
@ -66,12 +65,10 @@ const OptionGroup = props => {
} }
return ( return (
<React.Fragment> <>
{props.options.map(name => { {props.options.map((name) => {
//let key = name;
let output = [] let output = []
if (typeof name === 'object') { if (typeof name === 'object') {
//key = Object.keys(name).pop();
// Subgroup // Subgroup
for (let subGroup of Object.keys(name)) { for (let subGroup of Object.keys(name)) {
let children = [] let children = []
@ -90,16 +87,8 @@ const OptionGroup = props => {
return output return output
})} })}
</React.Fragment> </>
) )
} }
OptionGroup.propTypes = {
config: PropTypes.object.isRequired,
options: PropTypes.array.isRequired,
units: PropTypes.oneOf(['metric', 'imperial']).isRequired
}
OptionGroup.defaultProps = {}
export default injectIntl(OptionGroup) export default injectIntl(OptionGroup)

View file

@ -1,11 +1,25 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import IconButton from '@material-ui/core/IconButton' import IconButton from '@material-ui/core/IconButton'
import RightIcon from '@material-ui/icons/KeyboardArrowRight' import RightIcon from '@material-ui/icons/KeyboardArrowRight'
import ResetIcon from '@material-ui/icons/SettingsBackupRestore' import ResetIcon from '@material-ui/icons/SettingsBackupRestore'
import { injectIntl } from 'react-intl' import { injectIntl } from 'react-intl'
const OptionPreamble = props => { const OptionPreamble = ({
intl,
title,
desc,
dflt,
designDflt,
option,
value,
displayValue,
displayFormat = 'node',
sameButDifferent,
expanded,
toggleExpanded,
reset,
designReset
}) => {
const styles = { const styles = {
container: { container: {
display: 'flex', display: 'flex',
@ -22,43 +36,41 @@ const OptionPreamble = props => {
} }
} }
const resetLabel = props.intl.formatMessage({ const resetLabel = intl.formatMessage({
id: 'app.restoreDefaults', id: 'app.restoreDefaults',
defaultMessage: ' ♻️ ' defaultMessage: ' ♻️ '
}) })
const resetDesignLabel = props.intl.formatMessage({ const resetDesignLabel = intl.formatMessage({
id: 'app.restoreDesignDefaults', id: 'app.restoreDesignDefaults',
defaultMessage: ' ♻️ ' defaultMessage: ' ♻️ '
}) })
const resetPatternLabel = props.intl.formatMessage({ const resetPatternLabel = intl.formatMessage({
id: 'app.restorePatternDefaults', id: 'app.restorePatternDefaults',
defaultMessage: ' ♻️ ' defaultMessage: ' ♻️ '
}) })
let pattern = false let pattern = false
if (props.dflt !== props.designDflt) pattern = true if (dflt !== designDflt) pattern = true
let displayClass = props.value === props.dflt ? 'dflt' : 'custom' let displayClass = value === dflt ? 'dflt' : 'custom'
if (pattern && props.value === props.designDflt) displayClass = 'p-dflt' if (pattern && value === designDflt) displayClass = 'p-dflt'
else if (pattern && props.sameButDifferent) displayClass = 'custom' else if (pattern && sameButDifferent) displayClass = 'custom'
let displayValue = <span className={displayClass}>{props.displayValue}</span> let dspValue = <span className={displayClass}>{displayValue}</span>
if (props.displayFormat === 'html') if (displayFormat === 'html')
displayValue = ( dspValue = <span className={displayClass} dangerouslySetInnerHTML={{ __html: displayValue }} />
<span className={displayClass} dangerouslySetInnerHTML={{ __html: props.displayValue }} />
)
return ( return (
<React.Fragment> <React.Fragment>
<div onClick={props.toggleExpanded} style={styles.container}> <div onClick={toggleExpanded} style={styles.container}>
<div style={styles.left}> <div style={styles.left}>
<RightIcon className={'icon-col-exp ' + (props.expanded ? 'expanded' : 'collapsed')} /> <RightIcon className={'icon-col-exp ' + (expanded ? 'expanded' : 'collapsed')} />
{props.title} {title}
</div> </div>
<div style={styles.right}>{displayValue}</div> <div style={styles.right}>{dspValue}</div>
</div> </div>
<div className={props.expanded ? 'col-exp expanded' : 'col-exp collapsed'}> <div className={expanded ? 'col-exp expanded' : 'col-exp collapsed'}>
<div style={styles.container}> <div style={styles.container}>
<div style={styles.left}> <div style={styles.left}>
<p>{props.desc}</p> <p>{desc}</p>
</div> </div>
<div style={styles.right}> <div style={styles.right}>
{pattern ? ( {pattern ? (
@ -66,8 +78,8 @@ const OptionPreamble = props => {
title={resetDesignLabel} title={resetDesignLabel}
aria-label={resetDesignLabel} aria-label={resetDesignLabel}
color="primary" color="primary"
disabled={props.value === props.designDflt ? true : false} disabled={value === designDflt ? true : false}
onClick={props.designReset} onClick={designReset}
className="mini-icon-btn pattern" className="mini-icon-btn pattern"
> >
<ResetIcon /> <ResetIcon />
@ -77,40 +89,18 @@ const OptionPreamble = props => {
title={pattern ? resetPatternLabel : resetLabel} title={pattern ? resetPatternLabel : resetLabel}
aria-label={pattern ? resetPatternLabel : resetLabel} aria-label={pattern ? resetPatternLabel : resetLabel}
color="primary" color="primary"
disabled={props.value === props.dflt && !props.sameButDifferent ? true : false} disabled={value === dflt && !sameButDifferent ? true : false}
onClick={props.reset} onClick={reset}
className={'mini-icon-btn' + (pattern ? ' pattern' : '')} className={'mini-icon-btn' + (pattern ? ' pattern' : '')}
> >
<ResetIcon /> <ResetIcon />
</IconButton> </IconButton>
</div> </div>
</div> </div>
{props.option} {option}
</div> </div>
</React.Fragment> </React.Fragment>
) )
} }
OptionPreamble.propTypes = {
dflt: PropTypes.oneOfType([
PropTypes.number.isRequired,
PropTypes.string.isRequired,
PropTypes.bool.isRequired
]),
value: PropTypes.oneOfType([
PropTypes.number.isRequired,
PropTypes.string.isRequired,
PropTypes.bool.isRequired
]),
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired,
reset: PropTypes.func.isRequired,
expanded: PropTypes.bool,
displayFormat: PropTypes.string
}
OptionPreamble.defaultProps = {
displayFormat: 'node'
}
export default injectIntl(OptionPreamble) export default injectIntl(OptionPreamble)

View file

@ -1,9 +1,8 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import FormFieldBool from '../../.form/FormFieldBool' import FormFieldBool from '../../.form/FormFieldBool'
import OptionPreamble from '../OptionPreamble' import OptionPreamble from '../OptionPreamble'
const PatternOptionBool = props => { const PatternOptionBool = (props) => {
const [value, setValue] = useState(props.value === null ? props.dflt : props.value) const [value, setValue] = useState(props.value === null ? props.dflt : props.value)
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
@ -62,18 +61,4 @@ const PatternOptionBool = props => {
) )
} }
PatternOptionBool.propTypes = {
raiseEvent: PropTypes.func.isRequired,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
dflt: PropTypes.oneOfType([
PropTypes.number.isRequired,
PropTypes.string.isRequired,
PropTypes.bool.isRequired
]),
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired,
labels: PropTypes.array.isRequired
}
export default PatternOptionBool export default PatternOptionBool

View file

@ -1,9 +1,8 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import FormFieldList from '../../.form/FormFieldList' import FormFieldList from '../../.form/FormFieldList'
import OptionPreamble from '../OptionPreamble' import OptionPreamble from '../OptionPreamble'
const PatternOptionList = props => { const PatternOptionList = (props) => {
const [value, setValue] = useState(props.dflt) const [value, setValue] = useState(props.dflt)
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
@ -70,13 +69,4 @@ const PatternOptionList = props => {
) )
} }
PatternOptionList.propTypes = {
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
dflt: PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.string.isRequired]),
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired,
list: PropTypes.array.isRequired
}
export default PatternOptionList export default PatternOptionList

View file

@ -1,94 +1,85 @@
import React, { useState } from "react"; import React, { useState } from 'react'
import PropTypes from "prop-types"; import sliderStep from '@freesewing/utils/sliderStep'
import sliderStep from "@freesewing/utils/sliderStep"; import roundMm from '@freesewing/utils/roundMm'
import roundMm from "@freesewing/utils/roundMm"; import roundMmUp from '@freesewing/utils/roundMmUp'
import roundMmUp from "@freesewing/utils/roundMmUp"; import roundMmDown from '@freesewing/utils/roundMmDown'
import roundMmDown from "@freesewing/utils/roundMmDown"; import formatMm from '@freesewing/utils/formatMm'
import formatMm from "@freesewing/utils/formatMm"; import FormFieldSlider from '../../.form/FormFieldSlider'
import FormFieldSlider from "../../.form/FormFieldSlider"; import OptionPreamble from '../OptionPreamble'
import OptionPreamble from "../OptionPreamble";
const PatternOptionMillimeter = props => { const PatternOptionMillimeter = ({
const [value, setValue] = useState(props.dflt); title = false,
const [previousValue, setPreviousValue] = useState(props.dflt); desc = false,
const [expanded, setExpanded] = useState(false); units = 'metric',
min = 0,
max = 100,
updateValue,
name,
dflt,
noDocs
}) => {
const [val, setVal] = useState(dflt)
const [previousValue, setPreviousValue] = useState(dflt)
const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => { const update = (name, newValue, evt) => {
newValue = roundMm(newValue, props.units); newValue = roundMm(newValue, units)
// Sometimes, when sliding, the rapid succession of updates // Sometimes, when sliding, the rapid succession of updates
// causes a weird timing issue to result in a value that is NaN. // causes a weird timing issue to result in a value that is NaN.
// If that's the case, just ignore this update and keep the // If that's the case, just ignore this update and keep the
// previous one instead // previous one instead
if (!isNaN(newValue)) { if (!isNaN(newValue)) {
setValue(newValue); setVal(newValue)
if (evt.type !== "mousemove") props.updateValue(props.name, newValue); if (evt.type !== 'mousemove') updateValue(name, newValue)
} else { } else {
if (evt.type !== "mousemove") props.updateValue(props.name, value); if (evt.type !== 'mousemove') updateValue(name, val)
}
} }
};
const reset = () => { const reset = () => {
setValue(props.dflt); setVal(dflt)
props.updateValue(props.name, props.dflt); updateValue(name, dflt)
}; }
const toggleExpanded = () => setExpanded(!expanded); const toggleExpanded = () => setExpanded(!expanded)
let option = ( let option = (
<FormFieldSlider <FormFieldSlider
name={props.name} name={name}
value={value} value={val}
min={roundMmUp(props.min, props.units)} min={roundMmUp(min, units)}
max={roundMmDown(props.max, props.units)} max={roundMmDown(units)}
step={sliderStep[props.units]} step={sliderStep[units]}
onChange={update} onChange={update}
label={"po-mm-" + props.name} label={'po-mm-' + name}
updateValue={update} updateValue={update}
/> />
); )
return ( return (
<li> <li>
<OptionPreamble <OptionPreamble
dflt={props.dflt} dflt={dflt}
value={value} value={val}
desc={props.desc} desc={desc}
title={props.title} title={title}
id={"po-mm-" + props.name} id={'po-mm-' + name}
displayValue={formatMm(value, props.units)} displayValue={formatMm(val, units)}
displayFormat="html" displayFormat="html"
reset={reset} reset={reset}
toggleExpanded={toggleExpanded} toggleExpanded={toggleExpanded}
expanded={expanded} expanded={expanded}
showHelp={() => showHelp={() =>
props.raiseEvent("showHelp", { raiseEvent('showHelp', {
type: "patternOption", type: 'patternOption',
value: props.name value: name
}) })
} }
option={option} option={option}
noDocs={props.noDocs} noDocs={noDocs}
/> />
</li> </li>
); )
}; }
PatternOptionMillimeter.propTypes = { export default PatternOptionMillimeter
min: PropTypes.number,
max: PropTypes.number,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
dflt: PropTypes.number.isRequired,
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired,
units: PropTypes.oneOf(["metric", "imperial"]).isRequired
};
PatternOptionMillimeter.defaultProps = {
min: 0,
max: 100,
title: false,
desc: false
};
export default PatternOptionMillimeter;

View file

@ -1,18 +1,27 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import FormFieldSlider from '../../.form/FormFieldSlider' import FormFieldSlider from '../../.form/FormFieldSlider'
import OptionPreamble from '../OptionPreamble' import OptionPreamble from '../OptionPreamble'
const PatternOptionPctDegCount = props => { const PatternOptionPctDegCount = ({
min = 0,
max = 100,
step = 0.1,
type = 'pct',
updateValue,
name,
dflt,
designDflt,
title,
desc,
value,
raiseEvent,
noDocs
}) => {
let factor = 1 let factor = 1
if (props.type === 'pct') factor = 100 if (type === 'pct') factor = 100
const round = val => Math.round(val * 10) / 10 const round = (val) => Math.round(val * 10) / 10
const [value, setValue] = useState( const [val, setVal] = useState(value === null ? dflt : round(value * factor))
props.value === null ? props.dflt : round(props.value * factor) const [previousValue, setPreviousValue] = useState(value === null ? dflt : round(value * factor))
)
const [previousValue, setPreviousValue] = useState(
props.value === null ? props.dflt : round(props.value * factor)
)
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
const update = (name, newValue, evt) => { const update = (name, newValue, evt) => {
@ -22,38 +31,38 @@ const PatternOptionPctDegCount = props => {
// If that's the case, just ignore this update and keep the // If that's the case, just ignore this update and keep the
// previous one instead // previous one instead
if (!isNaN(newValue)) { if (!isNaN(newValue)) {
setValue(newValue) setVal(newValue)
if (evt.type !== 'mousemove') props.updateValue(props.name, newValue / factor) if (evt.type !== 'mousemove') updateValue(name, newValue / factor)
} else { } else {
if (evt.type !== 'mousemove') props.updateValue(props.name, value / factor) if (evt.type !== 'mousemove') updateValue(name, value / factor)
} }
} }
const reset = () => { const reset = () => {
setValue(props.dflt) setVal(dflt)
props.updateValue(props.name, props.dflt / factor) updateValue(name, dflt / factor)
} }
const patternReset = () => { const patternReset = () => {
setValue(props.designDflt) setVal(designDflt)
props.updateValue(props.name, props.designDflt / factor) updateValue(name, designDflt / factor)
} }
const toggleExpanded = () => setExpanded(!expanded) const toggleExpanded = () => setExpanded(!expanded)
let unit = '' let unit = ''
if (props.type === 'pct') unit = '%' if (type === 'pct') unit = '%'
if (props.type === 'deg') unit = '°' if (type === 'deg') unit = '°'
let option = ( let option = (
<FormFieldSlider <FormFieldSlider
name={props.name} name={name}
value={value} value={val}
min={props.min} min={min}
max={props.max} max={max}
step={props.type === 'count' ? 1 : props.step} step={type === 'count' ? 1 : step}
onChange={update} onChange={update}
label={'po-' + props.type + '-' + props.name} label={'po-' + type + '-' + name}
updateValue={update} updateValue={update}
/> />
) )
@ -61,47 +70,28 @@ const PatternOptionPctDegCount = props => {
return ( return (
<li> <li>
<OptionPreamble <OptionPreamble
dflt={props.dflt} dflt={dflt}
designDflt={props.designDflt} designDflt={designDflt}
value={value} value={val}
desc={props.desc} desc={desc}
title={props.title} title={title}
id={'po-' + props.type + '-' + props.name} id={'po-' + type + '-' + name}
displayValue={value + unit} displayValue={val + unit}
reset={reset} reset={reset}
patternReset={patternReset} patternReset={patternReset}
toggleExpanded={toggleExpanded} toggleExpanded={toggleExpanded}
expanded={expanded} expanded={expanded}
showHelp={() => showHelp={() =>
props.raiseEvent('showHelp', { raiseEvent('showHelp', {
type: 'patternOption', type: 'patternOption',
value: props.name value: name
}) })
} }
option={option} option={option}
noDocs={props.noDocs} noDocs={noDocs}
/> />
</li> </li>
) )
} }
PatternOptionPctDegCount.propTypes = {
min: PropTypes.number,
max: PropTypes.number,
step: PropTypes.number,
updateValue: PropTypes.func.isRequired,
name: PropTypes.string.isRequired,
dflt: PropTypes.number.isRequired,
title: PropTypes.node.isRequired,
desc: PropTypes.node.isRequired,
type: PropTypes.oneOf(['pct', 'deg', 'count'])
}
PatternOptionPctDegCount.defaultProps = {
min: 0,
max: 100,
step: 0.1,
type: 'pct'
}
export default PatternOptionPctDegCount export default PatternOptionPctDegCount

View file

@ -1,12 +1,11 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import OptionGroup from '../OptionGroup' import OptionGroup from '../OptionGroup'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import RightIcon from '@material-ui/icons/KeyboardArrowRight' import RightIcon from '@material-ui/icons/KeyboardArrowRight'
const PatternOptions = props => { const PatternOptions = (props) => {
const [expanded, setExpanded] = useState([]) const [expanded, setExpanded] = useState([])
const toggleGroup = group => { const toggleGroup = (group) => {
let shown = expanded.slice(0) let shown = expanded.slice(0)
let index = shown.indexOf(group) let index = shown.indexOf(group)
if (index === -1) shown.push(group) if (index === -1) shown.push(group)
@ -14,7 +13,7 @@ const PatternOptions = props => {
setExpanded(shown) setExpanded(shown)
} }
const renderGroup = group => { const renderGroup = (group) => {
let open = true let open = true
if (expanded.indexOf(group) === -1) open = false if (expanded.indexOf(group) === -1) open = false
let output = [] let output = []
@ -58,11 +57,4 @@ const PatternOptions = props => {
return <ul className="config l2">{children}</ul> return <ul className="config l2">{children}</ul>
} }
PatternOptions.propTypes = {
config: PropTypes.object.isRequired,
raiseEvent: PropTypes.func
}
PatternOptions.defaultProps = {}
export default PatternOptions export default PatternOptions

View file

@ -1,11 +1,25 @@
import React, { useState } from 'react' import React from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import PatternOptions from './PatternOptions' import PatternOptions from './PatternOptions'
import DraftSettings from './DraftSettings' import DraftSettings from './DraftSettings'
const DraftConfigurator = props => { const DraftConfigurator = ({
const [expanded, setExpanded] = useState([]) noDocs = false,
units = 'metric',
config = {},
data = {},
pattern,
updatePatternData,
raiseEvent
}) => {
let childProps = {
noDocs,
units,
config,
data,
pattern,
raiseEvent
}
return ( return (
<ul className="config l1"> <ul className="config l1">
<li> <li>
@ -13,13 +27,8 @@ const DraftConfigurator = props => {
<FormattedMessage id="app.designOptions" /> <FormattedMessage id="app.designOptions" />
</span> </span>
<PatternOptions <PatternOptions
noDocs={props.noDocs} {...childProps}
config={props.config} updateValue={(name, value) => updatePatternData(value, 'settings', 'options', name)}
data={props.data}
pattern={props.pattern}
updateValue={(name, value) => props.updatePatternData(value, 'settings', 'options', name)}
raiseEvent={props.raiseEvent}
units={props.units}
/> />
</li> </li>
<li> <li>
@ -27,25 +36,12 @@ const DraftConfigurator = props => {
<FormattedMessage id="app.patternOptions" /> <FormattedMessage id="app.patternOptions" />
</span> </span>
<DraftSettings <DraftSettings
noDocs={props.noDocs} {...childProps}
config={props.config} updateValue={(name, value) => updatePatternData(value, 'settings', name)}
data={props.data}
pattern={props.pattern}
updateValue={(name, value) => props.updatePatternData(value, 'settings', name)}
raiseEvent={props.raiseEvent}
units={props.units}
/> />
</li> </li>
</ul> </ul>
) )
} }
DraftConfigurator.propTypes = {
units: PropTypes.oneOf(['metric', 'imperial']).isRequired
}
DraftConfigurator.defaultProps = {
noDocs: false
}
export default DraftConfigurator export default DraftConfigurator

View file

@ -1,21 +1,10 @@
import React from "react"; import React from 'react'
import PropTypes from "prop-types";
const Emblem = props => ( const Emblem = (props) => (
<React.Fragment> <React.Fragment>
<span className="emb">{props.t1}</span> <span className="emb">{props.t1 || 'Free'}</span>
<span className="lem">{props.t2}</span> <span className="lem">{props.t2 || 'Sewing'}</span>
</React.Fragment> </React.Fragment>
); )
Emblem.propTypes = { export default Emblem
t1: PropTypes.string,
t2: PropTypes.string
};
Emblem.defaultProps = {
t1: "Free",
t2: "Sewing"
};
export default Emblem;

View file

@ -1,41 +1,47 @@
import React, { useState } from "react"; import React, { useState } from 'react'
import PropTypes from "prop-types"; import examples from '@freesewing/examples'
import examples from "@freesewing/examples"; import rendertest from '@freesewing/rendertest'
import rendertest from "@freesewing/rendertest"; import tutorial from '@freesewing/tutorial'
import tutorial from "@freesewing/tutorial"; import Draft from '../Draft'
import Draft from "../Draft"; import Design from '../Workbench/Design'
import Design from "../Workbench/Design"; import IconButton from '@material-ui/core/IconButton'
import IconButton from "@material-ui/core/IconButton"; import ResetIcon from '@material-ui/icons/SettingsBackupRestore'
import ResetIcon from "@material-ui/icons/SettingsBackupRestore"; import Switch from '@material-ui/core/Switch'
import Switch from "@material-ui/core/Switch";
const Example = props => { const Example = ({
const [design, setDesign] = useState(false); pattern = 'examples',
const [focus, setFocus] = useState(null); design = true,
caption = '',
options = {},
settings,
part = '',
sample
}) => {
const [designMode, setDesignMode] = useState(false)
const [focus, setFocus] = useState(null)
const raiseEvent = (type, data) => { const raiseEvent = (type, data) => {
if (type === "clearFocusAll") return setFocus(null); if (type === 'clearFocusAll') return setFocus(null)
let f = {}; let f = {}
if (focus !== null) f = { ...focus }; if (focus !== null) f = { ...focus }
if (typeof f[data.part] === "undefined") if (typeof f[data.part] === 'undefined') f[data.part] = { paths: [], points: [], coords: [] }
f[data.part] = { paths: [], points: [], coords: [] }; if (type === 'point') f[data.part].points.push(data.name)
if (type === "point") f[data.part].points.push(data.name); else if (type === 'path') f[data.part].paths.push(data.name)
else if (type === "path") f[data.part].paths.push(data.name); else if (type === 'coords') f[data.part].coords.push(data.coords)
else if (type === "coords") f[data.part].coords.push(data.coords); else if (type === 'clearFocus') {
else if (type === "clearFocus") { let i = focus[data.part][data.type].indexOf(data.name)
let i = focus[data.part][data.type].indexOf(data.name); f[data.part][data.type].splice(i, 1)
f[data.part][data.type].splice(i, 1);
} }
setFocus(f); setFocus(f)
}; }
let focusCount = 0; let focusCount = 0
if (focus !== null) { if (focus !== null) {
for (let p of Object.keys(focus)) { for (let p of Object.keys(focus)) {
for (let i in focus[p].points) focusCount++; for (let i in focus[p].points) focusCount++
for (let i in focus[p].paths) focusCount++; for (let i in focus[p].paths) focusCount++
for (let i in focus[p].coords) focusCount++; for (let i in focus[p].coords) focusCount++
} }
} }
@ -43,75 +49,49 @@ const Example = props => {
examples, examples,
rendertest, rendertest,
tutorial tutorial
}; }
const settings = { settings = {
options: { ...props.options }, options: { ...options },
measurements: { headCircumference: 390 }, measurements: { headCircumference: 390 },
...props.settings ...settings
}; }
if (props.part !== "") settings.only = [props.part]; if (part !== '') settings.only = [part]
const pattern = new patterns[props.pattern](settings); const patternInstance = new patterns[pattern](settings)
if (props.sample) pattern.sample(); if (sample) patternInstance.sample()
else pattern.draft(); else patternInstance.draft()
const patternProps = pattern.getRenderProps(); const patternProps = patternInstance.getRenderProps()
return ( return (
<figure className={design ? "design example" : "example"}> <figure className={designMode ? 'design example' : 'example'}>
<div className="example"> <div className="example">
{props.design ? ( {designMode ? (
<div className="actions"> <div className="actions">
{design ? ( <IconButton color="primary" onClick={() => raiseEvent('clearFocusAll', null)}>
<IconButton
color="primary"
onClick={() => raiseEvent("clearFocusAll", null)}
>
<ResetIcon /> <ResetIcon />
</IconButton> </IconButton>
) : null}
<Switch <Switch
checked={design} checked={designMode}
onChange={() => setDesign(!design)} onChange={() => setDesignMode(!designMode)}
value={design} value={designMode}
color="primary" color="primary"
/> />
</div> </div>
) : null} ) : null}
<Draft <Draft {...patternProps} design={design} focus={focus} raiseEvent={raiseEvent} />
{...patternProps}
design={design}
focus={focus}
raiseEvent={raiseEvent}
/>
</div> </div>
<figcaption>{props.caption}</figcaption> <figcaption>{caption}</figcaption>
{design ? ( {designMode && (
<div className="design"> <div className="design">
<Design <Design
focus={focus} focus={focus}
design={design} design={designMode}
raiseEvent={raiseEvent} raiseEvent={raiseEvent}
parts={patternProps.parts} parts={patternProps.parts}
/> />
</div> </div>
) : null} )}
</figure> </figure>
); )
}; }
Example.propTypes = { export default Example
pattern: PropTypes.string,
design: PropTypes.bool,
caption: PropTypes.string,
part: PropTypes.string,
options: PropTypes.obj
};
Example.defaultProps = {
pattern: "examples",
design: true,
caption: "",
options: {},
part: ""
};
export default Example;

View file

@ -1,40 +1,24 @@
import React from "react"; import React from 'react'
import PropTypes from "prop-types"; import icons from './icons'
import icons from "./icons";
const Icon = props => { const Icon = ({
return ( size = 24,
viewBox = '0 0 24 24',
className = '',
icon = 'github',
color = false,
style = {}
}) => (
<svg <svg
style={props.style} style={style}
className={props.className} className={className}
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width={props.size} width={size}
height={props.size} height={size}
viewBox={props.viewBox} viewBox={viewBox}
> >
<path <path stroke="none" fill={color ? color : 'currentColor'} d={icons[icon]} />
stroke="none"
fill={props.color ? props.color : "currentColor"}
d={icons[props.icon]}
/>
</svg> </svg>
); )
};
Icon.propTypes = { export default Icon
size: PropTypes.number,
viewBox: PropTypes.string,
icon: PropTypes.string,
style: PropTypes.object
};
Icon.defaultProps = {
size: 24,
viewBox: "0 0 24 24",
className: "",
icon: "github",
color: false,
style: {}
};
export default Icon;

View file

@ -1,11 +1,10 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import patterns from './patterns' import patterns from './patterns'
const LineDrawing = props => { const LineDrawing = (props) => {
const attr = { const attr = {
style: props.style, style: props.style || {},
className: 'fs linedrawing ' + props.className, className: 'fs linedrawing ' + (props.className || ''),
xmlns: 'http://www.w3.org/2000/svg', xmlns: 'http://www.w3.org/2000/svg',
viewBox: '0 0 270 270' viewBox: '0 0 270 270'
} }
@ -13,20 +12,7 @@ const LineDrawing = props => {
attr.width = props.size attr.width = props.size
attr.height = props.size attr.height = props.size
} }
return <svg {...attr}>{patterns[props.pattern] || null}</svg> return <svg {...attr}>{patterns[props.pattern || 'aaron'] || null}</svg>
}
LineDrawing.propTypes = {
size: PropTypes.number,
pattern: PropTypes.string,
style: PropTypes.object
}
LineDrawing.defaultProps = {
size: 0,
className: '',
pattern: 'aaron',
style: {}
} }
export default LineDrawing export default LineDrawing

File diff suppressed because one or more lines are too long

View file

@ -1,11 +1,15 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import Logo from '../Logo' import Logo from '../Logo'
import Emblem from '../Emblem' import Emblem from '../Emblem'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import useMediaQuery from '@material-ui/core/useMediaQuery' import useMediaQuery from '@material-ui/core/useMediaQuery'
const Navbar = props => { const Navbar = ({
home = 'https://freesewing.org/',
navs = { left: [], right: [], mleft: {}, mright: {} },
logo = <Logo embed color="#e9ecef" />,
emblem = <Emblem />
}) => {
const mobile = useMediaQuery('(max-width:599px)') const mobile = useMediaQuery('(max-width:599px)')
if (mobile) return null if (mobile) return null
@ -47,49 +51,36 @@ const Navbar = props => {
let homeProps = { let homeProps = {
href: '#home' href: '#home'
} }
if (typeof props.home === 'function') homeProps.onClick = props.home if (typeof home === 'function') homeProps.onClick = home
else homeProps.href = props.home else homeProps.href = home
let logo = ( let logoDiv = (
<div className="logo"> <div className="logo">
<a id="home" {...homeProps} data-test="navbar-home"> <a id="home" {...homeProps} data-test="navbar-home">
{props.logo} {logo}
</a> </a>
</div> </div>
) )
let emblem = ( let emblemDiv = (
<div className="emblem"> <div className="emblem">
<a {...homeProps}>{props.emblem}</a> <a {...homeProps}>{emblem}</a>
</div> </div>
) )
return ( return (
<header className="navbar"> <header className="navbar">
<div> <div>
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
{logo} {logoDiv}
{emblem} {emblemDiv}
{Object.keys(props.navs.left).map(key => renderNav(key, props.navs.left[key]))} {Object.keys(navs.left).map((key) => renderNav(key, navs.left[key]))}
</div> </div>
<div className="spread" /> <div className="spread" />
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
{Object.keys(props.navs.right).map(key => renderNav(key, props.navs.right[key]))} {Object.keys(navs.right).map((key) => renderNav(key, navs.right[key]))}
</div> </div>
</div> </div>
</header> </header>
) )
} }
Navbar.propTypes = {
navs: PropTypes.object,
logo: PropTypes.node,
emblem: PropTypes.node,
home: PropTypes.oneOfType([PropTypes.string, PropTypes.func])
}
Navbar.defaultProps = {
home: 'https://freesewing.org/',
navs: { left: [], right: [], mleft: {}, mright: {} },
logo: <Logo embed color="#e9ecef" />,
emblem: <Emblem />
}
export default Navbar export default Navbar

File diff suppressed because one or more lines are too long

View file

@ -1,38 +1,23 @@
import React from "react"; import React from 'react'
import PropTypes from "prop-types"; import poses from './poses'
import poses from "./poses";
const Robot = props => { const Robot = ({
return ( size = 124,
viewBox = '0 0 500 500',
className = '',
pose = 'yay',
color = false,
embed = false
}) => (
<svg <svg
className={props.className} className={className || ''}
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width={props.embed ? "" : props.size} width={embed ? '' : size || 124}
height={props.embed ? "" : props.size} height={embed ? '' : size || 124}
viewBox={props.viewBox} viewBox={viewBox || '0 0 500 500'}
> >
<path <path stroke="none" fill={color ? color : 'currentColor'} d={poses[pose]} />
stroke="none"
fill={props.color ? props.color : "currentColor"}
d={poses[props.pose]}
/>
</svg> </svg>
); )
};
Robot.propTypes = { export default Robot
size: PropTypes.number,
viewBox: PropTypes.string,
pose: PropTypes.string,
embed: PropTypes.bool
};
Robot.defaultProps = {
size: 124,
viewBox: "0 0 500 500",
className: "",
pose: "yay",
color: false
};
export default Robot;

View file

@ -1,12 +1,11 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
import { injectIntl } from 'react-intl' import { injectIntl } from 'react-intl'
const OptionGroup = props => { const OptionGroup = (props) => {
return ( return (
<React.Fragment> <React.Fragment>
{props.options.map(name => { {props.options.map((name) => {
let output = [] let output = []
if (typeof name === 'object') { if (typeof name === 'object') {
// Subgroup // Subgroup
@ -44,11 +43,4 @@ const OptionGroup = props => {
) )
} }
OptionGroup.propTypes = {
config: PropTypes.object.isRequired,
options: PropTypes.array.isRequired
}
OptionGroup.defaultProps = {}
export default injectIntl(OptionGroup) export default injectIntl(OptionGroup)

View file

@ -1,46 +1,38 @@
import React from "react"; import React from 'react'
import PropTypes from "prop-types"; import OptionGroup from '../OptionGroup'
import OptionGroup from "../OptionGroup"; import { FormattedMessage } from 'react-intl'
import { FormattedMessage } from "react-intl";
const PatternOptions = props => { const PatternOptions = (props) => {
const renderGroup = group => { const renderGroup = (group) => {
let output = []; let output = []
let children = ( let children = (
<ul className="links"> <ul className="links">
<OptionGroup <OptionGroup
key={group + "-group"} key={group + '-group'}
units={props.units} units={props.units}
config={props.config} config={props.config}
options={props.config.optionGroups[group]} options={props.config.optionGroups[group]}
sampleOption={props.sampleOption} sampleOption={props.sampleOption}
/> />
</ul> </ul>
); )
output.push( output.push(
<li key={group + "-ghead"} className="nodot"> <li key={group + '-ghead'} className="nodot">
<h3> <h3>
<FormattedMessage id={"optiongroups." + group} /> <FormattedMessage id={'optiongroups.' + group} />
</h3> </h3>
{children} {children}
</li> </li>
); )
return output; return output
}; }
return ( return (
<ul className="links"> <ul className="links">
{Object.keys(props.config.optionGroups).map(group => renderGroup(group))} {Object.keys(props.config.optionGroups).map((group) => renderGroup(group))}
</ul> </ul>
); )
}; }
PatternOptions.propTypes = { export default PatternOptions
config: PropTypes.object.isRequired,
sampleOption: PropTypes.func.isRequired
};
PatternOptions.defaultProps = {};
export default PatternOptions;

View file

@ -1,12 +1,11 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
const Spinner = props => { const Spinner = (props) => {
return ( return (
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width={props.embed ? '' : props.size} width={props.embed ? '' : props.size || 200}
height={props.embed ? '' : props.size} height={props.embed ? '' : props.size || 200}
viewBox="-28 -28 108 108" viewBox="-28 -28 108 108"
className={'spinner ' + props.className} className={'spinner ' + props.className}
> >
@ -65,14 +64,4 @@ const Spinner = props => {
) )
} }
Spinner.propTypes = {
size: PropTypes.number,
embed: PropTypes.bool
}
Spinner.defaultProps = {
size: 200,
embed: false
}
export default Spinner export default Spinner

View file

@ -1,5 +1,4 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import PropTypes from 'prop-types'
import Draft from '../../Draft' import Draft from '../../Draft'
import Zoombox from '../Zoombox' import Zoombox from '../Zoombox'
import Design from '../Design' import Design from '../Design'
@ -115,7 +114,7 @@ const DraftPattern = (props) => {
return ( return (
<div className="fs-sa"> <div className="fs-sa">
<section> <section style={{ margin: '1rem' }}>
<Draft <Draft
{...patternProps} {...patternProps}
design={design} design={design}
@ -224,7 +223,7 @@ const DraftPattern = (props) => {
updatePatternData={props.updateGist} updatePatternData={props.updateGist}
raiseEvent={props.raiseEvent} raiseEvent={props.raiseEvent}
freesewing={props.freesewing} freesewing={props.freesewing}
units={props.units} units={props.units || 'metric'}
/> />
</div> </div>
</aside> </aside>
@ -232,18 +231,4 @@ const DraftPattern = (props) => {
) )
} }
DraftPattern.propTypes = {
gist: PropTypes.object.isRequired,
updateGist: PropTypes.func.isRequired,
config: PropTypes.object.isRequired,
raiseEvent: PropTypes.func.isRequired,
Pattern: PropTypes.func.isRequired,
units: PropTypes.oneOf(['metric', 'imperial'])
}
DraftPattern.defaultProps = {
units: 'metric',
pointInfo: null
}
export default DraftPattern export default DraftPattern

View file

@ -1,31 +1,30 @@
import React from "react"; import React from 'react'
import PropTypes from "prop-types"; import Button from '@material-ui/core/Button'
import Button from "@material-ui/core/Button"; import { FormattedMessage, FormattedHTMLMessage } from 'react-intl'
import { FormattedMessage, FormattedHTMLMessage } from "react-intl"; import FormFieldMeasurement from '../../.form/FormFieldMeasurement'
import FormFieldMeasurement from "../../.form/FormFieldMeasurement"; import { withBreasts, withoutBreasts } from '@freesewing/models'
import { withBreasts, withoutBreasts } from "@freesewing/models";
const Measurements = props => { const Measurements = (props) => {
const styles = { const styles = {
container: { container: {
display: "flex", display: 'flex',
flexDirection: "row", flexDirection: 'row',
width: "100%", width: '100%',
minHeight: "70vh" minHeight: '70vh'
}, },
chooser: { chooser: {
width: "100%", width: '100%',
maxWidth: "500px", maxWidth: '500px',
margin: "auto", margin: 'auto',
alignSelf: "center" alignSelf: 'center'
}
} }
};
const getValue = m => { const getValue = (m) => {
if (props.measurements === null) return ""; if (props.measurements === null) return ''
if (typeof props.measurements[m] === "undefined") return ""; if (typeof props.measurements[m] === 'undefined') return ''
return props.measurements[m]; return props.measurements[m]
}; }
if (props.required.length < 1) if (props.required.length < 1)
return ( return (
@ -43,18 +42,14 @@ const Measurements = props => {
<p> <p>
<FormattedMessage id="cfp.seeDocsAt" /> <FormattedMessage id="cfp.seeDocsAt" />
&nbsp; &nbsp;
<a <a href={'https://' + props.language + '/.freesewing.dev/core/config'}>
href={
"https://" + props.language + "/.freesewing.dev/core/config"
}
>
{props.language} {props.language}
.freesewing.dev/core/config .freesewing.dev/core/config
</a> </a>
</p> </p>
</div> </div>
</div> </div>
); )
return ( return (
<div style={styles.container}> <div style={styles.container}>
<div style={styles.chooser}> <div style={styles.chooser}>
@ -79,13 +74,13 @@ const Measurements = props => {
<h3 id="manual"> <h3 id="manual">
<FormattedMessage id="cfp.enterMeasurements" /> <FormattedMessage id="cfp.enterMeasurements" />
</h3> </h3>
{props.required.map(m => ( {props.required.map((m) => (
<FormFieldMeasurement <FormFieldMeasurement
key={m} key={m}
name={m} name={m}
units={props.units} units={props.units}
value={getValue(m)} value={getValue(m)}
label={"measurements." + m} label={'measurements.' + m}
updateValue={props.updateMeasurement} updateValue={props.updateMeasurement}
/> />
))} ))}
@ -96,11 +91,9 @@ const Measurements = props => {
<FormattedMessage id="app.withoutBreasts" /> <FormattedMessage id="app.withoutBreasts" />
</h4> </h4>
<ul> <ul>
{Object.keys(withoutBreasts).map(m => ( {Object.keys(withoutBreasts).map((m) => (
<li key={m}> <li key={m}>
<Button <Button onClick={() => props.preloadMeasurements(withoutBreasts[m])}>
onClick={() => props.preloadMeasurements(withoutBreasts[m])}
>
<FormattedMessage id="cfp.size" /> <FormattedMessage id="cfp.size" />
&nbsp; &nbsp;
{m.slice(-2)} {m.slice(-2)}
@ -112,7 +105,7 @@ const Measurements = props => {
<FormattedMessage id="app.withBreasts" /> <FormattedMessage id="app.withBreasts" />
</h4> </h4>
<ul> <ul>
{Object.keys(withBreasts).map(m => ( {Object.keys(withBreasts).map((m) => (
<li key={m}> <li key={m}>
<Button onClick={() => props.preloadMeasurements(withBreasts[m])}> <Button onClick={() => props.preloadMeasurements(withBreasts[m])}>
<FormattedMessage id="cfp.size" /> <FormattedMessage id="cfp.size" />
@ -124,15 +117,7 @@ const Measurements = props => {
</ul> </ul>
</div> </div>
</div> </div>
); )
}; }
Measurements.propTypes = { export default Measurements
measurements: PropTypes.object.isRequired,
required: PropTypes.array.isRequired,
units: PropTypes.oneOf(["metric", "imperial"]),
updateMeasurement: PropTypes.func.isRequired,
preloadMeasurements: PropTypes.func.isRequired
};
export default Measurements;

View file

@ -1,5 +1,4 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types'
import SampleConfigurator from '../../SampleConfigurator' import SampleConfigurator from '../../SampleConfigurator'
import svgattrPlugin from '@freesewing/plugin-svgattr' import svgattrPlugin from '@freesewing/plugin-svgattr'
import { FormattedMessage } from 'react-intl' import { FormattedMessage } from 'react-intl'
@ -35,7 +34,7 @@ const SamplePattern = (props) => {
updateGist={props.updateGist} updateGist={props.updateGist}
raiseEvent={props.raiseEvent} raiseEvent={props.raiseEvent}
freesewing={props.freesewing} freesewing={props.freesewing}
units={props.units} units={props.units || 'metric'}
/> />
</div> </div>
</aside> </aside>
@ -43,18 +42,4 @@ const SamplePattern = (props) => {
) )
} }
SamplePattern.propTypes = {
gist: PropTypes.object.isRequired,
updateGist: PropTypes.func.isRequired,
config: PropTypes.object.isRequired,
raiseEvent: PropTypes.func.isRequired,
Pattern: PropTypes.func.isRequired,
units: PropTypes.oneOf(['metric', 'imperial'])
}
SamplePattern.defaultProps = {
units: 'metric',
pointInfo: null
}
export default SamplePattern export default SamplePattern

View file

@ -1,30 +0,0 @@
import React from "react";
import PropTypes from "prop-types";
import Logo from "../../Logo";
import FormattedMessage from "react-intl";
import Button from "@material-ui/core/Button";
const Welcome = props => {
const style = {
textAlign: "center"
}
return (
<div className="fs-sa">
<section style={{style}}>
<div><Logo size={250} /></div>
<h1><FormattedMessage id="app.welcome" /></h1>
<p><FormattedMessage id="cfp.devDocsAvailableAt" /> <a href="https://freesewing.dev/">freesewing.dev</a></p>
<p><FormattedMessage id="cfp.talkToUs" />: <a href="https://gitter.im/freesewing/freesewing/">gitter.im/freesewing</a></p>
<Button
variant="outlined"
size="large"
onClick={() => props.setDisplay('pattern')}
><FormattedMessage id="app.docs" /></Button>
</section>
</div>
);
};
export default Welcome;

View file

@ -43,7 +43,6 @@ const Zoombox = (props) => {
setPanning(false) setPanning(false)
setPanFrom(false) setPanFrom(false)
updateViewBox(evt) updateViewBox(evt)
//props.setViewBox(`${from[0] * factor} ${from[1] * factor} ${to[0] * factor} ${to[1] * factor}`)
} }
} }
const handlePan = (evt) => { const handlePan = (evt) => {
@ -55,9 +54,9 @@ const Zoombox = (props) => {
// Bump into left // Bump into left
} else if (from[1] + (evt.clientY - panFrom[1]) <= -5) { } else if (from[1] + (evt.clientY - panFrom[1]) <= -5) {
// Bump into top // Bump into top
} else if (to[0] + (evt.clientX - panFrom[0]) >= box.width - 11) { } else if (to[0] + (evt.clientX - panFrom[0]) >= box.width + 5) {
// Bump into right // Bump into right
} else if (to[1] + (evt.clientY - panFrom[1]) >= box.height - 11) { } else if (to[1] + (evt.clientY - panFrom[1]) >= box.height + 5) {
// Bump into bottom // Bump into bottom
} else { } else {
setPanFrom([evt.clientX, evt.clientY]) setPanFrom([evt.clientX, evt.clientY])
@ -78,7 +77,12 @@ const Zoombox = (props) => {
if (dragging == 2) { if (dragging == 2) {
updateViewBox(evt) updateViewBox(evt)
if (falseAlarm) setFalseAlarm(false) if (falseAlarm) setFalseAlarm(false)
} else setFalseAlarm(true) } else {
setFalseAlarm(true)
let box = ref.current.getBoundingClientRect()
setBox(box)
setFactor(props.patternProps.width / box.width)
}
setDragging(false) setDragging(false)
setPanning(false) setPanning(false)
evt.stopPropagation() evt.stopPropagation()
@ -93,20 +97,15 @@ const Zoombox = (props) => {
setTo([evt.clientX - box.x, evt.clientY - box.y]) setTo([evt.clientX - box.x, evt.clientY - box.y])
} }
} }
const handleMouseOver = (evt) => {
evt.stopPropagation()
evt.preventDefault()
setFactor(props.patternProps.width / box.width)
}
const updateViewBox = (evt) => { const updateViewBox = (evt) => {
props.setViewBox( props.setViewBox(
from[0] * factor + from[0] * factor +
' ' + ' ' +
from[1] * factor + from[1] * factor +
' ' + ' ' +
(evt.clientX - box.x - from[0]) * factor + (to[0] - from[0]) * factor +
' ' + ' ' +
(evt.clientY - box.y - from[1]) * factor (to[1] - from[1]) * factor
) )
} }
@ -115,7 +114,6 @@ const Zoombox = (props) => {
<div <div
onMouseDown={handleMouseDown} onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp} onMouseUp={handleMouseUp}
onMouseOver={handleMouseOver}
onMouseMove={handleMouseMove} onMouseMove={handleMouseMove}
className="zoombox" className="zoombox"
ref={ref} ref={ref}

View file

@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import PropTypes from 'prop-types'
import withGist from '../withGist' import withGist from '../withGist'
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles' import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles'
import Navbar from '../Navbar' import Navbar from '../Navbar'
@ -17,7 +16,18 @@ import Welcome from './Welcome'
import Footer from '../Footer' import Footer from '../Footer'
import Measurements from './Measurements' import Measurements from './Measurements'
const Workbench = (props) => { const Workbench = ({
updateGist,
setLanguage,
userLanguage = 'en',
language = 'en',
gist,
importGist,
config,
freesewing,
Pattern,
units = 'metric'
}) => {
const [display, setDisplay] = useState(null) const [display, setDisplay] = useState(null)
const [pattern, setPattern] = useState(false) const [pattern, setPattern] = useState(false)
const [theme, setTheme] = useState('light') const [theme, setTheme] = useState('light')
@ -27,27 +37,23 @@ const Workbench = (props) => {
useEffect(() => { useEffect(() => {
let m = getMeasurements() let m = getMeasurements()
setMeasurements(m) setMeasurements(m)
props.updateGist(m, 'settings', 'measurements') updateGist(m, 'settings', 'measurements')
setDisplay(getDisplay()) setDisplay(getDisplay())
props.setLanguage(props.userLanguage || 'en') setLanguage(userLanguage)
}, []) }, [])
useEffect(() => { useEffect(() => {
if (props.from) props.importGist(props.from) if (language !== gist.settings.locale) updateGist(language, 'settings', 'locale')
}, [props.from]) }, [language])
useEffect(() => {
if (props.language !== props.gist.settings.locale)
props.updateGist(props.language, 'settings', 'locale')
}, [props.language])
const getDisplay = () => storage.get(props.config.name + '-display') const getDisplay = () => storage.get(config.name + '-display')
const saveDisplay = (d) => { const saveDisplay = (d) => {
setDisplay(d) setDisplay(d)
storage.set(props.config.name + '-display', d) storage.set(config.name + '-display', d)
} }
const getMeasurements = () => storage.get(props.config.name + '-measurements') const getMeasurements = () => storage.get(config.name + '-measurements')
const saveMeasurements = (data) => { const saveMeasurements = (data) => {
storage.set(props.config.name + '-measurements', data) storage.set(config.name + '-measurements', data)
props.updateGist(data, 'settings', 'measurements') updateGist(data, 'settings', 'measurements')
} }
const updateMeasurement = (name, val) => { const updateMeasurement = (name, val) => {
let updatedMeasurements = { ...measurements } let updatedMeasurements = { ...measurements }
@ -64,7 +70,7 @@ const Workbench = (props) => {
saveMeasurements(updatedMeasurements) saveMeasurements(updatedMeasurements)
} }
const measurementsMissing = () => { const measurementsMissing = () => {
let required = props.config.measurements let required = config.measurements
if (required.length < 1) return false if (required.length < 1) return false
if (measurements === null) return true if (measurements === null) return true
for (let m of required) { for (let m of required) {
@ -110,7 +116,7 @@ const Workbench = (props) => {
version: { version: {
type: 'link', type: 'link',
href: 'https://github.com/freesewing/freesewing/releases', href: 'https://github.com/freesewing/freesewing/releases',
text: 'v' + props.freesewing.version text: 'v' + freesewing.version
}, },
language: { language: {
type: 'button', type: 'button',
@ -140,19 +146,19 @@ const Workbench = (props) => {
let main = null let main = null
switch (display) { switch (display) {
case 'languages': case 'languages':
main = <LanguageChooser setLanguage={props.setLanguage} setDisplay={saveDisplay} /> main = <LanguageChooser setLanguage={setLanguage} setDisplay={saveDisplay} />
break break
case 'draft': case 'draft':
if (measurementsMissing()) saveDisplay('measurements') if (measurementsMissing()) saveDisplay('measurements')
main = ( main = (
<DraftPattern <DraftPattern
freesewing={props.freesewing} freesewing={freesewing}
Pattern={props.Pattern} Pattern={Pattern}
config={props.config} config={config}
gist={props.gist} gist={gist}
updateGist={props.updateGist} updateGist={updateGist}
raiseEvent={raiseEvent} raiseEvent={raiseEvent}
units={props.units} units={units}
svgExport={svgExport} svgExport={svgExport}
setSvgExport={setSvgExport} setSvgExport={setSvgExport}
theme={theme} theme={theme}
@ -163,13 +169,13 @@ const Workbench = (props) => {
if (measurementsMissing()) saveDisplay('measurements') if (measurementsMissing()) saveDisplay('measurements')
main = ( main = (
<SamplePattern <SamplePattern
freesewing={props.freesewing} freesewing={freesewing}
Pattern={props.Pattern} Pattern={Pattern}
config={props.config} config={config}
gist={props.gist} gist={gist}
updateGist={props.updateGist} updateGist={updateGist}
raiseEvent={raiseEvent} raiseEvent={raiseEvent}
units={props.units} units={units}
/> />
) )
break break
@ -177,59 +183,49 @@ const Workbench = (props) => {
main = ( main = (
<Measurements <Measurements
measurements={measurements} measurements={measurements}
required={props.config.measurements} required={config.measurements}
units={props.units} units={units}
updateMeasurement={updateMeasurement} updateMeasurement={updateMeasurement}
preloadMeasurements={preloadMeasurements} preloadMeasurements={preloadMeasurements}
language={props.language} language={language}
/> />
) )
break break
case 'json': case 'json':
main = <Json gist={props.gist} /> main = <Json gist={gist} />
break break
case 'inspect': case 'inspect':
main = ( main = (
<InspectPattern <InspectPattern
freesewing={props.freesewing} freesewing={freesewing}
Pattern={props.Pattern} Pattern={Pattern}
config={props.config} config={config}
gist={props.gist} gist={gist}
updateGist={props.updateGist} updateGist={updateGist}
raiseEvent={raiseEvent} raiseEvent={raiseEvent}
units={props.units} units={units}
svgExport={svgExport} svgExport={svgExport}
setSvgExport={setSvgExport} setSvgExport={setSvgExport}
/> />
) )
break break
default: default:
main = <Welcome language={props.language} setDisplay={saveDisplay} /> main = <Welcome language={language} setDisplay={saveDisplay} />
} }
const themes = { dark, light } const themes = { dark, light }
return ( return (
<MuiThemeProvider theme={createMuiTheme(themes[theme])}> <MuiThemeProvider theme={createMuiTheme(themes[theme])}>
<div className={theme === 'light' ? 'theme-wrapper light' : 'theme-wrapper dark'}> <div className={theme === 'light' ? 'theme-wrapper light' : 'theme-wrapper dark'}>
{display !== 'welcome' ? <Navbar navs={navs} home={() => saveDisplay('welcome')} /> : null} {display !== 'welcome' ? <Navbar navs={navs} home={() => saveDisplay('welcome')} /> : null}
{main} {main}
{display !== 'welcome' ? <Footer language={props.language} /> : null} {display !== 'welcome' ? <Footer language={language} /> : null}
</div> </div>
</MuiThemeProvider> </MuiThemeProvider>
) )
} }
Workbench.propTypes = {
freesewing: PropTypes.object.isRequired,
Pattern: PropTypes.func.isRequired,
config: PropTypes.object.isRequired,
from: PropTypes.object
}
Workbench.defaultProps = {
from: { settings: { embed: true } }
}
export default withLanguage( export default withLanguage(
withGist(Workbench, { withGist(Workbench, {
gist: defaultGist, gist: defaultGist,