diff --git a/ui/src/features/NotFoundPage/index.tsx b/ui/src/features/NotFoundPage/index.tsx index da16a6b22..f91064d75 100644 --- a/ui/src/features/NotFoundPage/index.tsx +++ b/ui/src/features/NotFoundPage/index.tsx @@ -10,8 +10,8 @@ type Props = { const NotFoundPage: React.FC = ({ message }) => { const t = useT(); - const { getMe } = useUser(); - const { me } = getMe(); + const { useGetMe } = useUser(); + const { me } = useGetMe(); return (
diff --git a/ui/src/features/PageWrapper/WorkspaceId.tsx b/ui/src/features/PageWrapper/WorkspaceId.tsx index cc5309293..e2da499a5 100644 --- a/ui/src/features/PageWrapper/WorkspaceId.tsx +++ b/ui/src/features/PageWrapper/WorkspaceId.tsx @@ -12,7 +12,7 @@ type Props = { }; const WorkspaceIdWrapper: React.FC = ({ children }) => { - const [currentWorkspace, setCurrentWorkspace] = useCurrentWorkspace(); + const [_, setCurrentWorkspace] = useCurrentWorkspace(); const { workspaceId }: { workspaceId: string } = useParams({ strict: false, @@ -23,11 +23,10 @@ const WorkspaceIdWrapper: React.FC = ({ children }) => { useEffect(() => { if (!workspace) return; - if (currentWorkspace?.id === workspace.id) return; setCurrentWorkspace(workspace); return; - }, [workspace, currentWorkspace, setCurrentWorkspace]); + }, [workspace, setCurrentWorkspace]); if (isLoading) return ; diff --git a/ui/src/features/TopNavigation/components/UserNavigation.tsx b/ui/src/features/TopNavigation/components/UserNavigation.tsx index b8565252f..cbd2bf6cc 100644 --- a/ui/src/features/TopNavigation/components/UserNavigation.tsx +++ b/ui/src/features/TopNavigation/components/UserNavigation.tsx @@ -33,8 +33,8 @@ const UserNavigation: React.FC = ({ const t = useT(); const [, setDialogType] = useDialogType(); const { logout: handleLogout, user } = useAuth(); - const { getMe } = useUser(); - const data = getMe().me; + const { useGetMe } = useUser(); + const { me } = useGetMe(); const { tosUrl, documentationUrl } = config(); @@ -47,12 +47,12 @@ const UserNavigation: React.FC = ({
- {data?.name ? data?.name.charAt(0).toUpperCase() : "F"} + {me?.name ? me.name.charAt(0).toUpperCase() : "F"} {!iconOnly ? (

- {data?.name ? data?.name : "User"} + {me?.name ? me.name : "User"}

diff --git a/ui/src/features/WorkspaceSettings/components/GeneralSettings.tsx b/ui/src/features/WorkspaceSettings/components/GeneralSettings.tsx index 1c3a90c2b..7b9c65c01 100644 --- a/ui/src/features/WorkspaceSettings/components/GeneralSettings.tsx +++ b/ui/src/features/WorkspaceSettings/components/GeneralSettings.tsx @@ -1,30 +1,53 @@ import { useNavigate } from "@tanstack/react-router"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import { Button, Input, Label } from "@flow/components"; import { useWorkspace } from "@flow/lib/gql"; import { useT } from "@flow/lib/i18n"; import { useCurrentWorkspace } from "@flow/stores"; +type Errors = "delete" | "update"; + const GeneralSettings: React.FC = () => { const t = useT(); const [currentWorkspace] = useCurrentWorkspace(); - const { deleteWorkspace } = useWorkspace(); + const { deleteWorkspace, updateWorkspace } = useWorkspace(); const navigate = useNavigate(); - const [showError, setShowError] = useState(false); + const [showError, setShowError] = useState(undefined); + const [workspaceName, setWorkspaceName] = useState(currentWorkspace?.name); + const [loading, setLoading] = useState(false); const handleDeleteWorkspace = async () => { - setShowError(false); + setLoading(true); + setShowError(undefined); if (!currentWorkspace) return; - // TODO: this trigger a pop up for confirming + // TODO: this should trigger a pop up for confirming const { workspaceId } = await deleteWorkspace(currentWorkspace.id); if (!workspaceId) { - setShowError(true); + setShowError("delete"); return; } navigate({ to: "/workspace" }); }; + + const handleUpdateWorkspace = async () => { + setLoading(true); + setShowError(undefined); + if (!currentWorkspace?.id || !workspaceName) return; + const { workspace } = await updateWorkspace(currentWorkspace?.id, workspaceName); + setLoading(false); + if (!workspace) { + setShowError("update"); + return; + } + }; + + // currentWorkspace can be changed from the navigation + useEffect(() => { + setWorkspaceName(currentWorkspace?.name); + }, [currentWorkspace]); + return (

{t("General Settings")}

@@ -34,29 +57,27 @@ const GeneralSettings: React.FC = () => { setWorkspaceName(e.target.value)} />
- {/*
- - -
*/} - +
- {t("Failed to delete workspace")} + {showError === "delete" && t("Failed to delete Workspace")} + {showError === "update" && t("Failed to update Workspace")}
diff --git a/ui/src/features/WorkspaceSettings/components/IntegrationsSettings.tsx b/ui/src/features/WorkspaceSettings/components/IntegrationsSettings.tsx index 97d2be95b..02be2cf0a 100644 --- a/ui/src/features/WorkspaceSettings/components/IntegrationsSettings.tsx +++ b/ui/src/features/WorkspaceSettings/components/IntegrationsSettings.tsx @@ -16,7 +16,7 @@ import { IntegrationMember } from "@flow/types/integration"; type Filter = "all" | Role; -const roles = ["admin", "reader", "writer"]; +const roles: Role[] = Object.values(Role); const IntegrationsSettings: React.FC = () => { const t = useT(); @@ -26,9 +26,10 @@ const IntegrationsSettings: React.FC = () => { const filters: { id: Filter; title: string }[] = [ { id: "all", title: t("All") }, - { id: "admin", title: t("Admin") }, - { id: "reader", title: t("Reader") }, - { id: "writer", title: t("Writer") }, + { id: Role.Owner, title: t("Owner") }, + { id: Role.Reader, title: t("Reader") }, + { id: Role.Reader, title: t("Maintainer") }, + { id: Role.Writer, title: t("Writer") }, ]; const integrations: IntegrationMember[] = diff --git a/ui/src/features/WorkspaceSettings/components/MembersSettings.tsx b/ui/src/features/WorkspaceSettings/components/MembersSettings.tsx index 204cf66ef..c00547fa5 100644 --- a/ui/src/features/WorkspaceSettings/components/MembersSettings.tsx +++ b/ui/src/features/WorkspaceSettings/components/MembersSettings.tsx @@ -3,87 +3,117 @@ import { useState } from "react"; import { Button, - Checkbox, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, + Input, } from "@flow/components"; +import { useUser, useWorkspace } from "@flow/lib/gql"; import { useT } from "@flow/lib/i18n"; import { useCurrentWorkspace } from "@flow/stores"; import { Role, UserMember } from "@flow/types"; type Filter = "all" | Role; -const roles = ["admin", "reader", "writer"]; +const roles: Role[] = Object.values(Role); const MembersSettings: React.FC = () => { const t = useT(); const [currentWorkspace] = useCurrentWorkspace(); - + const { addMemberToWorkspace, removeMemberFromWorkspace, updateMemberOfWorkspace } = + useWorkspace(); + const { searchUser, useGetMe } = useUser(); + const [email, setEmail] = useState(""); const [currentFilter, setFilter] = useState("all"); + const [error, setError] = useState(); + + const { me } = useGetMe(); const filters: { id: Filter; title: string }[] = [ { id: "all", title: t("All") }, - { id: "admin", title: t("Admin") }, - { id: "reader", title: t("Reader") }, - { id: "writer", title: t("Writer") }, + { id: Role.Owner, title: t("Owner") }, + { id: Role.Reader, title: t("Reader") }, + { id: Role.Maintainer, title: t("Maintainer") }, + { id: Role.Writer, title: t("Writer") }, ]; - const members = - (currentWorkspace?.members?.filter( - m => "userId" in m && (currentFilter !== "all" ? m.role === currentFilter : true), - ) as UserMember[]) ?? []; + const members = currentWorkspace?.members?.filter( + m => "userId" in m && (currentFilter === "all" || m.role === currentFilter), + ) as UserMember[]; + + const handleAddMember = async (email: string) => { + setError(undefined); + if (!currentWorkspace?.id) return; + + const alreadyExists = members.find(m => m.user?.email === email); + + if (alreadyExists) { + setError("User already exists"); + return; + } - const [selectedMembers, setSelectedMembers] = useState([]); + const { user } = await searchUser(email); + if (!user) { + setError(t("Could not find the user")); + return; + } + const { workspace } = await addMemberToWorkspace(currentWorkspace.id, user.id, Role.Reader); + + if (!workspace) { + setError(t("Failed to add member")); + return; + } + setEmail(""); + }; + + const handleChangeRole = async (userId: string, role: Role) => { + setError(undefined); + if (!currentWorkspace?.id) return; + const { workspace } = await updateMemberOfWorkspace(currentWorkspace.id, userId, role); + if (!workspace) { + setError(t("Failed to change role of the member")); + return; + } + }; + + const handleRemoveMembers = async (userId: string) => { + setError(undefined); + if (!currentWorkspace?.id) return; + const { workspace } = await removeMemberFromWorkspace(currentWorkspace.id, userId); + if (!workspace) { + setError(t("Failed to remove member")); + return; + } + }; return (

{t("Members Settings")}

- +
+
+ {/* TODO: This will be a dialog component */} + setEmail(e.target.value)} + /> +
- - setSelectedMembers( - selectedMembers.length !== members.length ? members.map(m => m.userId) : [], - ) - } - /> -

- {selectedMembers.length - ? `${selectedMembers.length} ${selectedMembers.length === 1 ? t("member selected") : t("members selected")}` - : `${members.length} ${t("Members")}`} -

+

{`${members.length} ${t("Members")}`}

- {selectedMembers.length > 0 && ( -
- - -

{t("Change role")}

- -
- - - {roles.map((role, idx) => ( - console.log(role)}> - {role} - - ))} - -
- -
- )}
@@ -105,26 +135,39 @@ const MembersSettings: React.FC = () => {
- {members.map(member => ( -
- - setSelectedMembers(prev => - prev.includes(member.userId) - ? [...prev.filter(pm => pm !== member.userId)] - : [...prev, member.userId], - ) - } - /> -

{member.user.name}

-

{member.role}

+ {members.map(m => ( +
+

{m.user?.name}

+

{m.role}

+ + +

{t("Change role")}

+ +
+ + + {roles.map((role, idx) => ( + handleChangeRole(m.userId, role)}> + {role} + + ))} + +
+
))}
- +

{error}

); diff --git a/ui/src/lib/gql/__gen__/gql.ts b/ui/src/lib/gql/__gen__/gql.ts index 645f1b79e..2be40b08f 100644 --- a/ui/src/lib/gql/__gen__/gql.ts +++ b/ui/src/lib/gql/__gen__/gql.ts @@ -14,8 +14,8 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ */ const documents = { "fragment Project on Project {\n id\n name\n description\n createdAt\n updatedAt\n workspaceId\n}\n\nmutation CreateProject($input: CreateProjectInput!) {\n createProject(input: $input) {\n project {\n ...Project\n }\n }\n}\n\nquery GetProjects($workspaceId: ID!, $first: Int!) {\n projects(workspaceId: $workspaceId, first: $first) {\n totalCount\n nodes {\n ...Project\n }\n pageInfo {\n startCursor\n endCursor\n hasNextPage\n hasPreviousPage\n }\n }\n}\n\nquery GetProjectById($projectId: ID!) {\n node(id: $projectId, type: PROJECT) {\n __typename\n ...Project\n }\n}\n\nmutation UpdateProject($input: UpdateProjectInput!) {\n updateProject(input: $input) {\n project {\n ...Project\n }\n }\n}\n\nmutation DeleteProject($input: DeleteProjectInput!) {\n deleteProject(input: $input) {\n projectId\n }\n}": types.ProjectFragmentDoc, - "query GetMe {\n me {\n id\n name\n email\n myWorkspaceId\n }\n}": types.GetMeDocument, - "fragment Workspace on Workspace {\n id\n name\n personal\n}\n\nmutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaces {\n me {\n workspaces {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaceById($workspaceId: ID!) {\n node(id: $workspaceId, type: WORKSPACE) {\n __typename\n ...Workspace\n }\n}\n\nmutation UpdateWorkspace($input: UpdateWorkspaceInput!) {\n updateWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation DeleteWorkspace($input: DeleteWorkspaceInput!) {\n deleteWorkspace(input: $input) {\n workspaceId\n }\n}": types.WorkspaceFragmentDoc, + "query GetMe {\n me {\n id\n name\n email\n myWorkspaceId\n }\n}\n\nquery SearchUser($email: String!) {\n searchUser(nameOrEmail: $email) {\n id\n name\n email\n }\n}": types.GetMeDocument, + "fragment Workspace on Workspace {\n id\n name\n personal\n members {\n userId\n role\n user {\n id\n email\n name\n }\n }\n}\n\nmutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaces {\n me {\n workspaces {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaceById($workspaceId: ID!) {\n node(id: $workspaceId, type: WORKSPACE) {\n __typename\n ...Workspace\n }\n}\n\nmutation UpdateWorkspace($input: UpdateWorkspaceInput!) {\n updateWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation DeleteWorkspace($input: DeleteWorkspaceInput!) {\n deleteWorkspace(input: $input) {\n workspaceId\n }\n}\n\nmutation AddMemberToWorkspace($input: AddMemberToWorkspaceInput!) {\n addMemberToWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation RemoveMemberFromWorkspace($input: RemoveMemberFromWorkspaceInput!) {\n removeMemberFromWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation UpdateMemberOfWorkspace($input: UpdateMemberOfWorkspaceInput!) {\n updateMemberOfWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}": types.WorkspaceFragmentDoc, }; /** @@ -39,11 +39,11 @@ export function graphql(source: "fragment Project on Project {\n id\n name\n /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "query GetMe {\n me {\n id\n name\n email\n myWorkspaceId\n }\n}"): (typeof documents)["query GetMe {\n me {\n id\n name\n email\n myWorkspaceId\n }\n}"]; +export function graphql(source: "query GetMe {\n me {\n id\n name\n email\n myWorkspaceId\n }\n}\n\nquery SearchUser($email: String!) {\n searchUser(nameOrEmail: $email) {\n id\n name\n email\n }\n}"): (typeof documents)["query GetMe {\n me {\n id\n name\n email\n myWorkspaceId\n }\n}\n\nquery SearchUser($email: String!) {\n searchUser(nameOrEmail: $email) {\n id\n name\n email\n }\n}"]; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ -export function graphql(source: "fragment Workspace on Workspace {\n id\n name\n personal\n}\n\nmutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaces {\n me {\n workspaces {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaceById($workspaceId: ID!) {\n node(id: $workspaceId, type: WORKSPACE) {\n __typename\n ...Workspace\n }\n}\n\nmutation UpdateWorkspace($input: UpdateWorkspaceInput!) {\n updateWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation DeleteWorkspace($input: DeleteWorkspaceInput!) {\n deleteWorkspace(input: $input) {\n workspaceId\n }\n}"): (typeof documents)["fragment Workspace on Workspace {\n id\n name\n personal\n}\n\nmutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaces {\n me {\n workspaces {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaceById($workspaceId: ID!) {\n node(id: $workspaceId, type: WORKSPACE) {\n __typename\n ...Workspace\n }\n}\n\nmutation UpdateWorkspace($input: UpdateWorkspaceInput!) {\n updateWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation DeleteWorkspace($input: DeleteWorkspaceInput!) {\n deleteWorkspace(input: $input) {\n workspaceId\n }\n}"]; +export function graphql(source: "fragment Workspace on Workspace {\n id\n name\n personal\n members {\n userId\n role\n user {\n id\n email\n name\n }\n }\n}\n\nmutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaces {\n me {\n workspaces {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaceById($workspaceId: ID!) {\n node(id: $workspaceId, type: WORKSPACE) {\n __typename\n ...Workspace\n }\n}\n\nmutation UpdateWorkspace($input: UpdateWorkspaceInput!) {\n updateWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation DeleteWorkspace($input: DeleteWorkspaceInput!) {\n deleteWorkspace(input: $input) {\n workspaceId\n }\n}\n\nmutation AddMemberToWorkspace($input: AddMemberToWorkspaceInput!) {\n addMemberToWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation RemoveMemberFromWorkspace($input: RemoveMemberFromWorkspaceInput!) {\n removeMemberFromWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation UpdateMemberOfWorkspace($input: UpdateMemberOfWorkspaceInput!) {\n updateMemberOfWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}"): (typeof documents)["fragment Workspace on Workspace {\n id\n name\n personal\n members {\n userId\n role\n user {\n id\n email\n name\n }\n }\n}\n\nmutation CreateWorkspace($input: CreateWorkspaceInput!) {\n createWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaces {\n me {\n workspaces {\n ...Workspace\n }\n }\n}\n\nquery GetWorkspaceById($workspaceId: ID!) {\n node(id: $workspaceId, type: WORKSPACE) {\n __typename\n ...Workspace\n }\n}\n\nmutation UpdateWorkspace($input: UpdateWorkspaceInput!) {\n updateWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation DeleteWorkspace($input: DeleteWorkspaceInput!) {\n deleteWorkspace(input: $input) {\n workspaceId\n }\n}\n\nmutation AddMemberToWorkspace($input: AddMemberToWorkspaceInput!) {\n addMemberToWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation RemoveMemberFromWorkspace($input: RemoveMemberFromWorkspaceInput!) {\n removeMemberFromWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}\n\nmutation UpdateMemberOfWorkspace($input: UpdateMemberOfWorkspaceInput!) {\n updateMemberOfWorkspace(input: $input) {\n workspace {\n ...Workspace\n }\n }\n}"]; export function graphql(source: string) { return (documents as any)[source] ?? {}; diff --git a/ui/src/lib/gql/__gen__/graphql.ts b/ui/src/lib/gql/__gen__/graphql.ts index f4abcbec3..fae66f2c9 100644 --- a/ui/src/lib/gql/__gen__/graphql.ts +++ b/ui/src/lib/gql/__gen__/graphql.ts @@ -511,7 +511,14 @@ export type GetMeQueryVariables = Exact<{ [key: string]: never; }>; export type GetMeQuery = { __typename?: 'Query', me?: { __typename?: 'Me', id: string, name: string, email: string, myWorkspaceId: string } | null }; -export type WorkspaceFragment = { __typename?: 'Workspace', id: string, name: string, personal: boolean } & { ' $fragmentName'?: 'WorkspaceFragment' }; +export type SearchUserQueryVariables = Exact<{ + email: Scalars['String']['input']; +}>; + + +export type SearchUserQuery = { __typename?: 'Query', searchUser?: { __typename?: 'User', id: string, name: string, email: string } | null }; + +export type WorkspaceFragment = { __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> } & { ' $fragmentName'?: 'WorkspaceFragment' }; export type CreateWorkspaceMutationVariables = Exact<{ input: CreateWorkspaceInput; @@ -558,16 +565,50 @@ export type DeleteWorkspaceMutationVariables = Exact<{ export type DeleteWorkspaceMutation = { __typename?: 'Mutation', deleteWorkspace?: { __typename?: 'DeleteWorkspacePayload', workspaceId: string } | null }; +export type AddMemberToWorkspaceMutationVariables = Exact<{ + input: AddMemberToWorkspaceInput; +}>; + + +export type AddMemberToWorkspaceMutation = { __typename?: 'Mutation', addMemberToWorkspace?: { __typename?: 'AddMemberToWorkspacePayload', workspace: ( + { __typename?: 'Workspace' } + & { ' $fragmentRefs'?: { 'WorkspaceFragment': WorkspaceFragment } } + ) } | null }; + +export type RemoveMemberFromWorkspaceMutationVariables = Exact<{ + input: RemoveMemberFromWorkspaceInput; +}>; + + +export type RemoveMemberFromWorkspaceMutation = { __typename?: 'Mutation', removeMemberFromWorkspace?: { __typename?: 'RemoveMemberFromWorkspacePayload', workspace: ( + { __typename?: 'Workspace' } + & { ' $fragmentRefs'?: { 'WorkspaceFragment': WorkspaceFragment } } + ) } | null }; + +export type UpdateMemberOfWorkspaceMutationVariables = Exact<{ + input: UpdateMemberOfWorkspaceInput; +}>; + + +export type UpdateMemberOfWorkspaceMutation = { __typename?: 'Mutation', updateMemberOfWorkspace?: { __typename?: 'UpdateMemberOfWorkspacePayload', workspace: ( + { __typename?: 'Workspace' } + & { ' $fragmentRefs'?: { 'WorkspaceFragment': WorkspaceFragment } } + ) } | null }; + export const ProjectFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]} as unknown as DocumentNode; -export const WorkspaceFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}}]}}]} as unknown as DocumentNode; +export const WorkspaceFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateProjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createProject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Project"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]} as unknown as DocumentNode; export const GetProjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetProjects"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"first"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"workspaceId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}},{"kind":"Argument","name":{"kind":"Name","value":"first"},"value":{"kind":"Variable","name":{"kind":"Name","value":"first"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"nodes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Project"}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}},{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]} as unknown as DocumentNode; export const GetProjectByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetProjectById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}},{"kind":"Argument","name":{"kind":"Name","value":"type"},"value":{"kind":"EnumValue","value":"PROJECT"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"Project"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]} as unknown as DocumentNode; export const UpdateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateProjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateProject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Project"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Project"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]} as unknown as DocumentNode; export const DeleteProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteProjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteProject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectId"}}]}}]}}]} as unknown as DocumentNode; export const GetMeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetMe"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"myWorkspaceId"}}]}}]}}]} as unknown as DocumentNode; -export const CreateWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}}]}}]} as unknown as DocumentNode; -export const GetWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}}]}}]} as unknown as DocumentNode; -export const GetWorkspaceByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaceById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}},{"kind":"Argument","name":{"kind":"Name","value":"type"},"value":{"kind":"EnumValue","value":"WORKSPACE"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}}]}}]} as unknown as DocumentNode; -export const UpdateWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}}]}}]} as unknown as DocumentNode; -export const DeleteWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file +export const SearchUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SearchUser"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"searchUser"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"nameOrEmail"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"email"}}]}}]}}]} as unknown as DocumentNode; +export const CreateWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; +export const GetWorkspacesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; +export const GetWorkspaceByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetWorkspaceById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}},{"kind":"Argument","name":{"kind":"Name","value":"type"},"value":{"kind":"EnumValue","value":"WORKSPACE"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; +export const UpdateWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; +export const DeleteWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}}]}}]}}]} as unknown as DocumentNode; +export const AddMemberToWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"AddMemberToWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"AddMemberToWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"addMemberToWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; +export const RemoveMemberFromWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"RemoveMemberFromWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"RemoveMemberFromWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"removeMemberFromWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; +export const UpdateMemberOfWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateMemberOfWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateMemberOfWorkspaceInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateMemberOfWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Workspace"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Workspace"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"personal"}},{"kind":"Field","name":{"kind":"Name","value":"members"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"userId"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"user"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]} as unknown as DocumentNode; \ No newline at end of file diff --git a/ui/src/lib/gql/__gen__/plugins/graphql-request.ts b/ui/src/lib/gql/__gen__/plugins/graphql-request.ts index e2c0ddac0..32ad538fa 100644 --- a/ui/src/lib/gql/__gen__/plugins/graphql-request.ts +++ b/ui/src/lib/gql/__gen__/plugins/graphql-request.ts @@ -500,33 +500,40 @@ export type GetMeQueryVariables = Exact<{ [key: string]: never; }>; export type GetMeQuery = { __typename?: 'Query', me?: { __typename?: 'Me', id: string, name: string, email: string, myWorkspaceId: string } | null }; -export type WorkspaceFragment = { __typename?: 'Workspace', id: string, name: string, personal: boolean }; +export type SearchUserQueryVariables = Exact<{ + email: Scalars['String']['input']; +}>; + + +export type SearchUserQuery = { __typename?: 'Query', searchUser?: { __typename?: 'User', id: string, name: string, email: string } | null }; + +export type WorkspaceFragment = { __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> }; export type CreateWorkspaceMutationVariables = Exact<{ input: CreateWorkspaceInput; }>; -export type CreateWorkspaceMutation = { __typename?: 'Mutation', createWorkspace?: { __typename?: 'CreateWorkspacePayload', workspace: { __typename?: 'Workspace', id: string, name: string, personal: boolean } } | null }; +export type CreateWorkspaceMutation = { __typename?: 'Mutation', createWorkspace?: { __typename?: 'CreateWorkspacePayload', workspace: { __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> } } | null }; export type GetWorkspacesQueryVariables = Exact<{ [key: string]: never; }>; -export type GetWorkspacesQuery = { __typename?: 'Query', me?: { __typename?: 'Me', workspaces: Array<{ __typename?: 'Workspace', id: string, name: string, personal: boolean }> } | null }; +export type GetWorkspacesQuery = { __typename?: 'Query', me?: { __typename?: 'Me', workspaces: Array<{ __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> }> } | null }; export type GetWorkspaceByIdQueryVariables = Exact<{ workspaceId: Scalars['ID']['input']; }>; -export type GetWorkspaceByIdQuery = { __typename?: 'Query', node?: { __typename: 'Asset' } | { __typename: 'Project' } | { __typename: 'User' } | { __typename: 'Workspace', id: string, name: string, personal: boolean } | null }; +export type GetWorkspaceByIdQuery = { __typename?: 'Query', node?: { __typename: 'Asset' } | { __typename: 'Project' } | { __typename: 'User' } | { __typename: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> } | null }; export type UpdateWorkspaceMutationVariables = Exact<{ input: UpdateWorkspaceInput; }>; -export type UpdateWorkspaceMutation = { __typename?: 'Mutation', updateWorkspace?: { __typename?: 'UpdateWorkspacePayload', workspace: { __typename?: 'Workspace', id: string, name: string, personal: boolean } } | null }; +export type UpdateWorkspaceMutation = { __typename?: 'Mutation', updateWorkspace?: { __typename?: 'UpdateWorkspacePayload', workspace: { __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> } } | null }; export type DeleteWorkspaceMutationVariables = Exact<{ input: DeleteWorkspaceInput; @@ -535,6 +542,27 @@ export type DeleteWorkspaceMutationVariables = Exact<{ export type DeleteWorkspaceMutation = { __typename?: 'Mutation', deleteWorkspace?: { __typename?: 'DeleteWorkspacePayload', workspaceId: string } | null }; +export type AddMemberToWorkspaceMutationVariables = Exact<{ + input: AddMemberToWorkspaceInput; +}>; + + +export type AddMemberToWorkspaceMutation = { __typename?: 'Mutation', addMemberToWorkspace?: { __typename?: 'AddMemberToWorkspacePayload', workspace: { __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> } } | null }; + +export type RemoveMemberFromWorkspaceMutationVariables = Exact<{ + input: RemoveMemberFromWorkspaceInput; +}>; + + +export type RemoveMemberFromWorkspaceMutation = { __typename?: 'Mutation', removeMemberFromWorkspace?: { __typename?: 'RemoveMemberFromWorkspacePayload', workspace: { __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> } } | null }; + +export type UpdateMemberOfWorkspaceMutationVariables = Exact<{ + input: UpdateMemberOfWorkspaceInput; +}>; + + +export type UpdateMemberOfWorkspaceMutation = { __typename?: 'Mutation', updateMemberOfWorkspace?: { __typename?: 'UpdateMemberOfWorkspacePayload', workspace: { __typename?: 'Workspace', id: string, name: string, personal: boolean, members: Array<{ __typename?: 'WorkspaceMember', userId: string, role: Role, user?: { __typename?: 'User', id: string, email: string, name: string } | null }> } } | null }; + export const ProjectFragmentDoc = gql` fragment Project on Project { id @@ -550,6 +578,15 @@ export const WorkspaceFragmentDoc = gql` id name personal + members { + userId + role + user { + id + email + name + } + } } `; export const CreateProjectDocument = gql` @@ -611,6 +648,15 @@ export const GetMeDocument = gql` } } `; +export const SearchUserDocument = gql` + query SearchUser($email: String!) { + searchUser(nameOrEmail: $email) { + id + name + email + } +} + `; export const CreateWorkspaceDocument = gql` mutation CreateWorkspace($input: CreateWorkspaceInput!) { createWorkspace(input: $input) { @@ -653,6 +699,33 @@ export const DeleteWorkspaceDocument = gql` } } `; +export const AddMemberToWorkspaceDocument = gql` + mutation AddMemberToWorkspace($input: AddMemberToWorkspaceInput!) { + addMemberToWorkspace(input: $input) { + workspace { + ...Workspace + } + } +} + ${WorkspaceFragmentDoc}`; +export const RemoveMemberFromWorkspaceDocument = gql` + mutation RemoveMemberFromWorkspace($input: RemoveMemberFromWorkspaceInput!) { + removeMemberFromWorkspace(input: $input) { + workspace { + ...Workspace + } + } +} + ${WorkspaceFragmentDoc}`; +export const UpdateMemberOfWorkspaceDocument = gql` + mutation UpdateMemberOfWorkspace($input: UpdateMemberOfWorkspaceInput!) { + updateMemberOfWorkspace(input: $input) { + workspace { + ...Workspace + } + } +} + ${WorkspaceFragmentDoc}`; export type SdkFunctionWrapper = (action: (requestHeaders?:Record) => Promise, operationName: string, operationType?: string, variables?: any) => Promise; @@ -679,6 +752,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = GetMe(variables?: GetMeQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { return withWrapper((wrappedRequestHeaders) => client.request(GetMeDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'GetMe', 'query', variables); }, + SearchUser(variables: SearchUserQueryVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(SearchUserDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'SearchUser', 'query', variables); + }, CreateWorkspace(variables: CreateWorkspaceMutationVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { return withWrapper((wrappedRequestHeaders) => client.request(CreateWorkspaceDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'CreateWorkspace', 'mutation', variables); }, @@ -693,6 +769,15 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = }, DeleteWorkspace(variables: DeleteWorkspaceMutationVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { return withWrapper((wrappedRequestHeaders) => client.request(DeleteWorkspaceDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'DeleteWorkspace', 'mutation', variables); + }, + AddMemberToWorkspace(variables: AddMemberToWorkspaceMutationVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(AddMemberToWorkspaceDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'AddMemberToWorkspace', 'mutation', variables); + }, + RemoveMemberFromWorkspace(variables: RemoveMemberFromWorkspaceMutationVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(RemoveMemberFromWorkspaceDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'RemoveMemberFromWorkspace', 'mutation', variables); + }, + UpdateMemberOfWorkspace(variables: UpdateMemberOfWorkspaceMutationVariables, requestHeaders?: GraphQLClientRequestHeaders): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(UpdateMemberOfWorkspaceDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'UpdateMemberOfWorkspace', 'mutation', variables); } }; } diff --git a/ui/src/lib/gql/project/useQueries.ts b/ui/src/lib/gql/project/useQueries.ts index d0135ff40..a2faa03c2 100644 --- a/ui/src/lib/gql/project/useQueries.ts +++ b/ui/src/lib/gql/project/useQueries.ts @@ -2,6 +2,7 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useCallback } from "react"; import { useGraphQLContext } from "@flow/lib/gql"; +import { isDefined } from "@flow/lib/utils"; import { Project } from "@flow/types"; import { @@ -54,9 +55,9 @@ export const useQueries = () => { projects: { nodes, ...rest }, } = data; - const projects: Project[] = nodes.flatMap(project => - project ? [createNewProjectObject(project)] : [], - ); + const projects: Project[] = nodes + .filter(isDefined) + .map(project => createNewProjectObject(project)); return { projects, meta: rest }; }, }); diff --git a/ui/src/lib/gql/user/queries.graphql b/ui/src/lib/gql/user/queries.graphql index e0f5482d2..d323a2895 100644 --- a/ui/src/lib/gql/user/queries.graphql +++ b/ui/src/lib/gql/user/queries.graphql @@ -6,3 +6,11 @@ query GetMe { myWorkspaceId } } + +query SearchUser($email: String!) { + searchUser(nameOrEmail: $email) { + id + name + email + } +} diff --git a/ui/src/lib/gql/user/useApi.ts b/ui/src/lib/gql/user/useApi.ts index 0ce60e741..2964037eb 100644 --- a/ui/src/lib/gql/user/useApi.ts +++ b/ui/src/lib/gql/user/useApi.ts @@ -1,23 +1,32 @@ -import { GetMe } from "@flow/types/user"; +import { GetMe, SearchUser } from "@flow/types/user"; import { useQueries } from "./useQueries"; export enum UserQueryKeys { GetMe = "getMe", + SearchUser = "User", } export const useUser = () => { - const { getMeQuery } = useQueries(); + const { useGetMeQuery, searchUserQuery } = useQueries(); - const getMe = (): GetMe => { - const { data, ...rest } = getMeQuery; + const useGetMe = (): GetMe => { + const { data, ...rest } = useGetMeQuery(); return { me: data, ...rest, }; }; + const searchUser = async (email: string): Promise => { + const data = await searchUserQuery(email); + return { + user: data, + }; + }; + return { - getMe, + useGetMe, + searchUser, }; }; diff --git a/ui/src/lib/gql/user/useQueries.ts b/ui/src/lib/gql/user/useQueries.ts index b9c991978..445469e13 100644 --- a/ui/src/lib/gql/user/useQueries.ts +++ b/ui/src/lib/gql/user/useQueries.ts @@ -1,32 +1,46 @@ import { useQuery } from "@tanstack/react-query"; import { useGraphQLContext } from "@flow/lib/gql"; -import { Me } from "@flow/types/user"; - -import { GetMeQuery } from "../__gen__/graphql"; import { UserQueryKeys } from "./useApi"; export const useQueries = () => { const graphQLContext = useGraphQLContext(); - const getMeQuery = useQuery({ - queryKey: [UserQueryKeys.GetMe], - queryFn: () => graphQLContext?.GetMe(), - select: (data: GetMeQuery | undefined): Me | undefined => { - if (!data?.me) return undefined; - const me = data.me; + const useGetMeQuery = () => + useQuery({ + queryKey: [UserQueryKeys.GetMe], + queryFn: async () => { + const data = await graphQLContext?.GetMe(); + if (!data?.me) return; + const me = data.me; + return { + id: me.id, + name: me.name, + email: me.email, + myWorkspaceId: me.myWorkspaceId, + }; + }, + staleTime: Infinity, + }); + + // Not using react-query because no observers are needed on this + const searchUserQuery = async (email: string) => { + try { + const data = await graphQLContext?.SearchUser({ email }); + if (!data?.searchUser) return; return { - id: me.id, - name: me.name, - email: me.email, - myWorkspaceId: me.myWorkspaceId, + id: data.searchUser.id, + name: data.searchUser.name, + email: data.searchUser.email, }; - }, - staleTime: Infinity, - }); + } catch (err) { + return; + } + }; return { - getMeQuery, + useGetMeQuery, + searchUserQuery, }; }; diff --git a/ui/src/lib/gql/workspace/queries.graphql b/ui/src/lib/gql/workspace/queries.graphql index 76089dfd8..3f38ac2c6 100644 --- a/ui/src/lib/gql/workspace/queries.graphql +++ b/ui/src/lib/gql/workspace/queries.graphql @@ -2,6 +2,15 @@ fragment Workspace on Workspace { id name personal + members { + userId + role + user { + id + email + name + } + } } mutation CreateWorkspace($input: CreateWorkspaceInput!) { @@ -41,3 +50,27 @@ mutation DeleteWorkspace($input: DeleteWorkspaceInput!) { workspaceId } } + +mutation AddMemberToWorkspace($input: AddMemberToWorkspaceInput!) { + addMemberToWorkspace(input: $input) { + workspace { + ...Workspace + } + } +} + +mutation RemoveMemberFromWorkspace($input: RemoveMemberFromWorkspaceInput!) { + removeMemberFromWorkspace(input: $input) { + workspace { + ...Workspace + } + } +} + +mutation UpdateMemberOfWorkspace($input: UpdateMemberOfWorkspaceInput!) { + updateMemberOfWorkspace(input: $input) { + workspace { + ...Workspace + } + } +} diff --git a/ui/src/lib/gql/workspace/useApi.ts b/ui/src/lib/gql/workspace/useApi.ts index 496624784..185c173eb 100644 --- a/ui/src/lib/gql/workspace/useApi.ts +++ b/ui/src/lib/gql/workspace/useApi.ts @@ -1,4 +1,4 @@ -import { GetWorkspaces, CreateWorkspace, DeleteWorkspace, GetWorkspace } from "@flow/types"; +import { GetWorkspaces, DeleteWorkspace, GetWorkspace, Role, WorkspaceMutation } from "@flow/types"; import { useQueries } from "./useQueries"; @@ -13,9 +13,13 @@ export const useWorkspace = () => { useGetWorkspacesQuery, deleteWorkspaceMutation, useGetWorkspaceByIdQuery, + updateWorkspaceMutation, + addMemberToWorkspaceMutation, + removeMemberFromWorkspaceMutation, + updateMemberOfWorkspaceMutation, } = useQueries(); - const createWorkspace = async (name: string): Promise => { + const createWorkspace = async (name: string): Promise => { const { mutateAsync, ...rest } = createWorkspaceMutation; try { const data = await mutateAsync(name); @@ -25,16 +29,6 @@ export const useWorkspace = () => { } }; - const deleteWorkspace = async (workspaceId: string): Promise => { - const { mutateAsync, ...rest } = deleteWorkspaceMutation; - try { - const data = await mutateAsync(workspaceId); - return { workspaceId: data, ...rest }; - } catch (err) { - return { workspaceId: undefined, ...rest }; - } - }; - const useGetWorkspaces = (): GetWorkspaces => { const { data: workspaces, ...rest } = useGetWorkspacesQuery(); return { @@ -51,10 +45,76 @@ export const useWorkspace = () => { }; }; + const updateWorkspace = async (workspaceId: string, name: string): Promise => { + const { mutateAsync, ...rest } = updateWorkspaceMutation; + try { + const data = await mutateAsync({ workspaceId, name }); + return { workspace: data, ...rest }; + } catch (err) { + return { workspace: undefined, ...rest }; + } + }; + + const deleteWorkspace = async (workspaceId: string): Promise => { + const { mutateAsync, ...rest } = deleteWorkspaceMutation; + try { + const data = await mutateAsync(workspaceId); + return { workspaceId: data, ...rest }; + } catch (err) { + return { workspaceId: undefined, ...rest }; + } + }; + + // Members in the Workspace + const addMemberToWorkspace = async ( + workspaceId: string, + userId: string, + role: Role, + ): Promise => { + const { mutateAsync, ...rest } = addMemberToWorkspaceMutation; + try { + const data = await mutateAsync({ workspaceId, userId, role }); + return { workspace: data, ...rest }; + } catch (err) { + return { workspace: undefined, ...rest }; + } + }; + + const removeMemberFromWorkspace = async ( + workspaceId: string, + userId: string, + ): Promise => { + const { mutateAsync, ...rest } = removeMemberFromWorkspaceMutation; + try { + const data = await mutateAsync({ workspaceId, userId }); + return { workspace: data, ...rest }; + } catch (err) { + return { workspace: undefined, ...rest }; + } + }; + + const updateMemberOfWorkspace = async ( + workspaceId: string, + userId: string, + role: Role, + ): Promise => { + const { mutateAsync, ...rest } = updateMemberOfWorkspaceMutation; + try { + const data = await mutateAsync({ workspaceId, userId, role }); + return { workspace: data, ...rest }; + } catch (err) { + return { workspace: undefined, ...rest }; + } + }; + return { createWorkspace, useGetWorkspaces, useGetWorkspace, deleteWorkspace, + updateWorkspace, + addMemberToWorkspace, + removeMemberFromWorkspace, + updateMemberOfWorkspace, }; }; diff --git a/ui/src/lib/gql/workspace/useQueries.ts b/ui/src/lib/gql/workspace/useQueries.ts index 6d12a404c..6fd7d5a4b 100644 --- a/ui/src/lib/gql/workspace/useQueries.ts +++ b/ui/src/lib/gql/workspace/useQueries.ts @@ -2,9 +2,16 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useCallback } from "react"; import { useGraphQLContext } from "@flow/lib/gql"; -import { Workspace } from "@flow/types"; +import { isDefined } from "@flow/lib/utils"; +import { Member, Workspace } from "@flow/types"; -import { WorkspaceFragment } from "../__gen__/graphql"; +import { + AddMemberToWorkspaceInput, + RemoveMemberFromWorkspaceInput, + UpdateMemberOfWorkspaceInput, + UpdateWorkspaceInput, + WorkspaceFragment, +} from "../__gen__/graphql"; import { WorkspaceQueryKeys } from "./useApi"; @@ -13,22 +20,45 @@ export const useQueries = () => { const graphQLContext = useGraphQLContext(); const queryClient = useQueryClient(); - const createNewWorkspaceObject = useCallback( - (w: WorkspaceFragment): Workspace => ({ + const createNewWorkspaceObject = useCallback((w?: WorkspaceFragment): Workspace | undefined => { + if (!w) return; + return { id: w.id, name: w.name, personal: w.personal, - }), - [], - ); + members: w.members.map( + (m): Member => ({ + userId: m.userId, + role: m.role, + user: m.user + ? { + id: m.user?.id, + name: m.user?.name, + email: m.user?.email, + } + : undefined, + }), + ), + }; + }, []); + + const updateWorkspace = (workspace?: Workspace) => { + if (!workspace) return; + queryClient.setQueryData([WorkspaceQueryKeys.GetWorkspaces], (data: Workspace[]) => { + data.splice( + data.findIndex(w => w.id === workspace?.id), + 1, + workspace, + ); + return [...data]; + }); + queryClient.setQueryData([WorkspaceQueryKeys.GetWorkspace, workspace.id], () => workspace); + }; const createWorkspaceMutation = useMutation({ mutationFn: async (name: string) => { const data = await graphQLContext?.CreateWorkspace({ input: { name } }); - return ( - data?.createWorkspace?.workspace && - createNewWorkspaceObject(data?.createWorkspace?.workspace) - ); + return createNewWorkspaceObject(data?.createWorkspace?.workspace); }, onSuccess: createdWorkspace => { queryClient.setQueryData([WorkspaceQueryKeys.GetWorkspaces], (data: Workspace[]) => [ @@ -41,20 +71,36 @@ export const useQueries = () => { const useGetWorkspacesQuery = () => useQuery({ queryKey: [WorkspaceQueryKeys.GetWorkspaces], - queryFn: () => graphQLContext?.GetWorkspaces(), - select: data => data?.me?.workspaces.map(w => createNewWorkspaceObject(w)), + queryFn: async () => { + const data = await graphQLContext?.GetWorkspaces(); + + return data?.me?.workspaces + .filter(isDefined) + .map(w => createNewWorkspaceObject(w) as Workspace); + }, staleTime: Infinity, }); const useGetWorkspaceByIdQuery = (workspaceId: string) => useQuery({ queryKey: [WorkspaceQueryKeys.GetWorkspace, workspaceId], - queryFn: () => graphQLContext?.GetWorkspaceById({ workspaceId }), - select: data => - data?.node?.__typename === "Workspace" ? createNewWorkspaceObject(data.node) : undefined, + queryFn: async () => { + const data = await graphQLContext?.GetWorkspaceById({ workspaceId }); + return data?.node?.__typename === "Workspace" + ? createNewWorkspaceObject(data.node) + : undefined; + }, staleTime: Infinity, }); + const updateWorkspaceMutation = useMutation({ + mutationFn: async (input: UpdateWorkspaceInput) => { + const data = await graphQLContext?.UpdateWorkspace({ input }); + return createNewWorkspaceObject(data?.updateWorkspace?.workspace); + }, + onSuccess: updateWorkspace, + }); + const deleteWorkspaceMutation = useMutation({ mutationFn: async (workspaceId: string) => { const data = await graphQLContext?.DeleteWorkspace({ input: { workspaceId } }); @@ -71,10 +117,45 @@ export const useQueries = () => { }, }); + // Members in the Workspace + const addMemberToWorkspaceMutation = useMutation({ + mutationFn: async (input: AddMemberToWorkspaceInput) => { + const data = await graphQLContext?.AddMemberToWorkspace({ + input, + }); + return createNewWorkspaceObject(data?.addMemberToWorkspace?.workspace); + }, + onSuccess: updateWorkspace, + }); + + const removeMemberFromWorkspaceMutation = useMutation({ + mutationFn: async (input: RemoveMemberFromWorkspaceInput) => { + const data = await graphQLContext?.RemoveMemberFromWorkspace({ + input, + }); + return createNewWorkspaceObject(data?.removeMemberFromWorkspace?.workspace); + }, + onSuccess: updateWorkspace, + }); + + const updateMemberOfWorkspaceMutation = useMutation({ + mutationFn: async (input: UpdateMemberOfWorkspaceInput) => { + const data = await graphQLContext?.UpdateMemberOfWorkspace({ + input, + }); + return createNewWorkspaceObject(data?.updateMemberOfWorkspace?.workspace); + }, + onSuccess: updateWorkspace, + }); + return { createWorkspaceMutation, useGetWorkspacesQuery, useGetWorkspaceByIdQuery, deleteWorkspaceMutation, + updateWorkspaceMutation, + addMemberToWorkspaceMutation, + removeMemberFromWorkspaceMutation, + updateMemberOfWorkspaceMutation, }; }; diff --git a/ui/src/lib/i18n/locales/en.json b/ui/src/lib/i18n/locales/en.json index a283f71af..b8c13705e 100644 --- a/ui/src/lib/i18n/locales/en.json +++ b/ui/src/lib/i18n/locales/en.json @@ -117,10 +117,12 @@ "Workspace Name": "", "Save": "", "Delete Workspace": "", - "Failed to delete workspace": "", + "Failed to delete Workspace": "", + "Failed to update Workspace": "", "All": "", - "Admin": "", + "Owner": "", "Reader": "", + "Maintainer": "", "Writer": "", "Integrations Settings": "", "Connect Integration": "", @@ -130,7 +132,8 @@ "Change role": "", "Remove selected": "", "Members Settings": "", - "Add Members": "", + "Enter email": "", + "Add Member": "", "Members": "", "General": "" } diff --git a/ui/src/lib/i18n/locales/es.json b/ui/src/lib/i18n/locales/es.json index 403195773..59dd82acb 100644 --- a/ui/src/lib/i18n/locales/es.json +++ b/ui/src/lib/i18n/locales/es.json @@ -117,10 +117,12 @@ "Workspace Name": "", "Save": "", "Delete Workspace": "", - "Failed to delete workspace": "", + "Failed to delete Workspace": "", + "Failed to update Workspace": "", "All": "", - "Admin": "", + "Owner": "", "Reader": "", + "Maintainer": "", "Writer": "", "Integrations Settings": "", "Connect Integration": "", @@ -130,7 +132,8 @@ "Change role": "", "Remove selected": "", "Members Settings": "", - "Add Members": "", + "Enter email": "", + "Add Member": "", "Members": "", "General": "" } diff --git a/ui/src/lib/i18n/locales/fr.json b/ui/src/lib/i18n/locales/fr.json index ae9b5ccec..17f850583 100644 --- a/ui/src/lib/i18n/locales/fr.json +++ b/ui/src/lib/i18n/locales/fr.json @@ -117,10 +117,12 @@ "Workspace Name": "", "Save": "", "Delete Workspace": "", - "Failed to delete workspace": "", + "Failed to delete Workspace": "", + "Failed to update Workspace": "", "All": "", - "Admin": "", + "Owner": "", "Reader": "", + "Maintainer": "", "Writer": "", "Integrations Settings": "", "Connect Integration": "", @@ -130,7 +132,8 @@ "Change role": "", "Remove selected": "", "Members Settings": "", - "Add Members": "", + "Enter email": "", + "Add Member": "", "Members": "", "General": "" } diff --git a/ui/src/lib/i18n/locales/ja.json b/ui/src/lib/i18n/locales/ja.json index 080f728ec..5c14f9b82 100644 --- a/ui/src/lib/i18n/locales/ja.json +++ b/ui/src/lib/i18n/locales/ja.json @@ -117,10 +117,12 @@ "Workspace Name": "ワークスペース名", "Save": "保存", "Delete Workspace": "ワークスペースを削除", - "Failed to delete workspace": "ワークスペースの削除に失敗しました", + "Failed to delete Workspace": "", + "Failed to update Workspace": "", "All": "", - "Admin": "", + "Owner": "", "Reader": "", + "Maintainer": "", "Writer": "", "Integrations Settings": "", "Connect Integration": "", @@ -130,7 +132,8 @@ "Change role": "", "Remove selected": "", "Members Settings": "", - "Add Members": "", + "Enter email": "", + "Add Member": "", "Members": "", "General": "" } diff --git a/ui/src/lib/i18n/locales/zh.json b/ui/src/lib/i18n/locales/zh.json index f06d30b89..0ff4f2deb 100644 --- a/ui/src/lib/i18n/locales/zh.json +++ b/ui/src/lib/i18n/locales/zh.json @@ -117,10 +117,12 @@ "Workspace Name": "", "Save": "", "Delete Workspace": "", - "Failed to delete workspace": "", + "Failed to delete Workspace": "", + "Failed to update Workspace": "", "All": "", - "Admin": "", + "Owner": "", "Reader": "", + "Maintainer": "", "Writer": "", "Integrations Settings": "", "Connect Integration": "", @@ -130,7 +132,8 @@ "Change role": "", "Remove selected": "", "Members Settings": "", - "Add Members": "", + "Enter email": "", + "Add Member": "", "Members": "", "General": "" } diff --git a/ui/src/lib/utils.ts b/ui/src/lib/utils.ts index cffaf97a5..f9def1a16 100644 --- a/ui/src/lib/utils.ts +++ b/ui/src/lib/utils.ts @@ -5,3 +5,7 @@ import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } + +export function isDefined(argument: T | undefined | null): argument is T { + return argument !== undefined || argument !== null; +} diff --git a/ui/src/pages/LoadingPage.tsx b/ui/src/pages/LoadingPage.tsx index ccc131a7c..22672da67 100644 --- a/ui/src/pages/LoadingPage.tsx +++ b/ui/src/pages/LoadingPage.tsx @@ -6,8 +6,8 @@ import { useUser } from "@flow/lib/gql"; const LoadingPage: React.FC = () => { const navigate = useNavigate(); - const { getMe } = useUser(); - const { isLoading, me } = getMe(); + const { useGetMe } = useUser(); + const { me, isLoading } = useGetMe(); if (isLoading) return ; diff --git a/ui/src/routes/workspace_.$workspaceId_.settings.$tab.lazy.tsx b/ui/src/routes/workspace_.$workspaceId_.settings.$tab.lazy.tsx index 77ddd1bf1..1b26b5563 100644 --- a/ui/src/routes/workspace_.$workspaceId_.settings.$tab.lazy.tsx +++ b/ui/src/routes/workspace_.$workspaceId_.settings.$tab.lazy.tsx @@ -6,7 +6,7 @@ import { WorkspaceSettings } from "@flow/pages"; export const Route = createLazyFileRoute("/workspace/$workspaceId/settings/$tab")({ component: () => ( - , + ), }); diff --git a/ui/src/types/member.ts b/ui/src/types/member.ts index c8b8ffe82..1907a4059 100644 --- a/ui/src/types/member.ts +++ b/ui/src/types/member.ts @@ -1,12 +1,17 @@ import { IntegrationMember } from "./integration"; import { User } from "./user"; -export type Role = "reader" | "writer" | "admin"; +export enum Role { + Maintainer = "MAINTAINER", + Owner = "OWNER", + Reader = "READER", + Writer = "WRITER", +} export type UserMember = { userId: string; role: Role; - user: User; + user?: User; }; export type Member = UserMember | IntegrationMember; diff --git a/ui/src/types/user.ts b/ui/src/types/user.ts index 8ffb319b1..3456982eb 100644 --- a/ui/src/types/user.ts +++ b/ui/src/types/user.ts @@ -16,3 +16,7 @@ export type User = { name: string; email: string; }; + +export type SearchUser = { + user?: User; +}; diff --git a/ui/src/types/workspace.ts b/ui/src/types/workspace.ts index 5a71a31c2..9793ae2e4 100644 --- a/ui/src/types/workspace.ts +++ b/ui/src/types/workspace.ts @@ -4,16 +4,16 @@ export type Workspace = { id: string; name: string; personal: boolean; - members?: Member[]; + members: Member[]; projects?: Project[]; }; -export type CreateWorkspace = { - workspace: Workspace | undefined; +export type WorkspaceMutation = { + workspace?: Workspace; } & ApiResponse; export type GetWorkspaces = { - workspaces: Workspace[] | undefined; + workspaces?: Workspace[]; isLoading: boolean; } & ApiResponse; @@ -23,5 +23,5 @@ export type GetWorkspace = { } & ApiResponse; export type DeleteWorkspace = { - workspaceId: string | undefined; + workspaceId?: string; } & ApiResponse;