diff --git a/models/tracker/src/types.ts b/models/tracker/src/types.ts index 6b412575b7..8c5b0d8104 100644 --- a/models/tracker/src/types.ts +++ b/models/tracker/src/types.ts @@ -66,6 +66,7 @@ import { type TimeSpendReport } from '@hcengineering/tracker' import tracker from './plugin' +import { type TaskType } from '@hcengineering/task' export const DOMAIN_TRACKER = 'tracker' as Domain @@ -271,6 +272,9 @@ export class TIssueTemplate extends TDoc implements IssueTemplate { @Prop(ArrOf(TypeRef(tags.class.TagElement)), tracker.string.Labels) labels?: Ref[] + @Prop(TypeRef(task.class.TaskType), task.string.TaskType) + kind?: Ref + declare space: Ref @Prop(TypeDate(DateRangeMode.DATETIME), tracker.string.DueDate) diff --git a/plugins/task-resources/src/components/taskTypes/TaskKindSelector.svelte b/plugins/task-resources/src/components/taskTypes/TaskKindSelector.svelte index 11a7592469..b24cdbc4ce 100644 --- a/plugins/task-resources/src/components/taskTypes/TaskKindSelector.svelte +++ b/plugins/task-resources/src/components/taskTypes/TaskKindSelector.svelte @@ -2,7 +2,7 @@ import { Class, Doc, Ref, toIdMap } from '@hcengineering/core' import { getClient } from '@hcengineering/presentation' import task, { ProjectType, TaskType } from '@hcengineering/task' - import { DropdownLabels } from '@hcengineering/ui' + import { ButtonKind, DropdownLabels } from '@hcengineering/ui' import { createEventDispatcher, onDestroy } from 'svelte' import { selectedTaskTypeStore, taskTypeStore } from '../..' @@ -10,6 +10,7 @@ export let projectType: Ref | undefined export let focusIndex: number = -1 export let baseClass: Ref> | undefined = undefined + export let kind: ButtonKind = 'regular' export let allTypes = false const client = getClient() @@ -44,12 +45,5 @@ {#if projectType !== undefined && items.length > 1} - + {/if} diff --git a/plugins/tracker-resources/src/components/CreateIssue.svelte b/plugins/tracker-resources/src/components/CreateIssue.svelte index 3cd8b1ef2b..69083b0850 100644 --- a/plugins/tracker-resources/src/components/CreateIssue.svelte +++ b/plugins/tracker-resources/src/components/CreateIssue.svelte @@ -17,7 +17,17 @@ import { AttachmentPresenter, AttachmentStyledBox } from '@hcengineering/attachment-resources' import chunter from '@hcengineering/chunter' import { Employee } from '@hcengineering/contact' - import core, { Account, Class, Doc, DocData, Ref, SortingOrder, fillDefaults, generateId } from '@hcengineering/core' + import core, { + Account, + Class, + Doc, + DocData, + Ref, + SortingOrder, + fillDefaults, + generateId, + toIdMap + } from '@hcengineering/core' import { getResource, translate } from '@hcengineering/platform' import preference, { SpacePreference } from '@hcengineering/preference' import { @@ -64,6 +74,7 @@ import { activeComponent, activeMilestone, generateIssueShortLink, updateIssueRelation } from '../issues' import tracker from '../plugin' import SetParentIssueActionPopup from './SetParentIssueActionPopup.svelte' + import SubIssues from './SubIssues.svelte' import ComponentSelector from './components/ComponentSelector.svelte' import AssigneeEditor from './issues/AssigneeEditor.svelte' import IssueNotification from './issues/IssueNotification.svelte' @@ -107,7 +118,7 @@ let project: Project | undefined let object = getDefaultObjectFromDraft() ?? getDefaultObject(id) let isAssigneeTouched = false - let kind: Ref | undefined + let kind: Ref | undefined = undefined let templateId: Ref | undefined = draft?.template?.template let appliedTemplateId: Ref | undefined = draft?.template?.template @@ -156,6 +167,7 @@ _id: id ?? generateId(), title: '', description: '', + kind: '' as Ref, priority: priority ?? IssuePriority.NoPriority, space: _space as Ref, component: component ?? $activeComponent ?? null, @@ -258,14 +270,34 @@ } const { _class, _id, space, children, comments, attachments, labels, description, ...templBase } = template + const allLabels = new Set>() + for (const label of labels ?? []) { + allLabels.add(label) + } + for (const child of children) { + for (const label of child.labels ?? []) { + allLabels.add(label) + } + } + const tagElements = toIdMap(await client.findAll(tags.class.TagElement, { _id: { $in: Array.from(allLabels) } })) + object.subIssues = template.children.map((p) => { return { ...p, - _id: p.id, + kind: p.kind ?? kind ?? ('' as Ref), + _id: generateId(), space: _space as Ref, subIssues: [], dueDate: null, - labels: [], + labels: + p.labels !== undefined + ? (p.labels + .map((p) => { + const val = tagElements.get(p) + return val !== undefined ? tagAsRef(val) : undefined + }) + .filter((p) => p !== undefined) as TagReference[]) + : [], status: currentProject?.defaultIssueStatus } }) @@ -279,8 +311,19 @@ } } appliedTemplateId = templateId - const tagElements = await client.findAll(tags.class.TagElement, { _id: { $in: labels } }) - object.labels = tagElements.map(tagAsRef) + object.labels = + labels !== undefined + ? (labels + .map((p) => { + const val = tagElements.get(p) + return val !== undefined ? tagAsRef(val) : undefined + }) + .filter((p) => p !== undefined) as TagReference[]) + : [] + + if (object.kind !== undefined) { + kind = object.kind + } fillDefaults(hierarchy, object, tracker.class.Issue) } @@ -336,6 +379,8 @@ return value.trim() } + let subIssuesComponent: SubIssues + export function canClose (): boolean { return true } @@ -439,6 +484,15 @@ await operations.commit() await descriptionBox.createAttachments(_id) + + const parents = parentIssue + ? [ + { parentId: _id, parentTitle: value.title, space: parentIssue.space }, + { parentId: parentIssue._id, parentTitle: parentIssue.title, space: parentIssue.space }, + ...parentIssue.parents + ] + : [{ parentId: _id, parentTitle: value.title, space: _space }] + await subIssuesComponent.save(parents, _id) addNotification( await translate(tracker.string.IssueCreated, {}, $themeStore.language), getTitle(object.title), @@ -727,6 +781,16 @@ /> {/key} + {#if _space} + + {/if}
diff --git a/plugins/tracker-resources/src/components/SubIssues.svelte b/plugins/tracker-resources/src/components/SubIssues.svelte new file mode 100644 index 0000000000..9b9267ca8d --- /dev/null +++ b/plugins/tracker-resources/src/components/SubIssues.svelte @@ -0,0 +1,199 @@ + + + + +{#if subIssues.length > 0} +
+
+ + +
+ + + +
+
+{/if} + + diff --git a/plugins/tracker-resources/src/components/templates/DraftIssueChildEditor.svelte b/plugins/tracker-resources/src/components/templates/DraftIssueChildEditor.svelte index e445ef3e34..7128f62cd2 100644 --- a/plugins/tracker-resources/src/components/templates/DraftIssueChildEditor.svelte +++ b/plugins/tracker-resources/src/components/templates/DraftIssueChildEditor.svelte @@ -17,13 +17,15 @@ import { Account, Doc, generateId, Ref } from '@hcengineering/core' import presentation, { DraftController, getClient, KeyedAttribute } from '@hcengineering/presentation' import tags, { TagElement, TagReference } from '@hcengineering/tags' + import { TaskType } from '@hcengineering/task' + import { TaskKindSelector } from '@hcengineering/task-resources' import { Component as ComponentType, Issue, IssueDraft, IssuePriority, - Project, - Milestone + Milestone, + Project } from '@hcengineering/tracker' import { Button, Component, EditBox } from '@hcengineering/ui' import { createEventDispatcher, onDestroy } from 'svelte' @@ -65,6 +67,7 @@ _id: generateId(), title: '', description: '', + kind: '' as Ref, assignee: project.defaultAssignee ?? null, status: project.defaultIssueStatus, space: project._id, @@ -208,6 +211,12 @@ on:change={({ detail }) => (object.priority = detail)} />
+
{#key object.assignee}