Skip to content
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

feat: User tags backend adjustments (GSoC) #2460

Merged
merged 8 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 6 additions & 3 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1514,6 +1514,8 @@ type Query {
getNoteById(id: ID!): Note!
getPledgesByUserId(orderBy: PledgeOrderByInput, userId: ID!, where: PledgeWhereInput): [FundraisingCampaignPledge]
getPlugins: [Plugin]
getUserTag(id: ID!): UserTag
getUserTagAncestors(id: ID!): [UserTag]
getVenueByOrgId(first: Int, orderBy: VenueOrderByInput, orgId: ID!, skip: Int, where: VenueWhereInput): [Venue]
getlanguage(lang_code: String!): [Translation]
groupChatById(id: ID!): GroupChat
Expand Down Expand Up @@ -1799,9 +1801,9 @@ input UpdateUserPasswordInput {
}

input UpdateUserTagInput {
_id: ID!
name: String!
tagColor: String!
tagColor: String
tagId: ID!
}

scalar Upload
Expand Down Expand Up @@ -1939,7 +1941,7 @@ type UserTag {
type UserTagsConnection {
edges: [UserTagsConnectionEdge!]!
pageInfo: DefaultConnectionPageInfo!
totalCount: PositiveInt
totalCount: Int
}

"""A default connection edge on the UserTag type for UserTagsConnection."""
Expand Down Expand Up @@ -1987,6 +1989,7 @@ input UserWhereInput {
type UsersConnection {
edges: [UsersConnectionEdge!]!
pageInfo: DefaultConnectionPageInfo!
totalCount: Int
}

"""A default connection edge on the User type for UsersConnection."""
Expand Down
30 changes: 26 additions & 4 deletions src/resolvers/Mutation/assignUserTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,32 @@ export const assignUserTag: MutationResolvers["assignUserTag"] = async (
);
}

// Assign the tag
await TagUser.create({
...args.input,
});
// assign all the ancestor tags
const allAncestorTags = [tag._id];
let currentTag = tag;
while (currentTag?.parentTagId) {
const currentParentTag = await OrganizationTagUser.findOne({
_id: currentTag.parentTagId,
}).lean();

if (currentParentTag) {
allAncestorTags.push(currentParentTag?._id);
currentTag = currentParentTag;
}
}

const assigneeId = args.input.userId;

const tagUserDocs = allAncestorTags.map((tagId) => ({
updateOne: {
filter: { userId: assigneeId, tagId },
update: { $setOnInsert: { userId: assigneeId, tagId } },
upsert: true,
setDefaultsOnInsert: true,
},
}));

await TagUser.bulkWrite(tagUserDocs);

return requestUser;
};
31 changes: 29 additions & 2 deletions src/resolvers/Mutation/unassignUserTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,36 @@ export const unassignUserTag: MutationResolvers["unassignUserTag"] = async (
);
}

// Get all the child tags of the current tag (including itself)
// on the OrganizationTagUser model
// The following implementation makes number of queries = max depth of nesting in the tag provided
let allTagIds: string[] = [];
let currentParents = [tag._id.toString()];

while (currentParents.length) {
allTagIds = allTagIds.concat(currentParents);
const foundTags = await OrganizationTagUser.find(
{
organizationId: tag.organizationId,
parentTagId: {
$in: currentParents,
},
},
{
_id: 1,
},
);
currentParents = foundTags
.map((tag) => tag._id.toString())
.filter((id: string | null) => id);
}

