mirror of
https://github.com/Donkie/Spoolman.git
synced 2026-10-22 01:52:17 -05:00
client_v2: require the material when creating a filament
Leaving Material blank sent you to Density instead. Density is only prefilled for a material Spoolman recognises, so a blank material surfaced as "Density is required" — an error on the field you didn't fill in because of the field you did miss, and inside the collapsed Advanced block at that. Material is now required on this form, so the error lands on the field that actually needs attention and Advanced stays shut. Typing a material we don't have specs for still asks for a density afterwards, which is the right order to be asked in. Client-side only: the API still accepts a filament with no material, so existing ones are unaffected.
This commit is contained in:
1 parent
aec9b276b2
commit
2d08061c45
2 files changed
+13
-1
No files matched your search
@@ -500,6 +500,11 @@
|
||||
// Mirrors the filament creation API (spoolman/api/v1/filament.py):
|
||||
// density & diameter are required and must be > 0; name/material ≤ 64 chars;
|
||||
// weight > 0, spool_weight/price ≥ 0; color_hex must be 6 or 8 hex chars.
|
||||
// Material is the one field this form is stricter about than the API, which
|
||||
// accepts a null one. Leaving it blank is nearly always an oversight, and it
|
||||
// takes density down with it: density is only prefilled for a material we
|
||||
// recognise, so a blank material surfaced as "Density is required" — an error
|
||||
// on the field the user didn't fill in *because of* the field they did miss.
|
||||
function numErr(
|
||||
v: string,
|
||||
{ required = false, min, max, gt }: { required?: boolean; min?: number; max?: number; gt?: number } = {}
|
||||
@@ -520,7 +525,8 @@
|
||||
if (creating) {
|
||||
if (nf.name.trim().length === 0) e.name = m['validation.required']();
|
||||
else if (nf.name.trim().length > 64) e.name = m['validation.maxChars']({ max: 64 });
|
||||
if (nf.material.trim().length > 64) e.material = m['validation.maxChars']({ max: 64 });
|
||||
if (nf.material.trim().length === 0) e.material = m['validation.required']();
|
||||
else if (nf.material.trim().length > 64) e.material = m['validation.maxChars']({ max: 64 });
|
||||
if (nf.vendorName.trim().length > 64) e.vendor = m['validation.maxChars']({ max: 64 });
|
||||
e.density = numErr(nf.density, { required: true, gt: 0 });
|
||||
e.diameter = numErr(nf.diameter, { required: true, gt: 0 });
|
||||
@@ -771,10 +777,12 @@
|
||||
</label>
|
||||
<label data-field="material" onfocusout={() => touch('material')}>
|
||||
{m['filament.fields.material']()}
|
||||
{@render req()}
|
||||
<Combobox
|
||||
value={nf.material}
|
||||
options={materialNames}
|
||||
placeholder="PLA"
|
||||
required
|
||||
invalid={!!err('material')}
|
||||
oninput={onMaterial}
|
||||
/>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
placeholder?: string;
|
||||
mono?: boolean;
|
||||
invalid?: boolean;
|
||||
/** Announce the field as required. The visible marker is the caller's `*`. */
|
||||
required?: boolean;
|
||||
disabled?: boolean;
|
||||
/** Dashed-underline style (matches EditableField) instead of the bordered
|
||||
* box style used in forms. */
|
||||
@@ -24,6 +26,7 @@
|
||||
placeholder = '',
|
||||
mono = false,
|
||||
invalid = false,
|
||||
required = false,
|
||||
disabled = false,
|
||||
underline = false,
|
||||
oninput,
|
||||
@@ -162,6 +165,7 @@
|
||||
aria-labelledby={ariaLabel ? undefined : fieldLabelId}
|
||||
aria-autocomplete="list"
|
||||
aria-invalid={invalid ? 'true' : undefined}
|
||||
aria-required={required ? 'true' : undefined}
|
||||
autocomplete="off"
|
||||
onfocus={openList}
|
||||
onclick={openList}
|
||||
|
||||
Reference in new issue
Block a user