Add workspace members (#536)
* Add workspace members * Remove workspace provider * Lint
This commit is contained in:
@ -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>
|
||||
}
|
||||
/>
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
@ -1 +1,2 @@
|
||||
export * from './select';
|
||||
export * from './update';
|
||||
19
front/src/modules/workspace/queries/select.ts
Normal file
19
front/src/modules/workspace/queries/select.ts
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
39
front/src/pages/settings/SettingsWorkspaceMembers.tsx
Normal file
39
front/src/pages/settings/SettingsWorkspaceMembers.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user