// Unassign the tag
await TagUser.deleteOne({
...args.input,
await TagUser.deleteMany({
tagId: {
$in: allTagIds,
},
userId: args.input.userId,
});

return requestUser;
Expand Down
4 changes: 2 additions & 2 deletions src/resolvers/Mutation/updateUserTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const updateUserTag: MutationResolvers["updateUserTag"] = async (

// Get the tag object
const existingTag = await OrganizationTagUser.findOne({
_id: args.input._id,
_id: args.input.tagId,
}).lean();

if (!existingTag) {
Expand Down Expand Up @@ -130,7 +130,7 @@ export const updateUserTag: MutationResolvers["updateUserTag"] = async (
// Update the title of the tag and return it
return await OrganizationTagUser.findOneAndUpdate(
{
_id: args.input._id,
_id: args.input.tagId,
},
{
name: args.input.name,
Expand Down
1 change: 1 addition & 0 deletions src/resolvers/Organization/userTags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export const userTags: OrganizationResolvers["userTags"] = async (
OrganizationTagUser.find({
...filter,
organizationId: parent._id,
parentTagId: null,
})
.sort(sort)
.limit(parsedArgs.limit)
Expand Down
21 changes: 21 additions & 0 deletions src/resolvers/Query/getUserTag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { OrganizationTagUser } from "../../models";
import { errors, requestContext } from "../../libraries";
import type { QueryResolvers } from "../../types/generatedGraphQLTypes";
import { TAG_NOT_FOUND } from "../../constants";

export const getUserTag: QueryResolvers["getUserTag"] = async (
_parent,
args,
) => {
const userTag = await OrganizationTagUser.findById(args.id).lean();

if (!userTag) {
throw new errors.NotFoundError(
requestContext.translate(TAG_NOT_FOUND.MESSAGE),
TAG_NOT_FOUND.CODE,
TAG_NOT_FOUND.PARAM,
);
}

return userTag;
};
32 changes: 32 additions & 0 deletions src/resolvers/Query/getUserTagAncestors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { OrganizationTagUser } from "../../models";
import { errors, requestContext } from "../../libraries";
import type { QueryResolvers } from "../../types/generatedGraphQLTypes";
import { TAG_NOT_FOUND } from "../../constants";

export const getUserTagAncestors: QueryResolvers["getUserTagAncestors"] =
async (_parent, args) => {
let currentTag = await OrganizationTagUser.findById(args.id).lean();

const tagAncestors = [currentTag];

while (currentTag?.parentTagId) {
const currentParent = await OrganizationTagUser.findById(
currentTag.parentTagId,
).lean();

if (currentParent) {
tagAncestors.push(currentParent);
currentTag = currentParent;
}
}

if (!currentTag) {
throw new errors.NotFoundError(
requestContext.translate(TAG_NOT_FOUND.MESSAGE),
TAG_NOT_FOUND.CODE,
TAG_NOT_FOUND.PARAM,
);
}

return tagAncestors.reverse();
};
4 changes: 4 additions & 0 deletions src/resolvers/Query/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import { getFundraisingCampaigns } from "./getFundraisingCampaigns";
import { getPledgesByUserId } from "./getPledgesByUserId";
import { getPlugins } from "./getPlugins";
import { getlanguage } from "./getlanguage";
import { getUserTag } from "./getUserTag";
import { getUserTagAncestors } from "./getUserTagAncestors";
import { me } from "./me";
import { myLanguage } from "./myLanguage";
import { organizations } from "./organizations";
Expand Down Expand Up @@ -84,6 +86,8 @@ export const Query: QueryResolvers = {
getNoteById,
getlanguage,
getPlugins,
getUserTag,
getUserTagAncestors,
isSampleOrganization,
me,
myLanguage,
Expand Down
4 changes: 2 additions & 2 deletions src/typeDefs/inputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,8 +490,8 @@ export const inputs = gql`
}

input UpdateUserTagInput {
_id: ID!
tagColor: String!
tagId: ID!
tagColor: String
name: String!
}

Expand Down
4 changes: 4 additions & 0 deletions src/typeDefs/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ export const queries = gql`

getNoteById(id: ID!): Note!

getUserTag(id: ID!): UserTag

getUserTagAncestors(id: ID!): [UserTag]

getAllNotesForAgendaItem(agendaItemId: ID!): [Note]

advertisementsConnection(
Expand Down
3 changes: 2 additions & 1 deletion src/typeDefs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ export const types = gql`
type UserTagsConnection {
edges: [UserTagsConnectionEdge!]!
pageInfo: DefaultConnectionPageInfo!
totalCount: PositiveInt
totalCount: Int
}

"""
Expand All @@ -759,6 +759,7 @@ export const types = gql`
type UsersConnection {
edges: [UsersConnectionEdge!]!
pageInfo: DefaultConnectionPageInfo!
totalCount: Int
}

"""
Expand Down
24 changes: 20 additions & 4 deletions src/types/generatedGraphQLTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2306,6 +2306,8 @@ export type Query = {
getNoteById: Note;
getPledgesByUserId?: Maybe<Array<Maybe<FundraisingCampaignPledge>>>;
getPlugins?: Maybe<Array<Maybe<Plugin>>>;
getUserTag?: Maybe<UserTag>;
getUserTagAncestors?: Maybe<Array<Maybe<UserTag>>>;
getVenueByOrgId?: Maybe<Array<Maybe<Venue>>>;
getlanguage?: Maybe<Array<Maybe<Translation>>>;
groupChatById?: Maybe<GroupChat>;
Expand Down Expand Up @@ -2521,6 +2523,16 @@ export type QueryGetPledgesByUserIdArgs = {
};


export type QueryGetUserTagArgs = {
id: Scalars['ID']['input'];
};


export type QueryGetUserTagAncestorsArgs = {
id: Scalars['ID']['input'];
};


export type QueryGetVenueByOrgIdArgs = {
first?: InputMaybe<Scalars['Int']['input']>;
orderBy?: InputMaybe<VenueOrderByInput>;
Expand Down Expand Up @@ -2908,9 +2920,9 @@ export type UpdateUserPasswordInput = {
};

export type UpdateUserTagInput = {
_id: Scalars['ID']['input'];
name: Scalars['String']['input'];
tagColor: Scalars['String']['input'];
tagColor?: InputMaybe<Scalars['String']['input']>;
tagId: Scalars['ID']['input'];
};

export type User = {
Expand Down Expand Up @@ -3084,7 +3096,7 @@ export type UserTagsConnection = {
__typename?: 'UserTagsConnection';
edges: Array<UserTagsConnectionEdge>;
pageInfo: DefaultConnectionPageInfo;
totalCount?: Maybe<Scalars['PositiveInt']['output']>;
totalCount?: Maybe<Scalars['Int']['output']>;
};

/** A default connection edge on the UserTag type for UserTagsConnection. */
Expand Down Expand Up @@ -3133,6 +3145,7 @@ export type UsersConnection = {
__typename?: 'UsersConnection';
edges: Array<UsersConnectionEdge>;
pageInfo: DefaultConnectionPageInfo;
totalCount?: Maybe<Scalars['Int']['output']>;
};

/** A default connection edge on the User type for UsersConnection. */
Expand Down Expand Up @@ -4600,6 +4613,8 @@ export type QueryResolvers<ContextType = any, ParentType extends ResolversParent
getNoteById?: Resolver<ResolversTypes['Note'], ParentType, ContextType, RequireFields<QueryGetNoteByIdArgs, 'id'>>;
getPledgesByUserId?: Resolver<Maybe<Array<Maybe<ResolversTypes['FundraisingCampaignPledge']>>>, ParentType, ContextType, RequireFields<QueryGetPledgesByUserIdArgs, 'userId'>>;
getPlugins?: Resolver<Maybe<Array<Maybe<ResolversTypes['Plugin']>>>, ParentType, ContextType>;
getUserTag?: Resolver<Maybe<ResolversTypes['UserTag']>, ParentType, ContextType, RequireFields<QueryGetUserTagArgs, 'id'>>;
getUserTagAncestors?: Resolver<Maybe<Array<Maybe<ResolversTypes['UserTag']>>>, ParentType, ContextType, RequireFields<QueryGetUserTagAncestorsArgs, 'id'>>;
getVenueByOrgId?: Resolver<Maybe<Array<Maybe<ResolversTypes['Venue']>>>, ParentType, ContextType, RequireFields<QueryGetVenueByOrgIdArgs, 'orgId'>>;
getlanguage?: Resolver<Maybe<Array<Maybe<ResolversTypes['Translation']>>>, ParentType, ContextType, RequireFields<QueryGetlanguageArgs, 'lang_code'>>;
groupChatById?: Resolver<Maybe<ResolversTypes['GroupChat']>, ParentType, ContextType, RequireFields<QueryGroupChatByIdArgs, 'id'>>;
Expand Down Expand Up @@ -4784,7 +4799,7 @@ export type UserTagResolvers<ContextType = any, ParentType extends ResolversPare
export type UserTagsConnectionResolvers<ContextType = any, ParentType extends ResolversParentTypes['UserTagsConnection'] = ResolversParentTypes['UserTagsConnection']> = {
edges?: Resolver<Array<ResolversTypes['UserTagsConnectionEdge']>, ParentType, ContextType>;
pageInfo?: Resolver<ResolversTypes['DefaultConnectionPageInfo'], ParentType, ContextType>;
totalCount?: Resolver<Maybe<ResolversTypes['PositiveInt']>, ParentType, ContextType>;
totalCount?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

Expand All @@ -4797,6 +4812,7 @@ export type UserTagsConnectionEdgeResolvers<ContextType = any, ParentType extend
export type UsersConnectionResolvers<ContextType = any, ParentType extends ResolversParentTypes['UsersConnection'] = ResolversParentTypes['UsersConnection']> = {
edges?: Resolver<Array<ResolversTypes['UsersConnectionEdge']>, ParentType, ContextType>;
pageInfo?: Resolver<ResolversTypes['DefaultConnectionPageInfo'], ParentType, ContextType>;
totalCount?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

Expand Down
Loading
Loading