Chore: Duplicate certain user fields to workspaceMember (#1514)

* Move certain user fields to workspaceMember

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Merge main

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Update the generated GraphQL

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Update hooks

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>

* Rework typing

* Fix tests

* Remove console logs

---------

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: chiazokam <chiazokamecheta@gmail.com>
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
gitstart-twenty
2023-09-16 01:32:58 +01:00
committed by GitHub
parent 0a7a0ac6cb
commit 549335054a
23 changed files with 890 additions and 115 deletions

View File

@ -9,6 +9,7 @@ import { Entity } from '@/ui/input/relation-picker/types/EntityTypeForSelect';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import {
Activity,
useGetWorkspaceMembersLazyQuery,
User,
useSearchUserQuery,
useUpdateActivityMutation,
@ -38,6 +39,7 @@ export function ActivityAssigneePicker({
relationPickerSearchFilterScopedState,
);
const [updateActivity] = useUpdateActivityMutation();
const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery();
const users = useFilteredSearchEntityQuery({
queryHook: useSearchUserQuery,
@ -66,15 +68,28 @@ export function ActivityAssigneePicker({
fragment: ACTIVITY_UPDATE_FRAGMENT,
});
function handleEntitySelected(
async function handleEntitySelected(
selectedUser: UserForSelect | null | undefined,
) {
if (selectedUser) {
const workspaceMemberAssignee = (
await getWorkspaceMember({
variables: {
where: {
userId: { equals: selectedUser.id },
},
},
})
).data?.workspaceMembers?.[0];
updateActivity({
variables: {
where: { id: activity.id },
data: {
assignee: { connect: { id: selectedUser.id } },
workspaceMemberAssignee: {
connect: { id: workspaceMemberAssignee?.id },
},
},
},
optimisticResponse: {

View File

@ -48,7 +48,13 @@ export function useOpenCreateActivityDrawer() {
createdAt: now,
updatedAt: now,
author: { connect: { id: currentUser?.id ?? '' } },
workspaceMemberAuthor: {
connect: { id: currentUser?.workspaceMember?.id ?? '' },
},
assignee: { connect: { id: assigneeId ?? currentUser?.id ?? '' } },
workspaceMemberAssignee: {
connect: { id: currentUser?.workspaceMember?.id ?? '' },
},
type: type,
activityTargets: {
createMany: {

View File

@ -20,6 +20,33 @@ export const USER_QUERY_FRAGMENT = gql`
logo
inviteHash
}
assignedActivities {
id
title
}
authoredActivities {
id
title
}
authoredAttachments {
id
name
type
}
settings {
id
colorScheme
locale
}
companies {
id
name
domainName
}
comments {
id
body
}
}
settings {
id

View File

@ -60,7 +60,21 @@ export function useAuth() {
throw new Error('No verify result');
}
setCurrentUser(verifyResult.data?.verify.user);
if (!verifyResult.data?.verify.user.workspaceMember) {
throw new Error('No workspace member');
}
if (!verifyResult.data?.verify.user.workspaceMember.settings) {
throw new Error('No settings');
}
setCurrentUser({
...verifyResult.data?.verify.user,
workspaceMember: {
...verifyResult.data?.verify.user.workspaceMember,
settings: verifyResult.data?.verify.user.workspaceMember.settings,
},
});
setTokenPair(verifyResult.data?.verify.tokens);
return verifyResult.data?.verify;

View File

@ -1,8 +1,32 @@
import { atom } from 'recoil';
import { GetCurrentUserQuery } from '~/generated/graphql';
import {
User,
UserSettings,
Workspace,
WorkspaceMember,
} from '~/generated/graphql';
export type CurrentUser = GetCurrentUserQuery['currentUser'];
export type CurrentUser = Pick<
User,
| 'id'
| 'email'
| 'displayName'
| 'firstName'
| 'lastName'
| 'avatarUrl'
| 'canImpersonate'
| 'supportUserHash'
> & {
workspaceMember: Pick<WorkspaceMember, 'id' | 'allowImpersonation'> & {
workspace: Pick<
Workspace,
'id' | 'displayName' | 'domainName' | 'inviteHash' | 'logo'
>;
settings: Pick<UserSettings, 'id' | 'colorScheme' | 'locale'>;
};
settings: Pick<UserSettings, 'id' | 'colorScheme' | 'locale'>;
};
export const currentUserState = atom<CurrentUser | null>({
key: 'currentUserState',

View File

@ -15,6 +15,7 @@ import { useTableViews } from '@/views/hooks/useTableViews';
import {
UpdateOneCompanyMutationVariables,
useGetCompaniesQuery,
useGetWorkspaceMembersLazyQuery,
useUpdateOneCompanyMutation,
} from '~/generated/graphql';
import { companiesFilters } from '~/pages/companies/companies-filters';
@ -33,6 +34,7 @@ export function CompanyTable() {
const [updateEntityMutation] = useUpdateOneCompanyMutation();
const upsertEntityTableItem = useUpsertEntityTableItem();
const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery();
const { createView, deleteView, submitCurrentView, updateView } =
useTableViews({
objectId: 'company',
@ -44,6 +46,40 @@ export function CompanyTable() {
const { setContextMenuEntries } = useCompanyTableContextMenuEntries();
const { setActionBarEntries } = useCompanyTableActionBarEntries();
async function updateCompany(variables: UpdateOneCompanyMutationVariables) {
const workspaceMemberAccountOwner = variables.data.accountOwner
? (
await getWorkspaceMember({
variables: {
where: {
userId: { equals: variables.data.accountOwner.connect?.id },
},
},
})
).data?.workspaceMembers?.[0]
: undefined;
const data = {
...variables.data,
workspaceMemberAccountOwner: {
connect: { id: workspaceMemberAccountOwner?.id },
},
};
updateEntityMutation({
variables: {
...variables,
data,
},
onCompleted: (data) => {
if (!data.updateOneCompany) {
return;
}
upsertEntityTableItem(data.updateOneCompany);
},
});
}
return (
<>
<EntityTableEffect
@ -75,17 +111,7 @@ export function CompanyTable() {
variables,
}: {
variables: UpdateOneCompanyMutationVariables;
}) =>
updateEntityMutation({
variables,
onCompleted: (data) => {
if (!data.updateOneCompany) {
return;
}
upsertEntityTableItem(data.updateOneCompany);
},
})
}
}) => updateCompany(variables)}
/>
</ViewBarContext.Provider>
</>

View File

@ -2,20 +2,36 @@ import { useCallback } from 'react';
import { useRecoilState } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { ColorScheme, useUpdateUserMutation } from '~/generated/graphql';
import {
ColorScheme,
useUpdateOneWorkspaceMemberMutation,
useUpdateUserMutation,
} from '~/generated/graphql';
export function useColorScheme() {
const [currentUser, setCurrentUser] = useRecoilState(currentUserState);
const [updateUser] = useUpdateUserMutation();
const [updateWorkspaceMember] = useUpdateOneWorkspaceMemberMutation();
const colorScheme = !currentUser?.settings?.colorScheme
? ColorScheme.System
: currentUser.settings.colorScheme;
const colorScheme =
!currentUser?.workspaceMember.settings?.colorScheme &&
!currentUser?.settings?.colorScheme
? ColorScheme.System
: currentUser.workspaceMember.settings?.colorScheme ??
currentUser.settings.colorScheme;
const setColorScheme = useCallback(
async (value: ColorScheme) => {
try {
// connect settings to workspace member if not already connected
await updateWorkspaceMember({
variables: {
where: { id: currentUser?.workspaceMember.id },
data: { settings: { connect: { id: currentUser?.settings.id } } },
},
});
const result = await updateUser({
variables: {
where: {
@ -29,13 +45,14 @@ export function useColorScheme() {
},
},
},
optimisticResponse:
currentUser && currentUser.settings
? {
__typename: 'Mutation',
updateUser: {
__typename: 'User',
...currentUser,
optimisticResponse: currentUser
? {
__typename: 'Mutation',
updateUser: {
__typename: 'User',
...currentUser,
workspaceMember: {
...currentUser.workspaceMember,
settings: {
__typename: 'UserSettings',
id: currentUser.settings.id,
@ -43,15 +60,34 @@ export function useColorScheme() {
locale: currentUser.settings.locale,
},
},
}
: undefined,
settings: {
__typename: 'UserSettings',
id: currentUser.settings.id,
colorScheme: value,
locale: currentUser.settings.locale,
},
},
}
: undefined,
update: (_cache, { data }) => {
if (data?.updateUser && currentUser) {
if (
data?.updateUser.workspaceMember?.settings?.colorScheme &&
currentUser
) {
setCurrentUser({
...currentUser,
workspaceMember: {
...currentUser.workspaceMember,
settings: {
...currentUser.workspaceMember.settings,
colorScheme:
data.updateUser.workspaceMember.settings.colorScheme,
},
},
settings: {
...currentUser.settings,
colorScheme: data?.updateUser.settings.colorScheme,
colorScheme:
data.updateUser.workspaceMember.settings.colorScheme,
},
});
}
@ -63,7 +99,7 @@ export function useColorScheme() {
}
} catch (err) {}
},
[currentUser, updateUser, setCurrentUser],
[updateWorkspaceMember, currentUser, updateUser, setCurrentUser],
);
return {

View File

@ -14,8 +14,14 @@ export function UserProvider({ children }: React.PropsWithChildren) {
if (!loading) {
setIsLoading(false);
}
if (data?.currentUser) {
setCurrentUser(data?.currentUser);
if (data?.currentUser?.workspaceMember?.settings) {
setCurrentUser({
...data.currentUser,
workspaceMember: {
...data.currentUser.workspaceMember,
settings: data.currentUser.workspaceMember.settings,
},
});
}
}, [setCurrentUser, data, isLoading, loading]);

View File

@ -18,6 +18,33 @@ export const UPDATE_USER = gql`
logo
inviteHash
}
assignedActivities {
id
title
}
authoredActivities {
id
title
}
authoredAttachments {
id
name
type
}
settings {
id
colorScheme
locale
}
companies {
id
name
domainName
}
comments {
id
body
}
}
settings {
id

View File

@ -20,6 +20,33 @@ export const GET_CURRENT_USER = gql`
logo
inviteHash
}
assignedActivities {
id
title
}
authoredActivities {
id
title
}
authoredAttachments {
id
name
type
}
settings {
id
colorScheme
locale
}
companies {
id
name
domainName
}
comments {
id
body
}
}
settings {
id

View File

@ -0,0 +1,47 @@
import { gql } from '@apollo/client';
export const UPDATE_WORKSPACE_MEMBER = gql`
mutation UpdateOneWorkspaceMember(
$data: WorkspaceMemberUpdateInput!
$where: WorkspaceMemberWhereUniqueInput!
) {
UpdateOneWorkspaceMember(data: $data, where: $where) {
id
allowImpersonation
workspace {
id
domainName
displayName
logo
inviteHash
}
assignedActivities {
id
title
}
authoredActivities {
id
title
}
authoredAttachments {
id
name
type
}
settings {
id
colorScheme
locale
}
companies {
id
name
domainName
}
comments {
id
body
}
}
}
`;

View File

@ -1,8 +1,8 @@
import { gql } from '@apollo/client';
export const GET_WORKSPACE_MEMBERS = gql`
query GetWorkspaceMembers {
workspaceMembers: findManyWorkspaceMember {
query GetWorkspaceMembers($where: WorkspaceMemberWhereInput) {
workspaceMembers: findManyWorkspaceMember(where: $where) {
id
user {
id