1
0
Fork 0

[react] chore: Guard against undefined settings

This commit is contained in:
joostdecock 2025-04-28 07:06:35 +02:00
parent 5e5edd9d29
commit 663528fa36
17 changed files with 79 additions and 66 deletions

View file

@ -264,6 +264,7 @@ export const HeaderMenuDraftViewFlags = (props) => {
export const HeaderMenuDraftViewIcons = (props) => { export const HeaderMenuDraftViewIcons = (props) => {
const { update, state } = props const { update, state } = props
const { settings = {} } = state // Guard against undefined settings
const Button = HeaderMenuButton const Button = HeaderMenuButton
const size = 'tw:w-5 tw:h-5' const size = 'tw:w-5 tw:h-5'
const muted = 'tw:text-current tw:opacity-50' const muted = 'tw:text-current tw:opacity-50'
@ -281,55 +282,49 @@ export const HeaderMenuDraftViewIcons = (props) => {
updateHandler={update.toggleSa} updateHandler={update.toggleSa}
tooltip="Turns Seam Allowance on or off (see Core Settings)" tooltip="Turns Seam Allowance on or off (see Core Settings)"
> >
<SaIcon className={`${size} ${state.settings.sabool ? 'tw:text-secondary' : muted}`} /> <SaIcon className={`${size} ${settings.sabool ? 'tw:text-secondary' : muted}`} />
</Button> </Button>
) : null} ) : null}
{ux >= levels.units ? ( {ux >= levels.units ? (
<Button <Button
lgOnly lgOnly
updateHandler={() => updateHandler={() =>
update.settings('units', state.settings.units === 'imperial' ? 'metric' : 'imperial') update.settings('units', settings.units === 'imperial' ? 'metric' : 'imperial')
} }
tooltip="Switches Units between metric and imperial (see Core Settings)" tooltip="Switches Units between metric and imperial (see Core Settings)"
> >
<UnitsIcon <UnitsIcon
className={`${size} ${ className={`${size} ${settings.units === 'imperial' ? 'tw:text-secondary' : muted}`}
state.settings.units === 'imperial' ? 'tw:text-secondary' : muted
}`}
/> />
</Button> </Button>
) : null} ) : null}
{ux >= levels.paperless ? ( {ux >= levels.paperless ? (
<Button <Button
lgOnly lgOnly
updateHandler={() => update.settings('paperless', state.settings.paperless ? 0 : 1)} updateHandler={() => update.settings('paperless', settings.paperless ? 0 : 1)}
tooltip="Turns Paperless on or off (see Core Settings)" tooltip="Turns Paperless on or off (see Core Settings)"
> >
<PaperlessIcon <PaperlessIcon
className={`${size} ${state.settings.paperless ? 'tw:text-secondary' : muted}`} className={`${size} ${settings.paperless ? 'tw:text-secondary' : muted}`}
/> />
</Button> </Button>
) : null} ) : null}
{ux >= levels.complete ? ( {ux >= levels.complete ? (
<Button <Button
lgOnly lgOnly
updateHandler={() => update.settings('complete', state.settings.complete ? 0 : 1)} updateHandler={() => update.settings('complete', settings.complete ? 0 : 1)}
tooltip="Turns Details on or off (see Core Settings)" tooltip="Turns Details on or off (see Core Settings)"
> >
<DetailIcon <DetailIcon className={`${size} ${!settings.complete ? 'tw:text-secondary' : muted}`} />
className={`${size} ${!state.settings.complete ? 'tw:text-secondary' : muted}`}
/>
</Button> </Button>
) : null} ) : null}
{ux >= levels.expand ? ( {ux >= levels.expand ? (
<Button <Button
lgOnly lgOnly
updateHandler={() => update.settings('expand', state.settings.expand ? 0 : 1)} updateHandler={() => update.settings('expand', settings.expand ? 0 : 1)}
tooltip="Turns Expand on or off (see Core Settings)" tooltip="Turns Expand on or off (see Core Settings)"
> >
<ExpandIcon <ExpandIcon className={`${size} ${settings.expand ? 'tw:text-secondary' : muted}`} />
className={`${size} ${state.settings.expand ? 'tw:text-secondary' : muted}`}
/>
</Button> </Button>
) : null} ) : null}
<HeaderMenuIconSpacer /> <HeaderMenuIconSpacer />
@ -450,6 +445,7 @@ export const HeaderMenuTestIcons = (props) => {
export const HeaderMenuSaveIcons = (props) => { export const HeaderMenuSaveIcons = (props) => {
const { update, state } = props const { update, state } = props
const { settings = {} } = state // Guard against undefined settings
const backend = useBackend() const backend = useBackend()
const Button = HeaderMenuButton const Button = HeaderMenuButton
const size = 'tw:w-5 tw:h-5' const size = 'tw:w-5 tw:h-5'
@ -463,9 +459,7 @@ export const HeaderMenuSaveIcons = (props) => {
if (pid) { if (pid) {
const loadingId = 'savePattern' const loadingId = 'savePattern'
update.startLoading(loadingId) update.startLoading(loadingId)
const patternData = { const patternData = { settings }
settings: state.settings,
}
const result = await backend.updatePattern(pid, patternData) const result = await backend.updatePattern(pid, patternData)
if (result[0] === 200) { if (result[0] === 200) {
update.stopLoading(loadingId) update.stopLoading(loadingId)
@ -599,6 +593,7 @@ export const HeaderMenuLayoutView = (props) => (
export const HeaderMenuLayoutViewIcons = (props) => { export const HeaderMenuLayoutViewIcons = (props) => {
const { pattern, update, state } = props const { pattern, update, state } = props
const { settings = {} } = state // Guard against undefined settings
const [tweaks, setTweaks] = useState(0) const [tweaks, setTweaks] = useState(0)
// Is the current custom layout an actual layout? // Is the current custom layout an actual layout?
@ -611,12 +606,12 @@ export const HeaderMenuLayoutViewIcons = (props) => {
*/ */
if ( if (
tweaks === 0 && tweaks === 0 &&
typeof props.state.ui?.layout === 'object' && typeof state.ui?.layout === 'object' &&
typeof props.state.settings?.layout !== 'object' typeof settings?.layout !== 'object'
) )
applyLayout() applyLayout()
setTweaks(tweaks + 1) setTweaks(tweaks + 1)
}, [props.state.ui.layout]) }, [state.ui.layout])
const applyLayout = () => { const applyLayout = () => {
setTweaks(-1) setTweaks(-1)
@ -633,7 +628,7 @@ export const HeaderMenuLayoutViewIcons = (props) => {
const pages = pattern.setStores[0].get('pages', {}) const pages = pattern.setStores[0].get('pages', {})
const format = state.ui.print?.pages?.size const format = state.ui.print?.pages?.size
? state.ui.print.pages.size ? state.ui.print.pages.size
: state.settings?.units === 'imperial' : settings.units === 'imperial'
? 'letter' ? 'letter'
: 'a4' : 'a4'
const { cols, rows, count } = pages const { cols, rows, count } = pages

View file

@ -31,9 +31,11 @@ import { SettingsIcon } from '@freesewing/react/components/Icon'
* @param {Object} props.update - Object holding state handlers * @param {Object} props.update - Object holding state handlers
*/ */
export const CoreSettingsMenu = ({ Design, state, i18n, update }) => { export const CoreSettingsMenu = ({ Design, state, i18n, update }) => {
const { settings = {} } = state // Guard against undefined settings
const structure = menuCoreSettingsStructure({ const structure = menuCoreSettingsStructure({
units: state.settings?.units, units: settings.units,
sabool: state.settings?.sabool, sabool: settings.sabool,
parts: Design.patternConfig.draftOrder, parts: Design.patternConfig.draftOrder,
}) })
@ -66,7 +68,7 @@ export const CoreSettingsMenu = ({ Design, state, i18n, update }) => {
{...{ {...{
structure, structure,
ux: state.ui.ux, ux: state.ui.ux,
currentValues: state.settings || {}, currentValues: settings,
Icon: SettingsIcon, Icon: SettingsIcon,
Item: (props) => ( Item: (props) => (
<CoreSetting updateHandler={update} {...{ inputs, values, Design, i18n }} {...props} /> <CoreSetting updateHandler={update} {...{ inputs, values, Design, i18n }} {...props} />
@ -75,7 +77,7 @@ export const CoreSettingsMenu = ({ Design, state, i18n, update }) => {
name: 'Core Settings', name: 'Core Settings',
passProps: { passProps: {
ux: state.ui.ux, ux: state.ui.ux,
settings: state.settings, settings,
patternConfig: Design.patternConfig, patternConfig: Design.patternConfig,
toggleSa: update.toggleSa, toggleSa: update.toggleSa,
}, },

View file

@ -35,14 +35,19 @@ import { OptionsIcon } from '@freesewing/react/components/Icon'
* @param {Object} props.update - Object holding state handlers * @param {Object} props.update - Object holding state handlers
*/ */
export const DesignOptionsMenu = ({ Design, isFirst = true, state, i18n, update }) => { export const DesignOptionsMenu = ({ Design, isFirst = true, state, i18n, update }) => {
/*
* Ensure state is not undefined
*/
const { settings = {} } = state
const structure = useMemo( const structure = useMemo(
() => () =>
menuDesignOptionsStructure( menuDesignOptionsStructure(
Design.designConfig.data.id, Design.designConfig.data.id,
Design.patternConfig.options, Design.patternConfig.options,
state.settings settings
), ),
[Design.designConfig.data.id, Design.patternConfig, state.settings] [Design.designConfig.data.id, Design.patternConfig, settings]
) )
const updateHandler = useCallback( const updateHandler = useCallback(
(name, value = '__UNSET__') => update.settings(['options', ...name], value), (name, value = '__UNSET__') => update.settings(['options', ...name], value),
@ -76,14 +81,14 @@ export const DesignOptionsMenu = ({ Design, isFirst = true, state, i18n, update
{...{ {...{
structure, structure,
ux: state.ui.ux, ux: state.ui.ux,
currentValues: state.settings.options || {}, currentValues: settings.options || {},
Icon: OptionsIcon, Icon: OptionsIcon,
Item: (props) => <DesignOption {...{ inputs, values, update, Design }} {...props} />, Item: (props) => <DesignOption {...{ inputs, values, update, Design }} {...props} />,
isFirst, isFirst,
name: 'Design Options', name: 'Design Options',
passProps: { passProps: {
ux: state.ui.ux, ux: state.ui.ux,
settings: state.settings, settings,
patternConfig: Design.patternConfig, patternConfig: Design.patternConfig,
}, },
updateHandler, updateHandler,

View file

@ -282,6 +282,7 @@ export const MenuSliderInput = ({
state, state,
Design, Design,
}) => { }) => {
const { settings = {} } = state // Guard against undefined settings
const { max, min } = config const { max, min } = config
const handleChange = useSharedHandlers({ const handleChange = useSharedHandlers({
current, current,
@ -330,10 +331,10 @@ export const MenuSliderInput = ({
__html: formatMm( __html: formatMm(
config.toAbs( config.toAbs(
val / 100, val / 100,
state.settings, settings,
mergeOptions(state.settings, Design.patternConfig.options) mergeOptions(settings, Design.patternConfig.options)
), ),
state.settings?.units settings.units
), ),
}} }}
/> />
@ -360,25 +361,22 @@ export const MenuSliderInput = ({
export const MenuEditOption = (props) => { export const MenuEditOption = (props) => {
const { config, handleChange } = props const { config, handleChange } = props
const { settings = {} } = props.state // Guard against undefined settings
const type = designOptionType(config) const type = designOptionType(config)
const [manualEdit, setManualEdit] = useState(props.current) const [manualEdit, setManualEdit] = useState(props.current)
const [abs, setAbs] = useState(false) const [abs, setAbs] = useState(false)
const [units, setUnits] = useState( const [units, setUnits] = useState(
abs abs ? (settings.units === 'imperial' ? 'inch' : 'cm') : defaultConfig.menuOptionEditLabels[type]
? props.state.settings?.units === 'imperial'
? 'inch'
: 'cm'
: defaultConfig.menuOptionEditLabels[type]
) )
const onUpdate = useCallback( const onUpdate = useCallback(
(validVal, units) => { (validVal, units) => {
if (validVal !== null && validVal !== false) { if (validVal !== null && validVal !== false) {
if (type === 'pct' && units === 'cm') if (type === 'pct' && units === 'cm')
return handleChange(config.fromAbs(Number(validVal) * 1000, props.state.settings)) return handleChange(config.fromAbs(Number(validVal) * 1000, settings))
if (type === 'pct' && units === 'inch') if (type === 'pct' && units === 'inch')
return handleChange(config.fromAbs(Number(validVal) * 2540, props.state.settings)) return handleChange(config.fromAbs(Number(validVal) * 2540, settings))
return handleChange(validVal) return handleChange(validVal)
} }
}, },
@ -387,7 +385,7 @@ export const MenuEditOption = (props) => {
const toggleInputUnits = () => { const toggleInputUnits = () => {
if (abs) setUnits(defaultConfig.menuOptionEditLabels[type]) if (abs) setUnits(defaultConfig.menuOptionEditLabels[type])
else setUnits(props.state.settings?.units === 'imperial' ? 'inch' : 'cm') else setUnits(settings.units === 'imperial' ? 'inch' : 'cm')
setAbs(!abs) setAbs(!abs)
console.log('in toogg;e') console.log('in toogg;e')
} }

View file

@ -48,7 +48,7 @@ export const LayoutSettingsMenu = ({ update, state, Design }) => {
name: 'UI Preferences', name: 'UI Preferences',
passProps: { passProps: {
ux: state.ui?.ux, ux: state.ui?.ux,
settings: state.settings, settings: state?.settings,
patternConfig: Design.patternConfig, patternConfig: Design.patternConfig,
}, },
updateHandler: (key, val) => update.ui(['layout', key], val), updateHandler: (key, val) => update.ui(['layout', key], val),

View file

@ -16,14 +16,15 @@ import { BeakerIcon, OptionsIcon } from '@freesewing/react/components/Icon'
* @param {Object} props.update - Object holding state handlers * @param {Object} props.update - Object holding state handlers
*/ */
export const TestOptionsMenu = ({ Design, state, i18n, update }) => { export const TestOptionsMenu = ({ Design, state, i18n, update }) => {
const { settings = {} } = state // Guard against undefined settings
const structure = useMemo( const structure = useMemo(
() => () =>
menuDesignOptionsStructure( menuDesignOptionsStructure(
Design.designConfig.data.id, Design.designConfig.data.id,
Design.patternConfig.options, Design.patternConfig.options,
state.settings settings
), ),
[Design.designConfig.data.id, Design.patternConfig, state.settings] [Design.designConfig.data.id, Design.patternConfig, settings]
) )
return ( return (

View file

@ -10,6 +10,7 @@ export const UiPreferencesMenu = ({ update, state, Design }) => {
const structure = menuUiPreferencesStructure() const structure = menuUiPreferencesStructure()
const drillProps = { Design, state, update } const drillProps = { Design, state, update }
const { settings = {} } = state // Guard against undefined settings
const inputs = { const inputs = {
aside: (props) => <MenuListInput {...drillProps} {...props} />, aside: (props) => <MenuListInput {...drillProps} {...props} />,
ux: (props) => <MenuUxSettingInput {...drillProps} {...props} />, ux: (props) => <MenuUxSettingInput {...drillProps} {...props} />,
@ -37,7 +38,7 @@ export const UiPreferencesMenu = ({ update, state, Design }) => {
language: state.locale, language: state.locale,
passProps: { passProps: {
ux: state.ui?.ux, ux: state.ui?.ux,
settings: state.settings, settings,
patternConfig: Design.patternConfig, patternConfig: Design.patternConfig,
}, },
updateHandler: update.ui, updateHandler: update.ui,

View file

@ -21,7 +21,7 @@ import { yaml as yamlLang } from '@codemirror/lang-yaml'
* @param {Object} props.update - Helper object for updating the editor state * @param {Object} props.update - Helper object for updating the editor state
*/ */
export const EditSettingsView = (props) => { export const EditSettingsView = (props) => {
const [settings, setSettings] = useState(props.state.settings) const [settings, setSettings] = useState(props.state?.settings || {})
const { state, config, update } = props const { state, config, update } = props
return ( return (
@ -49,21 +49,22 @@ export const PrimedSettingsEditor = (props) => {
* Destructure props * Destructure props
*/ */
const { state } = props const { state } = props
const stateSettings = state.settings || {} // Guard against undefined settings
/* /*
* React state * React state
*/ */
/* eslint-disable-next-line no-unused-vars */ /* eslint-disable-next-line no-unused-vars */
const [settings, update, setSettings] = useStateObject(state.settings) // Holds the settings const [settings, update, setSettings] = useStateObject(stateSettings) // Holds the settings
const [showDelta, setShowDelta] = useState(false) const [showDelta, setShowDelta] = useState(false)
const [localYaml, setLocalYaml] = useState(yaml.stringify(state.settings)) // Holds the settings as YAML const [localYaml, setLocalYaml] = useState(yaml.stringify(stateSettings)) // Holds the settings as YAML
/* /*
* Method to revert to the settings in the editor state * Method to revert to the settings in the editor state
*/ */
const revert = () => { const revert = () => {
setSettings(clone(state.settings)) setSettings(clone(stateSettings))
setLocalYaml(yaml.stringify(state.settings)) setLocalYaml(yaml.stringify(stateSettings))
} }
/* /*
@ -79,7 +80,7 @@ export const PrimedSettingsEditor = (props) => {
* Handle settings delta * Handle settings delta
*/ */
const delta = const delta =
diffCheck(yaml.stringify(state.settings), yaml.stringify(settings)).length > 1 ? true : false diffCheck(yaml.stringify(stateSettings), yaml.stringify(settings)).length > 1 ? true : false
const onChangeYaml = (input) => { const onChangeYaml = (input) => {
let newSettings let newSettings
@ -131,7 +132,7 @@ export const PrimedSettingsEditor = (props) => {
{showDelta ? ( {showDelta ? (
<div className="tw:my-4 tw:w-full tw:overflow-scroll"> <div className="tw:my-4 tw:w-full tw:overflow-scroll">
<DiffViewer <DiffViewer
oldValue={yaml.stringify(state.settings)} oldValue={yaml.stringify(stateSettings)}
newValue={yaml.stringify(settings)} newValue={yaml.stringify(settings)}
extraLinesSurroundingDiff="1" extraLinesSurroundingDiff="1"
fromTitle="Currently deployed settings" fromTitle="Currently deployed settings"

View file

@ -22,6 +22,7 @@ import { EditIcon, CodeIcon, TipIcon, PrintIcon } from '@freesewing/react/compon
*/ */
export const ExportView = (props) => { export const ExportView = (props) => {
const { config, state, update } = props const { config, state, update } = props
const { settings = {} } = state // Guard against undefined settings
const [link, setLink] = useState(false) const [link, setLink] = useState(false)
const [format, setFormat] = useState(false) const [format, setFormat] = useState(false)
@ -41,7 +42,7 @@ export const ExportView = (props) => {
design: props.design, design: props.design,
Design: props.Design, Design: props.Design,
ui: props.state.ui, ui: props.state.ui,
settings: props.state.settings, settings,
setLink, setLink,
setFormat, setFormat,
startLoading: update.startLoading, startLoading: update.startLoading,

View file

@ -24,6 +24,7 @@ import { DraftErrorHandler } from './DraftErrorHandler.mjs'
* @return {function} DraftView - React component * @return {function} DraftView - React component
*/ */
export const InspectView = ({ Design, state, update, config }) => { export const InspectView = ({ Design, state, update, config }) => {
const { settings = {} } = state // Guard against undefined settings
const { setModal, clearModal, modalContent } = useContext(ModalContext) const { setModal, clearModal, modalContent } = useContext(ModalContext)
const info = { const info = {
@ -48,7 +49,7 @@ export const InspectView = ({ Design, state, update, config }) => {
/* /*
* First, attempt to draft * First, attempt to draft
*/ */
const { pattern, failure, errors } = draft(Design, state.settings) const { pattern, failure, errors } = draft(Design, settings)
/* /*
* Create object holding strings for translation * Create object holding strings for translation

View file

@ -21,7 +21,8 @@ const levels = ['error', 'warn', 'info', 'debug']
*/ */
export const LogView = (props) => { export const LogView = (props) => {
const { state, config, update } = props const { state, config, update } = props
const { pattern } = draft(props.Design, state.settings) const { settings = {} } = state // Guard against undefined settings
const { pattern } = draft(props.Design, settings)
return ( return (
<> <>

View file

@ -23,6 +23,7 @@ import { HeaderMenu } from '../HeaderMenu.mjs'
* @param {Object} props.update - Helper object for updating the editor state * @param {Object} props.update - Helper object for updating the editor state
*/ */
export const SaveView = ({ config, state, update }) => { export const SaveView = ({ config, state, update }) => {
const { settings = {} } = state // Guard against undefined settings
// Hooks // Hooks
const backend = useBackend() const backend = useBackend()
@ -34,7 +35,7 @@ export const SaveView = ({ config, state, update }) => {
const [saveAs] = useState(false) // FIXME const [saveAs] = useState(false) // FIXME
const addSettingsToNotes = () => { const addSettingsToNotes = () => {
setNotes(notes + '\n\n#### Settings\n\n```yaml\n' + yaml.dump(state.settings) + '\n````') setNotes(notes + '\n\n#### Settings\n\n```yaml\n' + yaml.dump(settings) + '\n````')
} }
const saveAsNewPattern = async () => { const saveAsNewPattern = async () => {
@ -44,7 +45,7 @@ export const SaveView = ({ config, state, update }) => {
design: state.design, design: state.design,
name, name,
public: false, public: false,
settings: state.settings, settings,
data: {}, data: {},
} }
if (withNotes) patternData.notes = notes if (withNotes) patternData.notes = notes
@ -69,7 +70,7 @@ export const SaveView = ({ config, state, update }) => {
setLoadingStatus([true, 'Saving pattern...']) setLoadingStatus([true, 'Saving pattern...'])
const patternData = { const patternData = {
design: state.design, design: state.design,
settings: state.settings, settings,
name, name,
public: false, public: false,
data: {}, data: {},

View file

@ -143,14 +143,15 @@ export const TestView = ({ Design, state, update, config }) => {
} }
const SampleOptionsMenu = ({ Design, state, update }) => { const SampleOptionsMenu = ({ Design, state, update }) => {
const { settings = {} } = state // Guard against undefined settings
const structure = useMemo( const structure = useMemo(
() => () =>
menuDesignOptionsStructure( menuDesignOptionsStructure(
Design.designConfig.data.id, Design.designConfig.data.id,
Design.patternConfig.options, Design.patternConfig.options,
state.settings settings
), ),
[Design.designConfig.data.id, Design.patternConfig, state.settings] [Design.designConfig.data.id, Design.patternConfig, settings]
) )
return <SampleOptionsSubMenu structure={structure} update={update} /> return <SampleOptionsSubMenu structure={structure} update={update} />

View file

@ -17,6 +17,7 @@ import { getUndoStepData } from '../../lib/index.mjs'
* @param {object} update - ViewWrapper state update object * @param {object} update - ViewWrapper state update object
*/ */
export const UndosView = ({ Design, update, state, config }) => { export const UndosView = ({ Design, update, state, config }) => {
const { settings = {} } = state // Guard against undefined settings
const steps = orderBy(state._.undos, 'time', 'desc') const steps = orderBy(state._.undos, 'time', 'desc')
return ( return (
@ -32,7 +33,7 @@ export const UndosView = ({ Design, update, state, config }) => {
<p>For example, you can click the button below to change the pattern rotation:</p> <p>For example, you can click the button below to change the pattern rotation:</p>
<button <button
className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize" className="tw:daisy-btn tw:daisy-btn-primary tw:capitalize"
onClick={() => update.settings('ui.rotate', state.settings?.ui?.rotate ? 0 : 1)} onClick={() => update.settings('ui.rotate', settings.ui?.rotate ? 0 : 1)}
> >
Example: Rotate pattern Example: Rotate pattern
</button> </button>
@ -71,6 +72,7 @@ export const UndoStepTimeAgo = ({ step }) => {
} }
export const UndoStep = ({ update, state, step, Design, compact = false, index = 0 }) => { export const UndoStep = ({ update, state, step, Design, compact = false, index = 0 }) => {
const { settings = {} } = state // Guard against undefined settings
/* /*
* Ensure path is always an array * Ensure path is always an array
*/ */
@ -79,7 +81,7 @@ export const UndoStep = ({ update, state, step, Design, compact = false, index =
/* /*
* Figure this out once * Figure this out once
*/ */
const imperial = state.settings?.units === 'imperial' ? true : false const imperial = settings.units === 'imperial' ? true : false
/* /*
* Metadata can be ignored * Metadata can be ignored

View file

@ -157,6 +157,7 @@ export const Editor = ({
* @param (object) props.config - The editor config * @param (object) props.config - The editor config
*/ */
const viewfinder = ({ design, designs, state, config }) => { const viewfinder = ({ design, designs, state, config }) => {
const { settings = {} } = state // Guard against undefined settings
/* /*
* Grab Design from props or state and make them extra props * Grab Design from props or state and make them extra props
*/ */
@ -174,7 +175,7 @@ const viewfinder = ({ design, designs, state, config }) => {
*/ */
const [measurementsOk, missingMeasurements] = hasRequiredMeasurements( const [measurementsOk, missingMeasurements] = hasRequiredMeasurements(
designs[design], designs[design],
state.settings?.measurements settings.measurements
) )
if (missingMeasurements) extraProps.missingMeasurements = missingMeasurements if (missingMeasurements) extraProps.missingMeasurements = missingMeasurements

View file

@ -111,7 +111,8 @@ export function menuDesignOptionsStructure(design, options, settings, asFullList
* Since these structures can be nested with option groups, this needs some extra logic * Since these structures can be nested with option groups, this needs some extra logic
*/ */
export function getOptionStructure(option, Design, state) { export function getOptionStructure(option, Design, state) {
const structure = menuDesignOptionsStructure(Design.patternConfig.options, state.settings) const { settings = {} } = state // Guard against undefined settings
const structure = menuDesignOptionsStructure(Design.patternConfig.options, settings)
return findOption(structure, option) return findOption(structure, option)
} }

View file

@ -159,10 +159,11 @@ export function getUiPreferenceUndoStepData({ step }) {
export function getCoreSettingUndoStepData({ step, state, Design }) { export function getCoreSettingUndoStepData({ step, state, Design }) {
const field = step.path[1] const field = step.path[1]
const { settings = {} } = state // Guard against undefined settings
const structure = menuCoreSettingsStructure({ const structure = menuCoreSettingsStructure({
language: state.language, language: state.language,
units: state.settings.units, units: settings.units,
sabool: state.settings.sabool, sabool: settings.sabool,
parts: Design.patternConfig.draftOrder, parts: Design.patternConfig.draftOrder,
}) })