Skip to content

Commit

Permalink
feat(UserProfile): add curator in profile
Browse files Browse the repository at this point in the history
  • Loading branch information
Katrin-kudryash committed Nov 21, 2024
1 parent 3ee7d73 commit e49f023
Show file tree
Hide file tree
Showing 16 changed files with 88 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- DropForeignKey
ALTER TABLE "_userCurators" DROP CONSTRAINT "_userCurators_B_fkey";

-- AddForeignKey
ALTER TABLE "_userCurators" ADD CONSTRAINT "_userCurators_B_fkey" FOREIGN KEY ("B") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
1 change: 0 additions & 1 deletion src/components/UserPage/UserPage.i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@
"Transfer": "",
"Supplemental: ": "",
"Previous names": "",
"Curator": "",
"Curator of users": ""
}
3 changes: 1 addition & 2 deletions src/components/UserPage/UserPage.i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,5 @@
"Transfer": "Перевод",
"Supplemental: ": "Дополнительно: ",
"Previous names": "Предыдущие ФИО",
"Curator": "",
"Curator of users": ""
"Curator of users": "Куратор у пользователей"
}
9 changes: 0 additions & 9 deletions src/components/UserPage/UserPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,6 @@ export const UserPageInner = ({ user }: UserPageInnerProps) => {
))}
</NarrowSection>
))}
{nullable(user.curatorOf?.length, () => (
<NarrowSection title={tr('Curator of users')}>
{user.curatorOf?.map((u) => (
<StyledUserListWrapper key={u.id}>
<UserListItem user={u} />
</StyledUserListWrapper>
))}
</NarrowSection>
))}

{nullable(user.supervisorIn?.length, () => (
<NarrowSection title={tr('Supervisor in teams')}>
Expand Down
3 changes: 2 additions & 1 deletion src/components/UserSummary/UserSummary.i18n/en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"Quick summary": "",
"Supervisor": ""
"Supervisor": "",
"Curators:": ""
}
3 changes: 2 additions & 1 deletion src/components/UserSummary/UserSummary.i18n/ru.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"Quick summary": "Быстрая сводка",
"Supervisor": "Руководитель"
"Supervisor": "Руководитель",
"Curators:": "Кураторы"
}
18 changes: 13 additions & 5 deletions src/components/UserSummary/UserSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { gapS, gray9 } from '@taskany/colors';
import styled from 'styled-components';
import { User } from 'prisma/prisma-client';

import { UserSupervisor } from '../../modules/userTypes';
import { UserCurators, UserSupervisor } from '../../modules/userTypes';
import { NarrowSection } from '../NarrowSection';
import { UserListItem } from '../UserListItem/UserListItem';

import { tr } from './UserSummary.i18n';

interface UserSummaryProps {
user: User & UserSupervisor;
user: User & UserSupervisor & UserCurators;
}

const StyledSupervisorText = styled(Text)`
Expand All @@ -21,13 +21,21 @@ const StyledSupervisorText = styled(Text)`
export const UserSummary = ({ user }: UserSummaryProps) => {
return (
<>
{nullable(user.supervisor, (supervisor) => (
<NarrowSection title={tr('Quick summary')}>
<NarrowSection title={tr('Quick summary')}>
{nullable(user.supervisor, (supervisor) => (
<StyledSupervisorText size="m" color={gray9}>
{tr('Supervisor')}
<UserListItem user={supervisor} />
</StyledSupervisorText>
</NarrowSection>
))}
</NarrowSection>
{nullable(user.curators, (curators) => (
<StyledSupervisorText size="m" color={gray9}>
{tr('Curators:')}
{curators.map((curator) => (
<UserListItem key={curator.id} user={curator} />
))}
</StyledSupervisorText>
))}
</>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/UserUpdateForm/UserUpdateForm.i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"Organization": "",
"Supplemental:": "",
"Save previous name:": "",
"Curator:": "",
"Curators:": "",
"Curator": ""
}
2 changes: 1 addition & 1 deletion src/components/UserUpdateForm/UserUpdateForm.i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"Organization": "Организация",
"Supplemental:": "Дополнительно",
"Save previous name:": "Сохранить предыдущее ФИО",
"Curator:": "",
"Curators:": "Кураторы",
"Curator": ""
}
7 changes: 6 additions & 1 deletion src/components/UserUpdateForm/UserUpdateForm.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@
display: flex;
align-items: center;
gap: var(--gap-s);
}
}

.Curator {
display: flex;
align-items: center;
}
20 changes: 13 additions & 7 deletions src/components/UserUpdateForm/UserUpdateForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
Text,
nullable,
} from '@taskany/bricks';
import { Checkbox, FormControl } from '@taskany/bricks/harmony';
import { Checkbox } from '@taskany/bricks/harmony';
import { zodResolver } from '@hookform/resolvers/zod';
import { User } from 'prisma/prisma-client';
import { gray8 } from '@taskany/colors';

import { FormControl } from '../FormControl/FormControl';
import { UserComboBox } from '../UserComboBox/UserComboBox';
import { EditUser, EditUserFields, editUserFieldsSchema } from '../../modules/userSchemas';
import { useUserMutations } from '../../modules/userHooks';
Expand Down Expand Up @@ -61,26 +62,27 @@ export const UserUpdateForm = ({ onClose, user }: UserDataFormProps) => {
name: user.name || undefined,
savePreviousName: undefined,
organizationUnitId: user.organizationUnitId || undefined,
curatorIds: user.curators?.map(({ id }) => id),
curatorIds: user?.curators?.map(({ id }) => id) || [],
},
mode: 'onChange',
resolver: zodResolver(editUserFieldsSchema),
});

const curatorIds = watch('curatorIds');
const savePreviousName = watch('savePreviousName') ?? false;

const updateUser = async (data: EditUser) => {
await editUser(data);
onClose();
};

const onUsersChange = (users: User[], type: keyof UserFormExternalTeamBlockType) => {
const onCuratorsChange = (users: User[], type: keyof UserFormExternalTeamBlockType) => {
setValue(
type,
users.map((user) => user.id),
);
trigger(type);
};

return (
<>
<ModalHeader>
Expand Down Expand Up @@ -118,12 +120,16 @@ export const UserUpdateForm = ({ onClose, user }: UserDataFormProps) => {
}}
/>
</div>

<div className={s.Field}>
<FormControl label={tr('Curator')} required>
<Text className={s.Text} weight="bold" color={gray8}>
{tr('Curators:')}
</Text>
<FormControl>
<UserSelect
mode="multiple"
// selectedUsers={watch('curatorIds') ? watch('curatorIds') : undefined}
onChange={(users) => onUsersChange(users, 'curatorIds')}
selectedUsers={curatorIds ?? undefined}
onChange={(curators) => onCuratorsChange(curators, 'curatorIds')}
error={errors.curatorIds}
/>
</FormControl>
Expand Down
2 changes: 1 addition & 1 deletion src/modules/externalUserTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export interface ExternalUserUpdate {
email: string;
name?: string;
supervisorId?: string | null;
curatorIds?: string[] | null;
curators?: string[] | null;
active?: boolean;
login?: string;
}
34 changes: 25 additions & 9 deletions src/modules/userMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,10 @@ export const userMethods = {
});
if (!user) throw new TRPCError({ code: 'NOT_FOUND', message: `No user with id ${id}` });

const { curators } = user;
const showAchievements = user.settings ? user.settings.showAchievements : true;

const userWithGroupMeta = {
...user,
curatorIds: curators.map(({ id }) => id),
achievements: showAchievements ? user.achievements : undefined,
memberships: await Promise.all(
user.memberships.map(async (m) => ({
Expand Down Expand Up @@ -405,20 +403,40 @@ export const userMethods = {
return prisma.user.findMany({ where: { memberships: { some: { groupId } }, active: { not: true } } });
},

edit: async ({ id, savePreviousName, supplementalPosition, ...data }: EditUserFields) => {
if (data.organizationUnitId) {
edit: async ({
id,
savePreviousName,
supplementalPosition,
organizationUnitId,
curatorIds,
...data
}: EditUserFields) => {
const updateUser: Prisma.UserUpdateInput = data;

if (organizationUnitId) {
const newOrganization = await prisma.organizationUnit.findUnique({
where: {
id: data.organizationUnitId,
id: organizationUnitId,
},
});

if (!newOrganization) {
throw new TRPCError({
code: 'BAD_REQUEST',
message: `No organization with id ${data.organizationUnitId}`,
message: `No organization with id ${organizationUnitId}`,
});
}

updateUser.organizationUnit = { connect: { id: organizationUnitId } };
}

if (curatorIds) {
updateUser.curators = {
connect: curatorIds.map((id) => ({ id })),
};
if (curatorIds.includes(id)) {
throw new TRPCError({ code: 'BAD_REQUEST', message: 'You can`t add the current user to the curators' });
}
}

if (supplementalPosition) {
Expand All @@ -441,7 +459,6 @@ export const userMethods = {
await externalUserMethods.update(id, {
name: data.name,
supervisorId: data.supervisorId,
curatorIds: data.curatorIds,
});

if (savePreviousName) {
Expand All @@ -450,8 +467,7 @@ export const userMethods = {
await prisma.userNames.create({ data: { userId: id, name: userBeforeUpdate.name } });
}
}

return prisma.user.update({ where: { id }, data });
return prisma.user.update({ where: { id }, data: updateUser, include: { curators: true } });
},

editActiveState: async (data: EditUserActiveState): Promise<User> => {
Expand Down
2 changes: 1 addition & 1 deletion src/modules/userSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const editUserSchema = z.object({
name: z.string().optional(),
savePreviousName: z.boolean().optional(),
supervisorId: z.string().nullish(),
curatorIds: z.array(z.string()).nullish(),
curatorIds: z.array(z.string()).optional(),
supplementalPosition: z
.object({
organizationUnitId: z.string(),
Expand Down
8 changes: 5 additions & 3 deletions src/modules/userTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ export interface UserMemberships {
export interface UserSupervisor {
supervisor: Nullish<User>;
}
export interface UserCurators {
curators: Nullish<User[]>;
}

export interface UserSupervisorOf {
supervisorOf: Nullish<User[]>;
}

export interface UserCurators {
curators: Nullish<User[]>;
}

export interface UserCuratorOf {
curatorOf: Nullish<User[]>;
}
Expand Down
14 changes: 12 additions & 2 deletions src/trpc/router/userRouter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from 'zod';
import { TRPCError } from '@trpc/server';

import { accessCheck, checkRoleForAccess } from '../../utils/access';
import { protectedProcedure, router } from '../trpcBackend';
Expand Down Expand Up @@ -141,8 +142,16 @@ export const userRouter = router({

edit: protectedProcedure.input(editUserFieldsSchema).mutation(async ({ input, ctx }) => {
accessCheck(checkRoleForAccess(ctx.session.user.role, 'editUser'));
const userBefore = await userMethods.getByIdOrThrow(input.id);

const userBefore = await prisma.user.findUnique({ where: { id: input.id }, include: { curators: true } });
if (!userBefore) throw new TRPCError({ code: 'NOT_FOUND', message: `No user with id ${input.id}` });

const result = await userMethods.edit(input);
const resultWithCurator = await prisma.user.update({
where: { id: input.id },
data: input,
include: { curators: true },
});

const { before, after } = dropUnchangedValuesFromEvent(
{
Expand All @@ -151,13 +160,14 @@ export const userRouter = router({
organizationalUnitId: userBefore.organizationUnitId ?? undefined,
email: userBefore.email,
savePreviousName: input.savePreviousName,
// curators: userBefore.curators
curatorIds: userBefore.curators.map(({ id }) => id),
},
{
name: result.name,
supervisorId: result.supervisorId,
organizationalUnitId: result.organizationUnitId ?? undefined,
email: result.email,
curatorIds: resultWithCurator.curators.map(({ id }) => id),
},
);
await historyEventMethods.create({ user: ctx.session.user.id }, 'editUser', {
Expand Down

0 comments on commit e49f023

Please sign in to comment.