* chore: refactor code in some modules * refactor: getTeamsOfUser functino * chore: remove unused import * chore: revert some changes
419 lines
12 KiB
TypeScript
419 lines
12 KiB
TypeScript
import {
|
|
Resolver,
|
|
ResolveField,
|
|
Parent,
|
|
Args,
|
|
Query,
|
|
Mutation,
|
|
Subscription,
|
|
ID,
|
|
} from '@nestjs/graphql';
|
|
import { CollectionReorderData, TeamCollection } from './team-collection.model';
|
|
import { Team, TeamMemberRole } from '../team/team.model';
|
|
import { TeamCollectionService } from './team-collection.service';
|
|
import { GqlAuthGuard } from '../guards/gql-auth.guard';
|
|
import { GqlTeamMemberGuard } from '../team/guards/gql-team-member.guard';
|
|
import { UseGuards } from '@nestjs/common';
|
|
import { RequiresTeamRole } from '../team/decorators/requires-team-role.decorator';
|
|
import { GqlCollectionTeamMemberGuard } from './guards/gql-collection-team-member.guard';
|
|
import { PubSubService } from 'src/pubsub/pubsub.service';
|
|
import { PaginationArgs } from 'src/types/input-types.args';
|
|
import {
|
|
CreateChildTeamCollectionArgs,
|
|
CreateRootTeamCollectionArgs,
|
|
GetRootTeamCollectionsArgs,
|
|
MoveTeamCollectionArgs,
|
|
RenameTeamCollectionArgs,
|
|
ReplaceTeamCollectionArgs,
|
|
UpdateTeamCollectionOrderArgs,
|
|
} from './input-type.args';
|
|
import * as E from 'fp-ts/Either';
|
|
import { throwErr } from 'src/utils';
|
|
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
|
|
import { SkipThrottle } from '@nestjs/throttler';
|
|
|
|
@UseGuards(GqlThrottlerGuard)
|
|
@Resolver(() => TeamCollection)
|
|
export class TeamCollectionResolver {
|
|
constructor(
|
|
private readonly teamCollectionService: TeamCollectionService,
|
|
private readonly pubsub: PubSubService,
|
|
) {}
|
|
|
|
// Field resolvers
|
|
@ResolveField(() => Team, {
|
|
description: 'Team the collection belongs to',
|
|
complexity: 5,
|
|
})
|
|
async team(@Parent() collection: TeamCollection) {
|
|
const team = await this.teamCollectionService.getTeamOfCollection(
|
|
collection.id,
|
|
);
|
|
if (E.isLeft(team)) throwErr(team.left);
|
|
return team.right;
|
|
}
|
|
|
|
@ResolveField(() => TeamCollection, {
|
|
description: 'Return the parent Team Collection (null if root )',
|
|
nullable: true,
|
|
complexity: 3,
|
|
})
|
|
async parent(@Parent() collection: TeamCollection) {
|
|
return this.teamCollectionService.getParentOfCollection(collection.id);
|
|
}
|
|
|
|
@ResolveField(() => [TeamCollection], {
|
|
description: 'List of children Team Collections',
|
|
complexity: 3,
|
|
})
|
|
async children(
|
|
@Parent() collection: TeamCollection,
|
|
@Args() args: PaginationArgs,
|
|
) {
|
|
return this.teamCollectionService.getChildrenOfCollection(
|
|
collection.id,
|
|
args.cursor,
|
|
args.take,
|
|
);
|
|
}
|
|
|
|
// Queries
|
|
|
|
@Query(() => String, {
|
|
description:
|
|
'Returns the JSON string giving the collections and their contents of the team',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.VIEWER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.OWNER,
|
|
)
|
|
async exportCollectionsToJSON(
|
|
@Args({ name: 'teamID', description: 'ID of the team', type: () => ID })
|
|
teamID: string,
|
|
) {
|
|
const jsonString = await this.teamCollectionService.exportCollectionsToJSON(
|
|
teamID,
|
|
);
|
|
|
|
if (E.isLeft(jsonString)) throwErr(jsonString.left as string);
|
|
return jsonString.right;
|
|
}
|
|
|
|
@Query(() => [TeamCollection], {
|
|
description: 'Returns the collections of a team',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.VIEWER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.OWNER,
|
|
)
|
|
async rootCollectionsOfTeam(@Args() args: GetRootTeamCollectionsArgs) {
|
|
return this.teamCollectionService.getTeamRootCollections(
|
|
args.teamID,
|
|
args.cursor,
|
|
args.take,
|
|
);
|
|
}
|
|
|
|
@Query(() => TeamCollection, {
|
|
description: 'Get a Team Collection with ID or null (if not exists)',
|
|
nullable: true,
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.VIEWER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.OWNER,
|
|
)
|
|
async collection(
|
|
@Args({
|
|
name: 'collectionID',
|
|
description: 'ID of the collection',
|
|
type: () => ID,
|
|
})
|
|
collectionID: string,
|
|
) {
|
|
const teamCollections = await this.teamCollectionService.getCollection(
|
|
collectionID,
|
|
);
|
|
|
|
if (E.isLeft(teamCollections)) throwErr(teamCollections.left);
|
|
return teamCollections.right;
|
|
}
|
|
|
|
// Mutations
|
|
@Mutation(() => TeamCollection, {
|
|
description:
|
|
'Creates a collection at the root of the team hierarchy (no parent collection)',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async createRootCollection(@Args() args: CreateRootTeamCollectionArgs) {
|
|
const teamCollection = await this.teamCollectionService.createCollection(
|
|
args.teamID,
|
|
args.title,
|
|
null,
|
|
);
|
|
|
|
if (E.isLeft(teamCollection)) throwErr(teamCollection.left);
|
|
return teamCollection.right;
|
|
}
|
|
|
|
@Mutation(() => Boolean, {
|
|
description: 'Import collections from JSON string to the specified Team',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async importCollectionsFromJSON(
|
|
@Args({
|
|
name: 'teamID',
|
|
type: () => ID,
|
|
description: 'Id of the team to add to',
|
|
})
|
|
teamID: string,
|
|
@Args({
|
|
name: 'jsonString',
|
|
description: 'JSON string to import',
|
|
})
|
|
jsonString: string,
|
|
@Args({
|
|
name: 'parentCollectionID',
|
|
type: () => ID,
|
|
description:
|
|
'ID to the collection to which to import to (null if to import to the root of team)',
|
|
nullable: true,
|
|
})
|
|
parentCollectionID?: string,
|
|
): Promise<boolean> {
|
|
const importedCollection =
|
|
await this.teamCollectionService.importCollectionsFromJSON(
|
|
jsonString,
|
|
teamID,
|
|
parentCollectionID ?? null,
|
|
);
|
|
if (E.isLeft(importedCollection)) throwErr(importedCollection.left);
|
|
return importedCollection.right;
|
|
}
|
|
|
|
@Mutation(() => Boolean, {
|
|
description:
|
|
'Replace existing collections of a specific team with collections in JSON string',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async replaceCollectionsWithJSON(@Args() args: ReplaceTeamCollectionArgs) {
|
|
const teamCollection =
|
|
await this.teamCollectionService.replaceCollectionsWithJSON(
|
|
args.jsonString,
|
|
args.teamID,
|
|
args.parentCollectionID ?? null,
|
|
);
|
|
|
|
if (E.isLeft(teamCollection)) throwErr(teamCollection.left);
|
|
return teamCollection.right;
|
|
}
|
|
|
|
@Mutation(() => TeamCollection, {
|
|
description: 'Create a collection that has a parent collection',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async createChildCollection(@Args() args: CreateChildTeamCollectionArgs) {
|
|
const team = await this.teamCollectionService.getTeamOfCollection(
|
|
args.collectionID,
|
|
);
|
|
if (E.isLeft(team)) throwErr(team.left);
|
|
|
|
const teamCollection = await this.teamCollectionService.createCollection(
|
|
team.right.id,
|
|
args.childTitle,
|
|
args.collectionID,
|
|
);
|
|
|
|
if (E.isLeft(teamCollection)) throwErr(teamCollection.left);
|
|
return teamCollection.right;
|
|
}
|
|
|
|
@Mutation(() => TeamCollection, {
|
|
description: 'Rename a collection',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async renameCollection(@Args() args: RenameTeamCollectionArgs) {
|
|
const updatedTeamCollection =
|
|
await this.teamCollectionService.renameCollection(
|
|
args.collectionID,
|
|
args.newTitle,
|
|
);
|
|
|
|
if (E.isLeft(updatedTeamCollection)) throwErr(updatedTeamCollection.left);
|
|
return updatedTeamCollection.right;
|
|
}
|
|
|
|
@Mutation(() => Boolean, {
|
|
description: 'Delete a collection',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async deleteCollection(
|
|
@Args({
|
|
name: 'collectionID',
|
|
description: 'ID of the collection',
|
|
type: () => ID,
|
|
})
|
|
collectionID: string,
|
|
) {
|
|
const result = await this.teamCollectionService.deleteCollection(
|
|
collectionID,
|
|
);
|
|
|
|
if (E.isLeft(result)) throwErr(result.left);
|
|
return result.right;
|
|
}
|
|
|
|
@Mutation(() => TeamCollection, {
|
|
description:
|
|
'Move a collection into a new parent collection or the root of the team',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async moveCollection(@Args() args: MoveTeamCollectionArgs) {
|
|
const res = await this.teamCollectionService.moveCollection(
|
|
args.collectionID,
|
|
args.parentCollectionID,
|
|
);
|
|
if (E.isLeft(res)) throwErr(res.left);
|
|
return res.right;
|
|
}
|
|
|
|
@Mutation(() => Boolean, {
|
|
description: 'Update the order of collections',
|
|
})
|
|
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
|
|
@RequiresTeamRole(TeamMemberRole.OWNER, TeamMemberRole.EDITOR)
|
|
async updateCollectionOrder(@Args() args: UpdateTeamCollectionOrderArgs) {
|
|
const request = await this.teamCollectionService.updateCollectionOrder(
|
|
args.collectionID,
|
|
args.destCollID,
|
|
);
|
|
if (E.isLeft(request)) throwErr(request.left);
|
|
return request.right;
|
|
}
|
|
|
|
// Subscriptions
|
|
|
|
@Subscription(() => TeamCollection, {
|
|
description:
|
|
'Listen to when a collection has been added to a team. The emitted value is the team added',
|
|
resolve: (value) => value,
|
|
})
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.OWNER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.VIEWER,
|
|
)
|
|
@SkipThrottle()
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
teamCollectionAdded(
|
|
@Args({
|
|
name: 'teamID',
|
|
description: 'ID of the team to listen to',
|
|
type: () => ID,
|
|
})
|
|
teamID: string,
|
|
) {
|
|
return this.pubsub.asyncIterator(`team_coll/${teamID}/coll_added`);
|
|
}
|
|
|
|
@Subscription(() => TeamCollection, {
|
|
description: 'Listen to when a collection has been updated.',
|
|
resolve: (value) => value,
|
|
})
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.OWNER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.VIEWER,
|
|
)
|
|
@SkipThrottle()
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
teamCollectionUpdated(
|
|
@Args({
|
|
name: 'teamID',
|
|
description: 'ID of the team to listen to',
|
|
type: () => ID,
|
|
})
|
|
teamID: string,
|
|
) {
|
|
return this.pubsub.asyncIterator(`team_coll/${teamID}/coll_updated`);
|
|
}
|
|
|
|
@Subscription(() => ID, {
|
|
description: 'Listen to when a collection has been removed',
|
|
resolve: (value) => value,
|
|
})
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.OWNER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.VIEWER,
|
|
)
|
|
@SkipThrottle()
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
teamCollectionRemoved(
|
|
@Args({
|
|
name: 'teamID',
|
|
description: 'ID of the team to listen to',
|
|
type: () => ID,
|
|
})
|
|
teamID: string,
|
|
) {
|
|
return this.pubsub.asyncIterator(`team_coll/${teamID}/coll_removed`);
|
|
}
|
|
|
|
@Subscription(() => TeamCollection, {
|
|
description: 'Listen to when a collection has been moved',
|
|
resolve: (value) => value,
|
|
})
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.OWNER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.VIEWER,
|
|
)
|
|
@SkipThrottle()
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
teamCollectionMoved(
|
|
@Args({
|
|
name: 'teamID',
|
|
description: 'ID of the team to listen to',
|
|
type: () => ID,
|
|
})
|
|
teamID: string,
|
|
) {
|
|
return this.pubsub.asyncIterator(`team_coll/${teamID}/coll_moved`);
|
|
}
|
|
|
|
@Subscription(() => CollectionReorderData, {
|
|
description: 'Listen to when a collections position has changed',
|
|
resolve: (value) => value,
|
|
})
|
|
@RequiresTeamRole(
|
|
TeamMemberRole.OWNER,
|
|
TeamMemberRole.EDITOR,
|
|
TeamMemberRole.VIEWER,
|
|
)
|
|
@SkipThrottle()
|
|
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
|
|
collectionOrderUpdated(
|
|
@Args({
|
|
name: 'teamID',
|
|
description: 'ID of the team to listen to',
|
|
type: () => ID,
|
|
})
|
|
teamID: string,
|
|
) {
|
|
return this.pubsub.asyncIterator(`team_coll/${teamID}/coll_order_updated`);
|
|
}
|
|
}
|