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:
@ -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: {
|
||||
|
||||
@ -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: {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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',
|
||||
|
||||
@ -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>
|
||||
</>
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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]);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user