mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-28 04:25:03 +02:00
Export & Import functionality for issues (#5733)
Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import {
|
||||
import core, {
|
||||
toIdMap,
|
||||
type Attribute,
|
||||
type Class,
|
||||
@@ -38,8 +38,11 @@ import task, {
|
||||
} from '@hcengineering/task'
|
||||
import { getCurrentLocation, navigate, showPopup } from '@hcengineering/ui'
|
||||
import { type ViewletDescriptor } from '@hcengineering/view'
|
||||
import { CategoryQuery, statusStore } from '@hcengineering/view-resources'
|
||||
import { CategoryQuery, groupBy, statusStore } from '@hcengineering/view-resources'
|
||||
import { get, writable } from 'svelte/store'
|
||||
import { type Employee, type PersonAccount } from '@hcengineering/contact'
|
||||
import activity from '@hcengineering/activity'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
|
||||
import AssignedTasks from './components/AssignedTasks.svelte'
|
||||
import Dashboard from './components/Dashboard.svelte'
|
||||
@@ -72,6 +75,7 @@ import ProjectTypeTasksTypeSectionEditor from './components/projectTypes/Project
|
||||
import ProjectTypeAutomationsSectionEditor from './components/projectTypes/ProjectTypeAutomationsSectionEditor.svelte'
|
||||
import ProjectTypeCollectionsSectionEditor from './components/projectTypes/ProjectTypeCollectionsSectionEditor.svelte'
|
||||
import TaskTypeEditor from './components/taskTypes/TaskTypeEditor.svelte'
|
||||
import { employeeByIdStore, personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
|
||||
|
||||
export { default as AssigneePresenter } from './components/AssigneePresenter.svelte'
|
||||
export { default as TypeSelector } from './components/TypeSelector.svelte'
|
||||
@@ -86,6 +90,76 @@ async function editStatuses (object: Project, ev: Event): Promise<void> {
|
||||
navigate(loc)
|
||||
}
|
||||
|
||||
async function exportTasks (docs: Task | Task[]): Promise<void> {
|
||||
const client = getClient()
|
||||
const ddocs = Array.isArray(docs) ? docs : [docs]
|
||||
const docsStatuses = ddocs.map((doc) => doc.status)
|
||||
const statuses = await client.findAll(core.class.Status, { _id: { $in: docsStatuses } })
|
||||
const personAccountById = get(personAccountByIdStore)
|
||||
const personById = get(personByIdStore)
|
||||
const employeeById = get(employeeByIdStore)
|
||||
const statusMap = toIdMap(statuses)
|
||||
const activityMessages = await client.findAll(activity.class.ActivityMessage, {
|
||||
_class: chunter.class.ChatMessage,
|
||||
attachedToClass: { $in: ddocs.map((d) => d._class) },
|
||||
attachedTo: { $in: ddocs.map((d) => d._id) }
|
||||
})
|
||||
const activityByDoc = groupBy(activityMessages, 'attachedTo')
|
||||
|
||||
const toExport = ddocs.map((d) => {
|
||||
const statusName = statusMap.get(d.status)?.name ?? d.status
|
||||
const createdByAccount = personAccountById.get(d.createdBy as Ref<PersonAccount>)?.person
|
||||
const modeifedByAccount = personAccountById.get(d.modifiedBy as Ref<PersonAccount>)?.person
|
||||
const createdBy = personById.get(createdByAccount as Ref<Employee>)?.name ?? d.createdBy
|
||||
const modifiedBy = personById.get(modeifedByAccount as Ref<Employee>)?.name ?? d.modifiedBy
|
||||
const assignee = employeeById.get(d.assignee as Ref<Employee>)?.name ?? d.assignee
|
||||
const collaborators = ((d as any)['notification:mixin:Collaborators']?.collaborators ?? []).map(
|
||||
(id: Ref<PersonAccount>) => {
|
||||
const personAccount = personAccountById.get(id)?.person
|
||||
return personAccount !== undefined ? personById.get(personAccount)?.name ?? id : id
|
||||
}
|
||||
)
|
||||
const activityForDoc = (activityByDoc[d._id] ?? []).map((act) => {
|
||||
const activityCreatedByAccount = personAccountById.get(act.createdBy as Ref<PersonAccount>)?.person
|
||||
const activityModifiedByAccount = personAccountById.get(act.modifiedBy as Ref<PersonAccount>)?.person
|
||||
const activitycreatedBy =
|
||||
employeeById.get((activityCreatedByAccount as any as Ref<Employee>) ?? ('' as Ref<Employee>))?.name ??
|
||||
act.createdBy
|
||||
const activitymodifiedBy =
|
||||
employeeById.get((activityModifiedByAccount as any as Ref<Employee>) ?? ('' as Ref<Employee>))?.name ??
|
||||
act.modifiedBy
|
||||
return {
|
||||
...act,
|
||||
createdBy: activitycreatedBy,
|
||||
modifiedBy: activitymodifiedBy
|
||||
}
|
||||
})
|
||||
return {
|
||||
...d,
|
||||
status: statusName,
|
||||
createdBy,
|
||||
modifiedBy,
|
||||
assignee,
|
||||
'notification:mixin:Collaborators': {
|
||||
collaborators
|
||||
},
|
||||
activity: activityForDoc
|
||||
}
|
||||
})
|
||||
const filename = 'tasks' + new Date().toLocaleDateString() + '.json'
|
||||
const link = document.createElement('a')
|
||||
link.style.display = 'none'
|
||||
link.setAttribute('target', '_blank')
|
||||
link.setAttribute(
|
||||
'href',
|
||||
'data:application/json;charset=utf-8,%EF%BB%BF' + encodeURIComponent(JSON.stringify(toExport))
|
||||
)
|
||||
link.setAttribute('download', filename)
|
||||
document.body.appendChild(link)
|
||||
link.click()
|
||||
document.body.removeChild(link)
|
||||
}
|
||||
|
||||
async function selectStatus (
|
||||
doc: Task | Task[],
|
||||
ev: any,
|
||||
@@ -137,7 +211,8 @@ export default async (): Promise<Resources> => ({
|
||||
},
|
||||
actionImpl: {
|
||||
EditStatuses: editStatuses,
|
||||
SelectStatus: selectStatus
|
||||
SelectStatus: selectStatus,
|
||||
ExportTasks: exportTasks
|
||||
},
|
||||
function: {
|
||||
GetAllStates: getAllStates,
|
||||
|
||||
Reference in New Issue
Block a user