feat(locations): validate Create Storage Location form (ARTESCA-4665) - #1199
Conversation
- add Joi schemas covering required fields for every location type - migrate LocationEditor to react-hook-form + joiResolver - validate Location Name inline ([a-z0-9-]+, max 63 chars) - drop locationFormCheck.ts (replaced by the schemas) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hello jeanmarcmilletscality,My role is to assist you with the merge of this Available options
Available commands
Status report is not available. |
Request integration branchesWaiting for integration branch creation to be requested by the user. To request integration branches, please comment on this pull request with the following command: Alternatively, the |
Waiting for approvalThe following approvals are needed before I can proceed with the merge:
Peer approvals must include at least 1 approval from the following list: |
Waiting for approvalThe following approvals are needed before I can proceed with the merge:
Peer approvals must include at least 1 approval from the following list: |
Summary
Fixes ARTESCA-4665 — the Create / Save Changes button on the Storage Location editor was enabled even when required fields were empty. The button is now disabled until the form is valid for the selected location type.
Validation is driven by a Joi schema (react-hook-form +
joiResolver, matching the pattern already used inEndpointCreate,AccountCreate, and the ISV engine) keyed offlocationType. Every storage type that has a form is covered: AWS, AWS Custom variants (ARTESCA, RING, Ceph, Atlas, Outscale Public/SNC, Orange OBS), GCP, Wasabi, DO Spaces, Oracle, Azure (with auth-type conditionals), Azure Archive (with queue + auth conditionals), Cold Locations (4 providers × polling/SQS queue), Hyperdrive V2, Sproxyd, Tape DMF, Tape Miria, CRR, and NFS.Secret fields stay optional in edit mode so existing locations can be saved without re-entering credentials (the children already clear them on mount).
What's in this PR
src/react/locations/schemas.ts(new) —buildLocationSchema(isEdit)returns a single Joi schema withJoi.alternatives().conditionalswitching thedetailsvalidation bylocationType. Helpers (reqStr,urlField,httpUrlField,editableSecret,nonEmptyListField) keep each per-type schema readable.src/react/locations/LocationEditor.tsx— switched fromuseState+locationFormChecktouseForm+joiResolver+FormProvider. Top-level Location Name is validated inline (/^[a-z0-9-]+$/, max 63 chars) matching the existing tooltip rule. The Create button usesdisabled={!isValid || loading || !isLocationExists(...)}. Component is split into outer (data fetching) + inner (useForm) so the resolver captures the correcteditingExistingvalue once the fetch completes.src/react/locations/locationFormCheck.ts(deleted) — its sparse per-type checks (NFS / Tape Miria / CRR only) are now part of the Joi schemas.LocationEditor.test.tsx— added two tests:accessKey/secretKey/bucketNameare all filled.Scope — what is not in this PR
This PR fixes the bug at the form level: the Create button can no longer submit an invalid form, regardless of type. It does not add inline "Field is required" errors inside the details panel for every individual field. That would require migrating each of the 14
LocationDetails*.tsxcomponents from its current class / local-state shape touseFormContextso eachFormGroupcan readerrors.details.<field>?.message. That refactor is ~3000 LOC of mechanical rewrites and is better suited to a follow-up PR.What you still get for inline per-field errors today:
How the bridge works without rewriting the children: each
LocationDetails*keeps its existingprops.onChange(details)callback.LocationEditorintercepts that callback and routes it tosetValue('details', details, { shouldValidate: true }). The Joi schema then validates whatever lands in the form values —isValidflips correctly even though the children never touch react-hook-form directly.Test plan
npm run check-types— cleannpx biome check src/react/locations/LocationEditor.tsx— clean (one pre-existing warning unchanged)npm test -- --testPathPattern="src/react/locations"— 150 passing / 6 pre-existing skips / 0 new failures🤖 Generated with Claude Code