feat(lab): Added language setting
This commit is contained in:
parent
91ddfd4580
commit
19f9be6a3c
7 changed files with 284 additions and 11 deletions
|
@ -141,6 +141,7 @@ function useApp(full = true) {
|
||||||
|
|
||||||
// Translation
|
// Translation
|
||||||
t,
|
t,
|
||||||
|
languages: Object.keys(strings),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
const defaultSettings = {
|
||||||
|
sa: 0,
|
||||||
|
complete: true,
|
||||||
|
paperless: false,
|
||||||
|
units: 'metric',
|
||||||
|
locale: 'en',
|
||||||
|
margin: 2,
|
||||||
|
debug: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defaultSettings
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
const CoreSettingList = props => {
|
||||||
|
const { dflt, list } = props
|
||||||
|
const val = props.gist?.settings?.[props.setting]
|
||||||
|
|
||||||
|
const [value, setValue] = useState(val)
|
||||||
|
|
||||||
|
const handleChange = (newVal) => {
|
||||||
|
if (newVal === dflt) reset()
|
||||||
|
else {
|
||||||
|
setValue(newVal)
|
||||||
|
props.updateGist(['settings', props.setting], newVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="py-4 mx-6 border-l-2 pl-2">
|
||||||
|
<p className="m-0 p-0 px-2 mb-2 text-neutral-content opacity-60 italic">
|
||||||
|
{props.app.t(`settings.${props.setting}.description`)}
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-row">
|
||||||
|
<div className="grow">
|
||||||
|
{props.list.map(entry => (
|
||||||
|
<button
|
||||||
|
key={entry.key}
|
||||||
|
onClick={() => handleChange(entry.key)}
|
||||||
|
className={`
|
||||||
|
mr-1 mb-1 text-left text-lg w-full hover:text-secondary-focus px-2
|
||||||
|
${entry.key === value && 'font-bold text-secondary'}
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
<span className={`
|
||||||
|
text-3xl mr-2 inline-block p-0 leading-3
|
||||||
|
translate-y-3
|
||||||
|
`}>
|
||||||
|
<>°</>
|
||||||
|
</span>
|
||||||
|
{entry.title}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CoreSettingList
|
|
@ -0,0 +1,39 @@
|
||||||
|
import SettingsIcon from 'shared/components/icons/settings.js'
|
||||||
|
import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
|
||||||
|
import Setting from './setting.js'
|
||||||
|
|
||||||
|
const settings = {
|
||||||
|
locale: {
|
||||||
|
dflt: 'en',
|
||||||
|
list: ['de', 'en', 'es', 'fr', 'nl'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const CoreSettings = props => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<details className='py-1' open>
|
||||||
|
<summary className={`
|
||||||
|
flex flex-row uppercase gap-4 font-bold text-lg
|
||||||
|
hover:cursor-row-resize
|
||||||
|
p-2
|
||||||
|
text-base-content
|
||||||
|
sm:text-neutral-content
|
||||||
|
items-center
|
||||||
|
`}>
|
||||||
|
<span className="text-secondary-focus mr-4"><SettingsIcon /></span>
|
||||||
|
<span className={`grow ${linkClasses}`}>
|
||||||
|
{props.app.t('app.settings')}
|
||||||
|
</span>
|
||||||
|
<Chevron />
|
||||||
|
</summary>
|
||||||
|
<ul className="pl-5 list-inside">
|
||||||
|
{Object.keys(settings).map(setting => (
|
||||||
|
<Setting key={setting} setting={setting} config={settings[setting]} {...props} />
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</details>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CoreSettings
|
|
@ -0,0 +1,169 @@
|
||||||
|
import { linkClasses, Chevron } from 'shared/components/navigation/primary.js'
|
||||||
|
import PctDegOption from 'shared/components/workbench/inputs/design-option-pct-deg'
|
||||||
|
import CountOption from 'shared/components/workbench/inputs/design-option-count'
|
||||||
|
import ListSetting from './core-setting-list'
|
||||||
|
import { formatMm, formatPercentage, optionType } from 'shared/utils.js'
|
||||||
|
|
||||||
|
const settings = {
|
||||||
|
locale: props => {
|
||||||
|
return (
|
||||||
|
<span className="text-secondary">
|
||||||
|
{props.app.t(`i18n.${props.gist.settings.locale}`)}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
pct: props => {
|
||||||
|
const val = (typeof props.gist?.options?.[props.option] === 'undefined')
|
||||||
|
? props.pattern.config.options[props.option].pct/100
|
||||||
|
: props.gist.options[props.option]
|
||||||
|
return (
|
||||||
|
<span className={
|
||||||
|
val=== props.pattern.config.options[props.option].pct/100
|
||||||
|
? 'text-secondary'
|
||||||
|
: 'text-accent'
|
||||||
|
}>
|
||||||
|
{formatPercentage(val)}
|
||||||
|
{props.pattern.config.options[props.option]?.toAbs
|
||||||
|
? ' | ' +formatMm(props.pattern.config.options[props.option]?.toAbs(val, props.gist))
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
bool: props => {
|
||||||
|
const dflt = props.pattern.config.options[props.option].bool
|
||||||
|
const current = props.gist?.options?.[props.option]
|
||||||
|
return (
|
||||||
|
<span className={
|
||||||
|
(dflt==current || typeof current === 'undefined')
|
||||||
|
? 'text-secondary'
|
||||||
|
: 'text-accent'
|
||||||
|
}>
|
||||||
|
{props.gist?.options?.[props.option]
|
||||||
|
? props.app.t('app.yes')
|
||||||
|
: props.app.t('app.no')
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
count: props => {
|
||||||
|
const dflt = props.pattern.config.options[props.option].count
|
||||||
|
const current = props.gist?.options?.[props.option]
|
||||||
|
return (dflt==current || typeof current === 'undefined')
|
||||||
|
? <span className="text-secondary">{dflt}</span>
|
||||||
|
: <span className="text-accent">{current}</span>
|
||||||
|
},
|
||||||
|
deg: props => {
|
||||||
|
const dflt = props.pattern.config.options[props.option].deg
|
||||||
|
const current = props.gist?.options?.[props.option]
|
||||||
|
return (dflt==current || typeof current === 'undefined')
|
||||||
|
? <span className="text-secondary">{dflt}°</span>
|
||||||
|
: <span className="text-accent">{current}°</span>
|
||||||
|
},
|
||||||
|
mm: props => {
|
||||||
|
return <p>No mm val yet</p>
|
||||||
|
},
|
||||||
|
constant: props => {
|
||||||
|
return <p>No constant val yet</p>
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tmp = props => <p>not yet</p>
|
||||||
|
|
||||||
|
const inputs = {
|
||||||
|
locale: props => <ListSetting
|
||||||
|
{...props}
|
||||||
|
list={props.app.languages.map(key => ({
|
||||||
|
key,
|
||||||
|
title: props.app.t(`i18n.${key}`)
|
||||||
|
}))}
|
||||||
|
/>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Setting = props => {
|
||||||
|
const Input = inputs[props.setting]
|
||||||
|
const Value = settings[props.setting]
|
||||||
|
|
||||||
|
const toggleBoolean = () => {
|
||||||
|
const dflt = props.pattern.config.options[props.option].bool
|
||||||
|
const current = props.gist?.options?.[props.option]
|
||||||
|
if (typeof current === 'undefined')
|
||||||
|
props.updateGist(['options', props.option], !dflt)
|
||||||
|
else props.unsetGist(['options', props.option])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.setting === 'bool') return (
|
||||||
|
<li className="flex flex-row">
|
||||||
|
<button className={`
|
||||||
|
flex flex-row
|
||||||
|
w-full
|
||||||
|
justify-between
|
||||||
|
px-2
|
||||||
|
text-left
|
||||||
|
text-base-content
|
||||||
|
sm:text-neutral-content
|
||||||
|
items-center
|
||||||
|
pr-6
|
||||||
|
`} onClick={toggleBoolean}>
|
||||||
|
<div className={`
|
||||||
|
grow pl-2 border-l-2
|
||||||
|
${linkClasses}
|
||||||
|
hover:border-secondary
|
||||||
|
sm:hover:border-secondary-focus
|
||||||
|
text-base-content sm:text-neutral-content
|
||||||
|
`}>
|
||||||
|
<span className={`
|
||||||
|
text-3xl mr-2 inline-block p-0 leading-3
|
||||||
|
translate-y-3
|
||||||
|
`}>
|
||||||
|
<>°</>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{ props.app.t(`options.${props.pattern.config.name}.${props.option}.title`) }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Value setting={props.setting} {...props} />
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li className="flex flex-row">
|
||||||
|
<details className="grow">
|
||||||
|
<summary className={`
|
||||||
|
flex flex-row
|
||||||
|
px-2
|
||||||
|
text-base-content
|
||||||
|
sm:text-neutral-content
|
||||||
|
hover:cursor-row-resize
|
||||||
|
items-center
|
||||||
|
`}>
|
||||||
|
<div className={`
|
||||||
|
grow pl-2 border-l-2
|
||||||
|
${linkClasses}
|
||||||
|
hover:border-secondary
|
||||||
|
sm:hover:border-secondary-focus
|
||||||
|
text-base-content sm:text-neutral-content
|
||||||
|
`}>
|
||||||
|
<span className={`
|
||||||
|
text-3xl inline-block p-0 leading-3 px-2
|
||||||
|
translate-y-3
|
||||||
|
`}>
|
||||||
|
<>°</>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
{ props.app.t(`settings.${props.setting}.title`) }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<Value setting={props.setting} {...props} />
|
||||||
|
<Chevron w={6} m={3}/>
|
||||||
|
</summary>
|
||||||
|
<Input {...props} />
|
||||||
|
</details>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Setting
|
|
@ -1,11 +1,17 @@
|
||||||
import ModesMenu from './modes.js'
|
import ModesMenu from './modes.js'
|
||||||
import DesignOptions from './design-options'
|
import DesignOptions from './design-options'
|
||||||
|
import CoreSettings from './core-settings'
|
||||||
|
|
||||||
const WorkbenchMenu = props => {
|
const WorkbenchMenu = props => {
|
||||||
return (
|
return (
|
||||||
<nav className="smmax-w-96 grow mb-12">
|
<nav className="smmax-w-96 grow mb-12">
|
||||||
<ModesMenu {...props} />
|
<ModesMenu {...props} />
|
||||||
{props.mode === 'draft' && <DesignOptions {...props} />}
|
{props.mode === 'draft' && (
|
||||||
|
<>
|
||||||
|
<DesignOptions {...props} />
|
||||||
|
<CoreSettings {...props} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,21 +6,20 @@ import Measurements, { Input } from 'shared/components/workbench/measurements/in
|
||||||
import LabDraft from 'shared/components/workbench/draft/index.js'
|
import LabDraft from 'shared/components/workbench/draft/index.js'
|
||||||
import set from 'lodash.set'
|
import set from 'lodash.set'
|
||||||
import unset from 'lodash.unset'
|
import unset from 'lodash.unset'
|
||||||
|
import defaultSettings from 'shared/components/workbench/default-settings.js'
|
||||||
|
|
||||||
|
|
||||||
// Generates a default pattern gist to start from
|
// Generates a default pattern gist to start from
|
||||||
const defaultGist = (pattern, language='en') => ({
|
const defaultGist = (pattern, language='en') => {
|
||||||
|
const gist = {
|
||||||
design: pattern.config.name,
|
design: pattern.config.name,
|
||||||
version: pattern.config.version,
|
version: pattern.config.version,
|
||||||
settings: {
|
settings: defaultSettings
|
||||||
sa: 0,
|
|
||||||
complete: true,
|
|
||||||
paperless: false,
|
|
||||||
units: 'metric',
|
|
||||||
locale: language,
|
|
||||||
margin: 2,
|
|
||||||
debug: true,
|
|
||||||
}
|
}
|
||||||
})
|
if (language) gist.settings.locale = language
|
||||||
|
|
||||||
|
return gist
|
||||||
|
}
|
||||||
|
|
||||||
const hasRequiredMeasurements = (pattern, gist) => {
|
const hasRequiredMeasurements = (pattern, gist) => {
|
||||||
for (const m of pattern.config.measurements) {
|
for (const m of pattern.config.measurements) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue