Add workspace members (#536)

* Add workspace members

* Remove workspace provider

* Lint
This commit is contained in:
Emilien Chauvet
2023-07-07 18:56:22 -07:00
committed by GitHub
parent 66dcc9b2e1
commit c26a7fda9a
9 changed files with 212 additions and 1 deletions

View File

@ -15,6 +15,7 @@ import { Companies } from '~/pages/companies/Companies';
import { Opportunities } from '~/pages/opportunities/Opportunities';
import { People } from '~/pages/people/People';
import { SettingsProfile } from '~/pages/settings/SettingsProfile';
import { SettingsWorkspaceMembers } from '~/pages/settings/SettingsWorkspaceMembers';
import { AppInternalHooks } from './AppInternalHooks';
@ -71,6 +72,10 @@ export function App() {
element={
<Routes>
<Route path="profile" element={<SettingsProfile />} />
<Route
path="workspace-members"
element={<SettingsWorkspaceMembers />}
/>
</Routes>
}
/>

View File

@ -2288,6 +2288,7 @@ export type Query = {
__typename?: 'Query';
clientConfig: ClientConfig;
currentUser: User;
currentWorkspace: Workspace;
findManyCommentThreads: Array<CommentThread>;
findManyCompany: Array<Company>;
findManyPerson: Array<Person>;
@ -3061,6 +3062,11 @@ export type UpdateUserMutationVariables = Exact<{
export type UpdateUserMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } };
export type GetCurrentWorkspaceQueryVariables = Exact<{ [key: string]: never; }>;
export type GetCurrentWorkspaceQuery = { __typename?: 'Query', currentWorkspace: { __typename?: 'Workspace', id: string, workspaceMember?: Array<{ __typename?: 'WorkspaceMember', id: string, user: { __typename?: 'User', id: string, email: string, avatarUrl?: string | null, firstName?: string | null, lastName?: string | null } }> | null } };
export type UpdateWorkspaceMutationVariables = Exact<{
data: WorkspaceUpdateInput;
}>;
@ -4508,6 +4514,50 @@ export function useUpdateUserMutation(baseOptions?: Apollo.MutationHookOptions<U
export type UpdateUserMutationHookResult = ReturnType<typeof useUpdateUserMutation>;
export type UpdateUserMutationResult = Apollo.MutationResult<UpdateUserMutation>;
export type UpdateUserMutationOptions = Apollo.BaseMutationOptions<UpdateUserMutation, UpdateUserMutationVariables>;
export const GetCurrentWorkspaceDocument = gql`
query GetCurrentWorkspace {
currentWorkspace {
id
workspaceMember {
id
user {
id
email
avatarUrl
firstName
lastName
}
}
}
}
`;
/**
* __useGetCurrentWorkspaceQuery__
*
* To run a query within a React component, call `useGetCurrentWorkspaceQuery` and pass it any options that fit your needs.
* When your component renders, `useGetCurrentWorkspaceQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useGetCurrentWorkspaceQuery({
* variables: {
* },
* });
*/
export function useGetCurrentWorkspaceQuery(baseOptions?: Apollo.QueryHookOptions<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>(GetCurrentWorkspaceDocument, options);
}
export function useGetCurrentWorkspaceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>(GetCurrentWorkspaceDocument, options);
}
export type GetCurrentWorkspaceQueryHookResult = ReturnType<typeof useGetCurrentWorkspaceQuery>;
export type GetCurrentWorkspaceLazyQueryHookResult = ReturnType<typeof useGetCurrentWorkspaceLazyQuery>;
export type GetCurrentWorkspaceQueryResult = Apollo.QueryResult<GetCurrentWorkspaceQuery, GetCurrentWorkspaceQueryVariables>;
export const UpdateWorkspaceDocument = gql`
mutation UpdateWorkspace($data: WorkspaceUpdateInput!) {
updateWorkspace(data: $data) {

View File

@ -8,6 +8,7 @@ import {
IconLogout,
IconSettings,
IconUser,
IconUsers,
} from '@/ui/icons/index';
import NavItem from '@/ui/layout/navbar/NavItem';
import NavItemsContainer from '@/ui/layout/navbar/NavItemsContainer';
@ -51,6 +52,18 @@ export function SettingsNavbar() {
}
/>
<NavTitle label="Workspace" />
<NavItem
label="Members"
to="/settings/workspace-members"
icon={<IconUsers size={theme.icon.size.md} />}
soon={false}
active={
!!useMatch({
path: useResolvedPath('/settings/workspace-members').pathname,
end: true,
})
}
/>
<NavItem
label="General"
to="/settings/workspace"

View File

@ -0,0 +1,66 @@
import styled from '@emotion/styled';
import { Avatar } from '@/users/components/Avatar';
import { User } from '~/generated/graphql';
const StyledContainer = styled.div`
background: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.spacing(2)};
display: flex;
flex-direction: row;
margin-bottom: ${({ theme }) => theme.spacing(0)};
margin-top: ${({ theme }) => theme.spacing(4)};
`;
const AvatarContainer = styled.div`
margin: ${({ theme }) => theme.spacing(3)};
`;
const TextContainer = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
`;
const NameAndEmailContainer = styled.div`
display: flex;
flex-direction: column;
`;
const NameText = styled.span`
color: ${({ theme }) => theme.font.color.primary};
`;
const EmailText = styled.span`
color: ${({ theme }) => theme.font.color.tertiary};
`;
type OwnProps = {
workspaceMember: {
user: Pick<User, 'firstName' | 'lastName' | 'avatarUrl' | 'email'>;
};
};
export function WorkspaceMemberCard({ workspaceMember }: OwnProps) {
return (
<StyledContainer>
<AvatarContainer>
<Avatar
avatarUrl={workspaceMember.user.avatarUrl}
placeholder={workspaceMember.user.firstName || ''}
type="squared"
size={40}
/>
</AvatarContainer>
<TextContainer>
<NameAndEmailContainer>
<NameText>
{workspaceMember.user.firstName} {workspaceMember.user.lastName}{' '}
</NameText>
<EmailText>{workspaceMember.user.email}</EmailText>
</NameAndEmailContainer>
</TextContainer>
</StyledContainer>
);
}

View File

@ -1 +1,2 @@
export * from './select';
export * from './update';

View File

@ -0,0 +1,19 @@
import { gql } from '@apollo/client';
export const GET_CURRENT_WORKSPACE = gql`
query GetCurrentWorkspace {
currentWorkspace {
id
workspaceMember {
id
user {
id
email
avatarUrl
firstName
lastName
}
}
}
}
`;

View File

@ -0,0 +1,39 @@
import styled from '@emotion/styled';
import { MainSectionTitle } from '@/ui/components/section-titles/MainSectionTitle';
import { SubSectionTitle } from '@/ui/components/section-titles/SubSectionTitle';
import { NoTopBarContainer } from '@/ui/layout/containers/NoTopBarContainer';
import { WorkspaceMemberCard } from '@/workspace/components/WorkspaceMemberCard';
import { useGetCurrentWorkspaceQuery } from '~/generated/graphql';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
padding: ${({ theme }) => theme.spacing(8)};
width: 350px;
> * + * {
margin-top: ${({ theme }) => theme.spacing(8)};
}
`;
export function SettingsWorkspaceMembers() {
const { data } = useGetCurrentWorkspaceQuery();
return (
<NoTopBarContainer>
<StyledContainer>
<MainSectionTitle>Members</MainSectionTitle>
<SubSectionTitle
title="Members"
description="Manage the members of your space here"
/>
{data?.currentWorkspace?.workspaceMember?.map((member) => (
<WorkspaceMemberCard
key={member.user.id}
workspaceMember={{ user: member.user }}
/>
))}
</StyledContainer>
</NoTopBarContainer>
);
}

View File

@ -1,4 +1,4 @@
import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { Query, Args, Mutation, Resolver } from '@nestjs/graphql';
import { UseGuards } from '@nestjs/common';
import { Workspace } from 'src/core/@generated/workspace/workspace.model';
import { WorkspaceService } from '../services/workspace.service';
@ -10,6 +10,7 @@ import { AuthWorkspace } from 'src/decorators/auth-workspace.decorator';
import { WorkspaceUpdateInput } from 'src/core/@generated/workspace/workspace-update.input';
import { JwtAuthGuard } from 'src/guards/jwt.auth.guard';
import { Prisma } from '@prisma/client';
import { assert } from 'src/utils/assert';
@UseGuards(JwtAuthGuard)
@Resolver(() => Workspace)
@ -33,4 +34,21 @@ export class WorkspaceResolver {
select: prismaSelect.value,
} as Prisma.WorkspaceUpdateArgs);
}
@Query(() => Workspace)
async currentWorkspace(
@AuthWorkspace() workspace: Workspace,
@PrismaSelector({ modelName: 'User' })
prismaSelect: PrismaSelect<'User'>,
) {
const selectedWorkspace = await this.workspaceService.findUnique({
where: {
id: workspace.id,
},
select: prismaSelect.value,
});
assert(selectedWorkspace, 'User not found');
return selectedWorkspace;
}
}