mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-28 12:35:02 +02:00
TSK-1335 Improve draft (#3092)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user