feat(project-members): PR suggestions improvements

This commit is contained in:
carlosmonastyrski
2025-04-24 12:14:06 -03:00
parent aa893a40a9
commit bd2e2b7931
4 changed files with 37 additions and 9 deletions

View File

@@ -1,3 +1,4 @@
import slugify from "@sindresorhus/slugify";
import { z } from "zod";
import {
@@ -79,7 +80,16 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
.enum(["true", "false"])
.default("false")
.transform((value) => value === "true"),
roles: z.string().trim().transform(decodeURIComponent).optional()
roles: z
.string()
.trim()
.transform(decodeURIComponent)
.refine((value) => {
if (!value) return true;
const slugs = value.split(",");
return slugs.every((slug) => slugify(slug.trim(), { lowercase: true }) === slug.trim());
})
.optional()
}),
params: z.object({
workspaceId: z.string().trim()
@@ -118,7 +128,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const roles = req.query.roles?.split(",") ?? [];
const roles = (req.query.roles?.split(",") || []).filter(Boolean);
const users = await server.services.projectMembership.getProjectMemberships({
actorId: req.permission.id,
actor: req.permission.type,

View File

@@ -31,6 +31,26 @@ export const projectMembershipDALFactory = (db: TDbClient) => {
if (filter.id) {
void qb.where(`${TableName.ProjectMembership}.id`, filter.id);
}
if (filter.roles && filter.roles.length > 0) {
void qb.whereExists((subQuery) => {
void subQuery
.select("role")
.from(TableName.ProjectUserMembershipRole)
.leftJoin(
TableName.ProjectRoles,
`${TableName.ProjectRoles}.id`,
`${TableName.ProjectUserMembershipRole}.customRoleId`
)
.whereRaw(
`"${TableName.ProjectUserMembershipRole}"."projectMembershipId" = "${TableName.ProjectMembership}"."id"`
)
.where((subQb) => {
void subQb
.whereIn(`${TableName.ProjectUserMembershipRole}.role`, filter.roles as string[])
.orWhereIn(`${TableName.ProjectRoles}.slug`, filter.roles as string[]);
});
});
}
})
.join<TUserEncryptionKeys>(
TableName.UserEncryptionKey,
@@ -126,11 +146,6 @@ export const projectMembershipDALFactory = (db: TDbClient) => {
}
]
});
if (filter.roles && filter.roles.length > 0) {
return members.filter((member) =>
member.roles.some((role) => filter.roles?.includes(role.role) || filter.roles?.includes(role.customRoleSlug))
);
}
return members;
} catch (error) {
throw new DatabaseError({ error, name: "Find all project members" });

View File

@@ -445,7 +445,10 @@ export const useGetWorkspaceUsers = (
{
params: {
includeGroupMembers,
roles: roles && roles.length > 0 ? encodeURIComponent(roles.join(",")) : undefined
roles:
roles && roles.length > 0
? roles.map((role) => encodeURIComponent(role)).join(",")
: undefined
}
}
);

View File

@@ -173,7 +173,7 @@ export const MembersTable = ({ handlePopUpOpen }: Props) => {
setOrderDirection(OrderByDirection.ASC);
};
const isTableFiltered = Boolean(Object.values(filter.roles).length);
const isTableFiltered = Boolean(filter.roles.length);
const handleRoleToggle = useCallback(
(roleSlug: string) =>