mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
address feedback suggestions
This commit is contained in:
@@ -367,8 +367,8 @@ export const ORGANIZATIONS = {
|
|||||||
offset: "The offset to start from. If you enter 10, it will start from the 10th identity membership.",
|
offset: "The offset to start from. If you enter 10, it will start from the 10th identity membership.",
|
||||||
limit: "The number of identity memberships to return.",
|
limit: "The number of identity memberships to return.",
|
||||||
orderBy: "The column to order identity memberships by.",
|
orderBy: "The column to order identity memberships by.",
|
||||||
direction: "The direction identity memberships will be sorted in.",
|
orderDirection: "The direction identity memberships will be sorted in.",
|
||||||
textFilter: "The text string that identity membership names will be filtered by."
|
search: "The text string that identity membership names will be filtered by."
|
||||||
},
|
},
|
||||||
GET_PROJECTS: {
|
GET_PROJECTS: {
|
||||||
organizationId: "The ID of the organization to get projects from."
|
organizationId: "The ID of the organization to get projects from."
|
||||||
@@ -479,8 +479,8 @@ export const PROJECT_IDENTITIES = {
|
|||||||
offset: "The offset to start from. If you enter 10, it will start from the 10th identity membership.",
|
offset: "The offset to start from. If you enter 10, it will start from the 10th identity membership.",
|
||||||
limit: "The number of identity memberships to return.",
|
limit: "The number of identity memberships to return.",
|
||||||
orderBy: "The column to order identity memberships by.",
|
orderBy: "The column to order identity memberships by.",
|
||||||
direction: "The direction identity memberships will be sorted in.",
|
orderDirection: "The direction identity memberships will be sorted in.",
|
||||||
textFilter: "The text string that identity membership names will be filtered by."
|
search: "The text string that identity membership names will be filtered by."
|
||||||
},
|
},
|
||||||
GET_IDENTITY_MEMBERSHIP_BY_ID: {
|
GET_IDENTITY_MEMBERSHIP_BY_ID: {
|
||||||
identityId: "The ID of the identity to get the membership for.",
|
identityId: "The ID of the identity to get the membership for.",
|
||||||
|
|||||||
@@ -40,17 +40,12 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
.default(OrgIdentityOrderBy.Name)
|
.default(OrgIdentityOrderBy.Name)
|
||||||
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.orderBy)
|
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.orderBy)
|
||||||
.optional(),
|
.optional(),
|
||||||
direction: z
|
orderDirection: z
|
||||||
.nativeEnum(OrderByDirection)
|
.nativeEnum(OrderByDirection)
|
||||||
.default(OrderByDirection.ASC)
|
.default(OrderByDirection.ASC)
|
||||||
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.direction)
|
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.orderDirection)
|
||||||
.optional(),
|
.optional(),
|
||||||
textFilter: z
|
search: z.string().trim().describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.search).optional()
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.default("")
|
|
||||||
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.textFilter)
|
|
||||||
.optional()
|
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -80,8 +75,8 @@ export const registerIdentityOrgRouter = async (server: FastifyZodProvider) => {
|
|||||||
limit: req.query.limit,
|
limit: req.query.limit,
|
||||||
offset: req.query.offset,
|
offset: req.query.offset,
|
||||||
orderBy: req.query.orderBy,
|
orderBy: req.query.orderBy,
|
||||||
direction: req.query.direction,
|
orderDirection: req.query.orderDirection,
|
||||||
textFilter: req.query.textFilter
|
search: req.query.search
|
||||||
});
|
});
|
||||||
|
|
||||||
return { identityMemberships, totalCount };
|
return { identityMemberships, totalCount };
|
||||||
|
|||||||
@@ -235,17 +235,12 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
|||||||
.default(ProjectIdentityOrderBy.Name)
|
.default(ProjectIdentityOrderBy.Name)
|
||||||
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.orderBy)
|
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.orderBy)
|
||||||
.optional(),
|
.optional(),
|
||||||
direction: z
|
orderDirection: z
|
||||||
.nativeEnum(OrderByDirection)
|
.nativeEnum(OrderByDirection)
|
||||||
.default(OrderByDirection.ASC)
|
.default(OrderByDirection.ASC)
|
||||||
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.direction)
|
.describe(ORGANIZATIONS.LIST_IDENTITY_MEMBERSHIPS.orderDirection)
|
||||||
.optional(),
|
.optional(),
|
||||||
textFilter: z
|
search: z.string().trim().describe(PROJECT_IDENTITIES.LIST_IDENTITY_MEMBERSHIPS.search).optional()
|
||||||
.string()
|
|
||||||
.trim()
|
|
||||||
.default("")
|
|
||||||
.describe(PROJECT_IDENTITIES.LIST_IDENTITY_MEMBERSHIPS.textFilter)
|
|
||||||
.optional()
|
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@@ -287,8 +282,8 @@ export const registerIdentityProjectRouter = async (server: FastifyZodProvider)
|
|||||||
limit: req.query.limit,
|
limit: req.query.limit,
|
||||||
offset: req.query.offset,
|
offset: req.query.offset,
|
||||||
orderBy: req.query.orderBy,
|
orderBy: req.query.orderBy,
|
||||||
direction: req.query.direction,
|
orderDirection: req.query.orderDirection,
|
||||||
textFilter: req.query.textFilter
|
search: req.query.search
|
||||||
});
|
});
|
||||||
return { identityMemberships, totalCount };
|
return { identityMemberships, totalCount };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
projectId: string,
|
projectId: string,
|
||||||
filter: { identityId?: string } & Pick<
|
filter: { identityId?: string } & Pick<
|
||||||
TListProjectIdentityDTO,
|
TListProjectIdentityDTO,
|
||||||
"limit" | "offset" | "textFilter" | "orderBy" | "direction"
|
"limit" | "offset" | "search" | "orderBy" | "orderDirection"
|
||||||
> = {},
|
> = {},
|
||||||
tx?: Knex
|
tx?: Knex
|
||||||
) => {
|
) => {
|
||||||
@@ -126,8 +126,8 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
void qb.where("identityId", filter.identityId);
|
void qb.where("identityId", filter.identityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.textFilter) {
|
if (filter.search) {
|
||||||
void qb.whereILike(`${TableName.Identity}.name`, `%${filter.textFilter}%`);
|
void qb.whereILike(`${TableName.Identity}.name`, `%${filter.search}%`);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.join(
|
.join(
|
||||||
@@ -173,7 +173,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
if (filter.orderBy) {
|
if (filter.orderBy) {
|
||||||
switch (filter.orderBy) {
|
switch (filter.orderBy) {
|
||||||
case "name":
|
case "name":
|
||||||
void query.orderBy(`${TableName.Identity}.${filter.orderBy}`, filter.direction);
|
void query.orderBy(`${TableName.Identity}.${filter.orderBy}`, filter.orderDirection);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// do nothing
|
// do nothing
|
||||||
@@ -238,7 +238,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
|
|
||||||
const getCountByProjectId = async (
|
const getCountByProjectId = async (
|
||||||
projectId: string,
|
projectId: string,
|
||||||
filter: { identityId?: string } & Pick<TListProjectIdentityDTO, "textFilter"> = {},
|
filter: { identityId?: string } & Pick<TListProjectIdentityDTO, "search"> = {},
|
||||||
tx?: Knex
|
tx?: Knex
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
@@ -251,12 +251,13 @@ export const identityProjectDALFactory = (db: TDbClient) => {
|
|||||||
void qb.where("identityId", filter.identityId);
|
void qb.where("identityId", filter.identityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.textFilter) {
|
if (filter.search) {
|
||||||
void qb.whereILike(`${TableName.Identity}.name`, `%${filter.textFilter}%`);
|
void qb.whereILike(`${TableName.Identity}.name`, `%${filter.search}%`);
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.count();
|
||||||
|
|
||||||
return identities.length;
|
return Number(identities[0].count);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new DatabaseError({ error, name: "GetCountByProjectId" });
|
throw new DatabaseError({ error, name: "GetCountByProjectId" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -272,8 +272,8 @@ export const identityProjectServiceFactory = ({
|
|||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
orderBy,
|
orderBy,
|
||||||
direction,
|
orderDirection,
|
||||||
textFilter
|
search
|
||||||
}: TListProjectIdentityDTO) => {
|
}: TListProjectIdentityDTO) => {
|
||||||
const { permission } = await permissionService.getProjectPermission(
|
const { permission } = await permissionService.getProjectPermission(
|
||||||
actor,
|
actor,
|
||||||
@@ -288,11 +288,11 @@ export const identityProjectServiceFactory = ({
|
|||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
orderBy,
|
orderBy,
|
||||||
direction,
|
orderDirection,
|
||||||
textFilter
|
search
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalCount = await identityProjectDAL.getCountByProjectId(projectId, { textFilter });
|
const totalCount = await identityProjectDAL.getCountByProjectId(projectId, { search });
|
||||||
|
|
||||||
return { identityMemberships, totalCount };
|
return { identityMemberships, totalCount };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ export type TListProjectIdentityDTO = {
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
offset?: number;
|
offset?: number;
|
||||||
orderBy?: ProjectIdentityOrderBy;
|
orderBy?: ProjectIdentityOrderBy;
|
||||||
direction?: OrderByDirection;
|
orderDirection?: OrderByDirection;
|
||||||
textFilter?: string;
|
search?: string;
|
||||||
} & TProjectPermission;
|
} & TProjectPermission;
|
||||||
|
|
||||||
export type TGetProjectIdentityByIdentityIdDTO = {
|
export type TGetProjectIdentityByIdentityIdDTO = {
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
|||||||
limit,
|
limit,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
orderBy,
|
orderBy,
|
||||||
direction = OrderByDirection.ASC,
|
orderDirection = OrderByDirection.ASC,
|
||||||
textFilter,
|
search,
|
||||||
...filter
|
...filter
|
||||||
}: Partial<TIdentityOrgMemberships> &
|
}: Partial<TIdentityOrgMemberships> &
|
||||||
Pick<TListOrgIdentitiesByOrgIdDTO, "offset" | "limit" | "orderBy" | "direction" | "textFilter">,
|
Pick<TListOrgIdentitiesByOrgIdDTO, "offset" | "limit" | "orderBy" | "orderDirection" | "search">,
|
||||||
tx?: Knex
|
tx?: Knex
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
@@ -65,18 +65,18 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
|||||||
if (orderBy) {
|
if (orderBy) {
|
||||||
switch (orderBy) {
|
switch (orderBy) {
|
||||||
case "name":
|
case "name":
|
||||||
void query.orderBy(`${TableName.Identity}.${orderBy}`, direction);
|
void query.orderBy(`${TableName.Identity}.${orderBy}`, orderDirection);
|
||||||
break;
|
break;
|
||||||
case "role":
|
case "role":
|
||||||
void query.orderBy(`${TableName.IdentityOrgMembership}.${orderBy}`, direction);
|
void query.orderBy(`${TableName.IdentityOrgMembership}.${orderBy}`, orderDirection);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textFilter?.length) {
|
if (search?.length) {
|
||||||
void query.whereILike(`${TableName.Identity}.name`, `%${textFilter}%`);
|
void query.whereILike(`${TableName.Identity}.name`, `%${search}%`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const docs = await query;
|
const docs = await query;
|
||||||
@@ -117,21 +117,22 @@ export const identityOrgDALFactory = (db: TDbClient) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const countAllOrgIdentities = async (
|
const countAllOrgIdentities = async (
|
||||||
{ textFilter, ...filter }: Partial<TIdentityOrgMemberships> & Pick<TListOrgIdentitiesByOrgIdDTO, "textFilter">,
|
{ search, ...filter }: Partial<TIdentityOrgMemberships> & Pick<TListOrgIdentitiesByOrgIdDTO, "search">,
|
||||||
tx?: Knex
|
tx?: Knex
|
||||||
) => {
|
) => {
|
||||||
try {
|
try {
|
||||||
const query = (tx || db.replicaNode())(TableName.IdentityOrgMembership)
|
const query = (tx || db.replicaNode())(TableName.IdentityOrgMembership)
|
||||||
.where(filter)
|
.where(filter)
|
||||||
.join(TableName.Identity, `${TableName.IdentityOrgMembership}.identityId`, `${TableName.Identity}.id`);
|
.join(TableName.Identity, `${TableName.IdentityOrgMembership}.identityId`, `${TableName.Identity}.id`)
|
||||||
|
.count();
|
||||||
|
|
||||||
if (textFilter?.length) {
|
if (search?.length) {
|
||||||
void query.whereILike(`${TableName.Identity}.name`, `%${textFilter}%`);
|
void query.whereILike(`${TableName.Identity}.name`, `%${search}%`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const identities = await query;
|
const identities = await query;
|
||||||
|
|
||||||
return identities.length;
|
return Number(identities[0].count);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new DatabaseError({ error, name: "countAllOrgIdentities" });
|
throw new DatabaseError({ error, name: "countAllOrgIdentities" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,8 +204,8 @@ export const identityServiceFactory = ({
|
|||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
orderBy,
|
orderBy,
|
||||||
direction,
|
orderDirection,
|
||||||
textFilter
|
search
|
||||||
}: TListOrgIdentitiesByOrgIdDTO) => {
|
}: TListOrgIdentitiesByOrgIdDTO) => {
|
||||||
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId, actorAuthMethod, actorOrgId);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
|
||||||
@@ -215,13 +215,13 @@ export const identityServiceFactory = ({
|
|||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
orderBy,
|
orderBy,
|
||||||
direction,
|
orderDirection,
|
||||||
textFilter
|
search
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalCount = await identityOrgMembershipDAL.countAllOrgIdentities({
|
const totalCount = await identityOrgMembershipDAL.countAllOrgIdentities({
|
||||||
[`${TableName.IdentityOrgMembership}.orgId` as "orgId"]: orgId,
|
[`${TableName.IdentityOrgMembership}.orgId` as "orgId"]: orgId,
|
||||||
textFilter
|
search
|
||||||
});
|
});
|
||||||
|
|
||||||
return { identityMemberships, totalCount };
|
return { identityMemberships, totalCount };
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ export type TListOrgIdentitiesByOrgIdDTO = {
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
offset?: number;
|
offset?: number;
|
||||||
orderBy?: OrgIdentityOrderBy;
|
orderBy?: OrgIdentityOrderBy;
|
||||||
direction?: OrderByDirection;
|
orderDirection?: OrderByDirection;
|
||||||
textFilter?: string;
|
search?: string;
|
||||||
} & TOrgPermission;
|
} & TOrgPermission;
|
||||||
|
|
||||||
export enum OrgIdentityOrderBy {
|
export enum OrgIdentityOrderBy {
|
||||||
|
|||||||
4
frontend/src/hooks/api/generic/types.ts
Normal file
4
frontend/src/hooks/api/generic/types.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export enum OrderByDirection {
|
||||||
|
ASC = "asc",
|
||||||
|
DESC = "desc"
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useMutation, useQuery, useQueryClient, UseQueryOptions } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient, UseQueryOptions } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
|
|
||||||
import { TGroupOrgMembership } from "../groups/types";
|
import { TGroupOrgMembership } from "../groups/types";
|
||||||
import {
|
import {
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
Invoice,
|
Invoice,
|
||||||
License,
|
License,
|
||||||
Organization,
|
Organization,
|
||||||
|
OrgIdentityOrderBy,
|
||||||
OrgPlanTable,
|
OrgPlanTable,
|
||||||
PlanBillingInfo,
|
PlanBillingInfo,
|
||||||
PmtMethod,
|
PmtMethod,
|
||||||
@@ -372,9 +374,9 @@ export const useGetIdentityMembershipOrgs = (
|
|||||||
organizationId,
|
organizationId,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
limit = 100,
|
limit = 100,
|
||||||
orderBy = "name",
|
orderBy = OrgIdentityOrderBy.Name,
|
||||||
direction = "asc",
|
orderDirection = OrderByDirection.ASC,
|
||||||
textFilter = ""
|
search = ""
|
||||||
}: TListOrgIdentitiesDTO,
|
}: TListOrgIdentitiesDTO,
|
||||||
options?: Omit<
|
options?: Omit<
|
||||||
UseQueryOptions<
|
UseQueryOptions<
|
||||||
@@ -390,8 +392,8 @@ export const useGetIdentityMembershipOrgs = (
|
|||||||
offset: String(offset),
|
offset: String(offset),
|
||||||
limit: String(limit),
|
limit: String(limit),
|
||||||
orderBy: String(orderBy),
|
orderBy: String(orderBy),
|
||||||
direction: String(direction),
|
orderDirection: String(orderDirection),
|
||||||
textFilter: String(textFilter)
|
search: String(search)
|
||||||
});
|
});
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: organizationKeys.getOrgIdentityMembershipsWithParams({
|
queryKey: organizationKeys.getOrgIdentityMembershipsWithParams({
|
||||||
@@ -399,8 +401,8 @@ export const useGetIdentityMembershipOrgs = (
|
|||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
orderBy,
|
orderBy,
|
||||||
direction,
|
orderDirection,
|
||||||
textFilter
|
search
|
||||||
}),
|
}),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await apiRequest.get<TOrgIdentitiesList>(
|
const { data } = await apiRequest.get<TOrgIdentitiesList>(
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
import { IdentityMembershipOrg } from "@app/hooks/api/identities/types";
|
import { IdentityMembershipOrg } from "@app/hooks/api/identities/types";
|
||||||
|
|
||||||
export type Organization = {
|
export type Organization = {
|
||||||
@@ -109,12 +110,17 @@ export type TListOrgIdentitiesDTO = {
|
|||||||
organizationId: string;
|
organizationId: string;
|
||||||
offset?: number;
|
offset?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
orderBy?: string;
|
orderBy?: OrgIdentityOrderBy;
|
||||||
direction?: string;
|
orderDirection?: OrderByDirection;
|
||||||
textFilter?: string;
|
search?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TOrgIdentitiesList = {
|
export type TOrgIdentitiesList = {
|
||||||
identityMemberships: IdentityMembershipOrg[];
|
identityMemberships: IdentityMembershipOrg[];
|
||||||
totalCount: number;
|
totalCount: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum OrgIdentityOrderBy {
|
||||||
|
Name = "name",
|
||||||
|
Role = "role"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useMutation, useQuery, useQueryClient, UseQueryOptions } from "@tanstack/react-query";
|
import { useMutation, useQuery, useQueryClient, UseQueryOptions } from "@tanstack/react-query";
|
||||||
|
|
||||||
import { apiRequest } from "@app/config/request";
|
import { apiRequest } from "@app/config/request";
|
||||||
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
|
|
||||||
import { CaStatus } from "../ca/enums";
|
import { CaStatus } from "../ca/enums";
|
||||||
import { TCertificateAuthority } from "../ca/types";
|
import { TCertificateAuthority } from "../ca/types";
|
||||||
@@ -23,6 +24,7 @@ import {
|
|||||||
DeleteEnvironmentDTO,
|
DeleteEnvironmentDTO,
|
||||||
DeleteWorkspaceDTO,
|
DeleteWorkspaceDTO,
|
||||||
NameWorkspaceSecretsDTO,
|
NameWorkspaceSecretsDTO,
|
||||||
|
ProjectIdentityOrderBy,
|
||||||
RenameWorkspaceDTO,
|
RenameWorkspaceDTO,
|
||||||
TGetUpgradeProjectStatusDTO,
|
TGetUpgradeProjectStatusDTO,
|
||||||
TListProjectIdentitiesDTO,
|
TListProjectIdentitiesDTO,
|
||||||
@@ -538,9 +540,9 @@ export const useGetWorkspaceIdentityMemberships = (
|
|||||||
workspaceId,
|
workspaceId,
|
||||||
offset = 0,
|
offset = 0,
|
||||||
limit = 100,
|
limit = 100,
|
||||||
orderBy = "name",
|
orderBy = ProjectIdentityOrderBy.Name,
|
||||||
direction = "asc",
|
orderDirection = OrderByDirection.ASC,
|
||||||
textFilter = ""
|
search = ""
|
||||||
}: TListProjectIdentitiesDTO,
|
}: TListProjectIdentitiesDTO,
|
||||||
options?: Omit<
|
options?: Omit<
|
||||||
UseQueryOptions<
|
UseQueryOptions<
|
||||||
@@ -558,16 +560,16 @@ export const useGetWorkspaceIdentityMemberships = (
|
|||||||
offset,
|
offset,
|
||||||
limit,
|
limit,
|
||||||
orderBy,
|
orderBy,
|
||||||
direction,
|
orderDirection,
|
||||||
textFilter
|
search
|
||||||
}),
|
}),
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const params = new URLSearchParams({
|
const params = new URLSearchParams({
|
||||||
offset: String(offset),
|
offset: String(offset),
|
||||||
limit: String(limit),
|
limit: String(limit),
|
||||||
orderBy: String(orderBy),
|
orderBy: String(orderBy),
|
||||||
direction: String(direction),
|
orderDirection: String(orderDirection),
|
||||||
textFilter: String(textFilter)
|
search: String(search)
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data } = await apiRequest.get<TProjectIdentitiesList>(
|
const { data } = await apiRequest.get<TProjectIdentitiesList>(
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
|
|
||||||
import { TProjectRole } from "../roles/types";
|
import { TProjectRole } from "../roles/types";
|
||||||
|
|
||||||
export enum ProjectVersion {
|
export enum ProjectVersion {
|
||||||
@@ -146,7 +148,11 @@ export type TListProjectIdentitiesDTO = {
|
|||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
offset?: number;
|
offset?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
orderBy?: string;
|
orderBy?: ProjectIdentityOrderBy;
|
||||||
direction?: string;
|
orderDirection?: OrderByDirection;
|
||||||
textFilter?: string;
|
search?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum ProjectIdentityOrderBy {
|
||||||
|
Name = "name"
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ import {
|
|||||||
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||||
import { useDebounce } from "@app/hooks";
|
import { useDebounce } from "@app/hooks";
|
||||||
import { useGetIdentityMembershipOrgs, useGetOrgRoles, useUpdateIdentity } from "@app/hooks/api";
|
import { useGetIdentityMembershipOrgs, useGetOrgRoles, useUpdateIdentity } from "@app/hooks/api";
|
||||||
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
|
import { OrgIdentityOrderBy } from "@app/hooks/api/organization/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -55,10 +57,10 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
const { currentOrg } = useOrganization();
|
const { currentOrg } = useOrganization();
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [perPage, setPerPage] = useState(INIT_PER_PAGE);
|
const [perPage, setPerPage] = useState(INIT_PER_PAGE);
|
||||||
const [direction, setDirection] = useState("asc");
|
const [orderDirection, setOrderDirection] = useState(OrderByDirection.ASC);
|
||||||
const [orderBy, setOrderBy] = useState("name");
|
const [orderBy, setOrderBy] = useState(OrgIdentityOrderBy.Name);
|
||||||
const [textFilter, setTextFilter] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const debouncedTextFilter = useDebounce(textFilter);
|
const debouncedSearch = useDebounce(search);
|
||||||
|
|
||||||
const organizationId = currentOrg?.id || "";
|
const organizationId = currentOrg?.id || "";
|
||||||
|
|
||||||
@@ -70,9 +72,9 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
organizationId,
|
organizationId,
|
||||||
offset,
|
offset,
|
||||||
limit: perPage,
|
limit: perPage,
|
||||||
direction,
|
orderDirection,
|
||||||
orderBy,
|
orderBy,
|
||||||
textFilter: debouncedTextFilter
|
search: debouncedSearch
|
||||||
},
|
},
|
||||||
{ keepPreviousData: true }
|
{ keepPreviousData: true }
|
||||||
);
|
);
|
||||||
@@ -84,14 +86,16 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
|
|
||||||
const { data: roles } = useGetOrgRoles(organizationId);
|
const { data: roles } = useGetOrgRoles(organizationId);
|
||||||
|
|
||||||
const handleSort = (column: string) => {
|
const handleSort = (column: OrgIdentityOrderBy) => {
|
||||||
if (column === orderBy) {
|
if (column === orderBy) {
|
||||||
setDirection((prev) => (prev === "asc" ? "desc" : "asc"));
|
setOrderDirection((prev) =>
|
||||||
|
prev === OrderByDirection.ASC ? OrderByDirection.DESC : OrderByDirection.ASC
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setOrderBy(column);
|
setOrderBy(column);
|
||||||
setDirection("asc");
|
setOrderDirection(OrderByDirection.ASC);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChangeRole = async ({ identityId, role }: { identityId: string; role: string }) => {
|
const handleChangeRole = async ({ identityId, role }: { identityId: string; role: string }) => {
|
||||||
@@ -122,8 +126,8 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
<div>
|
<div>
|
||||||
<Input
|
<Input
|
||||||
containerClassName="mb-4"
|
containerClassName="mb-4"
|
||||||
value={textFilter}
|
value={search}
|
||||||
onChange={(e) => setTextFilter(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||||
placeholder="Search identities by name..."
|
placeholder="Search identities by name..."
|
||||||
/>
|
/>
|
||||||
@@ -136,12 +140,17 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
Name
|
Name
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="plain"
|
variant="plain"
|
||||||
className={`ml-2 ${orderBy === "name" ? "" : "opacity-30"}`}
|
className={`ml-2 ${orderBy === OrgIdentityOrderBy.Name ? "" : "opacity-30"}`}
|
||||||
ariaLabel="sort"
|
ariaLabel="sort"
|
||||||
onClick={() => handleSort("name")}
|
onClick={() => handleSort(OrgIdentityOrderBy.Name)}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={direction === "desc" && orderBy === "name" ? faArrowUp : faArrowDown}
|
icon={
|
||||||
|
orderDirection === OrderByDirection.DESC &&
|
||||||
|
orderBy === OrgIdentityOrderBy.Name
|
||||||
|
? faArrowUp
|
||||||
|
: faArrowDown
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
@@ -151,12 +160,17 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
Role
|
Role
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="plain"
|
variant="plain"
|
||||||
className={`ml-2 ${orderBy === "role" ? "" : "opacity-30"}`}
|
className={`ml-2 ${orderBy === OrgIdentityOrderBy.Role ? "" : "opacity-30"}`}
|
||||||
ariaLabel="sort"
|
ariaLabel="sort"
|
||||||
onClick={() => handleSort("role")}
|
onClick={() => handleSort(OrgIdentityOrderBy.Role)}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={direction === "desc" && orderBy === "role" ? faArrowUp : faArrowDown}
|
icon={
|
||||||
|
orderDirection === OrderByDirection.DESC &&
|
||||||
|
orderBy === OrgIdentityOrderBy.Role
|
||||||
|
? faArrowUp
|
||||||
|
: faArrowDown
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
@@ -275,7 +289,7 @@ export const IdentityTable = ({ handlePopUpOpen }: Props) => {
|
|||||||
{!isLoading && data && data?.identityMemberships.length === 0 && (
|
{!isLoading && data && data?.identityMemberships.length === 0 && (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
title={
|
title={
|
||||||
debouncedTextFilter.trim().length > 0
|
debouncedSearch.trim().length > 0
|
||||||
? "No identities match search filter"
|
? "No identities match search filter"
|
||||||
: "No identities have been created in this organization"
|
: "No identities have been created in this organization"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,8 +46,10 @@ import { ProjectPermissionActions, ProjectPermissionSub, useWorkspace } from "@a
|
|||||||
import { withProjectPermission } from "@app/hoc";
|
import { withProjectPermission } from "@app/hoc";
|
||||||
import { useDebounce } from "@app/hooks";
|
import { useDebounce } from "@app/hooks";
|
||||||
import { useDeleteIdentityFromWorkspace, useGetWorkspaceIdentityMemberships } from "@app/hooks/api";
|
import { useDeleteIdentityFromWorkspace, useGetWorkspaceIdentityMemberships } from "@app/hooks/api";
|
||||||
|
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||||
import { IdentityMembership } from "@app/hooks/api/identities/types";
|
import { IdentityMembership } from "@app/hooks/api/identities/types";
|
||||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||||
|
import { ProjectIdentityOrderBy } from "@app/hooks/api/workspace/types";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
import { IdentityModal } from "./components/IdentityModal";
|
import { IdentityModal } from "./components/IdentityModal";
|
||||||
@@ -67,10 +69,10 @@ export const IdentityTab = withProjectPermission(
|
|||||||
|
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const [perPage, setPerPage] = useState(INIT_PER_PAGE);
|
const [perPage, setPerPage] = useState(INIT_PER_PAGE);
|
||||||
const [direction, setDirection] = useState("asc");
|
const [orderDirection, setOrderDirection] = useState(OrderByDirection.ASC);
|
||||||
const [orderBy, setOrderBy] = useState("name");
|
const [orderBy, setOrderBy] = useState(ProjectIdentityOrderBy.Name);
|
||||||
const [textFilter, setTextFilter] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const debouncedTextFilter = useDebounce(textFilter);
|
const debouncedSearch = useDebounce(search);
|
||||||
|
|
||||||
const workspaceId = currentWorkspace?.id ?? "";
|
const workspaceId = currentWorkspace?.id ?? "";
|
||||||
|
|
||||||
@@ -80,9 +82,9 @@ export const IdentityTab = withProjectPermission(
|
|||||||
workspaceId: currentWorkspace?.id || "",
|
workspaceId: currentWorkspace?.id || "",
|
||||||
offset,
|
offset,
|
||||||
limit: perPage,
|
limit: perPage,
|
||||||
direction,
|
orderDirection,
|
||||||
orderBy,
|
orderBy,
|
||||||
textFilter: debouncedTextFilter
|
search: debouncedSearch
|
||||||
},
|
},
|
||||||
{ keepPreviousData: true }
|
{ keepPreviousData: true }
|
||||||
);
|
);
|
||||||
@@ -125,14 +127,16 @@ export const IdentityTab = withProjectPermission(
|
|||||||
if (data && data.totalCount < offset) setPage(1);
|
if (data && data.totalCount < offset) setPage(1);
|
||||||
}, [data?.totalCount]);
|
}, [data?.totalCount]);
|
||||||
|
|
||||||
const handleSort = (column: string) => {
|
const handleSort = (column: ProjectIdentityOrderBy) => {
|
||||||
if (column === orderBy) {
|
if (column === orderBy) {
|
||||||
setDirection((prev) => (prev === "asc" ? "desc" : "asc"));
|
setOrderDirection((prev) =>
|
||||||
|
prev === OrderByDirection.ASC ? OrderByDirection.DESC : OrderByDirection.ASC
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setOrderBy(column);
|
setOrderBy(column);
|
||||||
setDirection("asc");
|
setOrderDirection(OrderByDirection.ASC);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -176,8 +180,8 @@ export const IdentityTab = withProjectPermission(
|
|||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
containerClassName="mb-4"
|
containerClassName="mb-4"
|
||||||
value={textFilter}
|
value={search}
|
||||||
onChange={(e) => setTextFilter(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
leftIcon={<FontAwesomeIcon icon={faMagnifyingGlass} />}
|
||||||
placeholder="Search identities by name..."
|
placeholder="Search identities by name..."
|
||||||
/>
|
/>
|
||||||
@@ -190,13 +194,18 @@ export const IdentityTab = withProjectPermission(
|
|||||||
Name
|
Name
|
||||||
<IconButton
|
<IconButton
|
||||||
variant="plain"
|
variant="plain"
|
||||||
className={`ml-2 ${orderBy === "name" ? "" : "opacity-30"}`}
|
className={`ml-2 ${
|
||||||
|
orderBy === ProjectIdentityOrderBy.Name ? "" : "opacity-30"
|
||||||
|
}`}
|
||||||
ariaLabel="sort"
|
ariaLabel="sort"
|
||||||
onClick={() => handleSort("name")}
|
onClick={() => handleSort(ProjectIdentityOrderBy.Name)}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon
|
<FontAwesomeIcon
|
||||||
icon={
|
icon={
|
||||||
direction === "desc" && orderBy === "name" ? faArrowUp : faArrowDown
|
orderDirection === OrderByDirection.DESC &&
|
||||||
|
orderBy === ProjectIdentityOrderBy.Name
|
||||||
|
? faArrowUp
|
||||||
|
: faArrowDown
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@@ -372,7 +381,7 @@ export const IdentityTab = withProjectPermission(
|
|||||||
{!isLoading && data && data?.identityMemberships.length === 0 && (
|
{!isLoading && data && data?.identityMemberships.length === 0 && (
|
||||||
<EmptyState
|
<EmptyState
|
||||||
title={
|
title={
|
||||||
debouncedTextFilter.trim().length > 0
|
debouncedSearch.trim().length > 0
|
||||||
? "No identities match search filter"
|
? "No identities match search filter"
|
||||||
: "No identities have been added to this project"
|
: "No identities have been added to this project"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user