-
Notifications
You must be signed in to change notification settings - Fork 887
fix: display explicit 'retry' button(s) when a workspace fails #10720
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
const { saveLocal, getLocal } = useLocalStorage(); | ||
|
||
const buildError = Boolean(workspaceErrors[WorkspaceErrors.BUILD_ERROR]) && ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two error JSX elements were moved into the return value, to bring them closer to where they're actually used
// 2023-11-15 - MES - This effect will be called every single render because | ||
// "now" will always change and invalidate the dependency array. Need to | ||
// figure out if this effect really should run every render (possibly meaning | ||
// no dependency array at all), or how to get the array stabilized (ideal) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having the effect re-run every single render isn't ideal, but I don't think it's breaking anything
During the sprint right before Christmas, I'm planning to do an audit for every single useEffect
/useLayoutEffect
call we have. I know we have a couple of other wonky calls, too. Just figured it'd be good to flag this for now, if someone has the bandwidth to fix it early while working on another issue
[ButtonTypesEnum.starting]: ( | ||
// A mapping of button type to their corresponding React components | ||
const buttonMapping: Record<ButtonType, ReactNode> = { | ||
update: <UpdateButton handleAction={handleUpdate} />, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lot of diffs, but only two major things changed:
- Enums got factored out, cleaning up how the properties were defined
retry
andretryDebug
properties got added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that enum was my complication; thanks for fixing :)
? buttonMapping[ButtonTypesEnum.updating] | ||
: buttonMapping[ButtonTypesEnum.update])} | ||
{canBeUpdated && ( | ||
<>{isUpdating ? buttonMapping.updating : buttonMapping.update}</> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a huge change, but I wanted to make it super explicit that the logic was accounting for three cases:
- Render nothing if
canBeUpdated
is false - Render updating component
- Render update component
* requests and that responses produce the correct UI. | ||
* | ||
* We don't need to test the UI exhaustively because Storybook does that; just | ||
* enough to prove that the workspaceStatus was calculated correctly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just reformatted the comment to properly fit an 80-character width
Going to double-check the Storybook tests later this morning – I don't have great internet where I am right now, and the pages are taking ages to load in |
} | ||
}} | ||
handleBuildRetry={() => handleBuildRetry(false)} | ||
handleBuildRetryDebug={() => handleBuildRetry(true)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of passing 2 props here, can we just have handleBuildRetry
and then pass it a boolean in the Workspace
component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would work – my main concern with setting up the functions the way I did was insulating the downstream components from changes, or having implementation details leak out
Right now, handleBuildRetry
and handleBuildRetryDebug
happen to use the same implementation under the hood, but that's just kind of by coincidence. If WorkspaceReadyPage
ever gets to the point where the two functions need to look drastically different, we can change things in the one file, and none of the other components have to be any the wiser
I am aware that it does kind of increase the number of props (when we already have a lot), but keeping the other components blind to the implementation details seemed like the lesser of two evils to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If WorkspaceReadyPage ever gets to the point where the two functions need to look drastically different, we can change things in the one file, and none of the other components have to be any the wiser
I think we might be pre-optimizing here, but I'm happy to keep as-is!
/** | ||
* A button type supported by the workspace actions UI | ||
*/ | ||
export type ButtonType = (typeof buttonTypes)[number]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not familiar with this syntax...what is going on here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a little bit to unpack, but:
- We take the runtime
buttonTypes
value and turn it into a type definition viatypeof
- And because
buttonTypes
is defined viaas const
, it's treated as a fixed-length tuple. So, TypeScript knows there are 16 elements in the array exactly, and it also knows the string literal that goes in each slot - Then, when we index that type definition via
[number]
, we're saying to grab the type values at each slot.(typeof buttonTypes)[0]
would give us"start"
, while(typeof buttonTypes)[0 | 1 | 2]
would give us"start" | "starting" | "stop"
. So the[number]
index basically says "give us everything at every numeric index you have" - At the end, we have a union of all the types, but the types are defined runtime-first via the const array, so we're free to use it as a value (like combining it with
Array.includes
)
I did forget to actually export the array, though, so I'll fix that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Appreciate the explanation. It would be nice to use this syntax with TypesGen.WorkspaceTransitions
but idk how to make that happen on the Go side
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Nice work.
Closes #7329
Changes made