Skip to content

Commit

Permalink
refactor: add recursive query to check nested project children
Browse files Browse the repository at this point in the history
  • Loading branch information
IgorGoryany committed Aug 22, 2024
1 parent 93c4004 commit 5f023f7
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/components/ProjectSettingsPage/ProjectSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export const ProjectSettingsPage = ({ user, ssrTime, params: { id } }: ExternalP
const project = trpc.project.getById.useQuery({ id });

const { updateProject, deleteProject, transferOwnership } = useProjectResource(id);
const { data: childrenIds = [] } = trpc.v2.project.childrenIds.useQuery({ in: [{ id }] });
const { data: childrenIds = [] } = trpc.v2.project.deepChildrenIds.useQuery({ in: [{ id }] });

const {
handleSubmit,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/projects/[id]/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const getServerSideProps = declareSsrProps(
async ({ ssrHelpers, params: { id } }) => {
try {
const project = await ssrHelpers.project.getById.fetch({ id });
await ssrHelpers.v2.project.childrenIds.fetch({ in: [{ id }] });
await ssrHelpers.v2.project.deepChildrenIds.fetch({ in: [{ id }] });

if (!project) {
throw new TRPCError({ code: 'NOT_FOUND' });
Expand Down
24 changes: 24 additions & 0 deletions trpc/queries/projectV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,30 @@ export const getChildrenProjectsId = (params: { in: Array<{ id: string }> }) =>
);
};

export const getDeepChildrenProjectsId = (params: { in: Array<{ id: string }> }) => {
return db
.withRecursive('childrenTree', (qb) =>
qb
.selectFrom('_parentChildren')
.select('_parentChildren.B as id')
.$if(params.in.length > 0, (qb) =>
qb.where(
'_parentChildren.A',
'in',
params.in.map(({ id }) => id),
),
)
.union((qb) =>
qb
.selectFrom('_parentChildren')
.select('_parentChildren.B as id')
.innerJoin('childrenTree', 'childrenTree.id', 'A'),
),
)
.selectFrom('childrenTree')
.selectAll();
};

interface GetUserProjectsQueryParams {
activityId: string;
role: Role;
Expand Down
18 changes: 8 additions & 10 deletions trpc/router/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { projectAccessMiddleware, projectEditAccessMiddleware } from '../access/
import { getProjectAccessFilter } from '../queries/access';
import { prepareRecipients } from '../../src/utils/prepareRecipients';
import { addCalculatedGoalsFields } from '../../src/utils/db/calculatedGoalsFields';
import { getDeepChildrenProjectsId } from '../queries/projectV2';

const getUserItemsWhereSchema = ({ type, activityId }: { type: 'goal' | 'project'; activityId: string }) => {
return [
Expand Down Expand Up @@ -503,16 +504,7 @@ export const project = router({
.use(projectEditAccessMiddleware)
.mutation(async ({ input: { id, parent, accessUsers, ...data }, ctx }) => {
const project = await prisma.project.findFirst({
where: {
id,
AND: {
children: {
none: {
id: { in: parent?.map(({ id }) => id) },
},
},
},
},
where: { id },
include: {
teams: true,
parent: true,
Expand All @@ -528,6 +520,12 @@ export const project = router({
const parentsToConnect = parent?.filter((pr) => !project.parent.some((p) => p.id === pr.id));
const parentsToDisconnect = project.parent.filter((p) => !parent?.some((pr) => p.id === pr.id));

const childrenIds = await getDeepChildrenProjectsId({ in: [{ id }] }).execute();

if (parentsToConnect?.some(({ id }) => childrenIds.map(({ id }) => id).includes(id))) {
throw new TRPCError({ code: 'BAD_REQUEST', message: 'Child project cannot be a parent project' });
}

const accessUsersToConnect =
accessUsers?.filter((pr) => !project.accessUsers.some((p) => p.id === pr.id)) ?? [];
const accessUsersToDisconnect = project.accessUsers.filter(
Expand Down
6 changes: 3 additions & 3 deletions trpc/router/projectV2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
getUserProjectsQuery,
getUserProjectsWithGoals,
getWholeGoalCountByProjectIds,
getChildrenProjectsId,
getDeepChildrenProjectsId,
} from '../queries/projectV2';
import { queryWithFiltersSchema } from '../../src/schema/common';
import {
Expand Down Expand Up @@ -142,8 +142,8 @@ export const project = router({
}
}),

childrenIds: protectedProcedure.input(projectsChildrenIdsSchema).query(async ({ input }) => {
return getChildrenProjectsId(input).execute();
deepChildrenIds: protectedProcedure.input(projectsChildrenIdsSchema).query(async ({ input }) => {
return getDeepChildrenProjectsId(input).execute();
}),

userProjectsWithGoals: protectedProcedure
Expand Down

0 comments on commit 5f023f7

Please sign in to comment.