mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-09 09:20:54 +00:00
TSK-1032: add confirmation dialog for projects, fix sprint deleting and allow deleting for Owner or creator only (#2964)
Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>
This commit is contained in:
parent
6bdb599e35
commit
e4a53a1b37
@ -36,8 +36,4 @@ export function createModel (builder: Builder): void {
|
|||||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||||
trigger: serverTracker.trigger.OnComponentRemove
|
trigger: serverTracker.trigger.OnComponentRemove
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
|
||||||
trigger: serverTracker.trigger.OnProjectDelete
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -594,7 +594,12 @@ export function createModel (builder: Builder): void {
|
|||||||
presenter: tracker.component.AssigneePresenter,
|
presenter: tracker.component.AssigneePresenter,
|
||||||
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
|
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
options: {
|
||||||
|
lookup: {
|
||||||
|
space: tracker.class.Project
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
tracker.viewlet.IssueList
|
tracker.viewlet.IssueList
|
||||||
)
|
)
|
||||||
@ -1137,8 +1142,8 @@ export function createModel (builder: Builder): void {
|
|||||||
builder,
|
builder,
|
||||||
{
|
{
|
||||||
action: tracker.actionImpl.DeleteProject,
|
action: tracker.actionImpl.DeleteProject,
|
||||||
label: tracker.string.DeleteProject,
|
label: workbench.string.Archive,
|
||||||
icon: view.icon.Delete,
|
icon: view.icon.Archive,
|
||||||
input: 'focus',
|
input: 'focus',
|
||||||
category: tracker.category.Tracker,
|
category: tracker.category.Tracker,
|
||||||
target: tracker.class.Project,
|
target: tracker.class.Project,
|
||||||
|
@ -180,8 +180,9 @@
|
|||||||
"EditWorkflowStatuses": "Edit issue statuses",
|
"EditWorkflowStatuses": "Edit issue statuses",
|
||||||
"EditProject": "Edit project",
|
"EditProject": "Edit project",
|
||||||
"DeleteProject": "Delete project",
|
"DeleteProject": "Delete project",
|
||||||
"DeleteProjectName": "Delete project {name}?",
|
"ArchiveProjectName": "Archive project {name}?",
|
||||||
"ProjectHasIssues": "There are existing issues in this project, are you sure that you want to delete? Both the project and the issues will be deleted.",
|
"ArchiveProjectConfirm": "Do you want to archive this project?",
|
||||||
|
"ProjectHasIssues": "There are existing issues in this project, are you sure that you want to archive?",
|
||||||
"ManageWorkflowStatuses": "Manage issue statuses within project",
|
"ManageWorkflowStatuses": "Manage issue statuses within project",
|
||||||
"AddWorkflowStatus": "Add issue status",
|
"AddWorkflowStatus": "Add issue status",
|
||||||
"EditWorkflowStatus": "Edit issue status",
|
"EditWorkflowStatus": "Edit issue status",
|
||||||
|
@ -180,8 +180,9 @@
|
|||||||
"EditWorkflowStatuses": "Редактировать статусы задач",
|
"EditWorkflowStatuses": "Редактировать статусы задач",
|
||||||
"EditProject": "Редактировать проект",
|
"EditProject": "Редактировать проект",
|
||||||
"DeleteProject": "Удалить проект",
|
"DeleteProject": "Удалить проект",
|
||||||
"DeleteProjectName": "Удалить проект {name}?",
|
"ArchiveProjectName": "Архивировать проект {name}?",
|
||||||
"ProjectHasIssues": "Для данного проекта существуют задачи, уверены, что хотите удалить? Задачи и проект будут удалены.",
|
"ArchiveProjectConfirm": "Вы действительно хотите заархивировать этот проект?",
|
||||||
|
"ProjectHasIssues": "Для данного проекта существуют задачи, уверены, что хотите заархивировать?",
|
||||||
"ManageWorkflowStatuses": "Управлять статусами задач для команды",
|
"ManageWorkflowStatuses": "Управлять статусами задач для команды",
|
||||||
"AddWorkflowStatus": "Добавить статус задачи",
|
"AddWorkflowStatus": "Добавить статус задачи",
|
||||||
"EditWorkflowStatus": "Редактировать статус задачи",
|
"EditWorkflowStatus": "Редактировать статус задачи",
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getQuery (mode: string, queries: { [key: string]: DocumentQuery<Issue> }) {
|
function getQuery (mode: string, queries: { [key: string]: DocumentQuery<Issue> }) {
|
||||||
return queries[mode]
|
return { ...queries[mode], '$lookup.space.archived': false }
|
||||||
}
|
}
|
||||||
$: query = getQuery(mode, { assigned, created, subscribed })
|
$: query = getQuery(mode, { assigned, created, subscribed })
|
||||||
</script>
|
</script>
|
||||||
|
@ -119,7 +119,6 @@ import {
|
|||||||
issuePrioritySort,
|
issuePrioritySort,
|
||||||
issueStatusSort,
|
issueStatusSort,
|
||||||
moveIssuesToAnotherSprint,
|
moveIssuesToAnotherSprint,
|
||||||
removeProject,
|
|
||||||
sprintSort,
|
sprintSort,
|
||||||
subIssueQuery
|
subIssueQuery
|
||||||
} from './utils'
|
} from './utils'
|
||||||
@ -218,19 +217,32 @@ async function deleteProject (project: Project | undefined): Promise<void> {
|
|||||||
showPopup(
|
showPopup(
|
||||||
MessageBox,
|
MessageBox,
|
||||||
{
|
{
|
||||||
label: tracker.string.DeleteProjectName,
|
label: tracker.string.ArchiveProjectName,
|
||||||
labelProps: { name: project.name },
|
labelProps: { name: project.name },
|
||||||
message: tracker.string.ProjectHasIssues
|
message: tracker.string.ProjectHasIssues
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
(result?: boolean) => {
|
(result?: boolean) => {
|
||||||
if (result === true) {
|
if (result === true) {
|
||||||
void removeProject(project)
|
void client.update(project, { archived: true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
await removeProject(project)
|
showPopup(
|
||||||
|
MessageBox,
|
||||||
|
{
|
||||||
|
label: tracker.string.ArchiveProjectName,
|
||||||
|
labelProps: { name: project.name },
|
||||||
|
message: tracker.string.ArchiveProjectConfirm
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
(result?: boolean) => {
|
||||||
|
if (result === true) {
|
||||||
|
void client.update(project, { archived: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,22 +272,25 @@ async function moveAndDeleteSprints (client: TxOperations, oldSprints: Sprint[],
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteSprint (sprints: Sprint[]): Promise<void> {
|
async function deleteSprint (sprints: Sprint | Sprint[]): Promise<void> {
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
const sprintArray = Array.isArray(sprints) ? sprints : [sprints]
|
||||||
// Check if available to move issues to another sprint
|
// Check if available to move issues to another sprint
|
||||||
const firstSearchedSprint = await client.findOne(tracker.class.Sprint, { _id: { $nin: sprints.map((p) => p._id) } })
|
const firstSearchedSprint = await client.findOne(tracker.class.Sprint, {
|
||||||
|
_id: { $nin: sprintArray.map((p) => p._id) }
|
||||||
|
})
|
||||||
if (firstSearchedSprint !== undefined) {
|
if (firstSearchedSprint !== undefined) {
|
||||||
showPopup(
|
showPopup(
|
||||||
MoveAndDeleteSprintPopup,
|
MoveAndDeleteSprintPopup,
|
||||||
{
|
{
|
||||||
sprints,
|
sprintArray,
|
||||||
moveAndDeleteSprint: async (selectedSprint?: Sprint) =>
|
moveAndDeleteSprint: async (selectedSprint?: Sprint) =>
|
||||||
await moveAndDeleteSprints(client, sprints, selectedSprint)
|
await moveAndDeleteSprints(client, sprintArray, selectedSprint)
|
||||||
},
|
},
|
||||||
'top'
|
'top'
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
await moveAndDeleteSprints(client, sprints)
|
await moveAndDeleteSprints(client, sprintArray)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,8 @@ export default mergeIds(trackerId, tracker, {
|
|||||||
EditWorkflowStatuses: '' as IntlString,
|
EditWorkflowStatuses: '' as IntlString,
|
||||||
EditProject: '' as IntlString,
|
EditProject: '' as IntlString,
|
||||||
DeleteProject: '' as IntlString,
|
DeleteProject: '' as IntlString,
|
||||||
DeleteProjectName: '' as IntlString,
|
ArchiveProjectName: '' as IntlString,
|
||||||
|
ArchiveProjectConfirm: '' as IntlString,
|
||||||
ProjectHasIssues: '' as IntlString,
|
ProjectHasIssues: '' as IntlString,
|
||||||
ManageWorkflowStatuses: '' as IntlString,
|
ManageWorkflowStatuses: '' as IntlString,
|
||||||
AddWorkflowStatus: '' as IntlString,
|
AddWorkflowStatus: '' as IntlString,
|
||||||
|
@ -33,7 +33,7 @@ import core, {
|
|||||||
TxUpdateDoc
|
TxUpdateDoc
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { Asset, IntlString } from '@hcengineering/platform'
|
import { Asset, IntlString } from '@hcengineering/platform'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
import { calcRank } from '@hcengineering/task'
|
import { calcRank } from '@hcengineering/task'
|
||||||
import {
|
import {
|
||||||
ComponentStatus,
|
ComponentStatus,
|
||||||
@ -550,11 +550,6 @@ export async function getPreviousAssignees (issue: Issue): Promise<Array<Ref<Emp
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function removeProject (project: Project): Promise<void> {
|
|
||||||
const client = getClient()
|
|
||||||
await client.removeDoc(tracker.class.Project, core.space.Space, project._id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateIssuesOnMove (
|
async function updateIssuesOnMove (
|
||||||
client: TxOperations,
|
client: TxOperations,
|
||||||
applyOps: ApplyOperations,
|
applyOps: ApplyOperations,
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import core, {
|
import core, {
|
||||||
|
AccountRole,
|
||||||
AttachedDoc,
|
AttachedDoc,
|
||||||
CategoryType,
|
CategoryType,
|
||||||
Class,
|
Class,
|
||||||
@ -22,6 +23,7 @@ import core, {
|
|||||||
Collection,
|
Collection,
|
||||||
Doc,
|
Doc,
|
||||||
DocumentUpdate,
|
DocumentUpdate,
|
||||||
|
getCurrentAccount,
|
||||||
getObjectValue,
|
getObjectValue,
|
||||||
Hierarchy,
|
Hierarchy,
|
||||||
Lookup,
|
Lookup,
|
||||||
@ -298,6 +300,8 @@ export async function buildModel (options: BuildModelOptions): Promise<Attribute
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteObject (client: TxOperations, object: Doc): Promise<void> {
|
export async function deleteObject (client: TxOperations, object: Doc): Promise<void> {
|
||||||
|
const currentAcc = getCurrentAccount()
|
||||||
|
if (currentAcc.role !== AccountRole.Owner && object.createdBy !== currentAcc._id) return
|
||||||
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
|
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
|
||||||
const adoc = object as AttachedDoc
|
const adoc = object as AttachedDoc
|
||||||
await client
|
await client
|
||||||
@ -309,6 +313,8 @@ export async function deleteObject (client: TxOperations, object: Doc): Promise<
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteObjects (client: TxOperations, objects: Doc[]): Promise<void> {
|
export async function deleteObjects (client: TxOperations, objects: Doc[]): Promise<void> {
|
||||||
|
const currentAcc = getCurrentAccount()
|
||||||
|
if (currentAcc.role !== AccountRole.Owner && objects.some((p) => p.createdBy !== currentAcc._id)) return
|
||||||
const ops = client.apply('delete')
|
const ops = client.apply('delete')
|
||||||
for (const object of objects) {
|
for (const object of objects) {
|
||||||
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
|
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
|
||||||
|
@ -33,7 +33,7 @@ import core, {
|
|||||||
import { getMetadata } from '@hcengineering/platform'
|
import { getMetadata } from '@hcengineering/platform'
|
||||||
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
||||||
import { addAssigneeNotification } from '@hcengineering/server-task-resources'
|
import { addAssigneeNotification } from '@hcengineering/server-task-resources'
|
||||||
import tracker, { Component, Issue, IssueParentInfo, Project, TimeSpendReport, trackerId } from '@hcengineering/tracker'
|
import tracker, { Component, Issue, IssueParentInfo, TimeSpendReport, trackerId } from '@hcengineering/tracker'
|
||||||
import { workbenchId } from '@hcengineering/workbench'
|
import { workbenchId } from '@hcengineering/workbench'
|
||||||
|
|
||||||
async function updateSubIssues (
|
async function updateSubIssues (
|
||||||
@ -84,32 +84,6 @@ export async function addTrackerAssigneeNotification (
|
|||||||
await addAssigneeNotification(control, res, issue, assignee, ptx)
|
await addAssigneeNotification(control, res, issue, assignee, ptx)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export async function OnProjectDelete (tx: Tx, control: TriggerControl): Promise<Tx[]> {
|
|
||||||
const actualTx = TxProcessor.extractTx(tx)
|
|
||||||
if (actualTx._class !== core.class.TxRemoveDoc) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const ctx = actualTx as TxRemoveDoc<Project>
|
|
||||||
|
|
||||||
if (ctx.objectClass !== tracker.class.Project) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
const issues = await control.findAll(tracker.class.Issue, {
|
|
||||||
space: ctx.objectId
|
|
||||||
})
|
|
||||||
|
|
||||||
const res: Tx[] = []
|
|
||||||
issues.forEach((issue) => {
|
|
||||||
res.push(control.txFactory.createTxRemoveDoc(issue._class, issue.space, issue._id))
|
|
||||||
})
|
|
||||||
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -216,8 +190,7 @@ export default async () => ({
|
|||||||
},
|
},
|
||||||
trigger: {
|
trigger: {
|
||||||
OnIssueUpdate,
|
OnIssueUpdate,
|
||||||
OnComponentRemove,
|
OnComponentRemove
|
||||||
OnProjectDelete
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ export default plugin(serverTrackerId, {
|
|||||||
},
|
},
|
||||||
trigger: {
|
trigger: {
|
||||||
OnIssueUpdate: '' as Resource<TriggerFunc>,
|
OnIssueUpdate: '' as Resource<TriggerFunc>,
|
||||||
OnComponentRemove: '' as Resource<TriggerFunc>,
|
OnComponentRemove: '' as Resource<TriggerFunc>
|
||||||
OnProjectDelete: '' as Resource<TriggerFunc>
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user