mirror of
https://github.com/nowcommunity/nowdatabase.git
synced 2026-10-12 19:13:52 +03:00
Enforce integer ranges for numeric fields
This commit is contained in:
@@ -129,9 +129,12 @@ export const ClimateTab = () => {
|
||||
]
|
||||
|
||||
const pollenRecord = [
|
||||
['Arboreal pollen (AP%)', textField('pers_pollen_ap', { type: 'number' })],
|
||||
['Non-arboreal pollen (NAP%)', textField('pers_pollen_nap', { type: 'number' })],
|
||||
['Other pollen (OP%)', textField('pers_pollen_other', { type: 'number' })],
|
||||
['Arboreal pollen (AP%)', textField('pers_pollen_ap', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
[
|
||||
'Non-arboreal pollen (NAP%)',
|
||||
textField('pers_pollen_nap', { type: 'number', integerOnly: true, min: 0, max: 100 }),
|
||||
],
|
||||
['Other pollen (OP%)', textField('pers_pollen_other', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
]
|
||||
|
||||
const pollenTotalError = ['pers_pollen_ap', 'pers_pollen_nap', 'pers_pollen_other']
|
||||
|
||||
@@ -13,8 +13,11 @@ export const EcometricsTab = () => {
|
||||
textField('estimate_precip', { type: 'number', integerOnly: true, min: 0 }),
|
||||
],
|
||||
['Estimate of mean annual temperature (°C)', textField('estimate_temp', { type: 'number' })],
|
||||
['Estimate of net primary productivity (g/m2/yr)', textField('estimate_npp', { type: 'number' })],
|
||||
['Woody cover percentage', textField('pers_woody_cover', { type: 'number' })],
|
||||
[
|
||||
'Estimate of net primary productivity (g/m2/yr)',
|
||||
textField('estimate_npp', { type: 'number', integerOnly: true, min: 0 }),
|
||||
],
|
||||
['Woody cover percentage', textField('pers_woody_cover', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
]
|
||||
|
||||
return (
|
||||
|
||||
@@ -135,7 +135,7 @@ export const LocalityTab = () => {
|
||||
'Approximate Coordinates'
|
||||
),
|
||||
],
|
||||
['Altitude (m)', textField('altitude')],
|
||||
['Altitude (m)', textField('altitude', { type: 'number', integerOnly: true, min: -500, max: 9000 })],
|
||||
]
|
||||
|
||||
const { notify } = useNotify()
|
||||
|
||||
@@ -118,9 +118,9 @@ export const TaphonomyTab = () => {
|
||||
const taphonomy = [
|
||||
['Time Represented (years)', dropdown('time_rep', timeRepresentedOptions, 'Time Represented (years)')],
|
||||
['Vertebrate Preservation', dropdown('vert_pres', vertebratePreservationOptions, 'Vertebrate Preservation')],
|
||||
['Approx. Number of Specimens', textField('appr_num_spm', { type: 'number' })],
|
||||
['Exact Number of Specimens', textField('num_spm', { type: 'number' })],
|
||||
['Number of Quadrats', textField('num_quad', { type: 'number' })],
|
||||
['Approx. Number of Specimens', textField('appr_num_spm', { type: 'number', integerOnly: true, min: 1 })],
|
||||
['Exact Number of Specimens', textField('num_spm', { type: 'number', integerOnly: true, min: 1 })],
|
||||
['Number of Quadrats', textField('num_quad', { type: 'number', integerOnly: true, min: 1 })],
|
||||
['Unbiased Collecting', dropdown('true_quant', unbiasedCollectingOptions, 'Unbiased Collecting')],
|
||||
['Species List Complete', dropdown('complete', speciesListCompleteOptions, 'Species List Complete')],
|
||||
]
|
||||
|
||||
@@ -43,10 +43,19 @@ export const OccurrenceCoreTab = () => {
|
||||
key="counts"
|
||||
title="Occurrence counts"
|
||||
array={[
|
||||
['NISP', mode.read ? toText(sourceData.nis) : textField('nis', { type: 'number' })],
|
||||
[
|
||||
'NISP',
|
||||
mode.read ? toText(sourceData.nis) : textField('nis', { type: 'number', integerOnly: true, min: 1 }),
|
||||
],
|
||||
['Percent', mode.read ? toText(sourceData.pct) : textField('pct', { type: 'number' })],
|
||||
['Quadrate', mode.read ? toText(sourceData.quad) : textField('quad', { type: 'number' })],
|
||||
['MNI', mode.read ? toText(sourceData.mni) : textField('mni', { type: 'number' })],
|
||||
[
|
||||
'Quadrate',
|
||||
mode.read ? toText(sourceData.quad) : textField('quad', { type: 'number', integerOnly: true, min: 1 }),
|
||||
],
|
||||
[
|
||||
'MNI',
|
||||
mode.read ? toText(sourceData.mni) : textField('mni', { type: 'number', integerOnly: true, min: 1 }),
|
||||
],
|
||||
['Quantity', mode.read ? formatQuantity(sourceData.qua) : dropdown('qua', quantityOptions, 'Quantity')],
|
||||
]}
|
||||
/>,
|
||||
@@ -54,7 +63,12 @@ export const OccurrenceCoreTab = () => {
|
||||
</HalfFrames>
|
||||
<ArrayFrame
|
||||
array={[
|
||||
['Body Mass (g)', mode.read ? toText(sourceData.body_mass) : textField('body_mass', { type: 'number' })],
|
||||
[
|
||||
'Body Mass (g)',
|
||||
mode.read
|
||||
? toText(sourceData.body_mass)
|
||||
: textField('body_mass', { type: 'number', integerOnly: true, min: 1 }),
|
||||
],
|
||||
]}
|
||||
title="Size"
|
||||
/>
|
||||
|
||||
@@ -16,7 +16,12 @@ export const OccurrenceIsotopeTab = () => {
|
||||
title="δ13C"
|
||||
array={[
|
||||
['Mean', mode.read ? toText(sourceData.dc13_mean) : textField('dc13_mean', { type: 'number' })],
|
||||
['N', mode.read ? toText(sourceData.dc13_n) : textField('dc13_n', { type: 'number' })],
|
||||
[
|
||||
'N',
|
||||
mode.read
|
||||
? toText(sourceData.dc13_n)
|
||||
: textField('dc13_n', { type: 'number', integerOnly: true, min: 1 }),
|
||||
],
|
||||
['Max', mode.read ? toText(sourceData.dc13_max) : textField('dc13_max', { type: 'number' })],
|
||||
['Min', mode.read ? toText(sourceData.dc13_min) : textField('dc13_min', { type: 'number' })],
|
||||
['Stdev', mode.read ? toText(sourceData.dc13_stdev) : textField('dc13_stdev', { type: 'number' })],
|
||||
@@ -27,7 +32,12 @@ export const OccurrenceIsotopeTab = () => {
|
||||
title="δ18O"
|
||||
array={[
|
||||
['Mean', mode.read ? toText(sourceData.do18_mean) : textField('do18_mean', { type: 'number' })],
|
||||
['N', mode.read ? toText(sourceData.do18_n) : textField('do18_n', { type: 'number' })],
|
||||
[
|
||||
'N',
|
||||
mode.read
|
||||
? toText(sourceData.do18_n)
|
||||
: textField('do18_n', { type: 'number', integerOnly: true, min: 1 }),
|
||||
],
|
||||
['Max', mode.read ? toText(sourceData.do18_max) : textField('do18_max', { type: 'number' })],
|
||||
['Min', mode.read ? toText(sourceData.do18_min) : textField('do18_min', { type: 'number' })],
|
||||
['Stdev', mode.read ? toText(sourceData.do18_stdev) : textField('do18_stdev', { type: 'number' })],
|
||||
|
||||
@@ -33,11 +33,36 @@ export const OccurrenceWearTab = () => {
|
||||
'Mesowear',
|
||||
mode.read ? formatMesowear(sourceData.mesowear) : dropdown('mesowear', mesowearOptions, 'Mesowear'),
|
||||
],
|
||||
['MW OR High', mode.read ? toText(sourceData.mw_or_high) : textField('mw_or_high', { type: 'number' })],
|
||||
['MW OR Low', mode.read ? toText(sourceData.mw_or_low) : textField('mw_or_low', { type: 'number' })],
|
||||
['MW CS Sharp', mode.read ? toText(sourceData.mw_cs_sharp) : textField('mw_cs_sharp', { type: 'number' })],
|
||||
['MW CS Round', mode.read ? toText(sourceData.mw_cs_round) : textField('mw_cs_round', { type: 'number' })],
|
||||
['MW CS Blunt', mode.read ? toText(sourceData.mw_cs_blunt) : textField('mw_cs_blunt', { type: 'number' })],
|
||||
[
|
||||
'MW OR High',
|
||||
mode.read
|
||||
? toText(sourceData.mw_or_high)
|
||||
: textField('mw_or_high', { type: 'number', integerOnly: true, min: 0, max: 100 }),
|
||||
],
|
||||
[
|
||||
'MW OR Low',
|
||||
mode.read
|
||||
? toText(sourceData.mw_or_low)
|
||||
: textField('mw_or_low', { type: 'number', integerOnly: true, min: 0, max: 100 }),
|
||||
],
|
||||
[
|
||||
'MW CS Sharp',
|
||||
mode.read
|
||||
? toText(sourceData.mw_cs_sharp)
|
||||
: textField('mw_cs_sharp', { type: 'number', integerOnly: true, min: 0, max: 100 }),
|
||||
],
|
||||
[
|
||||
'MW CS Round',
|
||||
mode.read
|
||||
? toText(sourceData.mw_cs_round)
|
||||
: textField('mw_cs_round', { type: 'number', integerOnly: true, min: 0, max: 100 }),
|
||||
],
|
||||
[
|
||||
'MW CS Blunt',
|
||||
mode.read
|
||||
? toText(sourceData.mw_cs_blunt)
|
||||
: textField('mw_cs_blunt', { type: 'number', integerOnly: true, min: 0, max: 100 }),
|
||||
],
|
||||
]}
|
||||
/>,
|
||||
<div key="wear-score-and-microwear">
|
||||
@@ -47,11 +72,15 @@ export const OccurrenceWearTab = () => {
|
||||
array={[
|
||||
[
|
||||
'MW scale min',
|
||||
mode.read ? toText(sourceData.mw_scale_min) : textField('mw_scale_min', { type: 'number' }),
|
||||
mode.read
|
||||
? toText(sourceData.mw_scale_min)
|
||||
: textField('mw_scale_min', { type: 'number', integerOnly: true, min: 0 }),
|
||||
],
|
||||
[
|
||||
'MW scale max',
|
||||
mode.read ? toText(sourceData.mw_scale_max) : textField('mw_scale_max', { type: 'number' }),
|
||||
mode.read
|
||||
? toText(sourceData.mw_scale_max)
|
||||
: textField('mw_scale_max', { type: 'number', integerOnly: true, min: 0 }),
|
||||
],
|
||||
['MW value', mode.read ? toText(sourceData.mw_value) : textField('mw_value', { type: 'number' })],
|
||||
['Normalized Score', normalizedScoreText],
|
||||
|
||||
@@ -98,9 +98,13 @@ export const ReferenceTab = () => {
|
||||
? bigTextField(field.field_name! as keyof ReferenceDetailsType)
|
||||
: textField(field.field_name! as keyof ReferenceDetailsType)
|
||||
if (field.field_name && numberFields.includes(field.field_name)) {
|
||||
const isPageField = field.field_name === 'start_page' || field.field_name === 'end_page'
|
||||
nonAuthorFieldsArray.push([
|
||||
field.ref_field_name,
|
||||
textField(field.field_name as keyof ReferenceDetailsType, { type: 'number' }),
|
||||
textField(field.field_name as keyof ReferenceDetailsType, {
|
||||
type: 'number',
|
||||
...(isPageField ? { integerOnly: true, min: 1 } : {}),
|
||||
}),
|
||||
])
|
||||
} else if (field.field_name == 'exact_date') {
|
||||
nonAuthorFieldsArray.push([
|
||||
|
||||
@@ -26,8 +26,8 @@ export const SizeTab = () => {
|
||||
]
|
||||
|
||||
const size = [
|
||||
['Body Mass (g)', textField('body_mass', { type: 'number' })],
|
||||
['Brain Mass (g)', textField('brain_mass', { type: 'number' })],
|
||||
['Body Mass (g)', textField('body_mass', { type: 'number', integerOnly: true, min: 1 })],
|
||||
['Brain Mass (g)', textField('brain_mass', { type: 'number', integerOnly: true, min: 1 })],
|
||||
['Snout-Vent Length', dropdown('sv_length', snoutVentLengthOptions, 'Snout-Vent Length')],
|
||||
]
|
||||
|
||||
|
||||
@@ -135,13 +135,13 @@ export const TeethTab = () => {
|
||||
const mesowear = [
|
||||
['Mesowear'],
|
||||
['Type', dropdown('mesowear', mesowearOptions, 'Type')],
|
||||
['Cusp Relief Low (OR%)', textField('mw_or_low', { type: 'number' })],
|
||||
['Cusp Relief High (OR%)', textField('mw_or_high', { type: 'number' })],
|
||||
['Cusp Shape Sharp (CS%)', textField('mw_cs_sharp', { type: 'number' })],
|
||||
['Cusp Shape Rounded (CS%)', textField('mw_cs_round', { type: 'number' })],
|
||||
['Cusp Shape Blunt (CS%)', textField('mw_cs_blunt', { type: 'number' })],
|
||||
['Scale Minimum', textField('mw_scale_min', { type: 'number' })],
|
||||
['Scale Maximum', textField('mw_scale_max', { type: 'number' })],
|
||||
['Cusp Relief Low (OR%)', textField('mw_or_low', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
['Cusp Relief High (OR%)', textField('mw_or_high', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
['Cusp Shape Sharp (CS%)', textField('mw_cs_sharp', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
['Cusp Shape Rounded (CS%)', textField('mw_cs_round', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
['Cusp Shape Blunt (CS%)', textField('mw_cs_blunt', { type: 'number', integerOnly: true, min: 0, max: 100 })],
|
||||
['Scale Minimum', textField('mw_scale_min', { type: 'number', integerOnly: true, min: 0 })],
|
||||
['Scale Maximum', textField('mw_scale_max', { type: 'number', integerOnly: true, min: 0 })],
|
||||
['Reported Value', textField('mw_value', { type: 'number' })],
|
||||
[
|
||||
'Normalized score',
|
||||
|
||||
@@ -15,7 +15,18 @@ const validatePollenPercentage = (name: string, num: number) => {
|
||||
}
|
||||
|
||||
const validateNonNegativeInteger = (name: string, num: number) => {
|
||||
if (!Number.isInteger(num) || num < 0) return `${name} must be a positive integer.`
|
||||
if (!Number.isInteger(num) || num < 0) return `${name} must be a non-negative integer.`
|
||||
return
|
||||
}
|
||||
|
||||
const validateIntegerInRange = (name: string, num: number, min: number, max: number) => {
|
||||
if (!Number.isInteger(num)) return `${name} must be an integer value`
|
||||
if (num < min || num > max) return `${name} must be between ${min} and ${max}`
|
||||
return
|
||||
}
|
||||
|
||||
const validatePositiveInteger = (name: string, num: number) => {
|
||||
if (!Number.isInteger(num) || num < 1) return `${name} must be a positive integer.`
|
||||
return
|
||||
}
|
||||
|
||||
@@ -202,6 +213,30 @@ export const validateLocality = (
|
||||
name: 'Estimate of annual precipitation (mm)',
|
||||
asNumber: (num: number) => validateNonNegativeInteger('Estimate of annual precipitation (mm)', num),
|
||||
},
|
||||
altitude: {
|
||||
name: 'Altitude (m)',
|
||||
asNumber: (num: number) => validateIntegerInRange('Altitude (m)', num, -500, 9000),
|
||||
},
|
||||
appr_num_spm: {
|
||||
name: 'Approx. Number of Specimens',
|
||||
asNumber: (num: number) => validatePositiveInteger('Approx. Number of Specimens', num),
|
||||
},
|
||||
num_spm: {
|
||||
name: 'Exact Number of Specimens',
|
||||
asNumber: (num: number) => validatePositiveInteger('Exact Number of Specimens', num),
|
||||
},
|
||||
num_quad: {
|
||||
name: 'Number of Quadrats',
|
||||
asNumber: (num: number) => validatePositiveInteger('Number of Quadrats', num),
|
||||
},
|
||||
estimate_npp: {
|
||||
name: 'Estimate of net primary productivity (g/m2/yr)',
|
||||
asNumber: (num: number) => validateNonNegativeInteger('Estimate of net primary productivity (g/m2/yr)', num),
|
||||
},
|
||||
pers_woody_cover: {
|
||||
name: 'Woody cover percentage',
|
||||
asNumber: (num: number) => validateIntegerInRange('Woody cover percentage', num, 0, 100),
|
||||
},
|
||||
}
|
||||
|
||||
return validator<EditDataType<LocalityDetailsType>>(validators, editData, fieldName)
|
||||
|
||||
@@ -23,6 +23,17 @@ const validatePositiveInteger = (name: string, value: number) => {
|
||||
return
|
||||
}
|
||||
|
||||
const validateNonNegativeInteger = (name: string, value: number) => {
|
||||
if (!Number.isInteger(value) || value < 0) return `${name} must be a non-negative integer.`
|
||||
return
|
||||
}
|
||||
|
||||
const validateIntegerInRange = (name: string, value: number, min: number, max: number) => {
|
||||
if (!Number.isInteger(value)) return `${name} must be a whole number.`
|
||||
if (value < min || value > max) return `${name} must be between ${min} and ${max}.`
|
||||
return
|
||||
}
|
||||
|
||||
const validatePositiveDecimal = (name: string, value: number) => {
|
||||
if (!Number.isFinite(value) || value <= 0) return `${name} must be a positive decimal number.`
|
||||
return
|
||||
@@ -61,15 +72,15 @@ export const validateOccurrence = (editData: EditableOccurrenceData, fieldName:
|
||||
body_mass: { name: 'Body mass', asNumber: value => validatePositiveInteger('Body mass', value) },
|
||||
dc13_n: { name: 'δ13C N', asNumber: value => validatePositiveInteger('δ13C N', value) },
|
||||
do18_n: { name: 'δ18O N', asNumber: value => validatePositiveInteger('δ18O N', value) },
|
||||
mw_or_high: { name: 'MW OR High', asNumber: value => validatePositiveInteger('MW OR High', value) },
|
||||
mw_or_low: { name: 'MW OR Low', asNumber: value => validatePositiveInteger('MW OR Low', value) },
|
||||
mw_cs_sharp: { name: 'MW CS Sharp', asNumber: value => validatePositiveInteger('MW CS Sharp', value) },
|
||||
mw_cs_round: { name: 'MW CS Round', asNumber: value => validatePositiveInteger('MW CS Round', value) },
|
||||
mw_cs_blunt: { name: 'MW CS Blunt', asNumber: value => validatePositiveInteger('MW CS Blunt', value) },
|
||||
mw_or_high: { name: 'MW OR High', asNumber: value => validateIntegerInRange('MW OR High', value, 0, 100) },
|
||||
mw_or_low: { name: 'MW OR Low', asNumber: value => validateIntegerInRange('MW OR Low', value, 0, 100) },
|
||||
mw_cs_sharp: { name: 'MW CS Sharp', asNumber: value => validateIntegerInRange('MW CS Sharp', value, 0, 100) },
|
||||
mw_cs_round: { name: 'MW CS Round', asNumber: value => validateIntegerInRange('MW CS Round', value, 0, 100) },
|
||||
mw_cs_blunt: { name: 'MW CS Blunt', asNumber: value => validateIntegerInRange('MW CS Blunt', value, 0, 100) },
|
||||
mw_scale_min: {
|
||||
name: 'Scale Minimum',
|
||||
asNumber: value => {
|
||||
const positivityError = validatePositiveInteger('Scale Minimum', value)
|
||||
const positivityError = validateNonNegativeInteger('Scale Minimum', value)
|
||||
if (positivityError) return positivityError
|
||||
if (hasNumericValue(editData.mw_scale_max) && value > editData.mw_scale_max)
|
||||
return 'Scale Minimum cannot be greater than Scale Maximum.'
|
||||
@@ -79,7 +90,7 @@ export const validateOccurrence = (editData: EditableOccurrenceData, fieldName:
|
||||
mw_scale_max: {
|
||||
name: 'Scale Maximum',
|
||||
asNumber: value => {
|
||||
const positivityError = validatePositiveInteger('Scale Maximum', value)
|
||||
const positivityError = validateNonNegativeInteger('Scale Maximum', value)
|
||||
if (positivityError) return positivityError
|
||||
if (hasNumericValue(editData.mw_scale_min) && value < editData.mw_scale_min)
|
||||
return 'Scale Maximum cannot be less than Scale Minimum.'
|
||||
|
||||
@@ -109,6 +109,13 @@ const yearCheck: (year: number) => ValidationError = (year: number) => {
|
||||
return null
|
||||
}
|
||||
|
||||
const positiveIntegerCheck: (name: string, num: number) => ValidationError = (name: string, num: number) => {
|
||||
if (!Number.isFinite(num)) return `${name} must be a valid number`
|
||||
if (!Number.isInteger(num)) return `${name} must be a whole number`
|
||||
if (num < 1) return `${name} must be a positive integer`
|
||||
return null
|
||||
}
|
||||
|
||||
export type ReferenceFieldDisplayNames = Partial<Record<keyof EditDataType<ReferenceDetailsType>, string>>
|
||||
|
||||
export type ReferenceDisplayLabelMap = Partial<Record<number, ReferenceFieldDisplayNames>>
|
||||
@@ -217,12 +224,19 @@ export const validateReference = (
|
||||
start_page: {
|
||||
name: 'start_page',
|
||||
required: false,
|
||||
asNumber: true,
|
||||
asNumber: (num: number) => positiveIntegerCheck('start_page', num),
|
||||
},
|
||||
end_page: {
|
||||
name: 'end_page',
|
||||
required: false,
|
||||
asNumber: true,
|
||||
asNumber: (num: number) => {
|
||||
const base = positiveIntegerCheck('end_page', num)
|
||||
if (base) return base
|
||||
if (typeof editData.start_page === 'number' && num < editData.start_page) {
|
||||
return 'end_page must be greater than or equal to start_page'
|
||||
}
|
||||
return null
|
||||
},
|
||||
},
|
||||
date_secondary: {
|
||||
name: 'date_secondary',
|
||||
|
||||
@@ -11,6 +11,22 @@ export const validateSpecies = (
|
||||
editData: EditDataType<SpeciesDetailsType>,
|
||||
fieldName: keyof EditDataType<SpeciesDetailsType>
|
||||
) => {
|
||||
const validatePositiveInteger = (name: string, value: number) => {
|
||||
if (!Number.isInteger(value) || value < 1) return `${name} must be a positive integer.`
|
||||
return
|
||||
}
|
||||
|
||||
const validateNonNegativeInteger = (name: string, value: number) => {
|
||||
if (!Number.isInteger(value) || value < 0) return `${name} must be a non-negative integer.`
|
||||
return
|
||||
}
|
||||
|
||||
const validateIntegerInRange = (name: string, value: number, min: number, max: number) => {
|
||||
if (!Number.isInteger(value)) return `${name} must be a whole number.`
|
||||
if (value < min || value > max) return `${name} must be between ${min} and ${max}.`
|
||||
return
|
||||
}
|
||||
|
||||
const validators: Validators<Partial<EditDataType<SpeciesDetailsType>>> = {
|
||||
subclass_or_superorder_name: {
|
||||
name: 'Subclass or Superorder',
|
||||
@@ -103,11 +119,40 @@ export const validateSpecies = (
|
||||
return
|
||||
},
|
||||
},
|
||||
body_mass: {
|
||||
name: 'Body Mass (g)',
|
||||
asNumber: (value: number) => validatePositiveInteger('Body Mass (g)', value),
|
||||
},
|
||||
brain_mass: {
|
||||
name: 'Brain Mass (g)',
|
||||
asNumber: (value: number) => validatePositiveInteger('Brain Mass (g)', value),
|
||||
},
|
||||
mw_or_low: {
|
||||
name: 'Cusp Relief Low (OR%)',
|
||||
asNumber: (value: number) => validateIntegerInRange('Cusp Relief Low (OR%)', value, 0, 100),
|
||||
},
|
||||
mw_or_high: {
|
||||
name: 'Cusp Relief High (OR%)',
|
||||
asNumber: (value: number) => validateIntegerInRange('Cusp Relief High (OR%)', value, 0, 100),
|
||||
},
|
||||
mw_cs_sharp: {
|
||||
name: 'Cusp Shape Sharp (CS%)',
|
||||
asNumber: (value: number) => validateIntegerInRange('Cusp Shape Sharp (CS%)', value, 0, 100),
|
||||
},
|
||||
mw_cs_round: {
|
||||
name: 'Cusp Shape Rounded (CS%)',
|
||||
asNumber: (value: number) => validateIntegerInRange('Cusp Shape Rounded (CS%)', value, 0, 100),
|
||||
},
|
||||
mw_cs_blunt: {
|
||||
name: 'Cusp Shape Blunt (CS%)',
|
||||
asNumber: (value: number) => validateIntegerInRange('Cusp Shape Blunt (CS%)', value, 0, 100),
|
||||
},
|
||||
|
||||
mw_scale_min: {
|
||||
name: 'Scale Minimum',
|
||||
asNumber: (value: number) => {
|
||||
if (value < 0) return 'Scale Minimum cannot be negative.'
|
||||
const nonNegativeError = validateNonNegativeInteger('Scale Minimum', value)
|
||||
if (nonNegativeError) return nonNegativeError
|
||||
if (typeof editData.mw_scale_max === 'number' && value > editData.mw_scale_max)
|
||||
return 'Scale Minimum cannot be greater than Scale Maximum.'
|
||||
return
|
||||
@@ -116,7 +161,8 @@ export const validateSpecies = (
|
||||
mw_scale_max: {
|
||||
name: 'Scale Maximum',
|
||||
asNumber: (value: number) => {
|
||||
if (value < 0) return 'Scale Maximum cannot be negative.'
|
||||
const nonNegativeError = validateNonNegativeInteger('Scale Maximum', value)
|
||||
if (nonNegativeError) return nonNegativeError
|
||||
if (typeof editData.mw_scale_min === 'number' && value < editData.mw_scale_min)
|
||||
return 'Scale Maximum cannot be less than Scale Minimum.'
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user