both menus using same structure and components
This commit is contained in:
parent
75bc302dd4
commit
cc14c562d2
12 changed files with 164 additions and 264 deletions
|
@ -99,6 +99,7 @@ export const loadSettingsConfig = ({
|
||||||
only: {
|
only: {
|
||||||
control: 4, // Show when control > 3
|
control: 4, // Show when control > 3
|
||||||
dflt: false,
|
dflt: false,
|
||||||
|
list: parts,
|
||||||
parts,
|
parts,
|
||||||
emoji: '🛍️',
|
emoji: '🛍️',
|
||||||
},
|
},
|
||||||
|
|
|
@ -82,28 +82,28 @@ export const CoreSettings = ({
|
||||||
sabool: settings.sabool,
|
sabool: settings.sabool,
|
||||||
parts: patternConfig.draftOrder,
|
parts: patternConfig.draftOrder,
|
||||||
})
|
})
|
||||||
// Default control level is 2 (in case people are not logged in)
|
|
||||||
const control = account.control || 5
|
const control = account.control
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WorkbenchMenu
|
<WorkbenchMenu
|
||||||
{...{
|
{...{
|
||||||
updateFunc: update.settings,
|
|
||||||
ns,
|
|
||||||
Icon: SettingsIcon,
|
|
||||||
name: 'coreSettings',
|
|
||||||
config: settingsConfig,
|
config: settingsConfig,
|
||||||
control,
|
control,
|
||||||
inputs,
|
|
||||||
values,
|
|
||||||
currentValues: settings,
|
currentValues: settings,
|
||||||
|
DynamicDocs,
|
||||||
|
getDocsPath: (setting) => `site/draft/core-settings${setting ? `/${setting}` : ''}`,
|
||||||
|
Icon: SettingsIcon,
|
||||||
|
inputs,
|
||||||
|
language,
|
||||||
|
name: 'coreSettings',
|
||||||
|
ns,
|
||||||
passProps: {
|
passProps: {
|
||||||
samm: typeof settings.samm === 'undefined' ? defaultSamm(settings.units) : settings.samm,
|
samm: typeof settings.samm === 'undefined' ? defaultSamm(settings.units) : settings.samm,
|
||||||
units: settings.units,
|
units: settings.units,
|
||||||
},
|
},
|
||||||
language,
|
updateFunc: update.settings,
|
||||||
DynamicDocs,
|
values,
|
||||||
getDocsPath: (setting) => `site/draft/core-settings${setting ? `/${setting}` : ''}`,
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,46 +12,26 @@ export const PaperlessSettingInput = ListInput
|
||||||
|
|
||||||
export const MarginSettingInput = MmInput
|
export const MarginSettingInput = MmInput
|
||||||
export const ScaleSettingInput = SliderInput
|
export const ScaleSettingInput = SliderInput
|
||||||
export const OnlySettingInput = ({ name, config, current, updateFunc, t, draftOrder, design }) => {
|
export const OnlySettingInput = (props) => {
|
||||||
const partNames = config.parts.map((part) => ({
|
props.config.choiceTitles = {}
|
||||||
id: part,
|
props.config.list.forEach((p) => (props.config.choiceTitles[p] = p))
|
||||||
t: t(`${design}:${part}.t`),
|
|
||||||
d: t(`${design}:${part}.d`),
|
|
||||||
}))
|
|
||||||
|
|
||||||
const togglePart = (part) => {
|
const onlyUpdateFunc = useCallback(
|
||||||
const parts = current || []
|
(path, part) => {
|
||||||
const newParts = new Set(parts)
|
if (part === undefined) return props.updateFunc(path, part)
|
||||||
|
|
||||||
|
let newParts = new Set(props.current || [])
|
||||||
if (newParts.has(part)) newParts.delete(part)
|
if (newParts.has(part)) newParts.delete(part)
|
||||||
else newParts.add(part)
|
else newParts.add(part)
|
||||||
if (newParts.size < 1) reset()
|
if (newParts.size < 1) newParts = undefined
|
||||||
else updateFunc(['only'], [...newParts])
|
else newParts = [...newParts]
|
||||||
}
|
|
||||||
|
|
||||||
const reset = () => {
|
props.updateFunc(path, newParts)
|
||||||
updateFunc(['only'])
|
},
|
||||||
}
|
[props.updateFunc, props.current]
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>{t(`core-settings:only.d`)}</p>
|
|
||||||
{orderBy(partNames, ['name'], ['asc']).map((part) => {
|
|
||||||
const included = Array.isArray(current) ? (current.includes(part.id) ? true : false) : true
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChoiceButton
|
|
||||||
key={part.id}
|
|
||||||
title={part.t}
|
|
||||||
color={included ? 'secondary' : 'accent'}
|
|
||||||
active={included}
|
|
||||||
onClick={() => togglePart(part.id)}
|
|
||||||
>
|
|
||||||
{part.d}
|
|
||||||
</ChoiceButton>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return <ListInput {...props} updateFunc={onlyUpdateFunc} />
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SaMmSettingInput = (props) => {
|
export const SaMmSettingInput = (props) => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ListValue, MmValue, PlainValue, HighlightedValue } from '../shared/values'
|
import { ListValue, MmValue, PlainValue } from '../shared/values'
|
||||||
|
|
||||||
export const RendererSettingValue = ListValue
|
export const RendererSettingValue = ListValue
|
||||||
export const LocaleSettingValue = ListValue
|
export const LocaleSettingValue = ListValue
|
||||||
|
@ -10,11 +10,14 @@ export const UnitsSettingValue = ListValue
|
||||||
export const MarginSettingValue = MmValue
|
export const MarginSettingValue = MmValue
|
||||||
export const SaMmSettingValue = MmValue
|
export const SaMmSettingValue = MmValue
|
||||||
|
|
||||||
export const ScaleSettingValue = PlainValue
|
export const ScaleSettingValue = ({ current, config, changed }) => (
|
||||||
|
<PlainValue current={current} dflt={config.dflt} changed={changed} />
|
||||||
|
)
|
||||||
|
|
||||||
export const OnlySettingValue = ({ current, config }) => (
|
export const OnlySettingValue = ({ current, config }) => (
|
||||||
<HighlightedValue changed={current !== undefined}>
|
<PlainValue
|
||||||
{' '}
|
current={current?.length}
|
||||||
{current ? current.length : config.parts.length}{' '}
|
dflt={config.parts.length}
|
||||||
</HighlightedValue>
|
changed={current !== undefined}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -39,7 +39,7 @@ const inputs = {
|
||||||
count: SliderInput,
|
count: SliderInput,
|
||||||
deg: DegInput,
|
deg: DegInput,
|
||||||
list: ListInput,
|
list: ListInput,
|
||||||
mm: MmInput,
|
mm: () => <span>FIXME: Mm options are deprecated. Please report this </span>,
|
||||||
pct: PctInput,
|
pct: PctInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ export const DesignOption = ({
|
||||||
current,
|
current,
|
||||||
config,
|
config,
|
||||||
settings,
|
settings,
|
||||||
update,
|
updateFunc,
|
||||||
t,
|
t,
|
||||||
loadDocs,
|
loadDocs,
|
||||||
changed = false,
|
changed = false,
|
||||||
|
@ -81,30 +81,13 @@ export const DesignOption = ({
|
||||||
// Hide option?
|
// Hide option?
|
||||||
if (config?.hide || (typeof config?.hide === 'function' && config.hide(settings))) return null
|
if (config?.hide || (typeof config?.hide === 'function' && config.hide(settings))) return null
|
||||||
|
|
||||||
if (type === 'bool') {
|
|
||||||
config = {
|
|
||||||
...config,
|
|
||||||
list: [0, 1],
|
|
||||||
choiceTitles: {
|
|
||||||
0: `${name}No`,
|
|
||||||
1: `${name}Yes`,
|
|
||||||
},
|
|
||||||
valueTitles: {
|
|
||||||
0: 'no',
|
|
||||||
1: 'yes',
|
|
||||||
},
|
|
||||||
dflt: config.dflt ? 1 : 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
{...{
|
{...{
|
||||||
name,
|
name,
|
||||||
config,
|
config,
|
||||||
current,
|
current,
|
||||||
updateFunc: update.settings,
|
updateFunc,
|
||||||
updatePath: ['options'],
|
|
||||||
t,
|
t,
|
||||||
changed,
|
changed,
|
||||||
loadDocs,
|
loadDocs,
|
||||||
|
@ -117,53 +100,6 @@ export const DesignOption = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DesignOptionGroup = ({
|
|
||||||
design,
|
|
||||||
patternConfig,
|
|
||||||
settings,
|
|
||||||
update,
|
|
||||||
group,
|
|
||||||
options,
|
|
||||||
t,
|
|
||||||
loadDocs,
|
|
||||||
}) => (
|
|
||||||
<Collapse
|
|
||||||
bottom
|
|
||||||
color="secondary"
|
|
||||||
title={
|
|
||||||
<ItemTitle
|
|
||||||
{...{
|
|
||||||
name: group,
|
|
||||||
t,
|
|
||||||
emoji: emojis[group] ? emojis[group] : emojis.groupDflt,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
openTitle={t(group)}
|
|
||||||
>
|
|
||||||
{Object.entries(options).map(([option, type]) =>
|
|
||||||
typeof type === 'string' ? (
|
|
||||||
<DesignOption
|
|
||||||
{...{ t, design, update, settings, loadDocs }}
|
|
||||||
key={option}
|
|
||||||
name={option}
|
|
||||||
settings={settings}
|
|
||||||
current={settings.options?.[option]}
|
|
||||||
config={patternConfig.options[option]}
|
|
||||||
changed={wasChanged(settings.options?.[option], option, patternConfig.options)}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<DesignOptionGroup
|
|
||||||
{...{ design, patternConfig, settings, update, Option, t, loadDocs }}
|
|
||||||
group={option}
|
|
||||||
options={type}
|
|
||||||
key={option}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</Collapse>
|
|
||||||
)
|
|
||||||
|
|
||||||
export const DesignOptions = ({
|
export const DesignOptions = ({
|
||||||
design,
|
design,
|
||||||
patternConfig,
|
patternConfig,
|
||||||
|
@ -183,31 +119,19 @@ export const DesignOptions = ({
|
||||||
return (
|
return (
|
||||||
<WorkbenchMenu
|
<WorkbenchMenu
|
||||||
{...{
|
{...{
|
||||||
name: 'design-options:designOptions',
|
config: optionsMenu,
|
||||||
updateFunc: update.settings,
|
|
||||||
ns: menuNs,
|
|
||||||
Icon: OptionsIcon,
|
|
||||||
inputs,
|
|
||||||
values,
|
|
||||||
currentValues: settings.options,
|
currentValues: settings.options,
|
||||||
language,
|
|
||||||
DynamicDocs,
|
DynamicDocs,
|
||||||
getDocsPath,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItemGroup
|
|
||||||
{...{
|
|
||||||
collapsible: false,
|
|
||||||
groupConfig: patternConfig.options,
|
|
||||||
currents: settings.options,
|
|
||||||
items: optionsMenu,
|
|
||||||
Item: DesignOption,
|
|
||||||
loadDocs,
|
|
||||||
itemProps: { design, update, settings },
|
|
||||||
emojis,
|
emojis,
|
||||||
t,
|
getDocsPath,
|
||||||
|
Icon: OptionsIcon,
|
||||||
|
Item: DesignOption,
|
||||||
|
name: 'design-options:designOptions',
|
||||||
|
language,
|
||||||
|
ns: menuNs,
|
||||||
|
passProps: { settings },
|
||||||
|
updateFunc: (name, value) => update.settings(['options', name], value),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</WorkbenchMenu>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { formatMm, formatPercentage } from 'shared/utils.mjs'
|
import { formatMm, formatPercentage } from 'shared/utils.mjs'
|
||||||
import { ListValue, HighlightedValue, PlainValue } from '../shared/values'
|
import { ListValue, HighlightedValue, PlainValue } from '../shared/values'
|
||||||
export const PctOptionValue = ({ name, config, current, settings, changed }) => {
|
export const PctOptionValue = ({ name, config, current, settings, changed }) => {
|
||||||
const val = typeof current === 'undefined' ? config.pct / 100 : current
|
const val = changed ? current : config.pct / 100
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HighlightedValue changed={changed}>
|
<HighlightedValue changed={changed}>
|
||||||
|
@ -23,7 +23,7 @@ export const BoolOptionValue = ({ name, config, current, t, changed }) => (
|
||||||
)
|
)
|
||||||
|
|
||||||
export const CountOptionValue = ({ config, current, changed }) => (
|
export const CountOptionValue = ({ config, current, changed }) => (
|
||||||
<PlainValue {...{ current, changed, config: { ...config, dflt: config.count } }} />
|
<PlainValue {...{ current, changed, dflt: config.count }} />
|
||||||
)
|
)
|
||||||
|
|
||||||
export const ListOptionValue = ({ name, config, current, t, changed }) => {
|
export const ListOptionValue = ({ name, config, current, t, changed }) => {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
import { Collapse } from 'shared/components/collapse.mjs'
|
import { Collapse } from 'shared/components/collapse.mjs'
|
||||||
import { MenuItem, wasChanged } from './menu-item.mjs'
|
import { MenuItemGroup, wasChanged } from './menu-item.mjs'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
import { HelpIcon } from 'shared/components/icons.mjs'
|
import { HelpIcon } from 'shared/components/icons.mjs'
|
||||||
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
import { ModalWrapper } from 'shared/components/wrappers/modal.mjs'
|
||||||
|
@ -25,7 +25,6 @@ export const useDocsLoader = (DynamicDocs, getDocsPath, language) => {
|
||||||
|
|
||||||
export const WorkbenchMenu = ({
|
export const WorkbenchMenu = ({
|
||||||
updateFunc,
|
updateFunc,
|
||||||
updatePath = [],
|
|
||||||
ns,
|
ns,
|
||||||
Icon,
|
Icon,
|
||||||
name,
|
name,
|
||||||
|
@ -38,6 +37,8 @@ export const WorkbenchMenu = ({
|
||||||
DynamicDocs = false,
|
DynamicDocs = false,
|
||||||
getDocsPath = () => {},
|
getDocsPath = () => {},
|
||||||
language,
|
language,
|
||||||
|
emojis,
|
||||||
|
Item,
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const { t, i18n } = useTranslation(ns)
|
const { t, i18n } = useTranslation(ns)
|
||||||
|
@ -69,29 +70,24 @@ export const WorkbenchMenu = ({
|
||||||
openTitle={t(`${name}.t`)}
|
openTitle={t(`${name}.t`)}
|
||||||
openButtons={openButtons}
|
openButtons={openButtons}
|
||||||
>
|
>
|
||||||
<p>{t('core-settings:coreSettings.d')}</p>
|
{children || (
|
||||||
{children ||
|
<MenuItemGroup
|
||||||
Object.keys(config)
|
|
||||||
.filter((name) => config[name].control <= control)
|
|
||||||
.map((name) => (
|
|
||||||
<MenuItem
|
|
||||||
key={name}
|
|
||||||
{...{
|
{...{
|
||||||
name,
|
collapsible: false,
|
||||||
config: config[name],
|
control,
|
||||||
current: currentValues[name],
|
currentValues,
|
||||||
updateFunc,
|
structure: config,
|
||||||
updatePath,
|
Item,
|
||||||
t,
|
values,
|
||||||
passProps,
|
inputs,
|
||||||
changed: wasChanged(currentValues[name], name, config),
|
|
||||||
loadDocs,
|
loadDocs,
|
||||||
Input: inputs[name],
|
passProps,
|
||||||
Value: values[name],
|
updateFunc,
|
||||||
i18n: i18n,
|
emojis,
|
||||||
|
t,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
)}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,17 +29,17 @@ const EditCount = (props) => (
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
const useSharedHandlers = ({ dflt, updateFunc, updatePath, name, setReset }) => {
|
const useSharedHandlers = ({ dflt, updateFunc, name, setReset }) => {
|
||||||
const reset = useCallback(() => updateFunc([...updatePath, name]), [updatePath, updateFunc, name])
|
const reset = useCallback(() => updateFunc(name), [updateFunc, name])
|
||||||
|
|
||||||
const handleChange = useCallback(
|
const handleChange = useCallback(
|
||||||
(newCurrent) => {
|
(newCurrent) => {
|
||||||
if (newCurrent === dflt) reset()
|
if (newCurrent === dflt) reset()
|
||||||
else {
|
else {
|
||||||
updateFunc([...updatePath, name], newCurrent)
|
updateFunc(name, newCurrent)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[dflt, updateFunc, updatePath, name]
|
[dflt, updateFunc, name]
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => setReset(() => reset), [reset, setReset])
|
useEffect(() => setReset(() => reset), [reset, setReset])
|
||||||
|
@ -47,20 +47,10 @@ const useSharedHandlers = ({ dflt, updateFunc, updatePath, name, setReset }) =>
|
||||||
return { handleChange, reset }
|
return { handleChange, reset }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ListInput = ({
|
export const ListInput = ({ name, config, current, updateFunc, compact = false, t, setReset }) => {
|
||||||
name,
|
|
||||||
config,
|
|
||||||
current,
|
|
||||||
updateFunc,
|
|
||||||
updatePath = [],
|
|
||||||
compact = false,
|
|
||||||
t,
|
|
||||||
setReset,
|
|
||||||
}) => {
|
|
||||||
const { handleChange, reset, set } = useSharedHandlers({
|
const { handleChange, reset, set } = useSharedHandlers({
|
||||||
dflt: config.dflt,
|
dflt: config.dflt,
|
||||||
updateFunc,
|
updateFunc,
|
||||||
updatePath,
|
|
||||||
name,
|
name,
|
||||||
setReset,
|
setReset,
|
||||||
})
|
})
|
||||||
|
@ -86,7 +76,23 @@ export const ListInput = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BoolInput = ListInput
|
export const BoolInput = (props) => {
|
||||||
|
const boolConfig = {
|
||||||
|
list: [0, 1],
|
||||||
|
choiceTitles: {
|
||||||
|
0: `${props.name}No`,
|
||||||
|
1: `${props.name}Yes`,
|
||||||
|
},
|
||||||
|
valueTitles: {
|
||||||
|
0: 'no',
|
||||||
|
1: 'yes',
|
||||||
|
},
|
||||||
|
dflt: props.config.dflt ? 1 : 0,
|
||||||
|
...props.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
return <ListInput {...props} config={boolConfig} />
|
||||||
|
}
|
||||||
|
|
||||||
const EditInputValue = (props) => (
|
const EditInputValue = (props) => (
|
||||||
<div className="form-control mb-2 w-full">
|
<div className="form-control mb-2 w-full">
|
||||||
|
@ -123,7 +129,6 @@ export const SliderInput = ({
|
||||||
config,
|
config,
|
||||||
current,
|
current,
|
||||||
updateFunc,
|
updateFunc,
|
||||||
updatePath = [],
|
|
||||||
t,
|
t,
|
||||||
override,
|
override,
|
||||||
suffix = '',
|
suffix = '',
|
||||||
|
@ -136,7 +141,6 @@ export const SliderInput = ({
|
||||||
current,
|
current,
|
||||||
dflt: config.dflt,
|
dflt: config.dflt,
|
||||||
updateFunc,
|
updateFunc,
|
||||||
updatePath,
|
|
||||||
name,
|
name,
|
||||||
setReset,
|
setReset,
|
||||||
})
|
})
|
||||||
|
@ -192,8 +196,7 @@ export const SliderInput = ({
|
||||||
export const PctInput = ({ config, settings, current, updateFunc, type = 'pct', ...rest }) => {
|
export const PctInput = ({ config, settings, current, updateFunc, type = 'pct', ...rest }) => {
|
||||||
const suffix = type === 'deg' ? '°' : '%'
|
const suffix = type === 'deg' ? '°' : '%'
|
||||||
const factor = type === 'deg' ? 1 : 100
|
const factor = type === 'deg' ? 1 : 100
|
||||||
const dflt = config[type]
|
let pctCurrent = typeof current === 'undefined' ? config.dflt : current * factor
|
||||||
let pctCurrent = typeof current === 'undefined' ? dflt : current * factor
|
|
||||||
|
|
||||||
const valFormatter = (val) => round(val)
|
const valFormatter = (val) => round(val)
|
||||||
const pctUpdateFunc = useCallback(
|
const pctUpdateFunc = useCallback(
|
||||||
|
@ -208,7 +211,6 @@ export const PctInput = ({ config, settings, current, updateFunc, type = 'pct',
|
||||||
config: {
|
config: {
|
||||||
...config,
|
...config,
|
||||||
step: 0.1,
|
step: 0.1,
|
||||||
dflt,
|
|
||||||
},
|
},
|
||||||
current: pctCurrent,
|
current: pctCurrent,
|
||||||
updateFunc: pctUpdateFunc,
|
updateFunc: pctUpdateFunc,
|
||||||
|
@ -217,7 +219,7 @@ export const PctInput = ({ config, settings, current, updateFunc, type = 'pct',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-row justify-around">
|
<div className="flex flex-row justify-around">
|
||||||
<span className={current === dflt ? 'text-secondary' : 'text-accent'}>
|
<span className={current === config.dflt ? 'text-secondary' : 'text-accent'}>
|
||||||
{config.toAbs && settings.measurements
|
{config.toAbs && settings.measurements
|
||||||
? formatMm(config.toAbs(current / factor, settings))
|
? formatMm(config.toAbs(current / factor, settings))
|
||||||
: ' '}
|
: ' '}
|
||||||
|
@ -238,6 +240,7 @@ export const MmInput = (props) => {
|
||||||
},
|
},
|
||||||
[props.updateFunc, props.units]
|
[props.updateFunc, props.units]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SliderInput
|
<SliderInput
|
||||||
{...{
|
{...{
|
||||||
|
|
|
@ -2,9 +2,9 @@ import { ClearIcon, HelpIcon, EditIcon } from 'shared/components/icons.mjs'
|
||||||
import { Collapse } from 'shared/components/collapse.mjs'
|
import { Collapse } from 'shared/components/collapse.mjs'
|
||||||
import { useState, useMemo } from 'react'
|
import { useState, useMemo } from 'react'
|
||||||
|
|
||||||
export const wasChanged = (current, name, settingsConfig) => {
|
export const wasChanged = (current, config) => {
|
||||||
if (typeof current === 'undefined') return false
|
if (typeof current === 'undefined') return false
|
||||||
if (current === settingsConfig[name].dflt) return false
|
if (current === config.dflt) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -16,18 +16,17 @@ export const ItemTitle = ({ name, t, changed, current = null, open = false, emoj
|
||||||
{emoji}
|
{emoji}
|
||||||
</span>
|
</span>
|
||||||
{t(`${name}.t`)}
|
{t(`${name}.t`)}
|
||||||
{open ? ':' : ''}
|
|
||||||
</span>
|
</span>
|
||||||
<span className="font-bold">{current}</span>
|
<span className="font-bold">{current}</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const openButtonClass = 'btn btn-xs btn-ghost px-0'
|
||||||
export const MenuItem = ({
|
export const MenuItem = ({
|
||||||
name,
|
name,
|
||||||
config,
|
config,
|
||||||
current,
|
current,
|
||||||
updateFunc,
|
updateFunc,
|
||||||
updatePath = [],
|
|
||||||
t,
|
t,
|
||||||
passProps = {},
|
passProps = {},
|
||||||
changed,
|
changed,
|
||||||
|
@ -35,9 +34,10 @@ export const MenuItem = ({
|
||||||
Input,
|
Input,
|
||||||
Value,
|
Value,
|
||||||
allowOverride = false,
|
allowOverride = false,
|
||||||
|
control = Infinity,
|
||||||
}) => {
|
}) => {
|
||||||
const [override, setOverride] = useState(false)
|
const [override, setOverride] = useState(false)
|
||||||
const [reset, setReset] = useState(() => () => updateFunc([...updatePath, name]))
|
const [reset, setReset] = useState(() => () => updateFunc(name))
|
||||||
|
|
||||||
const drillProps = useMemo(
|
const drillProps = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
|
@ -47,23 +47,20 @@ export const MenuItem = ({
|
||||||
updateFunc,
|
updateFunc,
|
||||||
t,
|
t,
|
||||||
changed,
|
changed,
|
||||||
updatePath,
|
|
||||||
override,
|
override,
|
||||||
setReset,
|
setReset,
|
||||||
...passProps,
|
...passProps,
|
||||||
}),
|
}),
|
||||||
[name, config, current, updateFunc, t, changed, updatePath, override, setReset, passProps]
|
[name, config, current, updateFunc, t, changed, override, setReset, passProps]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (config.control && config.control > control) return null
|
||||||
|
|
||||||
const buttons = []
|
const buttons = []
|
||||||
const openButtons = []
|
const openButtons = []
|
||||||
if (loadDocs)
|
if (loadDocs)
|
||||||
openButtons.push(
|
openButtons.push(
|
||||||
<button
|
<button className={openButtonClass} key="help" onClick={(evt) => loadDocs(evt, name)}>
|
||||||
className="btn btn-xs btn-ghost px-0"
|
|
||||||
key="help"
|
|
||||||
onClick={(evt) => loadDocs(evt, name)}
|
|
||||||
>
|
|
||||||
<HelpIcon className="w-4 h-4" />
|
<HelpIcon className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
@ -71,7 +68,7 @@ export const MenuItem = ({
|
||||||
openButtons.push(
|
openButtons.push(
|
||||||
<button
|
<button
|
||||||
key="edit"
|
key="edit"
|
||||||
className="btn btn-xs btn-ghost px-0"
|
className={openButtonClass}
|
||||||
onClick={(evt) => {
|
onClick={(evt) => {
|
||||||
evt.stopPropagation()
|
evt.stopPropagation()
|
||||||
setOverride(!override)
|
setOverride(!override)
|
||||||
|
@ -81,22 +78,9 @@ export const MenuItem = ({
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
if (changed) {
|
if (changed) {
|
||||||
buttons.push(
|
const ResetButton = ({ open }) => (
|
||||||
<button
|
<button
|
||||||
className="btn btn-accent"
|
className={open ? openButtonClass : 'btn btn-accent'}
|
||||||
key="clear"
|
|
||||||
onClick={(evt) => {
|
|
||||||
evt.stopPropagation()
|
|
||||||
reset()
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ClearIcon />
|
|
||||||
</button>
|
|
||||||
)
|
|
||||||
openButtons.push(
|
|
||||||
<button
|
|
||||||
className="btn btn-ghost btn-xs px-0"
|
|
||||||
key="clear"
|
|
||||||
onClick={(evt) => {
|
onClick={(evt) => {
|
||||||
evt.stopPropagation()
|
evt.stopPropagation()
|
||||||
reset()
|
reset()
|
||||||
|
@ -105,6 +89,8 @@ export const MenuItem = ({
|
||||||
<ClearIcon />
|
<ClearIcon />
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
|
buttons.push(<ResetButton key="clear" />)
|
||||||
|
openButtons.push(<ResetButton open key="clear" />)
|
||||||
}
|
}
|
||||||
|
|
||||||
const titleProps = { name, t, current: <Value {...drillProps} />, emoji: config.emoji }
|
const titleProps = { name, t, current: <Value {...drillProps} />, emoji: config.emoji }
|
||||||
|
@ -124,29 +110,37 @@ export const MenuItem = ({
|
||||||
|
|
||||||
export const MenuItemGroup = ({
|
export const MenuItemGroup = ({
|
||||||
collapsible = true,
|
collapsible = true,
|
||||||
|
control,
|
||||||
name,
|
name,
|
||||||
groupConfig,
|
currentValues = {},
|
||||||
currents = {},
|
structure,
|
||||||
items,
|
|
||||||
Item = MenuItem,
|
Item = MenuItem,
|
||||||
|
values = {},
|
||||||
|
inputs = {},
|
||||||
loadDocs,
|
loadDocs,
|
||||||
itemProps = {},
|
passProps = {},
|
||||||
emojis = {},
|
emojis = {},
|
||||||
|
updateFunc,
|
||||||
t,
|
t,
|
||||||
}) => {
|
}) => {
|
||||||
const content = Object.entries(items).map(([itemName, item]) => {
|
const content = Object.entries(structure).map(([itemName, item]) => {
|
||||||
if (typeof item === 'string')
|
if (itemName === 'isMenu' || item === false) return null
|
||||||
|
if (!item.isMenu)
|
||||||
return (
|
return (
|
||||||
<Item
|
<Item
|
||||||
key={itemName}
|
key={itemName}
|
||||||
{...{
|
{...{
|
||||||
name: itemName,
|
name: itemName,
|
||||||
current: currents[itemName],
|
current: currentValues[itemName],
|
||||||
config: groupConfig[itemName],
|
config: item,
|
||||||
changed: wasChanged(currents[itemName], itemName, groupConfig),
|
control,
|
||||||
|
changed: wasChanged(currentValues[itemName], item),
|
||||||
|
Value: values[itemName],
|
||||||
|
Input: inputs[itemName],
|
||||||
t,
|
t,
|
||||||
loadDocs,
|
loadDocs,
|
||||||
...itemProps,
|
updateFunc,
|
||||||
|
passProps,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
@ -156,43 +150,34 @@ export const MenuItemGroup = ({
|
||||||
key={itemName}
|
key={itemName}
|
||||||
{...{
|
{...{
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
|
control,
|
||||||
name: itemName,
|
name: itemName,
|
||||||
groupConfig,
|
currentValues,
|
||||||
currents,
|
structure: item,
|
||||||
items: item,
|
|
||||||
Item,
|
Item,
|
||||||
|
values,
|
||||||
|
inputs,
|
||||||
loadDocs,
|
loadDocs,
|
||||||
itemProps,
|
passProps,
|
||||||
emojis,
|
emojis,
|
||||||
|
updateFunc,
|
||||||
t,
|
t,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const titleProps = {
|
||||||
|
name,
|
||||||
|
t,
|
||||||
|
emoji: emojis[name] || emojis.dflt,
|
||||||
|
}
|
||||||
return collapsible ? (
|
return collapsible ? (
|
||||||
<Collapse
|
<Collapse
|
||||||
bottom
|
bottom
|
||||||
color="secondary"
|
color="secondary"
|
||||||
title={
|
title={<ItemTitle {...titleProps} />}
|
||||||
<ItemTitle
|
openTitle={<ItemTitle open {...titleProps} />}
|
||||||
{...{
|
|
||||||
name,
|
|
||||||
t,
|
|
||||||
emoji: emojis[name] || emojis.dflt,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
openTitle={
|
|
||||||
<ItemTitle
|
|
||||||
open
|
|
||||||
{...{
|
|
||||||
name,
|
|
||||||
t,
|
|
||||||
emoji: emojis[name] || emojis.dflt,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{content}
|
{content}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
import { formatMm, formatFraction128 } from 'shared/utils.mjs'
|
import { formatMm, formatFraction128 } from 'shared/utils.mjs'
|
||||||
|
|
||||||
export const HighlightedValue = ({ changed, children }) => (
|
export const HighlightedValue = ({ changed, children }) => (
|
||||||
<span className={changed ? 'text-accent' : 'text-secondary-focus'}> {children} </span>
|
<span className={changed ? 'text-info' : ''}> {children} </span>
|
||||||
)
|
)
|
||||||
|
|
||||||
export const PlainValue = ({ current, config, changed }) => (
|
export const PlainValue = ({ current, dflt, changed }) => (
|
||||||
<HighlightedValue changed={changed}> {changed ? current : config.dflt} </HighlightedValue>
|
<HighlightedValue changed={changed}> {changed ? current : dflt} </HighlightedValue>
|
||||||
)
|
)
|
||||||
|
|
||||||
export const ListValue = ({ current, t, config, changed }) => (
|
export const ListValue = ({ current, t, config, changed }) => {
|
||||||
<HighlightedValue changed={changed}>
|
const val = changed ? current : config.dflt
|
||||||
{changed ? t(`${config.valueTitles[current]}`) : t(`${config.valueTitles[config.dflt]}`)}
|
let key
|
||||||
</HighlightedValue>
|
if (config.valueTitles) key = config.valueTitles[val]
|
||||||
)
|
else if (typeof val === 'string') key = val
|
||||||
|
else if (val) key = 'yes'
|
||||||
|
else key = 'no'
|
||||||
|
|
||||||
|
return <HighlightedValue changed={changed}>{t(key)}</HighlightedValue>
|
||||||
|
}
|
||||||
|
|
||||||
export const MmValue = ({ current, t, config, units, changed }) => (
|
export const MmValue = ({ current, t, config, units, changed }) => (
|
||||||
<HighlightedValue changed={changed}>
|
<HighlightedValue changed={changed}>
|
||||||
|
|
|
@ -8,9 +8,9 @@ const usePersistedToken = createPersistedState('fs-token')
|
||||||
const usePersistedSeenUser = createPersistedState('fs-seen-user')
|
const usePersistedSeenUser = createPersistedState('fs-seen-user')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Make it possible to always check for account.username
|
* Make it possible to always check for account.username and account.control
|
||||||
*/
|
*/
|
||||||
const noAccount = { username: false }
|
const noAccount = { username: false, control: 2 }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The useAccount hook
|
* The useAccount hook
|
||||||
|
|
|
@ -197,8 +197,11 @@ export const optionsMenuStructure = (options) => {
|
||||||
// Fixme: One day we should sort this based on the translation
|
// Fixme: One day we should sort this based on the translation
|
||||||
for (const option of orderBy(sorted, ['menu', 'name'], ['asc'])) {
|
for (const option of orderBy(sorted, ['menu', 'name'], ['asc'])) {
|
||||||
if (typeof option === 'object') {
|
if (typeof option === 'object') {
|
||||||
if (option.menu) set(menu, `${option.menu}.${option.name}`, optionType(option))
|
option.dflt = option.dflt || option[optionType(option)]
|
||||||
else if (typeof option.menu === 'undefined') {
|
if (option.menu) {
|
||||||
|
set(menu, `${option.menu}.isMenu`, true)
|
||||||
|
set(menu, `${option.menu}.${option.name}`, option)
|
||||||
|
} else if (typeof option.menu === 'undefined') {
|
||||||
console.log(
|
console.log(
|
||||||
`Warning: Option ${option.name} does not have a menu config. ` +
|
`Warning: Option ${option.name} does not have a menu config. ` +
|
||||||
'Either configure it, or set it to false to hide this option.'
|
'Either configure it, or set it to false to hide this option.'
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue