mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
181 lines
4.6 KiB
TypeScript
181 lines
4.6 KiB
TypeScript
import { checkAdminOrOwner } from "@calcom/features/auth/lib/checkAdminOrOwner";
|
|
import { getTranslation } from "@calcom/i18n/server";
|
|
import prisma from "@calcom/prisma";
|
|
import type { TrpcSessionUser } from "@calcom/trpc/server/types";
|
|
|
|
import { TRPCError } from "@trpc/server";
|
|
|
|
import { type TOutOfOfficeEntriesListSchema } from "./outOfOfficeEntriesList.schema";
|
|
|
|
type GetOptions = {
|
|
ctx: {
|
|
user: NonNullable<TrpcSessionUser>;
|
|
};
|
|
input: TOutOfOfficeEntriesListSchema;
|
|
};
|
|
|
|
export const outOfOfficeEntriesList = async ({ ctx, input }: GetOptions) => {
|
|
const t = await getTranslation(ctx.user.locale, "common");
|
|
const {
|
|
cursor,
|
|
limit,
|
|
fetchTeamMembersEntries,
|
|
searchTerm,
|
|
endDateFilterStartRange,
|
|
endDateFilterEndRange,
|
|
} = input;
|
|
let fetchOOOEntriesForIds = [ctx.user.id];
|
|
let reportingUserIds = [0];
|
|
|
|
if (fetchTeamMembersEntries) {
|
|
// Get teams of context user
|
|
const teams = await prisma.membership.findMany({
|
|
where: {
|
|
userId: ctx.user.id,
|
|
accepted: true,
|
|
},
|
|
select: {
|
|
teamId: true,
|
|
role: true,
|
|
},
|
|
});
|
|
if (teams.length === 0) {
|
|
throw new TRPCError({ code: "NOT_FOUND", message: t("user_has_no_team_yet") });
|
|
}
|
|
const ownerOrAdminTeamIds = teams
|
|
.filter((team) => checkAdminOrOwner(team.role))
|
|
.map((team) => team.teamId);
|
|
|
|
// Fetch team member userIds
|
|
const teamMembers = await prisma.team.findMany({
|
|
where: {
|
|
id: {
|
|
in: teams.map((team) => team.teamId),
|
|
},
|
|
},
|
|
select: {
|
|
id: true,
|
|
members: {
|
|
select: {
|
|
userId: true,
|
|
accepted: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
const userIds = teamMembers
|
|
.flatMap((team) => team.members.filter((member) => member.accepted).map((member) => member.userId))
|
|
.filter((id) => id !== ctx.user.id);
|
|
if (userIds.length === 0) {
|
|
throw new TRPCError({ code: "NOT_FOUND", message: t("no_team_members") });
|
|
}
|
|
fetchOOOEntriesForIds = userIds;
|
|
|
|
const adminTeams = teamMembers.filter(({ id }) => ownerOrAdminTeamIds.includes(id));
|
|
|
|
reportingUserIds = adminTeams.flatMap(({ members }) =>
|
|
members.filter(({ accepted, userId }) => accepted && userId !== ctx.user.id).map(({ userId }) => userId)
|
|
);
|
|
}
|
|
|
|
const whereClause = {
|
|
userId: {
|
|
in: fetchOOOEntriesForIds,
|
|
},
|
|
end: {
|
|
gte: endDateFilterStartRange ?? new Date().toISOString(),
|
|
lte: endDateFilterEndRange,
|
|
},
|
|
...(searchTerm
|
|
? {
|
|
OR: [
|
|
{ notes: { contains: searchTerm } },
|
|
{ reason: { reason: { contains: searchTerm } } },
|
|
{
|
|
toUser: {
|
|
OR: [{ email: { contains: searchTerm } }, { name: { contains: searchTerm } }],
|
|
},
|
|
},
|
|
...(fetchTeamMembersEntries
|
|
? [
|
|
{
|
|
user: {
|
|
OR: [{ email: { contains: searchTerm } }, { name: { contains: searchTerm } }],
|
|
},
|
|
},
|
|
]
|
|
: []),
|
|
],
|
|
}
|
|
: {}),
|
|
};
|
|
|
|
const getTotalEntries = await prisma.outOfOfficeEntry.count({
|
|
where: whereClause,
|
|
});
|
|
|
|
const outOfOfficeEntries = await prisma.outOfOfficeEntry.findMany({
|
|
where: whereClause,
|
|
select: {
|
|
id: true,
|
|
uuid: true,
|
|
start: true,
|
|
end: true,
|
|
toUserId: true,
|
|
toUser: {
|
|
select: {
|
|
username: true,
|
|
name: true,
|
|
email: true,
|
|
},
|
|
},
|
|
reason: {
|
|
select: {
|
|
id: true,
|
|
emoji: true,
|
|
reason: true,
|
|
userId: true,
|
|
},
|
|
},
|
|
notes: true,
|
|
showNotePublicly: true,
|
|
user: fetchTeamMembersEntries
|
|
? {
|
|
select: {
|
|
id: true,
|
|
username: true,
|
|
email: true,
|
|
avatarUrl: true,
|
|
name: true,
|
|
},
|
|
}
|
|
: false,
|
|
},
|
|
orderBy: {
|
|
start: "asc",
|
|
},
|
|
cursor: cursor ? { id: cursor } : undefined,
|
|
take: limit + 1,
|
|
});
|
|
|
|
let nextCursor: number | undefined = undefined;
|
|
if (outOfOfficeEntries && outOfOfficeEntries.length > limit) {
|
|
const nextItem = outOfOfficeEntries.pop();
|
|
nextCursor = nextItem?.id;
|
|
}
|
|
|
|
return {
|
|
rows:
|
|
outOfOfficeEntries.map((ooo) => {
|
|
return {
|
|
...ooo,
|
|
canEditAndDelete: fetchTeamMembersEntries ? reportingUserIds.includes(ooo.user.id) : true,
|
|
};
|
|
}) || [],
|
|
nextCursor,
|
|
meta: {
|
|
totalRowCount: getTotalEntries || 0,
|
|
},
|
|
};
|
|
};
|