Skip to content
This repository has been archived by the owner on Nov 21, 2020. It is now read-only.

Commit

Permalink
fix(deal/ticket/task): move card labels bug
Browse files Browse the repository at this point in the history
close #676
  • Loading branch information
Buyantogtokh authored and batamar committed Dec 16, 2019
1 parent fdef0db commit 35136a1
Show file tree
Hide file tree
Showing 9 changed files with 183 additions and 19 deletions.
17 changes: 14 additions & 3 deletions src/__tests__/dealMutations.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { graphqlRequest } from '../db/connection';
import { boardFactory, dealFactory, pipelineFactory, stageFactory, userFactory } from '../db/factories';
import { Boards, Deals, Pipelines, Stages } from '../db/models';
import {
boardFactory,
dealFactory,
pipelineFactory,
pipelineLabelFactory,
stageFactory,
userFactory,
} from '../db/factories';
import { Boards, Deals, PipelineLabels, Pipelines, Stages } from '../db/models';
import { IBoardDocument, IPipelineDocument, IStageDocument } from '../db/models/definitions/boards';
import { BOARD_TYPES } from '../db/models/definitions/constants';
import { IDealDocument } from '../db/models/definitions/deals';
import { IPipelineLabelDocument } from '../db/models/definitions/pipelineLabels';

import './setup.ts';

