TSK-1335 Improve draft (#3092)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov
2023-04-27 23:52:31 +07:00
committed by GitHub
parent 97396cc5f2
commit be1872abe5
11 changed files with 343 additions and 141 deletions
@@ -22,10 +22,10 @@
Card,
createQuery,
DraftController,
draftsStore,
getClient,
KeyedAttribute,
MessageBox,
MultipleDraftController,
SpaceSelector
} from '@hcengineering/presentation'
import tags, { TagElement, TagReference } from '@hcengineering/tags'
@@ -57,7 +57,7 @@
} from '@hcengineering/ui'
import view from '@hcengineering/view'
import { ObjectBox } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'
import { createEventDispatcher, onDestroy } from 'svelte'
import { activeComponent, activeSprint, generateIssueShortLink, getIssueId, updateIssueRelation } from '../issues'
import tracker from '../plugin'
import ComponentSelector from './ComponentSelector.svelte'
@@ -83,25 +83,26 @@
export let parentIssue: Issue | undefined
export let originalIssue: Issue | undefined
const draftController = new DraftController<any>(tracker.ids.IssueDraft)
const mDraftController = new MultipleDraftController(tracker.ids.IssueDraft)
const id: Ref<Issue> = generateId()
const draftController = new DraftController<IssueDraft>(
shouldSaveDraft ? mDraftController.getNext() ?? id : undefined,
tracker.ids.IssueDraft
)
let draft = shouldSaveDraft ? ($draftsStore[tracker.ids.IssueDraft] as IssueDraft) : undefined
$: draft = shouldSaveDraft ? ($draftsStore[tracker.ids.IssueDraft] as IssueDraft) : undefined
let draft = shouldSaveDraft ? draftController.get() : undefined
onDestroy(
draftController.subscribe((val) => {
draft = shouldSaveDraft ? val : undefined
})
)
const client = getClient()
const hierarchy = client.getHierarchy()
const parentQuery = createQuery()
let _space = space
let object = draft ?? getDefaultObject()
function draftChange (draft: IssueDraft | undefined) {
if (draft === undefined) {
object = getDefaultObject()
} else {
object = draft
descriptionBox?.setContent(object.description)
}
}
let object = draft ?? getDefaultObject(id)
function objectChange (object: IssueDraft, empty: any) {
if (shouldSaveDraft) {
@@ -110,7 +111,6 @@
}
$: objectChange(object, empty)
$: draftChange(draft)
$: if (object.parentIssue) {
parentQuery.query(
@@ -127,9 +127,9 @@
parentIssue = undefined
}
function getDefaultObject (ignoreOriginal = false): IssueDraft {
function getDefaultObject (id: Ref<Issue> | undefined = undefined, ignoreOriginal = false): IssueDraft {
const base: IssueDraft = {
_id: generateId(),
_id: id ?? generateId(),
title: '',
description: '',
priority,
@@ -199,7 +199,7 @@
function resetObject (): void {
templateId = undefined
template = undefined
object = getDefaultObject(true)
object = getDefaultObject(undefined, true)
fillDefaults(hierarchy, object, tracker.class.Issue)
}
@@ -502,7 +502,7 @@
async function showConfirmationDialog () {
draftController.save(object, empty)
const isFormEmpty = $draftsStore[tracker.ids.IssueDraft] === undefined
const isFormEmpty = draft === undefined
if (isFormEmpty) {
dispatch('close')
@@ -625,6 +625,7 @@
<SubIssues
bind:this={subIssuesComponent}
projectId={_space}
parendIssueId={object._id}
project={currentProject}
sprint={object.sprint}
component={object.component}
@@ -638,7 +639,7 @@
value={object}
kind={'secondary'}
size={'large'}
defaultIssueStatus={draft ? undefined : currentProject?.defaultIssueStatus}
defaultIssueStatus={currentProject?.defaultIssueStatus}
shouldShowLabel={true}
on:refocus={() => {
manager.setFocusPos(3)
@@ -14,8 +14,9 @@
-->
<script lang="ts">
import { Ref, Space } from '@hcengineering/core'
import { draftsStore, getClient } from '@hcengineering/presentation'
import { Button, showPopup, IconAdd } from '@hcengineering/ui'
import { MultipleDraftController, getClient } from '@hcengineering/presentation'
import { Button, IconAdd, showPopup } from '@hcengineering/ui'
import { onDestroy } from 'svelte'
import tracker from '../plugin'
import CreateIssue from './CreateIssue.svelte'
@@ -24,10 +25,17 @@
const client = getClient()
let space: Ref<Space> | undefined
let closed = true
$: updateSpace(currentSpace)
$: draftExists =
$draftsStore[tracker.ids.IssueDraft] !== undefined || $draftsStore[tracker.ids.IssueDraftChild] !== undefined
let draftExists = false
const draftController = new MultipleDraftController(tracker.ids.IssueDraft)
onDestroy(
draftController.hasNext((res) => {
draftExists = res
})
)
async function updateSpace (spaceId: Ref<Space> | undefined): Promise<void> {
if (spaceId !== undefined) {
@@ -44,15 +52,15 @@
const project = await client.findOne(tracker.class.Project, {})
space = project?._id
}
showPopup(CreateIssue, { space, shouldSaveDraft: true }, 'top')
closed = false
showPopup(CreateIssue, { space, shouldSaveDraft: true }, 'top', () => (closed = true))
}
</script>
<div class="antiNav-subheader">
<Button
icon={IconAdd}
label={draftExists ? tracker.string.ResumeDraft : tracker.string.NewIssue}
label={draftExists || !closed ? tracker.string.ResumeDraft : tracker.string.NewIssue}
justify={'left'}
kind={'primary'}
width={'100%'}
@@ -27,6 +27,7 @@
import DraftIssueChildEditor from './templates/DraftIssueChildEditor.svelte'
import DraftIssueChildList from './templates/DraftIssueChildList.svelte'
export let parendIssueId: Ref<Issue>
export let projectId: Ref<Project>
export let project: Project | undefined
export let sprint: Ref<Sprint> | null = null
@@ -36,7 +37,7 @@
let lastProject = project
let isCollapsed = false
$: isCreatingMode = $draftsStore[tracker.ids.IssueDraftChild] !== undefined
$: isCreatingMode = $draftsStore[`${parendIssueId}_subIssue`] !== undefined
let isManualCreating = false
$: isCreating = isCreatingMode || isManualCreating
@@ -233,6 +234,7 @@
<ExpandCollapse isExpanded={!isCollapsed} on:changeContent>
<DraftIssueChildEditor
bind:this={draftChild}
{parendIssueId}
{project}
{component}
{sprint}
@@ -83,15 +83,15 @@
value: ValueType,
defaultStatus: Ref<IssueStatus> | undefined
): WithLookup<IssueStatus> | undefined {
if (defaultStatus !== undefined) {
defaultIssueStatus = undefined
changeStatus(defaultStatus, false)
return statuses?.find((status) => status._id === defaultStatus)
if (value.status !== undefined) {
const current = statuses?.find((status) => status._id === value.status)
if (current) return current
}
if (defaultIssueStatus !== undefined) {
const res = statuses?.find((status) => status._id === defaultStatus)
changeStatus(res?._id, false)
return res
}
const current = statuses?.find((status) => status._id === value.status)
if (current) return current
changeStatus(statuses?.[0]?._id, false)
return statuses?.[0]
}
$: selectedStatus = getSelectedStatus(statuses, value, defaultIssueStatus)
@@ -19,25 +19,26 @@
import presentation, { DraftController, getClient, KeyedAttribute } from '@hcengineering/presentation'
import tags, { TagElement, TagReference } from '@hcengineering/tags'
import { calcRank, Issue, IssueDraft, IssuePriority, Project } from '@hcengineering/tracker'
import { addNotification, Button, Component, EditBox, deviceOptionsStore, ButtonSize } from '@hcengineering/ui'
import { createEventDispatcher, onDestroy } from 'svelte'
import { addNotification, Button, ButtonSize, Component, deviceOptionsStore, EditBox } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import { generateIssueShortLink, getIssueId } from '../../../issues'
import tracker from '../../../plugin'
import AssigneeEditor from '../AssigneeEditor.svelte'
import IssueNotification from '../IssueNotification.svelte'
import PriorityEditor from '../PriorityEditor.svelte'
import StatusEditor from '../StatusEditor.svelte'
import EstimationEditor from '../timereport/EstimationEditor.svelte'
import { generateIssueShortLink, getIssueId } from '../../../issues'
import { onDestroy } from 'svelte'
export let parentIssue: Issue
export let currentProject: Project
export let shouldSaveDraft: boolean = false
const draftController = new DraftController<IssueDraft>(parentIssue._id)
const draftController = new DraftController<IssueDraft>(`${parentIssue._id}_subIssue`)
const draft = shouldSaveDraft ? draftController.get() : undefined
const dispatch = createEventDispatcher()
const client = getClient()
onDestroy(() => draftController.unsubscribe())
onDestroy(() => draftController.destroy())
let object = draft ?? getIssueDefaults()
@@ -77,10 +78,14 @@
sprint: parentIssue.sprint
}
if (shouldSaveDraft) {
draftController.watch(object, empty)
function objectChange (object: IssueDraft, empty: any) {
if (shouldSaveDraft) {
draftController.save(object, empty)
}
}
$: objectChange(object, empty)
function resetToDefaults () {
object = getIssueDefaults()
focusIssueTitle?.()
@@ -46,7 +46,7 @@
let subIssueEditorRef: HTMLDivElement
let isCollapsed = false
let isCreating = $draftsStore[issue._id] !== undefined
let isCreating = $draftsStore[`${issue._id}_subIssue`] !== undefined
$: hasSubIssues = issue.subIssues > 0
@@ -15,9 +15,9 @@
<script lang="ts">
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
import { Account, Doc, generateId, Ref } from '@hcengineering/core'
import presentation, { DraftController, draftsStore, getClient, KeyedAttribute } from '@hcengineering/presentation'
import presentation, { DraftController, getClient, KeyedAttribute } from '@hcengineering/presentation'
import tags, { TagElement, TagReference } from '@hcengineering/tags'
import { Component as ComponentType, IssueDraft, IssuePriority, Project, Sprint } from '@hcengineering/tracker'
import { Component as ComponentType, Issue, IssueDraft, IssuePriority, Project, Sprint } from '@hcengineering/tracker'
import { Button, Component, EditBox } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
import tracker from '../../plugin'
@@ -25,7 +25,9 @@
import PriorityEditor from '../issues/PriorityEditor.svelte'
import StatusEditor from '../issues/StatusEditor.svelte'
import EstimationEditor from './EstimationEditor.svelte'
import { onDestroy } from 'svelte'
export let parendIssueId: Ref<Issue>
export let project: Project
export let sprint: Ref<Sprint> | null = null
export let component: Ref<ComponentType> | null = null
@@ -35,12 +37,14 @@
const dispatch = createEventDispatcher()
const client = getClient()
const draftController = new DraftController<IssueDraft>(tracker.ids.IssueDraftChild)
const draft = shouldSaveDraft ? ($draftsStore[tracker.ids.IssueDraftChild] as IssueDraft) : undefined
const draftController = new DraftController<IssueDraft>(`${parendIssueId}_subIssue`)
const draft = shouldSaveDraft ? draftController.get() : undefined
let object = childIssue !== undefined ? childIssue : draft ?? getIssueDefaults()
let thisRef: HTMLDivElement
let focusIssueTitle: () => void
onDestroy(() => draftController.destroy())
const key: KeyedAttribute = {
key: 'labels',
attr: client.getHierarchy().getAttribute(tracker.class.IssueTemplate, 'labels')
@@ -48,16 +52,6 @@
let descriptionBox: AttachmentStyledBox
function draftChange (draft: IssueDraft | undefined) {
if (draft === undefined) {
object = childIssue !== undefined ? childIssue : getIssueDefaults()
} else {
object = draft
descriptionBox?.setContent(object.description)
}
}
$: shouldSaveDraft && draftChange($draftsStore[tracker.ids.IssueDraftChild])
function getIssueDefaults (): IssueDraft {
return {
_id: generateId(),