Skip to content

chore(site): Use react-query and refactor the workspaces page to use it #5838

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

Merged
merged 10 commits into from
Jan 24, 2023

Conversation

BrunoQuaresma
Copy link
Collaborator

Explanation of some of the decisions: https://drive.google.com/file/d/1AA7Va1YNaUY-QlzKNkL4FoeVQ43mCbOY/view?usp=sharing

PS: The video was too big to share directly on GH.

export const updateWorkspaceVersion = async (
workspace: TypesGen.Workspace,
): Promise<TypesGen.WorkspaceBuild> => {
const template = await getTemplate(workspace.template_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to handle the error for getTemplate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is already handled. If it fails, it will throw an error that will be passed to the Alert component. But I guess, you were talking about handling errors in a more granular way. Since these operations are consecutive, one by one, the first one that fails will throw the error, so only one error will happen at a time. But even in case we could have two errors happening at the same time in this operation, I would ask: As a user are those two errors helpful? Or would be good enough to just show a single error like "Update template version failed"? IMO, as a user, usually don't need to know what is happening under the hood so I would avoid showing multiple errors which can make me confused. Makes sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, totally makes sense. I just see a blank screen with a toast when that error is thrown. Maybe down the road and outside of the PR, we can have a cuter error state, like even an empty table.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it should not be a toast, should be an alert banner, not VERY different tho. I agree we could have better error components when there is a main loading data error.

}

if (workspaces.length === 0) {
return isUsingFilter ? (
Copy link
Member

@Kira-Pilot Kira-Pilot Jan 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of prop drilling several levels for this, can we look for the existence of the filter query string in the URL using react-router? It doesn't seem to be present unless explicitly set by the user. Maybe your useFilter hook could return that boolean if you want to keep things colocated.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can, but this brings back the "container/page view" discussion. If we do that, we have to change our stories in Storybook to wrap the components with the <Router /> and pass the proper routes, adding some work. Let's see how painful it is and we can take a better decision, maybe? Curious to know your thoughts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me!

limit={pagination.limit}
onPageChange={pagination.goToPage}
onUpdateWorkspace={(workspace) => {
updateWorkspace.mutate(workspace)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious about the separation of WorkspacesPage and WorkspacesPageView. I notice some of the layout is in the parent component, and some is in the child - should we have the parent handle all the page layout, e.g. margins, page headers, subtitles?
I also see we're passing a lot of props down from the parent still - is this to facilitate testing or do we like that pattern for another reason?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no strong opinion on this, I kept what we were using, to be honest. But, in the current state, I would like to only keep data logic in the Page component and all the visuals in PageView. I think in this way, we can test more logic in the stories. What about you?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it keeps our stories running, I'm all for it.

})
},
onSuccess: (workspaceBuild) => {
queryClient.setQueryData<WorkspacesResponse>(queryKey, (oldResponse) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would the response on onSuccess be oldResponse? It's not an updated WorkspacesResponse?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updateWorkspaceVersion function does not return a WorkspacesResponse. It returns a workspace build of an individual workspace, so what we have to do is get the old response, find the workspace that was updated, and replace the last build with the one returned from the updateWorkspaceVersion response.

if (oldResponse) {
return assignLatestBuild(oldResponse, workspaceBuild)
}
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need an onError key?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh, good catch. I forgot to handle the update error. Thank you! But as the useQuery, the useMutation also returns an error object so if you want to just get the error and display it in the UI no onError is needed.

const updateVersion = useMutation()

if(updateVersion.error) {
   return <Alert error={error}>
}

but in this case, I think we can use onError to trigger a displayError notification.

@@ -0,0 +1,113 @@
import {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might call this file hooks.ts

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I thought the same and I was using it but when thinking about what this does, it just loads/handles the page data so I thought it would be a better name. Makes sense?

Copy link
Member

@Kira-Pilot Kira-Pilot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments but looks good. I like this pattern, and I like extracting the data layer into a page level hook in a separate file.

Copy link
Member

@code-asher code-asher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! I also enjoy the separated data layer.

Comment on lines 30 to 32
return isUsingFilter ? (
<TableEmpty message={t("emptyPageMessage")} />
) : (
Copy link
Member

@code-asher code-asher Jan 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not distinguishing whether this is the first page makes a search with no results say "No results on this page" which I think is a little bit confusing because it implies there are results on other pages (at least in my mind) but in this case there are actually no results at all (before it would say "No results matched your search").

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I saw that in Storybook 😔 I'm going to fix it but I think there is a better way of doing that without using an extra prop. I can be wrong so let's see.

/>

<PaginationWidget numRecords={count} paginationRef={paginationRef} />
{count && (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we might need Boolean(count) or a ternary or embed the zero logic into the component itself or something like that because I think when this is zero it displays a zero on the page.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is true, I've been seeing this happening some times.

@BrunoQuaresma BrunoQuaresma changed the title chore: Use react-query and refactor the workspaces page to use it chore(site): Use react-query and refactor the workspaces page to use it Jan 24, 2023
@BrunoQuaresma BrunoQuaresma merged commit 36384aa into main Jan 24, 2023
@BrunoQuaresma BrunoQuaresma deleted the bq/add-react-query branch January 24, 2023 19:22
@github-actions github-actions bot locked and limited conversation to collaborators Jan 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants