[WEB-1249] feat: Kanban multi dragndrop (#4479)
* Kanban multi dnd * complete Kanban multi dnd * add proper brackets to if conditions
This commit is contained in:
parent
bab52a2672
commit
1ad7011aac
24 changed files with 565 additions and 333 deletions
|
|
@ -60,6 +60,7 @@ export interface ICycleIssues {
|
|||
) => Promise<void>;
|
||||
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||
addCycleToIssue: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<void>;
|
||||
removeCycleFromIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>
|
||||
transferIssuesFromCycle: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -273,7 +274,13 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
const response = await this.createIssue(workspaceSlug, projectId, data, cycleId);
|
||||
|
||||
if (data.module_ids && data.module_ids.length > 0)
|
||||
await this.rootStore.moduleIssues.addModulesToIssue(workspaceSlug, projectId, response.id, data.module_ids);
|
||||
await this.rootStore.moduleIssues.changeModulesInIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
response.id,
|
||||
data.module_ids,
|
||||
[]
|
||||
);
|
||||
|
||||
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
|
||||
|
||||
|
|
@ -327,6 +334,36 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a cycle from issue
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param issueId
|
||||
* @returns
|
||||
*/
|
||||
removeCycleFromIssue = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
const issueCycleId = this.rootIssueStore.issues.getIssueById(issueId)?.cycle_id;
|
||||
if(!issueCycleId) return;
|
||||
try {
|
||||
// perform optimistic update, update store
|
||||
runInAction(() => {
|
||||
pull(this.issues[issueCycleId], issueId);
|
||||
});
|
||||
this.rootStore.issues.updateIssue(issueId, { cycle_id: null });
|
||||
|
||||
// make API call
|
||||
await this.issueService.removeIssueFromCycle(workspaceSlug, projectId, issueCycleId, issueId);
|
||||
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, issueCycleId);
|
||||
} catch (error) {
|
||||
// revert back changes if fails
|
||||
runInAction(() => {
|
||||
update(this.issues, issueCycleId, (cycleIssueIds = []) => uniq(concat(cycleIssueIds, [issueId])));
|
||||
});
|
||||
this.rootStore.issues.updateIssue(issueId, { cycle_id: issueCycleId });
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
removeIssueFromCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
|
|
|
|||
|
|
@ -197,11 +197,12 @@ export class IssueStore implements IIssueStore {
|
|||
};
|
||||
|
||||
addModulesToIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.addModulesToIssue(
|
||||
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.changeModulesInIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
moduleIds
|
||||
moduleIds,
|
||||
[]
|
||||
);
|
||||
if (moduleIds && moduleIds.length > 0)
|
||||
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
|
|
@ -209,10 +210,11 @@ export class IssueStore implements IIssueStore {
|
|||
};
|
||||
|
||||
removeModulesFromIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.removeModulesFromIssue(
|
||||
const currentModule = await this.rootIssueDetailStore.rootIssueStore.moduleIssues.changeModulesInIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
[],
|
||||
moduleIds
|
||||
);
|
||||
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ export interface IIssueKanBanViewStore {
|
|||
setIsDragging: (isDragging: boolean) => void;
|
||||
}
|
||||
|
||||
const DRAG_ALLOWED_GROUPS: TIssueGroupByOptions[] = ["state", "priority", "assignees", "labels", "module", "cycle"];
|
||||
|
||||
export class IssueKanBanViewStore implements IIssueKanBanViewStore {
|
||||
kanBanToggle: {
|
||||
groupByHeaderMinMax: string[];
|
||||
|
|
@ -53,9 +55,9 @@ export class IssueKanBanViewStore implements IIssueKanBanViewStore {
|
|||
|
||||
getCanUserDragDrop = computedFn(
|
||||
(group_by: TIssueGroupByOptions | undefined, sub_group_by: TIssueGroupByOptions | undefined) => {
|
||||
if (group_by && ["state", "priority"].includes(group_by)) {
|
||||
if (group_by && DRAG_ALLOWED_GROUPS.includes(group_by)) {
|
||||
if (!sub_group_by) return true;
|
||||
if (sub_group_by && ["state", "priority"].includes(sub_group_by)) return true;
|
||||
if (sub_group_by && DRAG_ALLOWED_GROUPS.includes(sub_group_by)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import concat from "lodash/concat";
|
||||
import pull from "lodash/pull";
|
||||
import isEmpty from "lodash/isEmpty";
|
||||
import set from "lodash/set";
|
||||
import uniq from "lodash/uniq";
|
||||
import update from "lodash/update";
|
||||
|
|
@ -63,12 +64,12 @@ export interface IModuleIssues {
|
|||
moduleId: string,
|
||||
issueIds: string[]
|
||||
) => Promise<void>;
|
||||
addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<void>;
|
||||
removeModulesFromIssue: (
|
||||
changeModulesInIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
moduleIds: string[]
|
||||
addModuleIds: string[],
|
||||
removeModuleIds: string[]
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
|
|
@ -104,8 +105,7 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
quickAddIssue: action,
|
||||
addIssuesToModule: action,
|
||||
removeIssuesFromModule: action,
|
||||
addModulesToIssue: action,
|
||||
removeModulesFromIssue: action,
|
||||
changeModulesInIssue: action,
|
||||
});
|
||||
|
||||
this.rootIssueStore = _rootStore;
|
||||
|
|
@ -368,67 +368,78 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
}
|
||||
};
|
||||
|
||||
addModulesToIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||
/**
|
||||
* change modules array in issue
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param issueId
|
||||
* @param addModuleIds array of modules to be added
|
||||
* @param removeModuleIds array of modules to be removed
|
||||
*/
|
||||
changeModulesInIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
addModuleIds: string[],
|
||||
removeModuleIds: string[]
|
||||
) => {
|
||||
// keep a copy of the original module ids
|
||||
const originalModuleIds = this.rootStore.issues.issuesMap[issueId]?.module_ids ?? [];
|
||||
const originalModuleIds = this.rootStore.issues.issuesMap[issueId]?.module_ids
|
||||
? [...this.rootStore.issues.issuesMap[issueId].module_ids!]
|
||||
: [];
|
||||
try {
|
||||
runInAction(() => {
|
||||
// add the new issue ids to the module issues map
|
||||
moduleIds.forEach((moduleId) => {
|
||||
// remove the new issue id to the module issues map
|
||||
removeModuleIds.forEach((moduleId) => {
|
||||
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
||||
if (moduleIssueIds.includes(issueId)) return pull(moduleIssueIds, issueId);
|
||||
else return moduleIssueIds;
|
||||
});
|
||||
});
|
||||
// add the new issue id to the module issues map
|
||||
addModuleIds.forEach((moduleId) => {
|
||||
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
||||
if (moduleIssueIds.includes(issueId)) return moduleIssueIds;
|
||||
else return uniq(concat(moduleIssueIds, [issueId]));
|
||||
});
|
||||
});
|
||||
});
|
||||
if(originalModuleIds){
|
||||
// update the root issue map with the new module ids
|
||||
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) =>
|
||||
uniq(concat(issueModuleIds, moduleIds))
|
||||
);
|
||||
});
|
||||
let currentModuleIds = concat([...originalModuleIds], addModuleIds);
|
||||
currentModuleIds = pull(currentModuleIds, ...removeModuleIds);
|
||||
this.rootStore.issues.updateIssue(issueId, { module_ids: uniq(currentModuleIds) });
|
||||
}
|
||||
|
||||
const issueToModule = await this.moduleService.addModulesToIssue(workspaceSlug, projectId, issueId, {
|
||||
modules: moduleIds,
|
||||
});
|
||||
//Perform API calls
|
||||
if (!isEmpty(addModuleIds)) {
|
||||
await this.moduleService.addModulesToIssue(workspaceSlug, projectId, issueId, {
|
||||
modules: addModuleIds,
|
||||
});
|
||||
}
|
||||
if (!isEmpty(removeModuleIds)) {
|
||||
await this.moduleService.removeModulesFromIssueBulk(workspaceSlug, projectId, issueId, removeModuleIds);
|
||||
}
|
||||
|
||||
return issueToModule;
|
||||
} catch (error) {
|
||||
// revert the issue back to its original module ids
|
||||
set(this.rootStore.issues.issuesMap, [issueId, "module_ids"], originalModuleIds);
|
||||
// remove the new issue ids from the module issues map
|
||||
moduleIds.forEach((moduleId) => {
|
||||
runInAction(() => {
|
||||
update(this.issues, moduleId, (moduleIssueIds = []) => pull(moduleIssueIds, issueId));
|
||||
// add the removed issue id to the module issues map
|
||||
addModuleIds.forEach((moduleId) => {
|
||||
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
||||
if (moduleIssueIds.includes(issueId)) return pull(moduleIssueIds, issueId);
|
||||
else return moduleIssueIds;
|
||||
});
|
||||
});
|
||||
// remove the added issue id to the module issues map
|
||||
removeModuleIds.forEach((moduleId) => {
|
||||
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
||||
if (moduleIssueIds.includes(issueId)) return moduleIssueIds;
|
||||
else return uniq(concat(moduleIssueIds, [issueId]));
|
||||
});
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
removeModulesFromIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
moduleIds.forEach((moduleId) => {
|
||||
update(this.issues, moduleId, (moduleIssueIds = []) => {
|
||||
if (moduleIssueIds.includes(issueId)) return pull(moduleIssueIds, issueId);
|
||||
else return uniq(concat(moduleIssueIds, [issueId]));
|
||||
});
|
||||
update(this.rootStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) =>
|
||||
pull(issueModuleIds, moduleId)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const response = await this.moduleService.removeModulesFromIssueBulk(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
moduleIds
|
||||
);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -243,7 +243,13 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI
|
|||
await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]);
|
||||
|
||||
if (data.module_ids && data.module_ids.length > 0)
|
||||
await this.rootStore.moduleIssues.addModulesToIssue(workspaceSlug, projectId, response.id, data.module_ids);
|
||||
await this.rootStore.moduleIssues.changeModulesInIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
response.id,
|
||||
data.module_ids,
|
||||
[]
|
||||
);
|
||||
|
||||
const quickAddIssueIndex = this.issues[viewId].findIndex((_issueId) => _issueId === data.id);
|
||||
if (quickAddIssueIndex >= 0)
|
||||
|
|
|
|||
|
|
@ -227,7 +227,13 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
await this.rootStore.cycleIssues.addIssueToCycle(workspaceSlug, projectId, data.cycle_id, [response.id]);
|
||||
|
||||
if (data.module_ids && data.module_ids.length > 0)
|
||||
await this.rootStore.moduleIssues.addModulesToIssue(workspaceSlug, projectId, response.id, data.module_ids);
|
||||
await this.rootStore.moduleIssues.changeModulesInIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
response.id,
|
||||
data.module_ids,
|
||||
[]
|
||||
);
|
||||
|
||||
const quickAddIssueIndex = this.issues[projectId].findIndex((_issueId) => _issueId === data.id);
|
||||
if (quickAddIssueIndex >= 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue