diff --git a/plugins/tracker-assets/lang/en.json b/plugins/tracker-assets/lang/en.json
index 04a158789f..3adce6e202 100644
--- a/plugins/tracker-assets/lang/en.json
+++ b/plugins/tracker-assets/lang/en.json
@@ -150,7 +150,14 @@
"CreatedOne": "Created",
"MoveIssues": "Move issues",
- "MoveIssuesDescription": "Select the project you want to move issues to.",
+ "MoveIssuesDescription": "Select the project you want to move issues to",
+ "KeepOriginalAttributes": "Keep original attributes",
+ "KeepOriginalAttributesTooltip": "Original issue statuses and components will be kept in the new project",
+ "SelectReplacement": "The following items are not available in the new project. Select a replacement.",
+ "MissingItem": "MISSING ITEM",
+ "Replacement": "REPLACEMENT",
+ "Original": "ORIGINAL",
+ "OriginalDescription": "Items from this section will be created in the new project",
"Relations": "Relations",
"RemoveRelation": "Remove relation...",
diff --git a/plugins/tracker-assets/lang/ru.json b/plugins/tracker-assets/lang/ru.json
index 652564bfd5..e301c20598 100644
--- a/plugins/tracker-assets/lang/ru.json
+++ b/plugins/tracker-assets/lang/ru.json
@@ -150,7 +150,14 @@
"CreatedOne": "Создана",
"MoveIssues": "Переместить задачи",
- "MoveIssuesDescription": "Выберите проект, в который вы хотите переместить задачи.",
+ "MoveIssuesDescription": "Выберите проект, в который вы хотите переместить задачи",
+ "KeepOriginalAttributes": "Оставить оригинальные аттрибуты",
+ "KeepOriginalAttributesTooltip": "Оригинальные статусы и компоненты будут сохранены в новом проекте",
+ "SelectReplacement": "Следующие элементы не доступны в новом проекте. Выберите замену.",
+ "MissingItem": "ОТСУТСТВУЮЩИЙ ЭЛЕМЕНТ",
+ "Replacement": "ЗАМЕНА",
+ "Original": "ОРИГИНАЛ",
+ "OriginalDescription": "Элементы из этой секции будут созданы в новом проекте",
"Relations": "Зависимости",
"RemoveRelation": "Удалить зависимость...",
diff --git a/plugins/tracker-resources/src/components/ComponentSelector.svelte b/plugins/tracker-resources/src/components/ComponentSelector.svelte
index e5a88d31a8..9b93eea577 100644
--- a/plugins/tracker-resources/src/components/ComponentSelector.svelte
+++ b/plugins/tracker-resources/src/components/ComponentSelector.svelte
@@ -57,7 +57,7 @@
$: handleSelectedComponentIdUpdated(value, rawComponents)
- $: translate(tracker.string.Component, {}).then((result) => (defaultComponentLabel = result))
+ $: translate(tracker.string.NoComponent, {}).then((result) => (defaultComponentLabel = result))
$: componentText = shouldShowLabel ? selectedComponent?.label ?? defaultComponentLabel : undefined
const handleSelectedComponentIdUpdated = async (
diff --git a/plugins/tracker-resources/src/components/issues/Move.svelte b/plugins/tracker-resources/src/components/issues/Move.svelte
index b5d5a347e7..7f942c91be 100644
--- a/plugins/tracker-resources/src/components/issues/Move.svelte
+++ b/plugins/tracker-resources/src/components/issues/Move.svelte
@@ -14,32 +14,44 @@
// limitations under the License.
-->
-
-
-
-
-
-
-
- {#if currentSpace && _class}
-
+ {#if !showManageAttributes}
+
+
+
+
+ dispatch('close')} />
+
+
+
+
+
+
+
+ {#if currentSpace !== undefined}
+
+
+ {
+ if (!isManageAttributesAvailable) {
+ return
+ }
+ showManageAttributes = !showManageAttributes
+ }}
+ >
+ Manage attributes >
+
+ {/if}
+
+
+
+ {#if currentSpace !== undefined && !keepOriginalAttribytes}
+
+
{/if}
-
-
-
-
-
- {#if loading}
-
- {:else if toMove.length > 0 && currentSpace}
- {#each toMove as issue}
- {@const upd = issueToUpdate.get(issue._id) ?? {}}
-
-
- {#if issue.space !== currentSpace._id}
- {#key upd.status}
-
- {/key}
- {#key upd.component}
-
- {/key}
- {#if upd.attachedTo === tracker.ids.NoParent && issue.attachedTo !== tracker.ids.NoParent}
-
-
+ {:else}
+
+
+ (showManageAttributes = !showManageAttributes)}
+ >
+
+
+ dispatch('close')} />
+
+
+
+
+ {#if loading}
+
+ {:else if toMove.length > 0 && currentSpace}
+ {#each toMove as issue}
+ {@const upd = issueToUpdate.get(issue._id) ?? {}}
+ {@const originalComponent = components.find((it) => it._id === issue.component)}
+ {@const targetComponent = components.find(
+ (it) => it.space === currentSpace?._id && it.label === originalComponent?.label
+ )}
+ {#key keepOriginalAttribytes}
+ {#if issue.space !== currentSpace._id && (upd.status !== undefined || upd.component !== undefined)}
+
+
+
+ {#key upd.status}
+
+ {/key}
+ {#if targetComponent === undefined}
+ {#key upd.component}
+
+ {/key}
+ {/if}
+
{/if}
- {/if}
-
- {/each}
- {/if}
-
-
- {#if currentSpace !== undefined}
-
-
+ {/key}
+ {/each}
+ {/if}
+
{/if}
-
@@ -195,45 +389,47 @@
.container {
display: flex;
flex-direction: column;
- padding: 2rem 1.75rem 1.75rem;
- width: 55rem;
+ padding: 1.25rem 1.5rem 1rem;
+ width: 480px;
max-width: 40rem;
background: var(--popup-bg-color);
- border-radius: 1.25rem;
+ border-radius: 8px;
user-select: none;
- box-shadow: var(--popup-shadow);
- .spaceSelect {
- padding: 0.75rem;
- background-color: var(--body-color);
- border: 1px solid var(--popup-divider);
- border-radius: 0.75rem;
+ .aligned-text {
+ display: flex;
+ justify-content: center;
+ align-items: center;
}
- .footer {
+ .space-between {
+ display: flex;
+ justify-content: space-between;
+ }
+
+ .buttons {
flex-shrink: 0;
display: grid;
grid-auto-flow: column;
direction: rtl;
justify-content: start;
align-items: center;
- margin-top: 1rem;
column-gap: 0.5rem;
}
.issues-move {
- height: 30rem;
overflow: auto;
}
.issue-move {
- border: 1px solid var(--popup-divider);
- }
-
- .status-option {
- border: 1px solid var(--popup-divider);
+ border-bottom: 1px solid var(--popup-divider);
}
}
- .unset-parent {
- background-color: var(--accent-bg-color);
+ .divider {
+ border-bottom: 1px solid var(--theme-divider-color);
+ }
+
+ .disabled {
+ cursor: not-allowed;
+ color: var(--dark-color);
}
diff --git a/plugins/tracker-resources/src/components/issues/move/ComponentMove.svelte b/plugins/tracker-resources/src/components/issues/move/ComponentMove.svelte
deleted file mode 100644
index 22192a4a74..0000000000
--- a/plugins/tracker-resources/src/components/issues/move/ComponentMove.svelte
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-{#if missingComponents.length > 0}
-
-
-
-
- {#each missingComponents as comp}
-
-
-
createMissingComponent(comp)} />
-
- {/each}
-
-{/if}
diff --git a/plugins/tracker-resources/src/components/issues/move/ComponentMovePresenter.svelte b/plugins/tracker-resources/src/components/issues/move/ComponentMovePresenter.svelte
index ccfd088df6..852b70248c 100644
--- a/plugins/tracker-resources/src/components/issues/move/ComponentMovePresenter.svelte
+++ b/plugins/tracker-resources/src/components/issues/move/ComponentMovePresenter.svelte
@@ -13,57 +13,72 @@
// limitations under the License.
-->
-{#if currentComponent !== undefined}
-
-
-
+{#if current !== undefined}
+
+
+
-
-
-
=>
-
- {#if targetComponent === undefined}
-
- {/if}
-
->
+
+ {
+ showPopup(
+ ComponentReplacementPopup,
+ {
+ components: components.filter((it) => it.space === targetProject._id),
+ original: current,
+ selected: replace
+ },
+ eventToHTMLElement(event),
+ (value) => {
+ if (value) {
+ const createComponent = typeof value === 'object'
+ const c = createComponent ? value.create : value
+ issueToUpdate.set(issue._id, {
+ ...issueToUpdate.get(issue._id),
+ component: c,
+ useComponent: true,
+ createComponent
+ })
+ }
+ }
+ )
}}
- on:change={(evt) => issueToUpdate.set(issue._id, { ...issueToUpdate.get(issue._id), status: evt.detail })}
- />
+ >
+
+
+
+
{/if}
diff --git a/plugins/tracker-resources/src/components/issues/move/ComponentReplacementPopup.svelte b/plugins/tracker-resources/src/components/issues/move/ComponentReplacementPopup.svelte
new file mode 100644
index 0000000000..d3b291b39d
--- /dev/null
+++ b/plugins/tracker-resources/src/components/issues/move/ComponentReplacementPopup.svelte
@@ -0,0 +1,101 @@
+
+
+
+{#if components !== undefined}
+
+{/if}
+
+
diff --git a/plugins/tracker-resources/src/components/issues/move/SelectReplacement.svelte b/plugins/tracker-resources/src/components/issues/move/SelectReplacement.svelte
new file mode 100644
index 0000000000..2f6bf3db62
--- /dev/null
+++ b/plugins/tracker-resources/src/components/issues/move/SelectReplacement.svelte
@@ -0,0 +1,191 @@
+
+
+
+{#if issues[0]?.space !== targetProject._id && (Object.keys(statusToUpdate).length > 0 || missingComponents.length > 0)}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {#each Object.keys(statusToUpdate) as status}
+ {@const newStatus = statusToUpdate[status]}
+
+
+
+
+
->
+
+ {
+ showPopup(
+ StatusReplacementPopup,
+ {
+ statuses,
+ original: $statusStore.get(getStatusRef(status)),
+ selected: getStatusRef(newStatus.ref)
+ },
+ eventToHTMLElement(event),
+ (value) => {
+ if (value) {
+ const createStatus = typeof value === 'object'
+ const s = createStatus ? value.create : value
+ statusToUpdate = { ...statusToUpdate, [status]: { ref: s, create: createStatus } }
+ }
+ }
+ )
+ }}
+ >
+
+
+
+
+
+
+ {/each}
+
+
+ {#each missingComponents as component}
+ {@const componentRef = componentToUpdate[component._id]?.ref}
+
+
+
+
+
->
+
+ {
+ showPopup(
+ ComponentReplacementPopup,
+ {
+ components: components.filter((it) => it.space === targetProject._id),
+ original: component,
+ selected: componentRef
+ },
+ eventToHTMLElement(event),
+ (value) => {
+ if (value !== undefined) {
+ const createComponent = typeof value === 'object'
+ const c = createComponent ? value.create : value
+ statusToUpdate = { ...statusToUpdate, [component._id]: { ref: c, create: createComponent } }
+ }
+ }
+ )
+ }}
+ >
+
+
+
+
+
+
+ {/each}
+
+
+
+{/if}
+
+
diff --git a/plugins/tracker-resources/src/components/issues/move/StatusMove.svelte b/plugins/tracker-resources/src/components/issues/move/StatusMove.svelte
deleted file mode 100644
index 48d1712e17..0000000000
--- a/plugins/tracker-resources/src/components/issues/move/StatusMove.svelte
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-{#if missingStatuses.length > 0}
-
-
-
-
- {#each missingStatuses as st}
-
-
-
createMissingStatus(st)} />
-
- {/each}
-
-{/if}
diff --git a/plugins/tracker-resources/src/components/issues/move/StatusMovePresenter.svelte b/plugins/tracker-resources/src/components/issues/move/StatusMovePresenter.svelte
index 4e272d33a1..239355c5d0 100644
--- a/plugins/tracker-resources/src/components/issues/move/StatusMovePresenter.svelte
+++ b/plugins/tracker-resources/src/components/issues/move/StatusMovePresenter.svelte
@@ -13,51 +13,67 @@
// limitations under the License.
-->
-
-
+
+
-
-
-
=>
-
- {#if targetStatus === undefined}
-
-
- =>
-
- {/if}
-
->
+
+ {
+ showPopup(
+ StatusReplacementPopup,
+ { statuses, original, selected: replace },
+ eventToHTMLElement(event),
+ (value) => {
+ if (value) {
+ const createStatus = typeof value === 'object'
+ const s = createStatus ? value.create : value
+ issueToUpdate.set(issue._id, {
+ ...issueToUpdate.get(issue._id),
+ status: s,
+ useStatus: true,
+ createStatus
+ })
+ }
+ }
+ )
}}
- on:change={(evt) => issueToUpdate.set(issue._id, { ...issueToUpdate.get(issue._id), status: evt.detail })}
- />
+ >
+
+
+
+
diff --git a/plugins/tracker-resources/src/components/issues/move/StatusReplacementPopup.svelte b/plugins/tracker-resources/src/components/issues/move/StatusReplacementPopup.svelte
new file mode 100644
index 0000000000..4d2a27a4f1
--- /dev/null
+++ b/plugins/tracker-resources/src/components/issues/move/StatusReplacementPopup.svelte
@@ -0,0 +1,109 @@
+
+
+
+{#if statuses !== undefined}
+
+{/if}
+
+
diff --git a/plugins/tracker-resources/src/plugin.ts b/plugins/tracker-resources/src/plugin.ts
index 2f9f9d0906..791b593ec6 100644
--- a/plugins/tracker-resources/src/plugin.ts
+++ b/plugins/tracker-resources/src/plugin.ts
@@ -180,6 +180,13 @@ export default mergeIds(trackerId, tracker, {
Duplicate: '' as IntlString,
MoveIssues: '' as IntlString,
MoveIssuesDescription: '' as IntlString,
+ KeepOriginalAttributes: '' as IntlString,
+ KeepOriginalAttributesTooltip: '' as IntlString,
+ SelectReplacement: '' as IntlString,
+ MissingItem: '' as IntlString,
+ Replacement: '' as IntlString,
+ Original: '' as IntlString,
+ OriginalDescription: '' 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 1e08f4642c..83086d3840 100644
--- a/plugins/tracker-resources/src/utils.ts
+++ b/plugins/tracker-resources/src/utils.ts
@@ -40,11 +40,13 @@ import { Asset, IntlString } from '@hcengineering/platform'
import { createQuery } from '@hcengineering/presentation'
import { calcRank } from '@hcengineering/task'
import {
+ Component,
Issue,
IssuePriority,
IssuesDateModificationPeriod,
IssuesGrouping,
IssuesOrdering,
+ IssueStatus,
Milestone,
MilestoneStatus,
Project,
@@ -653,3 +655,21 @@ export async function getVisibleFilters (filters: KeyFilter[], space?: Ref
f.key !== 'space')
}
+
+interface ManualUpdates {
+ useStatus: boolean
+ useComponent: boolean
+ createStatus: boolean
+ createComponent: boolean
+}
+export type IssueToUpdate = DocumentUpdate & Partial
+
+export interface StatusToUpdate {
+ ref: Ref
+ create?: boolean
+}
+
+export interface ComponentToUpdate {
+ ref: Ref
+ create?: boolean
+}