🚧 Added sampling to workbench
This commit is contained in:
parent
3754680841
commit
c2628a0a52
19 changed files with 463 additions and 33 deletions
|
@ -0,0 +1,51 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { optionType } from "@freesewing/utils";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { injectIntl } from "react-intl";
|
||||
|
||||
const OptionGroup = props => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
{props.options.map(name => {
|
||||
let key = name;
|
||||
let output = [];
|
||||
if (typeof name === "object") {
|
||||
key = Object.keys(name).pop();
|
||||
// Subgroup
|
||||
for (let subGroup of Object.keys(name)) {
|
||||
output.push(
|
||||
<h5 key={subGroup + "-title"} className="subheading">
|
||||
<FormattedMessage id={"optiongroups." + subGroup} />
|
||||
</h5>
|
||||
);
|
||||
let children = [];
|
||||
for (let option of name[subGroup]) children.push(<p>{option}</p>);
|
||||
output.push(<ul style={{ paddingLeft: "1rem" }}>{children}</ul>);
|
||||
}
|
||||
} else
|
||||
output.push(
|
||||
<li>
|
||||
<a href="#logo" onClick={() => props.sampleOption(name)}>
|
||||
<FormattedMessage
|
||||
id={"options." + props.config.name + "." + name + ".title"}
|
||||
/>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
|
||||
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);
|
|
@ -0,0 +1,40 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import OptionGroup from ".";
|
||||
|
||||
const options = {
|
||||
armholeDrop: { pct: 10, min: 1, max: 75 },
|
||||
backlineBend: { pct: 50, min: 50, max: 100 },
|
||||
chestEase: { pct: 8, min: 0, max: 20 },
|
||||
hipsEase: { pct: 8, min: 0, max: 20 },
|
||||
lengthBonus: { pct: 10, min: -20, max: 60 },
|
||||
necklineBend: { pct: 100, min: 40, max: 100 },
|
||||
necklineDrop: { pct: 20, min: 10, max: 35 },
|
||||
stretchFactor: { pct: 5, min: 0, max: 15 },
|
||||
shoulderStrapWidth: { pct: 15, min: 10, max: 40 },
|
||||
shoulderStrapPlacement: { pct: 40, min: 20, max: 80 }
|
||||
};
|
||||
|
||||
const props = {
|
||||
raiseEvent: (type, data) =>
|
||||
console.log(`Action of type ${type} triggered, data passed is`, data),
|
||||
updateValue: (type, data) =>
|
||||
console.log(`Update ${type} with new value`, data),
|
||||
gist: {
|
||||
settings: {
|
||||
options: {}
|
||||
}
|
||||
},
|
||||
pattern: {
|
||||
config: {
|
||||
name: "aaron",
|
||||
options: options
|
||||
}
|
||||
},
|
||||
dflts: { options: {} },
|
||||
options: Object.keys(options)
|
||||
};
|
||||
|
||||
storiesOf("Low level/OptionGroup", module).add("Simon metric", () => (
|
||||
<OptionGroup pattern="simon" {...props} units="metric" />
|
||||
));
|
|
@ -0,0 +1,49 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import OptionGroup from "../OptionGroup";
|
||||
import { optionType } from "@freesewing/utils";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import DownIcon from "@material-ui/icons/KeyboardArrowDown";
|
||||
|
||||
const PatternOptions = props => {
|
||||
const renderGroup = group => {
|
||||
let output = [];
|
||||
let children = (
|
||||
<ul className="links">
|
||||
<OptionGroup
|
||||
key={group + "-group"}
|
||||
units={props.units}
|
||||
config={props.config}
|
||||
options={props.config.optionGroups[group]}
|
||||
sampleOption={props.sampleOption}
|
||||
/>
|
||||
</ul>
|
||||
);
|
||||
output.push(
|
||||
<li key={group + "-ghead"} className="nodot">
|
||||
<h3>
|
||||
<FormattedMessage id={"optiongroups." + group} />
|
||||
</h3>
|
||||
{children}
|
||||
</li>
|
||||
);
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
return (
|
||||
<ul className="links">
|
||||
{Object.keys(props.config.optionGroups).map(group => renderGroup(group))}
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
PatternOptions.propTypes = {
|
||||
config: PropTypes.object.isRequired,
|
||||
gist: PropTypes.object.isRequired,
|
||||
sampleOption: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
PatternOptions.defaultProps = {};
|
||||
|
||||
export default PatternOptions;
|
|
@ -0,0 +1,28 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import PatternOptions from ".";
|
||||
|
||||
const props = {
|
||||
raiseEvent: (type, data) =>
|
||||
console.log(`Action of type ${type} triggered, data passed is`, data),
|
||||
updateValue: (type, data) =>
|
||||
console.log(`Update ${type} with new value`, data),
|
||||
gist: {
|
||||
settings: {
|
||||
options: {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
storiesOf("Low level/PatternOptions", module)
|
||||
.add("Simon metric", () => (
|
||||
<PatternOptions pattern="simon" gist={false} units="metric" {...props} />
|
||||
))
|
||||
.add("Trayvon imperial", () => (
|
||||
<PatternOptions
|
||||
pattern="trayvon"
|
||||
gist={false}
|
||||
units="imperial"
|
||||
{...props}
|
||||
/>
|
||||
));
|
109
packages/components/src/SampleConfigurator/index.js
Normal file
109
packages/components/src/SampleConfigurator/index.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
import React, { useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import PatternOptions from "./PatternOptions";
|
||||
import models from "@freesewing/models";
|
||||
|
||||
const SampleConfigurator = props => {
|
||||
const [expanded, setExpanded] = useState([]);
|
||||
|
||||
const toggleGroup = group => {
|
||||
let shown = expanded.slice(0);
|
||||
let index = shown.indexOf(group);
|
||||
if (index === -1) shown.push(group);
|
||||
else shown.splice(index, 1);
|
||||
setExpanded(shown);
|
||||
};
|
||||
|
||||
const sampleOption = option => {
|
||||
props.updateGist(
|
||||
{
|
||||
type: "option",
|
||||
option
|
||||
},
|
||||
"settings",
|
||||
"sample"
|
||||
);
|
||||
};
|
||||
|
||||
const sampleMeasurement = measurement => {
|
||||
props.updateGist(
|
||||
{
|
||||
type: "measurement",
|
||||
measurement
|
||||
},
|
||||
"settings",
|
||||
"sample"
|
||||
);
|
||||
};
|
||||
|
||||
const sampleModels = models => {
|
||||
props.updateGist(
|
||||
{
|
||||
type: "models",
|
||||
models
|
||||
},
|
||||
"settings",
|
||||
"sample"
|
||||
);
|
||||
};
|
||||
let antMan = {
|
||||
ant: {},
|
||||
man: models.manSize42
|
||||
};
|
||||
for (let m in models.manSize42) antMan.ant[m] = antMan.man[m] / 10;
|
||||
|
||||
return (
|
||||
<ul className="links">
|
||||
<li className="nodot">
|
||||
<h2>
|
||||
<FormattedMessage id="app.patternOptions" />
|
||||
</h2>
|
||||
<PatternOptions
|
||||
config={props.config}
|
||||
gist={props.gist}
|
||||
sampleOption={sampleOption}
|
||||
/>
|
||||
</li>
|
||||
<li className="nodot">
|
||||
<h2>
|
||||
<FormattedMessage id="app.measurements" />
|
||||
</h2>
|
||||
<ul style={{ paddingLeft: "1rem" }}>
|
||||
{props.config.measurements.map(m => (
|
||||
<li key={m}>
|
||||
<a href="#logo" onClick={() => sampleMeasurement(m)}>
|
||||
<FormattedMessage id={"measurements." + m} />
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</li>
|
||||
<li className="nodot">
|
||||
<h2>
|
||||
<FormattedMessage id="app.models" />
|
||||
</h2>
|
||||
<ul style={{ paddingLeft: "1rem" }}>
|
||||
<li>
|
||||
<a href="#logo" onClick={() => sampleModels(models)}>
|
||||
<FormattedMessage id="app.withoutBreasts" />
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#logo" onClick={() => sampleModels(antMan)}>
|
||||
Antman
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
);
|
||||
};
|
||||
|
||||
SampleConfigurator.propTypes = {
|
||||
units: PropTypes.oneOf(["metric", "imperial"]).isRequired
|
||||
};
|
||||
|
||||
SampleConfigurator.defaultProps = {};
|
||||
|
||||
export default SampleConfigurator;
|
20
packages/components/src/SampleConfigurator/stories.js
Normal file
20
packages/components/src/SampleConfigurator/stories.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
import React from "react";
|
||||
import { storiesOf } from "@storybook/react";
|
||||
import GistConfigurator from ".";
|
||||
//import { IntlProvider } from "react-intl";
|
||||
//import { strings } from "@freesewing/i18n";
|
||||
|
||||
const props = {
|
||||
raiseEvent: (type, data) =>
|
||||
console.log(`Action of type ${type} triggered, data passed is`, data),
|
||||
updateValue: (type, data) =>
|
||||
console.log(`Update ${type} with new value`, data)
|
||||
};
|
||||
|
||||
storiesOf("DraftConfigurator", module)
|
||||
.add("Simon metric", () => (
|
||||
<GistConfigurator pattern="simon" {...props} units="metric" />
|
||||
))
|
||||
.add("Trayvon imperial", () => (
|
||||
<GistConfigurator pattern="trayvon" {...props} units="imperial" />
|
||||
));
|
|
@ -3,21 +3,12 @@ import PropTypes from "prop-types";
|
|||
import { defaultGist } from "@freesewing/utils";
|
||||
import Draft from "../../Draft";
|
||||
import DraftConfigurator from "../../DraftConfigurator";
|
||||
//import themePlugin from "@freesewing/plugin-theme";
|
||||
//import svgattrPlugin from "@freesewing/plugin-svgattr";
|
||||
//import i18nPlugin from "@freesewing/plugin-i18n";
|
||||
//import validatePlugin from "@freesewing/plugin-validate";
|
||||
import { strings } from "@freesewing/i18n";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
const DraftPattern = props => {
|
||||
let pattern = new props.Pattern(props.gist.settings);
|
||||
pattern.draft();
|
||||
//.use(themePlugin)
|
||||
//.use(svgattrPlugin, { class: "freesewing draft" })
|
||||
//.use(i18nPlugin, { strings: strings })
|
||||
//.use(validatePlugin)
|
||||
//<pre>{pattern.render()}</pre>
|
||||
return (
|
||||
<div className="fs-sa">
|
||||
<section>
|
||||
|
|
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
|||
import PropTypes from "prop-types";
|
||||
import { storage } from "@freesewing/utils";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { FormattedMessage, FormattedHTMLMessage } from "react-intl";
|
||||
import FormFieldMeasurement from "../../.form/FormFieldMeasurement";
|
||||
import models from "@freesewing/models";
|
||||
|
||||
|
@ -11,7 +11,8 @@ const Measurements = props => {
|
|||
container: {
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
width: "100%"
|
||||
width: "100%",
|
||||
minHeight: "70vh"
|
||||
},
|
||||
chooser: {
|
||||
width: "100%",
|
||||
|
@ -27,6 +28,33 @@ const Measurements = props => {
|
|||
return props.measurements[m];
|
||||
};
|
||||
|
||||
if (props.required.length < 1)
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<div style={styles.chooser}>
|
||||
<h2>
|
||||
<FormattedMessage id="app.requiredMeasurements" />
|
||||
</h2>
|
||||
<h3>
|
||||
<FormattedMessage id="cfp.noRequiredMeasurements" />
|
||||
</h3>
|
||||
<p>
|
||||
<FormattedHTMLMessage id="cfp.howtoAddMeasurements" />
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage id="cfp.seeDocsAt" />
|
||||
|
||||
<a
|
||||
href={
|
||||
"https://" + props.language + "/.freesewing.dev/core/config"
|
||||
}
|
||||
>
|
||||
{props.language}.freesewing.dev/core/config
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div style={styles.container}>
|
||||
<div style={styles.chooser}>
|
||||
|
|
60
packages/components/src/Workbench/SamplePattern/index.js
Normal file
60
packages/components/src/Workbench/SamplePattern/index.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { defaultGist } from "@freesewing/utils";
|
||||
import Draft from "../../Draft";
|
||||
import SampleConfigurator from "../../SampleConfigurator";
|
||||
import svgattrPlugin from "@freesewing/plugin-svgattr";
|
||||
import { strings } from "@freesewing/i18n";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
const SamplePattern = props => {
|
||||
let pattern = new props.Pattern(props.gist.settings).use(svgattrPlugin, {
|
||||
class: "freesewing draft"
|
||||
});
|
||||
try {
|
||||
pattern.sample();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
return (
|
||||
<div className="fs-sa">
|
||||
<section>
|
||||
<h2>
|
||||
<FormattedMessage id="app.pattern" />
|
||||
</h2>
|
||||
<div dangerouslySetInnerHTML={{ __html: pattern.render() }} />
|
||||
<h2>gist</h2>
|
||||
<pre>{JSON.stringify(props.gist, null, 2)}</pre>
|
||||
</section>
|
||||
|
||||
<aside>
|
||||
<div className="sticky">
|
||||
<SampleConfigurator
|
||||
config={props.config}
|
||||
gist={props.gist}
|
||||
updateGist={props.updateGist}
|
||||
raiseEvent={props.raiseEvent}
|
||||
freesewing={props.freesewing}
|
||||
units={props.units}
|
||||
/>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
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;
|
|
@ -14,12 +14,13 @@ import LanguageIcon from "@material-ui/icons/Translate";
|
|||
import DarkModeIcon from "@material-ui/icons/Brightness3";
|
||||
import LanguageChooser from "./LanguageChooser";
|
||||
import DraftPattern from "./DraftPattern";
|
||||
import SamplePattern from "./SamplePattern";
|
||||
import Welcome from "./Welcome";
|
||||
import Footer from "../Footer";
|
||||
import Measurements from "./Measurements";
|
||||
|
||||
const Workbench = props => {
|
||||
const [display, setDisplay] = useState("welcome");
|
||||
const [display, setDisplay] = useState(null);
|
||||
const [pattern, setPattern] = useState(false);
|
||||
const [theme, setTheme] = useState("light");
|
||||
const [measurements, setMeasurements] = useState(null);
|
||||
|
@ -27,6 +28,7 @@ const Workbench = props => {
|
|||
let m = getMeasurements();
|
||||
setMeasurements(m);
|
||||
props.updateGist(m, "settings", "measurements");
|
||||
setDisplay(getDisplay());
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (props.from) props.importGist(props.from);
|
||||
|
@ -36,6 +38,11 @@ const Workbench = props => {
|
|||
props.updateGist(props.language, "settings", "locale");
|
||||
}, [props.language]);
|
||||
|
||||
const getDisplay = () => storage.get(props.config.name + "-display");
|
||||
const saveDisplay = d => {
|
||||
setDisplay(d);
|
||||
storage.set(props.config.name + "-display", d);
|
||||
};
|
||||
const getMeasurements = () =>
|
||||
storage.get(props.config.name + "-measurements");
|
||||
const saveMeasurements = data => {
|
||||
|
@ -66,7 +73,7 @@ const Workbench = props => {
|
|||
|
||||
return false;
|
||||
};
|
||||
const showLanguageChooser = () => setDisplay("language");
|
||||
const showLanguageChooser = () => saveDisplay("language");
|
||||
const updatePattern = p => {
|
||||
setPattern(p);
|
||||
store.set("pattern", p);
|
||||
|
@ -83,19 +90,19 @@ const Workbench = props => {
|
|||
left: {
|
||||
draft: {
|
||||
type: "button",
|
||||
onClick: () => setDisplay("draft"),
|
||||
onClick: () => saveDisplay("draft"),
|
||||
text: "cfp.draftYourPattern",
|
||||
active: display === "draft" ? true : false
|
||||
},
|
||||
sample: {
|
||||
type: "button",
|
||||
onClick: () => setDisplay("sample"),
|
||||
onClick: () => saveDisplay("sample"),
|
||||
text: "cfp.testYourPattern",
|
||||
active: display === "sample" ? true : false
|
||||
},
|
||||
measurements: {
|
||||
type: "button",
|
||||
onClick: () => setDisplay("measurements"),
|
||||
onClick: () => saveDisplay("measurements"),
|
||||
text: "app.measurements",
|
||||
active: display === "measurements" ? true : false
|
||||
}
|
||||
|
@ -108,7 +115,7 @@ const Workbench = props => {
|
|||
},
|
||||
language: {
|
||||
type: "button",
|
||||
onClick: () => setDisplay("languages"),
|
||||
onClick: () => saveDisplay("languages"),
|
||||
text: <LanguageIcon className="nav-icon" />,
|
||||
title: "Languages",
|
||||
active: display === "languages" ? true : false
|
||||
|
@ -128,12 +135,12 @@ const Workbench = props => {
|
|||
main = (
|
||||
<LanguageChooser
|
||||
setLanguage={props.setLanguage}
|
||||
setDisplay={setDisplay}
|
||||
setDisplay={saveDisplay}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "draft":
|
||||
if (measurementsMissing()) setDisplay("measurements");
|
||||
if (measurementsMissing()) saveDisplay("measurements");
|
||||
main = (
|
||||
<DraftPattern
|
||||
freesewing={props.freesewing}
|
||||
|
@ -147,8 +154,18 @@ const Workbench = props => {
|
|||
);
|
||||
break;
|
||||
case "sample":
|
||||
if (measurementsMissing()) setDisplay("measurements");
|
||||
main = <p>Sample: TODO</p>;
|
||||
if (measurementsMissing()) saveDisplay("measurements");
|
||||
main = (
|
||||
<SamplePattern
|
||||
freesewing={props.freesewing}
|
||||
Pattern={props.Pattern}
|
||||
config={props.config}
|
||||
gist={props.gist}
|
||||
updateGist={props.updateGist}
|
||||
raiseEvent={raiseEvent}
|
||||
units={props.units}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case "measurements":
|
||||
main = (
|
||||
|
@ -158,11 +175,12 @@ const Workbench = props => {
|
|||
units={props.units}
|
||||
updateMeasurement={updateMeasurement}
|
||||
preloadMeasurements={preloadMeasurements}
|
||||
language={props.language}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
main = <Welcome language={props.language} setDisplay={setDisplay} />;
|
||||
main = <Welcome language={props.language} setDisplay={saveDisplay} />;
|
||||
}
|
||||
|
||||
const themes = { dark, light };
|
||||
|
@ -175,7 +193,7 @@ const Workbench = props => {
|
|||
}
|
||||
>
|
||||
{display !== "welcome" ? (
|
||||
<Navbar navs={navs} home={() => setDisplay("welcome")} />
|
||||
<Navbar navs={navs} home={() => saveDisplay("welcome")} />
|
||||
) : null}
|
||||
{main}
|
||||
{display !== "welcome" ? <Footer language={props.language} /> : null}
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
@import "elements/a";
|
||||
@import "elements/footer";
|
||||
@import "elements/ul";
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
ul.nav { padding-left: 0;}
|
||||
ul.nav.l1 { overflow-x: hidden;}
|
||||
ul.nav.l1,
|
||||
ul.nav.l2,
|
||||
ul.nav.l3,
|
||||
ul.nav.l4 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@include title-font;
|
||||
}
|
||||
|
||||
ul.nav li {list-style-type: none;}
|
||||
|
@ -15,21 +14,17 @@ ul.nav h2,
|
|||
ul.nav h3,
|
||||
ul.nav h4,
|
||||
ul.nav h5 {
|
||||
font-weight: normal;
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0.5rem 0.25rem;
|
||||
padding: 0.5rem 0.25rem 0.5rem 1rem;
|
||||
}
|
||||
ul.nav h3:hover,
|
||||
ul.nav h4:hover {
|
||||
cursor: pointer;
|
||||
background: $oc-gray-3;
|
||||
}
|
||||
ul.nav h2 { font-size: 1.2rem; margin-left: 5px;}
|
||||
ul.nav h4 { font-size: 1rem; }
|
||||
ul.nav h5 { font-size: 1rem; padding-left: 1.5rem; font-weight: bold;}
|
||||
ul.nav h5 { padding-left: 1.5rem; }
|
||||
ul.nav h3 {
|
||||
font-size: 1.1rem;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background: $oc-gray-1;
|
||||
|
|
24
packages/css-theme/src/elements/_ul.scss
Normal file
24
packages/css-theme/src/elements/_ul.scss
Normal file
|
@ -0,0 +1,24 @@
|
|||
ul.links {
|
||||
padding-left: 1rem;
|
||||
li {
|
||||
list-style-type: none;
|
||||
}
|
||||
li:before {
|
||||
content: "\00a0";
|
||||
background: $oc-gray-5;
|
||||
border-radius: 3.5px;
|
||||
display: inline-block;
|
||||
height: 7px;
|
||||
width: 7px;
|
||||
padding: 0;
|
||||
margin: 0 0.5rem 0 0;
|
||||
font-size: 9px;
|
||||
transition: background 0.15s ease-in;
|
||||
}
|
||||
li.nodot:before {
|
||||
content: none;
|
||||
}
|
||||
li:hover:before {
|
||||
background: $fc-link-light;
|
||||
}
|
||||
}
|
|
@ -18,3 +18,7 @@ youCan: Sie können
|
|||
enterMeasurements: Geben Sie die Maße von Hand ein
|
||||
preloadMeasurements: Laden Sie eine Reihe von Messungen vor
|
||||
size: Größe
|
||||
noRequiredMeasurements: Dieses Muster hat keine erforderlichen Messungen.
|
||||
howtoAddMeasurements: Um Messungen anzufordern, fügen Sie sie dem <b>measurements</b> der Konfigurationsdatei des Musters hinzu.
|
||||
seeDocsAt: Dokumentation zu diesem Thema finden Sie unter
|
||||
|
||||
|
|
|
@ -17,3 +17,6 @@ youCan: You can
|
|||
enterMeasurements: Enter measurements by hand
|
||||
preloadMeasurements: Preload a set of measurements
|
||||
size: Size
|
||||
noRequiredMeasurements: This pattern has no required measurements
|
||||
howtoAddMeasurements: To require measurements, add them to the <b>measurements</b> section of the pattern's configuration file.
|
||||
seeDocsAt: Documentation on this topic is available at
|
||||
|
|
|
@ -18,3 +18,6 @@ youCan: Usted puede
|
|||
enterMeasurements: Introducir medidas a mano
|
||||
preloadMeasurements: Precargar un conjunto de medidas
|
||||
size: Tamaño
|
||||
noRequiredMeasurements: Este patrón no tiene medidas requeridas.
|
||||
howtoAddMeasurements: Para requerir mediciones, agréguelas a la sección de <b>measurements</b> del archivo de configuración del patrón.
|
||||
seeDocsAt: La documentación sobre este tema está disponible en
|
||||
|
|
|
@ -18,3 +18,6 @@ youCan: Vous pouvez
|
|||
enterMeasurements: Entrer les mesures à la main
|
||||
preloadMeasurements: Précharger un ensemble de mesures
|
||||
size: Taille
|
||||
noRequiredMeasurements: Ce patron n'a pas de mesures requises.
|
||||
howtoAddMeasurements: Pour exiger des mesures, ajoutez-les à la section <b>measurements</b> du fichier de configuration du patron.
|
||||
seeDocsAt: Documentation sur ce sujet est disponible à l'adresse
|
||||
|
|
|
@ -15,6 +15,9 @@ testYourPattern: Test je patroon
|
|||
renderInBrowser: Klik hieronder om uw patroon te renderen in de browser.
|
||||
weWillReRender: Telkens u wijzigingen aanbrengt renderen we opnieuw.
|
||||
youCan: Je kan
|
||||
enterMeasurements: Handmatig afmetingen invoeren
|
||||
preloadMeasurements: Een reeks afmetingen laden
|
||||
enterMeasurements: Handmatig lichaamsmaten invoeren
|
||||
preloadMeasurements: Een reeks lichaamsmaten laden
|
||||
size: Maat
|
||||
noRequiredMeasurements: Dit patroon vereist geen lichaamsmaten.
|
||||
howtoAddMeasurements: Om lichaamsmaten te vereisen, voegt u ze toe aan de <b>measurements</b> sectie van het configuratiebestand van het patroon.
|
||||
seeDocsAt: Documentatie over dit onderwerp is beschikbaar op
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue