refactor: Refactoring of Team Request with Reordering (HBE-151) (#20)

* feat: createdOn, updatedOn added in team-request schema and updateTeamReq resolver refactored

* feat: resolver name changed for updateTeamRequest

* refactor: searchForTeamRequest resolver

* refactor: some functions refactored

* refactor: team-request service and subscriptions

* refactor: update GqlRequestTeamMemberGuard

* feat: team request reordering add

* feat: handle exception on update Team Request

* chore: change some return statement

* fix: change field name of MoveTeamRequestArgs

* feat: publish message update for reorder team req

* test: fix all the exists cases

* fix: add return statement

* test: add few functions test cases

* feat: made backward compatible

* fix: team-member guard for retrive user

* fix: few bugs

* chore: destructured parameters in service methods

* test: fix test cases

* feat: updateLookUpRequestOrder resolver added

* test: fix test cases

* chore: improved code consistency

* fix: feedback changes

* fix: main changes
This commit is contained in:
Mir Arif Hasan
2023-03-09 20:59:39 +06:00
committed by GitHub
parent 2a715d5348
commit 7d3b2c064a
8 changed files with 1159 additions and 1347 deletions

View File

@@ -8,11 +8,15 @@ import {
Subscription,
ID,
} from '@nestjs/graphql';
import { RequestReorderData, TeamRequest } from './team-request.model';
import {
TeamRequest,
CreateTeamRequestInput,
UpdateTeamRequestInput,
} from './team-request.model';
SearchTeamRequestArgs,
GetTeamRequestInCollectionArgs,
MoveTeamRequestArgs,
UpdateLookUpRequestOrderArgs,
} from './input-type.args';
import { Team, TeamMemberRole } from '../team/team.model';
import { TeamRequestService } from './team-request.service';
import { TeamCollection } from '../team-collection/team-collection.model';
@@ -23,8 +27,8 @@ import { GqlCollectionTeamMemberGuard } from '../team-collection/guards/gql-coll
import { RequiresTeamRole } from '../team/decorators/requires-team-role.decorator';
import { GqlTeamMemberGuard } from '../team/guards/gql-team-member.guard';
import { PubSubService } from 'src/pubsub/pubsub.service';
import { pipe } from 'fp-ts/function';
import * as TE from 'fp-ts/TaskEither';
import * as E from 'fp-ts/Either';
import * as O from 'fp-ts/Option';
import { throwErr } from 'src/utils';
@Resolver(() => TeamRequest)
@@ -39,44 +43,40 @@ export class TeamRequestResolver {
description: 'Team the request belongs to',
complexity: 3,
})
team(@Parent() req: TeamRequest): Promise<Team> {
return this.teamRequestService.getTeamOfRequest(req);
async team(@Parent() req: TeamRequest) {
const team = await this.teamRequestService.getTeamOfRequest(req);
if (E.isLeft(team)) throwErr(team.left);
return team.right;
}
// @ResolveField(() => TeamCollection, {
// description: 'Collection the request belongs to',
// complexity: 3,
// })
// collection(@Parent() req: TeamRequest): Promise<TeamCollection> {
// return this.teamRequestService.getCollectionOfRequest(req);
// }
@ResolveField(() => TeamCollection, {
description: 'Collection the request belongs to',
complexity: 3,
})
async collection(@Parent() req: TeamRequest) {
const teamCollection = await this.teamRequestService.getCollectionOfRequest(
req,
);
if (E.isLeft(teamCollection)) throwErr(teamCollection.left);
return teamCollection.right;
}
// Query
@Query(() => [TeamRequest], {
description: 'Search the team for a specific request with title',
})
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
searchForRequest(
@Args({
name: 'teamID',
description: 'ID of the team to look in',
type: () => ID,
})
teamID: string,
@Args({ name: 'searchTerm', description: 'The title to search for' })
searchTerm: string,
@Args({
name: 'cursor',
type: () => ID,
description: 'ID of the last returned request or null',
nullable: true,
})
cursor?: string,
): Promise<TeamRequest[]> {
@RequiresTeamRole(
TeamMemberRole.EDITOR,
TeamMemberRole.OWNER,
TeamMemberRole.VIEWER,
)
async searchForRequest(@Args() args: SearchTeamRequestArgs) {
return this.teamRequestService.searchRequest(
teamID,
searchTerm,
cursor ?? null,
args.teamID,
args.searchTerm,
args.cursor,
args.take,
);
}
@@ -85,19 +85,26 @@ export class TeamRequestResolver {
nullable: true,
})
@UseGuards(GqlAuthGuard, GqlRequestTeamMemberGuard)
request(
@RequiresTeamRole(
TeamMemberRole.EDITOR,
TeamMemberRole.OWNER,
TeamMemberRole.VIEWER,
)
async request(
@Args({
name: 'requestID',
description: 'ID of the request',
type: () => ID,
})
requestID: string,
): Promise<TeamRequest | null> {
return this.teamRequestService.getRequest(requestID);
) {
const teamRequest = await this.teamRequestService.getRequest(requestID);
if (O.isNone(teamRequest)) return null;
return teamRequest.value;
}
@Query(() => [TeamRequest], {
description: 'Gives a list of requests in the collection',
description: 'Gives a paginated list of requests in the collection',
})
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
@RequiresTeamRole(
@@ -105,7 +112,21 @@ export class TeamRequestResolver {
TeamMemberRole.OWNER,
TeamMemberRole.VIEWER,
)
requestsInCollection(
async requestsInCollection(@Args() input: GetTeamRequestInCollectionArgs) {
return this.teamRequestService.getRequestsInCollection(
input.collectionID,
input.cursor,
input.take,
);
}
// Mutation
@Mutation(() => TeamRequest, {
description: 'Create a team request in the given collection.',
})
@UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
@RequiresTeamRole(TeamMemberRole.EDITOR, TeamMemberRole.OWNER)
async createRequestInCollection(
@Args({
name: 'collectionID',
description: 'ID of the collection',
@@ -113,49 +134,29 @@ export class TeamRequestResolver {
})
collectionID: string,
@Args({
name: 'cursor',
nullable: true,
type: () => ID,
description: 'ID of the last returned request (for pagination)',
name: 'data',
type: () => CreateTeamRequestInput,
description:
'The request data (stringified JSON of Hoppscotch request object)',
})
cursor?: string,
): Promise<TeamRequest[]> {
return this.teamRequestService.getRequestsInCollection(
data: CreateTeamRequestInput,
) {
const teamRequest = await this.teamRequestService.createTeamRequest(
collectionID,
cursor ?? null,
data.teamID,
data.title,
data.request,
);
if (E.isLeft(teamRequest)) throwErr(teamRequest.left);
return teamRequest.right;
}
// // Mutation
// @Mutation(() => TeamRequest, {
// description: 'Create a request in the given collection.',
// })
// @UseGuards(GqlAuthGuard, GqlCollectionTeamMemberGuard)
// @RequiresTeamRole(TeamMemberRole.EDITOR, TeamMemberRole.OWNER)
// createRequestInCollection(
// @Args({
// name: 'collectionID',
// description: 'ID of the collection',
// type: () => ID,
// })
// collectionID: string,
// @Args({
// name: 'data',
// type: () => CreateTeamRequestInput,
// description:
// 'The request data (stringified JSON of Hoppscotch request object)',
// })
// data: CreateTeamRequestInput,
// ): Promise<TeamRequest> {
// return this.teamRequestService.createTeamRequest(collectionID, data);
// }
@Mutation(() => TeamRequest, {
description: 'Update a request with the given ID',
})
@UseGuards(GqlAuthGuard, GqlRequestTeamMemberGuard)
@RequiresTeamRole(TeamMemberRole.EDITOR, TeamMemberRole.OWNER)
updateRequest(
async updateRequest(
@Args({
name: 'requestID',
description: 'ID of the request',
@@ -169,8 +170,14 @@ export class TeamRequestResolver {
'The updated request data (stringified JSON of Hoppscotch request object)',
})
data: UpdateTeamRequestInput,
): Promise<TeamRequest> {
return this.teamRequestService.updateTeamRequest(requestID, data);
) {
const teamRequest = await this.teamRequestService.updateTeamRequest(
requestID,
data.title,
data.request,
);
if (E.isLeft(teamRequest)) throwErr(teamRequest.left);
return teamRequest.right;
}
@Mutation(() => Boolean, {
@@ -185,35 +192,50 @@ export class TeamRequestResolver {
type: () => ID,
})
requestID: string,
): Promise<boolean> {
await this.teamRequestService.deleteTeamRequest(requestID);
) {
const isDeleted = await this.teamRequestService.deleteTeamRequest(
requestID,
);
if (E.isLeft(isDeleted)) throwErr(isDeleted.left);
return isDeleted.right;
}
@Mutation(() => Boolean, {
description: 'Update the order of requests in the lookup table',
})
@UseGuards(GqlAuthGuard, GqlRequestTeamMemberGuard)
@RequiresTeamRole(TeamMemberRole.EDITOR, TeamMemberRole.OWNER)
async updateLookUpRequestOrder(
@Args()
args: UpdateLookUpRequestOrderArgs,
) {
const teamRequest = await this.teamRequestService.moveRequest(
args.collectionID,
args.requestID,
args.collectionID,
args.nextRequestID,
'updateLookUpRequestOrder',
);
if (E.isLeft(teamRequest)) throwErr(teamRequest.left);
return true;
}
// @Mutation(() => TeamRequest, {
// description: 'Move a request to the given collection',
// })
// @UseGuards(GqlAuthGuard, GqlRequestTeamMemberGuard)
// @RequiresTeamRole(TeamMemberRole.EDITOR, TeamMemberRole.OWNER)
// moveRequest(
// @Args({
// name: 'requestID',
// description: 'ID of the request to move',
// type: () => ID,
// })
// requestID: string,
// @Args({
// name: 'destCollID',
// description: 'ID of the collection to move the request to',
// type: () => ID,
// })
// destCollID: string,
// ): Promise<TeamRequest> {
// return pipe(
// this.teamRequestService.moveRequest(requestID, destCollID),
// TE.getOrElse((e) => throwErr(e)),
// )();
// }
@Mutation(() => TeamRequest, {
description: 'Move a request to the given collection',
})
@UseGuards(GqlAuthGuard, GqlRequestTeamMemberGuard)
@RequiresTeamRole(TeamMemberRole.EDITOR, TeamMemberRole.OWNER)
async moveRequest(@Args() args: MoveTeamRequestArgs) {
const teamRequest = await this.teamRequestService.moveRequest(
args.srcCollID,
args.requestID,
args.destCollID,
args.nextRequestID,
'moveRequest',
);
if (E.isLeft(teamRequest)) throwErr(teamRequest.left);
return teamRequest.right;
}
// Subscriptions
@Subscription(() => TeamRequest, {
@@ -233,7 +255,7 @@ export class TeamRequestResolver {
type: () => ID,
})
teamID: string,
): AsyncIterator<TeamRequest> {
) {
return this.pubsub.asyncIterator(`team_req/${teamID}/req_created`);
}
@@ -254,7 +276,7 @@ export class TeamRequestResolver {
type: () => ID,
})
teamID: string,
): AsyncIterator<TeamRequest> {
) {
return this.pubsub.asyncIterator(`team_req/${teamID}/req_updated`);
}
@@ -276,7 +298,51 @@ export class TeamRequestResolver {
type: () => ID,
})
teamID: string,
): AsyncIterator<string> {
) {
return this.pubsub.asyncIterator(`team_req/${teamID}/req_deleted`);
}
@Subscription(() => RequestReorderData, {
description:
'Emitted when a requests position has been changed in its collection',
resolve: (value) => value,
})
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
@RequiresTeamRole(
TeamMemberRole.VIEWER,
TeamMemberRole.EDITOR,
TeamMemberRole.OWNER,
)
requestOrderUpdated(
@Args({
name: 'teamID',
description: 'ID of the team to listen to',
type: () => ID,
})
teamID: string,
) {
return this.pubsub.asyncIterator(`team_req/${teamID}/req_order_updated`);
}
@Subscription(() => TeamRequest, {
description:
'Emitted when a request has been moved from one collection into another',
resolve: (value) => value,
})
@UseGuards(GqlAuthGuard, GqlTeamMemberGuard)
@RequiresTeamRole(
TeamMemberRole.VIEWER,
TeamMemberRole.EDITOR,
TeamMemberRole.OWNER,
)
requestMoved(
@Args({
name: 'teamID',
description: 'ID of the team to listen to',
type: () => ID,
})
teamID: string,
) {
return this.pubsub.asyncIterator(`team_req/${teamID}/req_moved`);
}
}