♻️ filter sites & resources by labels

This commit is contained in:
Fred KISSIE
2026-05-12 20:45:12 +02:00
parent 12e777b32e
commit 7120ab4b22
2 changed files with 41 additions and 64 deletions

View File

@@ -162,8 +162,8 @@ export type ResourceWithTargets = {
labels?: Array<Pick<Label, "color" | "labelId" | "name">>; labels?: Array<Pick<Label, "color" | "labelId" | "name">>;
}; };
function queryResourcesBase(isLabelFeatureEnabled: boolean) { function queryResourcesBase() {
let query = db return db
.select({ .select({
resourceId: resources.resourceId, resourceId: resources.resourceId,
name: resources.name, name: resources.name,
@@ -209,24 +209,14 @@ function queryResourcesBase(isLabelFeatureEnabled: boolean) {
.leftJoin( .leftJoin(
targetHealthCheck, targetHealthCheck,
eq(targetHealthCheck.targetId, targets.targetId) eq(targetHealthCheck.targetId, targets.targetId)
)
.groupBy(
resources.resourceId,
resourcePassword.passwordId,
resourcePincode.pincodeId,
resourceHeaderAuth.headerAuthId,
resourceHeaderAuthExtendedCompatibility.headerAuthExtendedCompatibilityId
); );
if (isLabelFeatureEnabled) {
query = query
.leftJoin(
resourceLabels,
eq(resourceLabels.resourceId, resources.resourceId)
)
.leftJoin(labels, eq(labels.labelId, resourceLabels.labelId));
}
return query.groupBy(
resources.resourceId,
resourcePassword.passwordId,
resourcePincode.pincodeId,
resourceHeaderAuth.headerAuthId,
resourceHeaderAuthExtendedCompatibility.headerAuthExtendedCompatibilityId
);
} }
export type ListResourcesResponse = PaginatedResponse<{ export type ListResourcesResponse = PaginatedResponse<{
@@ -390,26 +380,25 @@ export async function listResources(
conditions.push(inArray(resources.resourceId, resourcesWithSite)); conditions.push(inArray(resources.resourceId, resourcesWithSite));
} }
if (query) { if (query) {
const q = "%" + query.toLowerCase() + "%";
const queryList = [ const queryList = [
like( like(sql`LOWER(${resources.name})`, q),
sql`LOWER(${resources.name})`, like(sql`LOWER(${resources.niceId})`, q),
"%" + query.toLowerCase() + "%" like(sql`LOWER(${resources.fullDomain})`, q)
),
like(
sql`LOWER(${resources.niceId})`,
"%" + query.toLowerCase() + "%"
),
like(
sql`LOWER(${resources.fullDomain})`,
"%" + query.toLowerCase() + "%"
)
]; ];
if (isLabelFeatureEnabled) { if (isLabelFeatureEnabled) {
queryList.push( queryList.push(
like( inArray(
sql`LOWER(${labels.name})`, resources.resourceId,
"%" + query.toLowerCase() + "%" db
.select({ id: resourceLabels.resourceId })
.from(resourceLabels)
.innerJoin(
labels,
eq(labels.labelId, resourceLabels.labelId)
)
.where(like(sql`LOWER(${labels.name})`, q))
) )
); );
} }
@@ -417,9 +406,7 @@ export async function listResources(
conditions.push(or(...queryList)); conditions.push(or(...queryList));
} }
const baseQuery = queryResourcesBase(isLabelFeatureEnabled).where( const baseQuery = queryResourcesBase().where(and(...conditions));
and(...conditions)
);
// we need to add `as` so that drizzle filters the result as a subquery // we need to add `as` so that drizzle filters the result as a subquery
const countQuery = db.$count(baseQuery.as("filtered_resources")); const countQuery = db.$count(baseQuery.as("filtered_resources"));

View File

@@ -190,8 +190,8 @@ const listSitesSchema = z.object({
}) })
}); });
function querySitesBase(isLabelFeatureEnabled: boolean) { function querySitesBase() {
let query = db return db
.selectDistinct({ .selectDistinct({
siteId: sites.siteId, siteId: sites.siteId,
niceId: sites.niceId, niceId: sites.niceId,
@@ -231,14 +231,6 @@ function querySitesBase(isLabelFeatureEnabled: boolean) {
remoteExitNodes, remoteExitNodes,
eq(remoteExitNodes.exitNodeId, sites.exitNodeId) eq(remoteExitNodes.exitNodeId, sites.exitNodeId)
); );
if (isLabelFeatureEnabled) {
query = query
.leftJoin(siteLabels, eq(siteLabels.siteId, sites.siteId))
.leftJoin(labels, eq(labels.labelId, siteLabels.labelId));
}
return query;
} }
type SiteRowBase = Awaited<ReturnType<typeof querySitesBase>>[0]; type SiteRowBase = Awaited<ReturnType<typeof querySitesBase>>[0];
@@ -346,37 +338,35 @@ export async function listSites(
conditions.push(eq(sites.status, status)); conditions.push(eq(sites.status, status));
} }
if (query) { if (query) {
const q = "%" + query.toLowerCase() + "%";
const queryList = [ const queryList = [
like( like(sql`LOWER(${sites.name})`, q),
sql`LOWER(${sites.name})`, like(sql`LOWER(${sites.niceId})`, q)
"%" + query.toLowerCase() + "%"
),
like(
sql`LOWER(${sites.niceId})`,
"%" + query.toLowerCase() + "%"
)
]; ];
if (isLabelFeatureEnabled) { if (isLabelFeatureEnabled) {
queryList.push( queryList.push(
like( inArray(
sql`LOWER(${labels.name})`, sites.siteId,
"%" + query.toLowerCase() + "%" db
.select({ id: siteLabels.siteId })
.from(siteLabels)
.innerJoin(
labels,
eq(labels.labelId, siteLabels.labelId)
)
.where(like(sql`LOWER(${labels.name})`, q))
) )
); );
} }
conditions.push(or(...queryList)); conditions.push(or(...queryList));
} }
const baseQuery = querySitesBase(isLabelFeatureEnabled).where( const baseQuery = querySitesBase().where(and(...conditions));
and(...conditions)
);
// we need to add `as` so that drizzle filters the result as a subquery // we need to add `as` so that drizzle filters the result as a subquery
const countQuery = db.$count( const countQuery = db.$count(
querySitesBase(isLabelFeatureEnabled) querySitesBase().where(and(...conditions)).as("filtered_sites")
.where(and(...conditions))
.as("filtered_sites")
); );
const siteListQuery = baseQuery const siteListQuery = baseQuery