Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

feat(plg): Use react-query for team management #63267

Merged
merged 24 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion client/web/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ ts_project(
"src/cody/sidebar/useSidebarSize.tsx",
"src/cody/subscription/CodySubscriptionPage.tsx",
"src/cody/subscription/queries.tsx",
"src/cody/subscription/subscriptionSummary.ts",
"src/cody/switch-account/CodySwitchAccountPage.tsx",
"src/cody/team/CodyManageTeamPage.tsx",
"src/cody/team/InviteUsers.tsx",
Expand Down
6 changes: 3 additions & 3 deletions client/web/src/cody/management/CodyManagementPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import { AcceptInviteBanner } from '../invites/AcceptInviteBanner'
import { isCodyEnabled } from '../isCodyEnabled'
import { CodyOnboarding, type IEditor } from '../onboarding/CodyOnboarding'
import { USER_CODY_PLAN, USER_CODY_USAGE } from '../subscription/queries'
import { useCodySubscriptionSummaryData } from '../subscription/subscriptionSummary'
import { getManageSubscriptionPageURL } from '../util'

import { useSubscriptionSummary } from './api/react-query/subscriptions'
import { SubscriptionStats } from './SubscriptionStats'
import { UseCodyInEditorSection } from './UseCodyInEditorSection'

Expand Down Expand Up @@ -74,8 +74,8 @@ export const CodyManagementPage: React.FunctionComponent<CodyManagementPageProps
{}
)

const [codySubscriptionSummary] = useCodySubscriptionSummaryData()
const isAdmin = codySubscriptionSummary?.userRole === 'admin'
const subscriptionSummaryQueryResult = useSubscriptionSummary()
const isAdmin = subscriptionSummaryQueryResult?.data?.userRole === 'admin'

const [selectedEditor, setSelectedEditor] = React.useState<IEditor | null>(null)
const [selectedEditorStep, setSelectedEditorStep] = React.useState<EditorStep | null>(null)
Expand Down
18 changes: 17 additions & 1 deletion client/web/src/cody/management/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,28 @@ export module Client {
return { method: 'GET', urlSuffix: '/team/current/members' }
}

export function updateTeamMember(requestBody: types.UpdateTeamMembersRequest): Call<unknown> {
return { method: 'PATCH', urlSuffix: '/team/current/members', requestBody }
}

// Invites

export function getInvite(teamId: string, inviteId: string): Call<types.TeamInvite> {
return { method: 'GET', urlSuffix: `/team/${teamId}/invites/${inviteId}` }
}

export function getTeamInvites(): Call<types.ListTeamInvitesResponse> {
return { method: 'GET', urlSuffix: '/team/current/invites' }
}

export function sendInvite(requestBody: types.CreateTeamInviteRequest): Call<types.ListTeamInvitesResponse> {
return { method: 'POST', urlSuffix: '/team/current/invites', requestBody }
}

export function resendInvite(inviteId: string): Call<unknown> {
return { method: 'POST', urlSuffix: `/team/current/invites/${inviteId}/resend` }
}

export function acceptInvite(teamId: string, inviteId: string): Call<unknown> {
return { method: 'POST', urlSuffix: `/team/${teamId}/invites/${inviteId}/accept` }
}
Expand All @@ -76,7 +92,7 @@ export module Client {
}

// Call is the bundle of data necessary for making an API request.
// This is a sort of "meta request" in the same veign as the `gql`
// This is a sort of "meta request" in the same vein as the `gql`
// template tag, see: https://github.com/apollographql/graphql-tag
export interface Call<Resp> {
method: 'GET' | 'POST' | 'PATCH' | 'DELETE'
Expand Down
38 changes: 35 additions & 3 deletions client/web/src/cody/management/api/react-query/invites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '@tanstack/react-query'

import { Client } from '../client'
import type { TeamInvite } from '../teamInvites'
import type { TeamInvite, ListTeamInvitesResponse, CreateTeamInviteRequest } from '../types'

import { callCodyProApi } from './callCodyProApi'
import { queryKeys } from './queryKeys'
Expand All @@ -27,6 +27,36 @@ export const useInvite = ({
},
})

export const useTeamInvites = (): UseQueryResult<Omit<TeamInvite, 'sentBy'>[] | undefined> =>
useQuery({
queryKey: queryKeys.invites.teamInvites(),
queryFn: async () => {
const response = await callCodyProApi(Client.getTeamInvites())
return ((await response.json()) as ListTeamInvitesResponse).invites
},
})

export const useSendInvite = (): UseMutationResult<Omit<TeamInvite, 'sentBy'>, Error, CreateTeamInviteRequest> => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async requestBody => (await callCodyProApi(Client.sendInvite(requestBody))).json(),
onSuccess: (newInvite: Omit<TeamInvite, 'sentBy'>) => {
queryClient.setQueryData(queryKeys.invites.teamInvites(), (prevInvites: Omit<TeamInvite, 'sentBy'>[]) => [
...prevInvites,
newInvite,
])
},
})
}

export const useResendInvite = (): UseMutationResult<unknown, Error, { inviteId: string }> => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async ({ inviteId }) => callCodyProApi(Client.resendInvite(inviteId)),
onSuccess: () => queryClient.invalidateQueries({ queryKey: queryKeys.invites.teamInvites() }),
})
}