Expand All @@ -12,6 +20,7 @@ describe('Test deals mutations', () => {
let pipeline: IPipelineDocument;
let stage: IStageDocument;
let deal: IDealDocument;
let label: IPipelineLabelDocument;

const commonDealParamDefs = `
$name: String!,
Expand All @@ -32,7 +41,8 @@ describe('Test deals mutations', () => {
board = await boardFactory({ type: BOARD_TYPES.DEAL });
pipeline = await pipelineFactory({ boardId: board._id, watchedUserIds: [user._id] });
stage = await stageFactory({ pipelineId: pipeline._id });
deal = await dealFactory({ stageId: stage._id });
label = await pipelineLabelFactory({ pipelineId: pipeline._id });
deal = await dealFactory({ stageId: stage._id, labelIds: [label._id] });
});

afterEach(async () => {
Expand All @@ -41,6 +51,7 @@ describe('Test deals mutations', () => {
await Pipelines.deleteMany({});
await Stages.deleteMany({});
await Deals.deleteMany({});
await PipelineLabels.deleteMany({});
});

test('Create deal', async () => {
Expand Down
72 changes: 68 additions & 4 deletions src/__tests__/taskMutations.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { graphqlRequest } from '../db/connection';
import { boardFactory, pipelineFactory, stageFactory, taskFactory, userFactory } from '../db/factories';
import { Boards, Pipelines, Stages, Tasks } from '../db/models';
import {
boardFactory,
pipelineFactory,
pipelineLabelFactory,
stageFactory,
taskFactory,
userFactory,
} from '../db/factories';
import { Boards, PipelineLabels, Pipelines, Stages, Tasks } from '../db/models';
import { IBoardDocument, IPipelineDocument, IStageDocument } from '../db/models/definitions/boards';
import { BOARD_TYPES } from '../db/models/definitions/constants';
import { IPipelineLabelDocument } from '../db/models/definitions/pipelineLabels';
import { ITaskDocument } from '../db/models/definitions/tasks';

import './setup.ts';
Expand All @@ -12,6 +20,8 @@ describe('Test tasks mutations', () => {
let pipeline: IPipelineDocument;
let stage: IStageDocument;
let task: ITaskDocument;
let label: IPipelineLabelDocument;
let label2: IPipelineLabelDocument;

const commonTaskParamDefs = `
$name: String!,
Expand All @@ -30,7 +40,9 @@ describe('Test tasks mutations', () => {
board = await boardFactory({ type: BOARD_TYPES.TASK });
pipeline = await pipelineFactory({ boardId: board._id });
stage = await stageFactory({ pipelineId: pipeline._id });
task = await taskFactory({ stageId: stage._id });
label = await pipelineLabelFactory({ pipelineId: pipeline._id });
label2 = await pipelineLabelFactory({ pipelineId: pipeline._id, name: 'new label' });
task = await taskFactory({ stageId: stage._id, labelIds: [label._id, label2._id] });
});

afterEach(async () => {
Expand All @@ -39,6 +51,7 @@ describe('Test tasks mutations', () => {
await Pipelines.deleteMany({});
await Stages.deleteMany({});
await Tasks.deleteMany({});
await PipelineLabels.deleteMany({});
});

test('Create task', async () => {
Expand Down Expand Up @@ -75,6 +88,8 @@ describe('Test tasks mutations', () => {
_id
name
stageId
labelIds
assignedUserIds
}
}
`;
Expand All @@ -88,7 +103,56 @@ describe('Test tasks mutations', () => {

updatedTask = await graphqlRequest(mutation, 'tasksEdit', args);

expect(updatedTask.stageId).toEqual(stage._id);
expect(updatedTask.assignedUserIds.length).toBe(1);
});

test('Move task between pipelines', async () => {
expect.assertions(3);

const pipeline2 = await pipelineFactory();
const stage2 = await stageFactory({ pipelineId: pipeline2._id });

await pipelineLabelFactory({
pipelineId: pipeline2._id,
name: label.name,
colorCode: label.colorCode,
});

const args: any = {
_id: task._id,
name: 'Edited task',
stageId: stage2._id,
};

const mutation = `
mutation tasksEdit($_id: String!, ${commonTaskParamDefs}) {
tasksEdit(_id: $_id, ${commonTaskParams}) {
_id
name
stageId
labelIds
}
}
`;

let updatedTask = await graphqlRequest(mutation, 'tasksEdit', args);

expect(updatedTask.stageId).toBe(stage2._id);

if (task.labelIds) {
const copiedLabels = await PipelineLabels.find({ pipelineId: pipeline2._id });

expect(copiedLabels.length).toBe(2);
}

try {
// to improve boardUtils coverage
args.stageId = 'demo-stage';

updatedTask = await graphqlRequest(mutation, 'tasksEdit', args);
} catch (e) {
expect(e[0].message).toBe('Stage not found');
}
});

test('Change task', async () => {
Expand Down
17 changes: 14 additions & 3 deletions src/__tests__/ticketMutations.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { graphqlRequest } from '../db/connection';
import { boardFactory, pipelineFactory, stageFactory, ticketFactory, userFactory } from '../db/factories';
import { Boards, Pipelines, Stages, Tickets } from '../db/models';
import {
boardFactory,
pipelineFactory,
pipelineLabelFactory,
stageFactory,
ticketFactory,
userFactory,
} from '../db/factories';
import { Boards, PipelineLabels, Pipelines, Stages, Tickets } from '../db/models';
import { IBoardDocument, IPipelineDocument, IStageDocument } from '../db/models/definitions/boards';
import { BOARD_TYPES } from '../db/models/definitions/constants';
import { IPipelineLabelDocument } from '../db/models/definitions/pipelineLabels';
import { ITicketDocument } from '../db/models/definitions/tickets';

import './setup.ts';
Expand All @@ -12,6 +20,7 @@ describe('Test tickets mutations', () => {
let pipeline: IPipelineDocument;
let stage: IStageDocument;
let ticket: ITicketDocument;
let label: IPipelineLabelDocument;
let context;

const commonTicketParamDefs = `
Expand All @@ -31,7 +40,8 @@ describe('Test tickets mutations', () => {
board = await boardFactory({ type: BOARD_TYPES.TICKET });
pipeline = await pipelineFactory({ boardId: board._id });
stage = await stageFactory({ pipelineId: pipeline._id });
ticket = await ticketFactory({ stageId: stage._id });
label = await pipelineLabelFactory({ pipelineId: pipeline._id });
ticket = await ticketFactory({ stageId: stage._id, labelIds: [label._id] });
context = { user: await userFactory({}) };
});

Expand All @@ -41,6 +51,7 @@ describe('Test tickets mutations', () => {
await Pipelines.deleteMany({});
await Stages.deleteMany({});
await Tickets.deleteMany({});
await PipelineLabels.deleteMany({});
});

test('Create ticket', async () => {
Expand Down
55 changes: 54 additions & 1 deletion src/data/resolvers/boardUtils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ActivityLogs, Boards, Conformities, Pipelines, Stages } from '../../db/models';
import { ActivityLogs, Boards, Conformities, PipelineLabels, Pipelines, Stages } from '../../db/models';
import { NOTIFICATION_TYPES } from '../../db/models/definitions/constants';
import { IDealDocument } from '../../db/models/definitions/deals';
import { ITaskDocument } from '../../db/models/definitions/tasks';
import { ITicketDocument } from '../../db/models/definitions/tickets';
import { IUserDocument } from '../../db/models/definitions/users';
import { can } from '../permissions/utils';
import { checkLogin } from '../permissions/wrappers';
Expand Down Expand Up @@ -235,3 +237,54 @@ export const createConformity = async ({
});
}
};

interface ILabelParams {
item: IDealDocument | ITaskDocument | ITicketDocument;
doc: any;
user: IUserDocument;
}

/**
* Copies pipeline labels alongside deal/task/tickets when they are moved between different pipelines.
*/
export const copyPipelineLabels = async (params: ILabelParams) => {
const { item, doc, user } = params;

const oldStage = await Stages.findOne({ _id: item.stageId });
const newStage = await Stages.findOne({ _id: doc.stageId });

if (!(oldStage && newStage)) {
throw new Error('Stage not found');
}

if (oldStage.pipelineId === newStage.pipelineId) {
return;
}

const oldLabels = await PipelineLabels.find({ _id: { $in: item.labelIds } });
const updatedLabelIds: string[] = [];

for (const label of oldLabels) {
const filter = {
name: label.name,
colorCode: label.colorCode,
pipelineId: newStage.pipelineId,
};

const exists = await PipelineLabels.findOne(filter);

if (!exists) {
const newLabel = await PipelineLabels.createPipelineLabel({
...filter,
createdAt: new Date(),
createdBy: user._id,
});

updatedLabelIds.push(newLabel._id);
} else {
updatedLabelIds.push(exists._id);
}
} // end label loop

await PipelineLabels.labelsLabel(newStage.pipelineId, item._id, updatedLabelIds);
};
12 changes: 10 additions & 2 deletions src/data/resolvers/mutations/deals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { IDeal } from '../../../db/models/definitions/deals';
import { checkPermission } from '../../permissions/wrappers';
import { IContext } from '../../types';
import { checkUserIds, putCreateLog, putDeleteLog, putUpdateLog } from '../../utils';
import { createConformity, IBoardNotificationParams, itemsChange, sendNotifications } from '../boardUtils';
import {
copyPipelineLabels,
createConformity,
IBoardNotificationParams,
itemsChange,
sendNotifications,
} from '../boardUtils';

interface IDealsEdit extends IDeal {
_id: string;
Expand Down Expand Up @@ -66,6 +72,8 @@ const dealMutations = {
modifiedBy: user._id,
});

await copyPipelineLabels({ item: oldDeal, doc, user });

const notificationDoc: IBoardNotificationParams = {
item: updatedDeal,
user,
Expand All @@ -76,7 +84,7 @@ const dealMutations = {
};

if (doc.assignedUserIds) {
const { addedUserIds, removedUserIds } = checkUserIds(oldDeal.assignedUserIds || [], doc.assignedUserIds);
const { addedUserIds, removedUserIds } = checkUserIds(oldDeal.assignedUserIds, doc.assignedUserIds);

notificationDoc.invitedUsers = addedUserIds;
notificationDoc.removedUsers = removedUserIds;
Expand Down
13 changes: 11 additions & 2 deletions src/data/resolvers/mutations/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@ import { NOTIFICATION_TYPES } from '../../../db/models/definitions/constants';
import { checkPermission } from '../../permissions/wrappers';
import { IContext } from '../../types';
import { checkUserIds, putCreateLog } from '../../utils';
import { createConformity, IBoardNotificationParams, itemsChange, sendNotifications } from '../boardUtils';
import {
copyPipelineLabels,
createConformity,
IBoardNotificationParams,
itemsChange,
sendNotifications,
} from '../boardUtils';

interface ITasksEdit extends ITask {
_id: string;
Expand Down Expand Up @@ -64,6 +70,9 @@ const taskMutations = {
modifiedBy: user._id,
});

// labels should be copied to newly moved pipeline
await copyPipelineLabels({ item: oldTask, doc, user });

const notificationDoc: IBoardNotificationParams = {
item: updatedTask,
user,
Expand All @@ -72,7 +81,7 @@ const taskMutations = {
};

if (doc.assignedUserIds) {
const { addedUserIds, removedUserIds } = checkUserIds(oldTask.assignedUserIds || [], doc.assignedUserIds);
const { addedUserIds, removedUserIds } = checkUserIds(oldTask.assignedUserIds, doc.assignedUserIds);

notificationDoc.invitedUsers = addedUserIds;
notificationDoc.removedUsers = removedUserIds;
Expand Down
12 changes: 10 additions & 2 deletions src/data/resolvers/mutations/tickets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@ import { ITicket } from '../../../db/models/definitions/tickets';
import { checkPermission } from '../../permissions/wrappers';
import { IContext } from '../../types';
import { checkUserIds, putCreateLog } from '../../utils';
import { createConformity, IBoardNotificationParams, itemsChange, sendNotifications } from '../boardUtils';
import {
copyPipelineLabels,
createConformity,
IBoardNotificationParams,
itemsChange,
sendNotifications,
} from '../boardUtils';

interface ITicketsEdit extends ITicket {
_id: string;
Expand Down Expand Up @@ -65,6 +71,8 @@ const ticketMutations = {
modifiedBy: user._id,
});

await copyPipelineLabels({ item: oldTicket, doc, user });

const notificationDoc: IBoardNotificationParams = {
item: updatedTicket,
user,
Expand All @@ -73,7 +81,7 @@ const ticketMutations = {
};

if (doc.assignedUserIds) {
const { addedUserIds, removedUserIds } = checkUserIds(oldTicket.assignedUserIds || [], doc.assignedUserIds);
const { addedUserIds, removedUserIds } = checkUserIds(oldTicket.assignedUserIds, doc.assignedUserIds);

notificationDoc.invitedUsers = addedUserIds;
notificationDoc.removedUsers = removedUserIds;
Expand Down
2 changes: 1 addition & 1 deletion src/data/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,7 @@ export const regexSearchText = (searchValue: string) => {
/**
* Check user ids whether its added or removed from array of ids
*/
export const checkUserIds = (oldUserIds: string[], newUserIds: string[]) => {
export const checkUserIds = (oldUserIds: string[] = [], newUserIds: string[]) => {
const removedUserIds = oldUserIds.filter(e => !newUserIds.includes(e));

const addedUserIds = newUserIds.filter(e => !oldUserIds.includes(e));
Expand Down
2 changes: 1 addition & 1 deletion src/db/models/definitions/pipelineLabels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface IPipelineLabel {
colorCode: string;
pipelineId: string;
createdBy?: string;
createdDate?: Date;
createdAt?: Date;
}

export interface IPipelineLabelDocument extends IPipelineLabel, Document {
Expand Down

0 comments on commit 35136a1

Please sign in to comment.