Add actor generation form - #74
Conversation
I implemented the actor-generation route with Formisch and Valibot validation, Kobalte controls, Relay global-ID mutation input, loading state, and distinct GraphQL, domain, and network error handling. Codex reviewed and explained the Relay and generated-type behavior, then made focused edits to route Kobalte numeric values into Formisch, correct a generated import suffix and typo, and resolve lint findings. I retained the design and implementation decisions. Codex ran the full repository check successfully. I will manually verify the UI before submitting the pull request. Assisted-by: Codex:gpt-5.6-sol
99fe1a6 to
68d9e61
Compare
|
Testing in progress |
I pinned Seroval 1.5.4 in the web package so Solid Relay uses the same OpaqueReference implementation as Solid SSR, preventing serialization failures when entering preloaded dynamic routes. Codex diagnosed the upstream peer-version mismatch and applied the dependency and lockfile changes. I confirmed the fix in the development environment by entering the instance route and observing its GraphQL query execute normally. Codex ran mise run check, mise run build, mise run test, and an SSR request to the affected dynamic route successfully. Assisted-by: Codex:gpt-5.6-sol
|
How about add 'useNavigate'? |
|
@dodok8 navigate to instance detail page? |
|
Yes. |
| const result = response.generateActors; | ||
| switch (result.resultType) { | ||
| case "CreateActorsSuccess": { | ||
| navigate(-1); |
There was a problem hiding this comment.
How about using navigate(-1), using more detatiled URL?
There was a problem hiding this comment.
Sorry, do you mean explicit URL rather than navigate(-1)? If so, I have been working on navigating to instance detail page with explicit URL and popping up success toast.
Navigate to the selected instance by slug after actor creation and refresh its cached actor list. Add a persistent Kobalte toast region with a dismissible success notification. Use the number field rawValue prop so clearing the actor count leaves the input editable. Codex generated these changes at my request. I verified that the toast worked and reported the empty-input NaN bug, which guided the subsequent input fix. The input fix has not been browser-verified. Validation: mise run check and mise run test (including the build) passed; lint reports a callback statement-count warning. Assisted-by: Codex:gpt-6-astra
| case "%other": { | ||
| setErrorMessage("Unable to generate actors."); | ||
| return; | ||
| } |
There was a problem hiding this comment.
This branch is unnecessary because it's same with default branch.
There was a problem hiding this comment.
without it, it violates lint rules. not satisfying the exhaustiveness check.
There was a problem hiding this comment.
I don't think it is a good rule... The default branch can take the role of the case "%other" branch. You can turn off the rule by adding "typescript/switch-exhaustiveness-check": ["error", { "considerDefaultExhaustiveForUnions": true }], in rules of .oxlintrc.json.
There was a problem hiding this comment.
Turning off that lint error won't trigger a lint error for a new union members. if we keep that intentional, then we can turn it off, remove %other branch, and only leave a generic fallback (default). we can leave a comment above. hows that sound
| case "CreateActorsError": { | ||
| switch (result.type) { | ||
| case "InvalidSize": { | ||
| setErrorMessage("Enter at least one actor."); | ||
| return; | ||
| } | ||
| case "InstanceNotFound": { | ||
| setErrorMessage( | ||
| "The selected instance could not be found or is no longer available.", | ||
| ); | ||
| return; | ||
| } | ||
| case "TooManyActors": { | ||
| setErrorMessage(result.message); | ||
| return; | ||
| } | ||
| case "%future added value": { | ||
| setErrorMessage( | ||
| "The server returned an unsupported actor-generation error.", | ||
| ); | ||
| return; | ||
| } | ||
| default: { | ||
| setErrorMessage("Unable to generate actors."); | ||
| return; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
I think it would be OK for now with following:
case "CreateActorsError": {
setErrorMessage(result.message);
return;
}Or,
case "CreateActorsError": {
if (["InvalidSize", "InstanceNotFound", "TooManyActors"].includes(result.type)) {
setErrorMessage(result.message);
} else {
setErrorMessage("Internal error.");
}
return;
}There was a problem hiding this comment.
They are meant to be shown to users. I don't think sending API error message directly to users is ideal.
There was a problem hiding this comment.
In fundamental, that's correct, but currently the error messages between both sides aren't that different and it seems like they'll be similar later on too. Also, the code is getting too long. If it still feels a bit off, how about something like this:
const ERROR_MESSAGES_BY_TYPE = {
// [ERROR_TYPE]: ERROR_MESSAGE
}
// ...
if (result.type in ERROR_MESSAGES_BY_TYPE) {
setErrorMessage(ERROR_MESSAGES_BY_TYPE[result.type]);
} else {
setErrorMessage("Internal error.");
}If the logic for each branch ends up being very different later, the current code might be better.
| case "%other": { | ||
| setErrorMessage("Unable to generate actors."); | ||
| return; | ||
| } |
There was a problem hiding this comment.
I don't think it is a good rule... The default branch can take the role of the case "%other" branch. You can turn off the rule by adding "typescript/switch-exhaustiveness-check": ["error", { "considerDefaultExhaustiveForUnions": true }], in rules of .oxlintrc.json.
| store.get(instance)?.invalidateRecord(); | ||
| } | ||
| }, | ||
| onCompleted: (response, errors) => { |
There was a problem hiding this comment.
By the way, the max-statements lint warning shows on the onCompleted callback.
| case "CreateActorsError": { | ||
| switch (result.type) { | ||
| case "InvalidSize": { | ||
| setErrorMessage("Enter at least one actor."); | ||
| return; | ||
| } | ||
| case "InstanceNotFound": { | ||
| setErrorMessage( | ||
| "The selected instance could not be found or is no longer available.", | ||
| ); | ||
| return; | ||
| } | ||
| case "TooManyActors": { | ||
| setErrorMessage(result.message); | ||
| return; | ||
| } | ||
| case "%future added value": { | ||
| setErrorMessage( | ||
| "The server returned an unsupported actor-generation error.", | ||
| ); | ||
| return; | ||
| } | ||
| default: { | ||
| setErrorMessage("Unable to generate actors."); | ||
| return; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
In fundamental, that's correct, but currently the error messages between both sides aren't that different and it seems like they'll be similar later on too. Also, the code is getting too long. If it still feels a bit off, how about something like this:
const ERROR_MESSAGES_BY_TYPE = {
// [ERROR_TYPE]: ERROR_MESSAGE
}
// ...
if (result.type in ERROR_MESSAGES_BY_TYPE) {
setErrorMessage(ERROR_MESSAGES_BY_TYPE[result.type]);
} else {
setErrorMessage("Internal error.");
}If the logic for each branch ends up being very different later, the current code might be better.

Closes #41
AI assistance
Used Codex (
gpt-5.6-sol) to review the Relay/Formisch/Kobalte integration and make focused corrections to numeric input binding, an import suffix, a typo, and lint issues. I reviewed and retained the design and implementation decisions.