export const useAcceptInvite = (): UseMutationResult<unknown, Error, { teamId: string; inviteId: string }> => {
const queryClient = useQueryClient()
return useMutation({
Expand All @@ -44,7 +74,9 @@ export const useCancelInvite = (): UseMutationResult<unknown, Error, { teamId: s
const queryClient = useQueryClient()
return useMutation({
mutationFn: async ({ teamId, inviteId }) => callCodyProApi(Client.cancelInvite(teamId, inviteId)),
onSuccess: (_, { teamId, inviteId }) =>
queryClient.invalidateQueries({ queryKey: queryKeys.invites.invite(teamId, inviteId) }),
onSuccess: (_, { inviteId }) =>
queryClient.setQueryData(queryKeys.invites.teamInvites(), (prevInvites: TeamInvite[]) =>
prevInvites.filter(invite => invite.id !== inviteId)
),
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ export const queryKeys = {
invites: {
all: ['invite'] as const,
invite: (teamId: string, inviteId: string) => [...queryKeys.invites.all, teamId, inviteId] as const,
teamInvites: () => [...queryKeys.invites.all, 'team-invites'] as const,
},
}
28 changes: 24 additions & 4 deletions client/web/src/cody/management/api/react-query/subscriptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import type {
PreviewResult,
PreviewCreateTeamRequest,
GetSubscriptionInvoicesResponse,
} from '../teamSubscriptions'
ListTeamMembersResponse,
ListTeamInvitesResponse,
} from '../types'

import { callCodyProApi } from './callCodyProApi'
import { queryKeys } from './queryKeys'
Expand All @@ -25,7 +27,7 @@ export const useCurrentSubscription = (): UseQueryResult<Subscription | undefine
queryKey: queryKeys.subscriptions.subscription(),
queryFn: async () => {
const response = await callCodyProApi(Client.getCurrentSubscription())
return response?.json()
return response.json()
vdavid marked this conversation as resolved.
Show resolved Hide resolved
},
})

Expand All @@ -34,7 +36,7 @@ export const useSubscriptionSummary = (): UseQueryResult<SubscriptionSummary | u
queryKey: queryKeys.subscriptions.subscriptionSummary(),
queryFn: async () => {
const response = await callCodyProApi(Client.getCurrentSubscriptionSummary())
return response?.json()
return response.json()
},
})

Expand All @@ -47,6 +49,24 @@ export const useSubscriptionInvoices = (): UseQueryResult<GetSubscriptionInvoice
},
})

export const useTeamMembers = (): UseQueryResult<ListTeamMembersResponse | undefined> =>
useQuery({
queryKey: queryKeys.teams.teamMembers(),
queryFn: async () => {
const response = await callCodyProApi(Client.getCurrentTeamMembers())
return response.ok ? response.json() : undefined
},
})

export const useTeamInvites = (): UseQueryResult<ListTeamInvitesResponse | undefined> =>
useQuery({
queryKey: queryKeys.invites.teamInvites(),
queryFn: async () => {
const response = await callCodyProApi(Client.getTeamInvites())
return response.ok ? response.json() : undefined
},
})

export const useUpdateCurrentSubscription = (): UseMutationResult<
Subscription | undefined,
Error,
Expand All @@ -56,7 +76,7 @@ export const useUpdateCurrentSubscription = (): UseMutationResult<
return useMutation({
mutationFn: async requestBody => {
const response = await callCodyProApi(Client.updateCurrentSubscription(requestBody))
return response?.json()
return response.json()
},
onSuccess: data => {
// We get updated subscription data in response - no need to refetch subscription.
Expand Down
18 changes: 16 additions & 2 deletions client/web/src/cody/management/api/react-query/teams.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { useQuery, type UseQueryResult } from '@tanstack/react-query'
import {
useMutation,
useQuery,
useQueryClient,
type UseQueryResult,
type UseMutationResult,
} from '@tanstack/react-query'

import { Client } from '../client'
import type { ListTeamMembersResponse } from '../teamMembers'
import type { ListTeamMembersResponse, UpdateTeamMembersRequest } from '../types'

import { callCodyProApi } from './callCodyProApi'
import { queryKeys } from './queryKeys'
Expand All @@ -14,3 +20,11 @@ export const useTeamMembers = (): UseQueryResult<ListTeamMembersResponse | undef
return response?.json()
},
})

export const useUpdateTeamMember = (): UseMutationResult<unknown, Error, UpdateTeamMembersRequest> => {
const queryClient = useQueryClient()
return useMutation({
mutationFn: async requestBody => callCodyProApi(Client.updateTeamMember(requestBody)),
onSuccess: () => queryClient.invalidateQueries({ queryKey: queryKeys.teams.teamMembers() }),
})
}
4 changes: 2 additions & 2 deletions client/web/src/cody/management/api/teamInvites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ export interface TeamInvite {
status: TeamInviteStatus
error?: string

sentAt: Date
sentAt: string
sentBy: string
acceptedAt?: Date
acceptedAt?: string
vdavid marked this conversation as resolved.
Show resolved Hide resolved
}

export interface CreateTeamInviteRequest {
Expand Down
4 changes: 2 additions & 2 deletions client/web/src/cody/management/api/teamMembers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ export type TeamRole = 'member' | 'admin'
export interface TeamMember {
accountId: string
displayName: string
email: string
Copy link
Contributor

Choose a reason for hiding this comment

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

Just checking: do we have an accompanying PR to SSC repo exposing this field?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It should already expose the field because the old approach was already using it. I'll double-check.

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like we don't expose it: convert function, type definition.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, weird. I'll add it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

avatarUrl: string

role: TeamRole
}

Expand All @@ -19,7 +19,7 @@ export interface ListTeamMembersResponse {
}

export interface UpdateTeamMembersRequest {
addMembver?: TeamMemberRef
addMember?: TeamMemberRef
vdavid marked this conversation as resolved.
Show resolved Hide resolved
removeMember?: TeamMemberRef
updateMemberRole?: TeamMemberRef
}
11 changes: 0 additions & 11 deletions client/web/src/cody/subscription/subscriptionSummary.ts

This file was deleted.

Loading
Loading