From eb8bd6634c1d0bbc483fe6de5846a5337b795757 Mon Sep 17 00:00:00 2001 From: Vyacheslav Tumanov Date: Wed, 29 Mar 2023 18:04:28 +0500 Subject: [PATCH] TSK-960: move for issues (#2846) * TSK-960: move for issues Signed-off-by: Vyacheslav Tumanov * TSK-960: remove validation and fix labels Signed-off-by: Vyacheslav Tumanov * TSK-960: apply changes in one transaction and get rid of text constant Signed-off-by: Vyacheslav Tumanov --------- Signed-off-by: Vyacheslav Tumanov --- models/tracker/src/index.ts | 2 +- models/tracker/src/plugin.ts | 1 + plugins/tracker-assets/lang/en.json | 2 + plugins/tracker-assets/lang/ru.json | 2 + .../src/components/issues/Move.svelte | 121 ++++++++++++++++++ plugins/tracker-resources/src/index.ts | 6 + plugins/tracker-resources/src/plugin.ts | 2 + plugins/tracker-resources/src/utils.ts | 77 +++++++++++ plugins/view-assets/lang/ru.json | 2 +- plugins/view-resources/src/plugin.ts | 3 - plugins/view/src/index.ts | 3 + 11 files changed, 216 insertions(+), 5 deletions(-) create mode 100644 plugins/tracker-resources/src/components/issues/Move.svelte diff --git a/models/tracker/src/index.ts b/models/tracker/src/index.ts index 9a641421f6..efe801682c 100644 --- a/models/tracker/src/index.ts +++ b/models/tracker/src/index.ts @@ -1598,7 +1598,7 @@ export function createModel (builder: Builder): void { createAction( builder, { - action: view.actionImpl.Move, + action: tracker.actionImpl.Move, label: tracker.string.MoveToProject, icon: view.icon.Move, keyBinding: [], diff --git a/models/tracker/src/plugin.ts b/models/tracker/src/plugin.ts index f1ca65f082..22ca7df6e2 100644 --- a/models/tracker/src/plugin.ts +++ b/models/tracker/src/plugin.ts @@ -58,6 +58,7 @@ export default mergeIds(trackerId, tracker, { IssueCategory: '' as Ref }, actionImpl: { + Move: '' as ViewAction, CopyToClipboard: '' as ViewAction, EditWorkflowStatuses: '' as ViewAction, EditProject: '' as ViewAction, diff --git a/plugins/tracker-assets/lang/en.json b/plugins/tracker-assets/lang/en.json index d126811ff5..dfb8b88acb 100644 --- a/plugins/tracker-assets/lang/en.json +++ b/plugins/tracker-assets/lang/en.json @@ -157,6 +157,8 @@ "Assigned": "Assigned", "Created": "Created", "Subscribed": "Subscribed", + "MoveIssues": "Move issues", + "MoveIssuesDescription": "Select the project you want to move issues to.", "Relations": "Relations", "RemoveRelation": "Remove relation...", diff --git a/plugins/tracker-assets/lang/ru.json b/plugins/tracker-assets/lang/ru.json index b312fbfdef..814574ab8a 100644 --- a/plugins/tracker-assets/lang/ru.json +++ b/plugins/tracker-assets/lang/ru.json @@ -157,6 +157,8 @@ "Assigned": "Назначенные", "Created": "{value, plural, =1 {Создана} other {Созданные}}", "Subscribed": "Отслеживаемые", + "MoveIssues": "Переместить задачи", + "MoveIssuesDescription": "Выберите проект, в который вы хотите переместить задачи.", "Relations": "Зависимости", "RemoveRelation": "Удалить зависимость...", diff --git a/plugins/tracker-resources/src/components/issues/Move.svelte b/plugins/tracker-resources/src/components/issues/Move.svelte new file mode 100644 index 0000000000..988745d575 --- /dev/null +++ b/plugins/tracker-resources/src/components/issues/Move.svelte @@ -0,0 +1,121 @@ + + + +
+
+
+
+
+
+ {#await getSpace() then} + {#if currentSpace && _class} + + {/if} + {/await} +
+ +
+ + diff --git a/plugins/tracker-resources/src/index.ts b/plugins/tracker-resources/src/index.ts index 2cfc8eafc6..5684e2b810 100644 --- a/plugins/tracker-resources/src/index.ts +++ b/plugins/tracker-resources/src/index.ts @@ -132,6 +132,7 @@ import IssueStatistics from './components/sprints/IssueStatistics.svelte' import SprintRefPresenter from './components/sprints/SprintRefPresenter.svelte' import CreateProject from './components/projects/CreateProject.svelte' import ProjectPresenter from './components/projects/ProjectPresenter.svelte' +import MoveIssues from './components/issues/Move.svelte' export { default as SubIssueList } from './components/issues/edit/SubIssueList.svelte' @@ -190,6 +191,10 @@ export async function queryIssue ( })) } +async function move (issues: Issue | Issue[]): Promise { + showPopup(MoveIssues, { selected: issues }) +} + async function editWorkflowStatuses (project: Project | undefined): Promise { if (project !== undefined) { showPopup(Statuses, { projectId: project._id, projectClass: project._class }, 'float') @@ -436,6 +441,7 @@ export default async (): Promise => ({ GetAllSprints: getAllSprints }, actionImpl: { + Move: move, EditWorkflowStatuses: editWorkflowStatuses, EditProject: editProject, DeleteSprint: deleteSprint, diff --git a/plugins/tracker-resources/src/plugin.ts b/plugins/tracker-resources/src/plugin.ts index c6bb76c31a..5c9f6cbc28 100644 --- a/plugins/tracker-resources/src/plugin.ts +++ b/plugins/tracker-resources/src/plugin.ts @@ -170,6 +170,8 @@ export default mergeIds(trackerId, tracker, { NumberLabels: '' as IntlString, MoveToProject: '' as IntlString, Duplicate: '' as IntlString, + MoveIssues: '' as IntlString, + MoveIssuesDescription: '' as IntlString, TypeIssuePriority: '' as IntlString, IssueTitlePlaceholder: '' as IntlString, diff --git a/plugins/tracker-resources/src/utils.ts b/plugins/tracker-resources/src/utils.ts index adebb9c964..cf6a7a4146 100644 --- a/plugins/tracker-resources/src/utils.ts +++ b/plugins/tracker-resources/src/utils.ts @@ -15,9 +15,13 @@ import { Employee, getName } from '@hcengineering/contact' import core, { + ApplyOperations, + AttachedDoc, Class, + Collection, Doc, DocumentQuery, + DocumentUpdate, IdMap, Ref, SortingOrder, @@ -58,6 +62,7 @@ import { CategoryQuery, ListSelectionProvider, SelectDirection } from '@hcengine import { writable } from 'svelte/store' import tracker from './plugin' import { defaultComponentStatuses, defaultPriorities, defaultSprintStatuses, issuePriorities } from './types' +import { calcRank } from '@hcengineering/task' export * from './types' @@ -685,6 +690,78 @@ export interface StatusStore { byId: IdMap> version: number } + +async function updateIssuesOnMove ( + client: TxOperations, + applyOps: ApplyOperations, + doc: Doc, + space: Ref, + extra?: DocumentUpdate +): Promise { + const hierarchy = client.getHierarchy() + const attributes = hierarchy.getAllAttributes(doc._class) + for (const attribute of attributes.values()) { + if (hierarchy.isDerived(attribute.type._class, core.class.Collection)) { + const collection = attribute.type as Collection + const allAttached = await client.findAll(collection.of, { attachedTo: doc._id }) + for (const attached of allAttached) { + // Do not use extra for childs. + if (hierarchy.isDerived(collection.of, tracker.class.Issue)) { + const lastOne = await client.findOne(tracker.class.Issue, {}, { sort: { rank: SortingOrder.Descending } }) + const incResult = await client.updateDoc( + tracker.class.Project, + core.space.Space, + space, + { + $inc: { sequence: 1 } + }, + true + ) + await updateIssuesOnMove(client, applyOps, attached, space, { + ...extra, + rank: calcRank(lastOne, undefined), + number: (incResult as any).object.sequence + }) + } else await updateIssuesOnMove(client, applyOps, attached, space) + } + } + } + await applyOps.update(doc, { + space, + ...extra + }) +} + +/** + * @public + */ +export async function moveIssueToSpace ( + client: TxOperations, + docs: Doc[], + space: Ref, + extra?: DocumentUpdate +): Promise { + const applyOps = client.apply(docs[0]._id) + for (const doc of docs) { + const lastOne = await client.findOne(tracker.class.Issue, {}, { sort: { rank: SortingOrder.Descending } }) + const incResult = await client.updateDoc( + tracker.class.Project, + core.space.Space, + space, + { + $inc: { sequence: 1 } + }, + true + ) + await updateIssuesOnMove(client, applyOps, doc, space, { + ...extra, + rank: calcRank(lastOne, undefined), + number: (incResult as any).object.sequence + }) + } + await applyOps.commit() +} + // Issue status live query export const statusStore = writable({ statuses: [], byId: new Map(), version: 0 }) diff --git a/plugins/view-assets/lang/ru.json b/plugins/view-assets/lang/ru.json index 09b942e3c9..d7eb92d4a4 100644 --- a/plugins/view-assets/lang/ru.json +++ b/plugins/view-assets/lang/ru.json @@ -1,7 +1,7 @@ { "string": { "MoveClass": "Переместить {class}", - "SelectToMove": "Выберите {classLabel} который вы хотите переместить в {class}.", + "SelectToMove": "Выберите {classLabel}, в который вы хотите переместить {class}.", "Delete": "Удалить", "Move": "Переместить", "Cancel": "Отменть", diff --git a/plugins/view-resources/src/plugin.ts b/plugins/view-resources/src/plugin.ts index 791dded97a..2bd37a7e46 100644 --- a/plugins/view-resources/src/plugin.ts +++ b/plugins/view-resources/src/plugin.ts @@ -28,9 +28,6 @@ export default mergeIds(viewId, view, { ProxyPresenter: '' as AnyComponent }, string: { - MoveClass: '' as IntlString, - SelectToMove: '' as IntlString, - Cancel: '' as IntlString, LabelYes: '' as IntlString, LabelNo: '' as IntlString, ChooseAColor: '' as IntlString, diff --git a/plugins/view/src/index.ts b/plugins/view/src/index.ts index 7853eef54e..0cccc193c9 100644 --- a/plugins/view/src/index.ts +++ b/plugins/view/src/index.ts @@ -654,6 +654,9 @@ const view = plugin(viewId, { NewFilteredView: '' as IntlString, FilteredViewName: '' as IntlString, Move: '' as IntlString, + MoveClass: '' as IntlString, + SelectToMove: '' as IntlString, + Cancel: '' as IntlString, List: '' as IntlString, Timeline: '' as IntlString },