Skip to content

Added mutations for action Item Category #3432

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

Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
996dc79
Added mutations for action Item Category
NishantSinghhhhh Apr 6, 2025
5c86d3b
Merge branch 'develop-postgres' into ActionItemCategory
NishantSinghhhhh Apr 7, 2025
75d910e
Added tests
NishantSinghhhhh Apr 7, 2025
04eba4f
Added test for createAction Item Category
NishantSinghhhhh Apr 9, 2025
0bb9e11
rabbits changes
NishantSinghhhhh Apr 9, 2025
c123acb
rabbits changes
NishantSinghhhhh Apr 9, 2025
0a07f4f
rabbits changes
NishantSinghhhhh Apr 9, 2025
5858194
rabbits changes
NishantSinghhhhh Apr 9, 2025
3645672
Merge branch 'develop-postgres' into ActionItemCategory
NishantSinghhhhh Apr 10, 2025
3372bd2
Created an input type for createActionItem
NishantSinghhhhh Apr 10, 2025
f689e29
Created an input type for createActionItem
NishantSinghhhhh Apr 10, 2025
cc2e986
Created an input type for createActionItem
NishantSinghhhhh Apr 10, 2025
9e3bb02
Created an input type for createActionItem
NishantSinghhhhh Apr 10, 2025
b03f5c2
Added types for 2 mutations and edited 1 mutation named createActionI…
NishantSinghhhhh Apr 10, 2025
040fef1
Merge branch 'develop-postgres' into ActionItemCategory
NishantSinghhhhh Apr 12, 2025
0143f00
changed files
NishantSinghhhhh Apr 14, 2025
ce056bc
Addedd changes
NishantSinghhhhh Apr 16, 2025
4889eeb
Merge branch 'ActionItemCategory' of https://github.com/NishantSinghh…
NishantSinghhhhh Apr 16, 2025
255c319
Added changes
NishantSinghhhhh Apr 18, 2025
6e3ce55
Added changes
NishantSinghhhhh Apr 18, 2025
8ffa4f0
Added changes
NishantSinghhhhh Apr 18, 2025
5ce99b4
Added changes
NishantSinghhhhh Apr 18, 2025
0ac4781
Added changes
NishantSinghhhhh Apr 18, 2025
4efeea4
Added changes
NishantSinghhhhh Apr 18, 2025
66de1bd
Added changes
NishantSinghhhhh Apr 18, 2025
e736e0a
Added changes
NishantSinghhhhh Apr 18, 2025
a2d07f1
Added changes
NishantSinghhhhh Apr 18, 2025
eaa3b9f
Added tests
NishantSinghhhhh Apr 18, 2025
56b290c
Added tests
NishantSinghhhhh Apr 18, 2025
00646cd
Added tests
NishantSinghhhhh Apr 18, 2025
b6d8ade
Added tests
NishantSinghhhhh Apr 18, 2025
335a92d
Added tests
NishantSinghhhhh Apr 18, 2025
1f96ef2
Added tests
NishantSinghhhhh Apr 18, 2025
95fdf64
Merge branch 'develop-postgres' into ActionItemCategory
NishantSinghhhhh Apr 18, 2025
267bb0c
Added tests
NishantSinghhhhh Apr 18, 2025
86c83e4
Added tests
NishantSinghhhhh Apr 18, 2025
6127a9a
Added tests
NishantSinghhhhh Apr 18, 2025
31b85f0
Added tests
NishantSinghhhhh Apr 18, 2025
8d5649d
Added tests
NishantSinghhhhh Apr 18, 2025
43ce3ff
Added tests
NishantSinghhhhh Apr 18, 2025
0b7b030
Added tests
NishantSinghhhhh Apr 18, 2025
a473043
Added alloted hours
NishantSinghhhhh Apr 21, 2025
b918f6d
Added changes
NishantSinghhhhh Apr 21, 2025
42610e6
Merge branch 'develop-postgres' into ActionItemCategory
NishantSinghhhhh Apr 21, 2025
9f8d528
Added changes
NishantSinghhhhh Apr 22, 2025
8fb5aa8
'Merge branch 'ActionItemCategory' of https://github.com/NishantSingh…
NishantSinghhhhh Apr 22, 2025
f1b412c
removed type errors
NishantSinghhhhh Apr 22, 2025
0eb60de
removed type errors
NishantSinghhhhh Apr 22, 2025
d8a85ca
removed type errors
NishantSinghhhhh Apr 22, 2025
fa3373a
changed names of tables
NishantSinghhhhh Apr 22, 2025
24804c3
Added alloted hours data in sample data for actionItems
NishantSinghhhhh Apr 22, 2025
c5a75eb
Added alloted hours data in sample data for actionItems
NishantSinghhhhh Apr 22, 2025
280ed54
Added alloted hours data in sample data for actionItems
NishantSinghhhhh Apr 22, 2025
a0ea106
Added changes in table
NishantSinghhhhh Apr 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 24 additions & 6 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,12 @@ type Community {
youtubeURL: String
}

