Skip to content

fix (advertisements): fetch advertisements correctly with their completion status in infinite scroll #3444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
16 changes: 15 additions & 1 deletion schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ enum AdvertisementType {
pop_up
}

"""Filter criteria for organization advertisements"""
input AdvertisementWhereInput {
"""Filter advertisements by completion status"""
isCompleted: Boolean
}

type AgendaFolder {
"""
GraphQL connection to traverse through the agenda folders that have the agenda folder as a parent folder.
Expand Down Expand Up @@ -2887,7 +2893,15 @@ type Organization {
"""
GraphQL connection to traverse through the advertisements belonging to the organization.
"""
advertisements(after: String, before: String, first: Int, last: Int): OrganizationAdvertisementsConnection
advertisements(
after: String
before: String
first: Int
last: Int

"""Filter criteria for advertisements"""
where: AdvertisementWhereInput
): OrganizationAdvertisementsConnection

"""Mime type of the avatar of the organization."""
avatarMimeType: String
Expand Down
14 changes: 14 additions & 0 deletions src/graphql/inputs/QueryOrganizationInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,17 @@ export const MembersWhereInput = builder
// Add other filter fields here
}),
});

export const AdvertisementWhereInput = builder
.inputRef("AdvertisementWhereInput")
.implement({
description: "Filter criteria for organization advertisements",
fields: (t) => ({
isCompleted: t.field({
type: "Boolean",
description: "Filter advertisements by completion status",
required: false,
}),
// Add other filter fields here
}),
});
175 changes: 142 additions & 33 deletions src/graphql/types/Organization/advertisements.ts
Original file line number Diff line number Diff line change
@@ -1,43 +1,60 @@
import { type SQL, and, asc, desc, eq, exists, gt, lt } from "drizzle-orm";
import type { z } from "zod";
import { z } from "zod";
import {
advertisementsTable,
advertisementsTableInsertSchema,
} from "~/src/drizzle/tables/advertisements";
import { Advertisement } from "~/src/graphql/types/Advertisement/Advertisement";
import { TalawaGraphQLError } from "~/src/utilities/TalawaGraphQLError";
import {
defaultGraphQLConnectionArgumentsSchema,
transformDefaultGraphQLConnectionArguments,
type ParsedDefaultGraphQLConnectionArgumentsWithWhere,
createGraphQLConnectionWithWhereSchema,
type defaultGraphQLConnectionArgumentsSchema,
transformGraphQLConnectionArgumentsWithWhere,
transformToDefaultGraphQLConnection,
} from "~/src/utilities/defaultGraphQLConnection";
import envConfig from "~/src/utilities/graphqLimits";
import { AdvertisementWhereInput } from "../../inputs/QueryOrganizationInput";
import { Organization } from "./Organization";
const advertisementsArgumentsSchema = defaultGraphQLConnectionArgumentsSchema
.transform(transformDefaultGraphQLConnectionArguments)
.transform((arg, ctx) => {
let cursor: z.infer<typeof cursorSchema> | undefined = undefined;

try {
if (arg.cursor !== undefined) {
cursor = cursorSchema.parse(
JSON.parse(Buffer.from(arg.cursor, "base64url").toString("utf-8")),
);
}
} catch (error) {
ctx.addIssue({
code: "custom",
message: "Not a valid cursor.",
path: [arg.isInversed ? "before" : "after"],
});
}

return {
cursor,
isInversed: arg.isInversed,
limit: arg.limit,
};
});
const advertisementWhereSchema = z
.object({
isCompleted: z.boolean().optional(),
})
.optional();

const advertisementsArgumentsSchema = createGraphQLConnectionWithWhereSchema(
advertisementWhereSchema,
).transform((arg, ctx) => {
const transformedArg = transformGraphQLConnectionArgumentsWithWhere(
{ ...arg, where: arg.where || {} } as z.infer<
typeof defaultGraphQLConnectionArgumentsSchema
> & { where: unknown },
ctx,
);
let cursor: z.infer<typeof cursorSchema> | undefined = undefined;
try {
if (transformedArg.cursor !== undefined) {
cursor = cursorSchema.parse(
JSON.parse(
Buffer.from(transformedArg.cursor, "base64url").toString("utf-8"),
),
);
}

Check warning on line 43 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L38-L43

Added lines #L38 - L43 were not covered by tests
} catch (error) {
ctx.addIssue({
code: "custom",
message: "Not a valid cursor.",
path: [transformedArg.isInversed ? "before" : "after"],
});
}

Check warning on line 50 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L45-L50

Added lines #L45 - L50 were not covered by tests
return {
cursor,
isInversed: transformedArg.isInversed,
limit: transformedArg.limit,
where: transformedArg.where || {}, // Default to empty object if where is undefined
};
});

const cursorSchema = advertisementsTableInsertSchema.pick({
name: true,
Expand All @@ -55,6 +72,13 @@
multiplier: args.first || args.last || 1,
};
},
args: {
where: t.arg({
type: AdvertisementWhereInput,
description: "Filter criteria for advertisements",
required: false,
}),
},
resolve: async (parent, args, ctx) => {
if (!ctx.currentClient.isAuthenticated) {
throw new TalawaGraphQLError({
Expand All @@ -69,7 +93,6 @@
error,
success,
} = advertisementsArgumentsSchema.safeParse(args);

if (!success) {
throw new TalawaGraphQLError({
extensions: {
Expand Down Expand Up @@ -124,7 +147,15 @@
});
}

const { cursor, isInversed, limit } = parsedArgs;
const {
cursor,
isInversed,
limit,
where: extendedArgs,
} = parsedArgs as ParsedDefaultGraphQLConnectionArgumentsWithWhere<
{ name: string },
{ isCompleted?: boolean }
>;

const orderBy = isInversed
? [desc(advertisementsTable.name)]
Expand All @@ -134,7 +165,7 @@

if (isInversed) {
if (cursor !== undefined) {
where = and(
const baseCondition = and(

Check warning on line 168 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L168

Added line #L168 was not covered by tests
exists(
ctx.drizzleClient
.select()
Expand All @@ -149,12 +180,51 @@
eq(advertisementsTable.organizationId, parent.id),
lt(advertisementsTable.name, cursor.name),
);

if (extendedArgs.isCompleted !== undefined) {
const today = new Date();

Check warning on line 185 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L184-L185

Added lines #L184 - L185 were not covered by tests

if (extendedArgs.isCompleted) {
where = and(
baseCondition,
lt(advertisementsTable.endAt, today),
);
} else {
where = and(
baseCondition,
gt(advertisementsTable.endAt, today),
);
}
} else {
where = baseCondition;
}

Check warning on line 200 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L187-L200

Added lines #L187 - L200 were not covered by tests
} else {
where = eq(advertisementsTable.organizationId, parent.id);
const baseCondition = eq(
advertisementsTable.organizationId,
parent.id,
);

Check warning on line 205 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L202-L205

Added lines #L202 - L205 were not covered by tests

if (extendedArgs.isCompleted !== undefined) {
const today = new Date();

Check warning on line 208 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L207-L208

Added lines #L207 - L208 were not covered by tests

if (extendedArgs.isCompleted) {
where = and(
baseCondition,
lt(advertisementsTable.endAt, today),
);
} else {
where = and(
baseCondition,
gt(advertisementsTable.endAt, today),
);
}
} else {
where = baseCondition;
}

Check warning on line 223 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L210-L223

Added lines #L210 - L223 were not covered by tests
}
} else {
if (cursor !== undefined) {
where = and(
const baseCondition = and(

Check warning on line 227 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L227

Added line #L227 was not covered by tests
exists(
ctx.drizzleClient
.select()
Expand All @@ -169,8 +239,47 @@
eq(advertisementsTable.organizationId, parent.id),
gt(advertisementsTable.name, cursor.name),
);

if (extendedArgs.isCompleted !== undefined) {
const today = new Date();

Check warning on line 244 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L243-L244

Added lines #L243 - L244 were not covered by tests

if (extendedArgs.isCompleted) {
where = and(
baseCondition,
lt(advertisementsTable.endAt, today),
);
} else {
where = and(
baseCondition,
gt(advertisementsTable.endAt, today),
);
}
} else {
where = baseCondition;
}

Check warning on line 259 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L246-L259

Added lines #L246 - L259 were not covered by tests
} else {
where = eq(advertisementsTable.organizationId, parent.id);
const baseCondition = eq(
advertisementsTable.organizationId,
parent.id,
);

if (extendedArgs.isCompleted !== undefined) {
const today = new Date();

if (extendedArgs.isCompleted) {
where = and(
baseCondition,
lt(advertisementsTable.endAt, today),
);
} else {
where = and(
baseCondition,
gt(advertisementsTable.endAt, today),
);
}
} else {
where = baseCondition;
}

Check warning on line 282 in src/graphql/types/Organization/advertisements.ts

View check run for this annotation

Codecov / codecov/patch

src/graphql/types/Organization/advertisements.ts#L281-L282

Added lines #L281 - L282 were not covered by tests
}
}

Expand Down
Loading
Loading