input CreateActionItemCategoryInput {
isDisabled: Boolean
name: String!
organizationId: ID!
}

input CreateActionItemInput {
assignedAt: String
assigneeId: ID!
Expand Down Expand Up @@ -773,6 +779,11 @@ type GetUrlResponse {
presignedUrl: String
}

type HasUserVoted {
"""Type of the post vote"""
type: PostVoteType!
}

"""
Possible variants of the two-letter language code defined in ISO 639-1, part of the ISO 639 standard published by the International Organization for Standardization (ISO), to represent natural languages.
"""
Expand Down Expand Up @@ -1472,6 +1483,9 @@ type Mutation {
"""Mutation field to create an action item."""
createActionItem(input: CreateActionItemInput!): ActionItem

"""Mutation field to create a new Action Item Category."""
createActionItemCategory(input: CreateActionItemCategoryInput!): ActionItemCategory

"""Mutation field to create an advertisement."""
createAdvertisement(input: MutationCreateAdvertisementInput!): Advertisement

Expand Down Expand Up @@ -1646,6 +1660,9 @@ type Mutation {
input: MutationUpdateActionItemInput!
): ActionItem

"""Mutation field to update an existing Action Item Category."""
updateActionItemCategory(input: UpdateActionItemCategoryInput!): ActionItemCategory

"""Mutation field to update an advertisement."""
updateAdvertisement(input: MutationUpdateAdvertisementInput!): Advertisement

Expand Down Expand Up @@ -3360,7 +3377,7 @@ type Query {
fundCampaignPledge(input: QueryFundCampaignPledgeInput!): FundCampaignPledge

"""Query field to read a post vote."""
hasUserVoted(input: QueryHasUserVotedInput!): hasUserVoted
hasUserVoted(input: QueryHasUserVotedInput!): HasUserVoted

"""Query field to read an organization."""
organization(input: QueryOrganizationInput!): Organization
Expand Down Expand Up @@ -3666,6 +3683,12 @@ type TagFolderTagsConnectionEdge {
node: Tag
}

input UpdateActionItemCategoryInput {
categoryId: ID!
isDisabled: Boolean
name: String
}

"""The `Upload` scalar type represents a file upload."""
scalar Upload

Expand Down Expand Up @@ -3894,9 +3917,4 @@ type VenueEventsConnection {
type VenueEventsConnectionEdge {
cursor: String!
node: Event
}

type hasUserVoted {
"""Type of the post vote"""
type: PostVoteType!
}
125 changes: 125 additions & 0 deletions src/graphql/types/Mutation/createActionItemCategory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { sql } from "drizzle-orm";
import { uuidv7 } from "uuidv7";
import { z } from "zod";
import { actionCategoriesTable } from "~/src/drizzle/tables/actionCategories";
import { builder } from "~/src/graphql/builder";
import { TalawaGraphQLError } from "~/src/utilities/TalawaGraphQLError";

// 1. Define your ActionItemCategory GraphQL output type (example)
import { ActionItemCategory } from "../ActionItemCategory/ActionItemCategory";

// 2. Create Zod schema for input validation
const mutationCreateActionItemCategoryArgumentsSchema = z.object({
input: z.object({
name: z.string().min(1, "Category name cannot be empty"),
organizationId: z.string().uuid(),
// Optional fields like isDisabled, if you allow it to be set:
isDisabled: z.boolean().optional(),
}),
});

builder.mutationField("createActionItemCategory", (t) =>
t.field({
type: ActionItemCategory, // The return type
args: {
input: t.arg({
required: true,
type: builder.inputType("CreateActionItemCategoryInput", {
fields: (t) => ({
name: t.field({ type: "String", required: true }),
organizationId: t.field({ type: "ID", required: true }),
isDisabled: t.field({ type: "Boolean" }), // Allow setting isDisabled from input
}),
}),
}),
},
description: "Mutation field to create a new Action Item Category.",
resolve: async (_parent, args, ctx) => {
// 4. Check authentication
if (!ctx.currentClient.isAuthenticated) {
throw new TalawaGraphQLError({
extensions: { code: "unauthenticated" },
});
}

// 5. Validate input with Zod
const parsedArgs =
mutationCreateActionItemCategoryArgumentsSchema.parse(args);
const currentUserId = ctx.currentClient.user.id;

// 6. Check if the organization exists
const existingOrganization =
await ctx.drizzleClient.query.organizationsTable.findFirst({
columns: { id: true },
where: (fields, operators) =>
operators.eq(fields.id, parsedArgs.input.organizationId),
});

if (!existingOrganization) {
throw new TalawaGraphQLError({
extensions: {
code: "arguments_associated_resources_not_found",
issues: [{ argumentPath: ["input", "organizationId"] }],
},
});
}

// 7. Check if the user is part of the organization
const userMembership =
await ctx.drizzleClient.query.organizationMembershipsTable.findFirst({
columns: { role: true },
where: (fields, operators) =>
sql`${operators.eq(fields.memberId, currentUserId)}
AND ${operators.eq(fields.organizationId, parsedArgs.input.organizationId)}`,
});

if (!userMembership) {
throw new TalawaGraphQLError({
extensions: {
code: "unauthorized_action_on_arguments_associated_resources",
issues: [{ argumentPath: ["input", "organizationId"] }],
},
});
}

// 8. Check if the user is an admin (similar logic as action item creation)
if (userMembership.role !== "administrator") {
throw new TalawaGraphQLError({
extensions: {
code: "forbidden_action_on_arguments_associated_resources",
issues: [
{
argumentPath: ["input", "organizationId"],
message:
"Only administrators can create categories for this organization.",
},
],
},
});
}

// 9. Insert the new category
const [createdCategory] = await ctx.drizzleClient
.insert(actionCategoriesTable)
.values({
id: uuidv7(),
name: parsedArgs.input.name,
organizationId: parsedArgs.input.organizationId,
creatorId: currentUserId,
isDisabled: parsedArgs.input.isDisabled ?? false,
createdAt: new Date(),
updatedAt: new Date(),
})
.returning();

if (!createdCategory) {
ctx.log.error(
"Postgres insert operation unexpectedly returned an empty array.",
);
throw new TalawaGraphQLError({ extensions: { code: "unexpected" } });
}

return createdCategory;
},
}),
);
2 changes: 2 additions & 0 deletions src/graphql/types/Mutation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,5 @@ import "./createPresignedUrl";
import "./deleteActionItem";
import "./updateActionItem";
import "./createActionItem";
import "./createActionItemCategory";
import "./updateActionItemCategory";
116 changes: 116 additions & 0 deletions src/graphql/types/Mutation/updateActionItemCategory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { eq, sql } from "drizzle-orm";
import { z } from "zod";
import { actionCategoriesTable } from "~/src/drizzle/tables/actionCategories";
import { builder } from "~/src/graphql/builder";
import { TalawaGraphQLError } from "~/src/utilities/TalawaGraphQLError";
import { ActionItemCategory } from "../ActionItemCategory/ActionItemCategory";

const mutationUpdateActionItemCategoryArgumentsSchema = z.object({
input: z.object({
categoryId: z.string().uuid(), // The ID of the category to update
name: z.string().optional(), // New name
isDisabled: z.boolean().optional(), // Enable/disable
}),
});

builder.mutationField("updateActionItemCategory", (t) =>
t.field({
type: ActionItemCategory,
args: {
input: t.arg({
required: true,
type: builder.inputType("UpdateActionItemCategoryInput", {
fields: (t) => ({
categoryId: t.field({ type: "ID", required: true }),
name: t.field({ type: "String" }),
isDisabled: t.field({ type: "Boolean" }),
}),
}),
}),
},
description: "Mutation field to update an existing Action Item Category.",
resolve: async (_parent, args, ctx) => {
// 1. Check user authentication
if (!ctx.currentClient.isAuthenticated) {
throw new TalawaGraphQLError({
extensions: { code: "unauthenticated" },
});
}

// 2. Validate input
const parsedArgs =
mutationUpdateActionItemCategoryArgumentsSchema.parse(args);
const { categoryId, name, isDisabled } = parsedArgs.input;
const currentUserId = ctx.currentClient.user.id;

// 3. Find the existing category
const existingCategory =
await ctx.drizzleClient.query.actionCategoriesTable.findFirst({
columns: {
id: true,
organizationId: true,
},
where: (fields, operators) => operators.eq(fields.id, categoryId),
});

if (!existingCategory) {
throw new TalawaGraphQLError({
extensions: {
code: "arguments_associated_resources_not_found",
issues: [{ argumentPath: ["input", "categoryId"] }],
},
});
}

// 4. Check if the user is an admin in that category's organization
const userMembership =
await ctx.drizzleClient.query.organizationMembershipsTable.findFirst({
columns: { role: true },
where: (fields, operators) =>
sql`${operators.eq(fields.memberId, currentUserId)}
AND ${operators.eq(fields.organizationId, existingCategory.organizationId)}`,
});

if (!userMembership || userMembership.role !== "administrator") {
throw new TalawaGraphQLError({
extensions: {
code: "forbidden_action_on_arguments_associated_resources",
issues: [
{
argumentPath: ["input", "categoryId"],
message: "Only administrators can update this category.",
},
],
},
});
}

// 5. Update the category
// Build a "set" object only with provided fields
const updates: Record<string, unknown> = { updatedAt: new Date() };
if (typeof name === "string") {
updates.name = name;
}
if (typeof isDisabled === "boolean") {
updates.isDisabled = isDisabled;
}

// ...

const [updatedCategory] = await ctx.drizzleClient
.update(actionCategoriesTable)
.set(updates)
.where(eq(actionCategoriesTable.id, categoryId))
.returning();

if (!updatedCategory) {
ctx.log.error(
"Postgres update operation unexpectedly returned an empty array.",
);
throw new TalawaGraphQLError({ extensions: { code: "unexpected" } });
}

return updatedCategory;
},
}),
);
Loading