mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-28 19:08:01 +00:00
Draft tabs sync (#3030)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
parent
67d361d856
commit
01afbab81d
@ -68,7 +68,6 @@
|
||||
let refInput: StyledTextBox
|
||||
|
||||
let inputFile: HTMLInputElement
|
||||
let draftAttachments: Record<Ref<Attachment>, Attachment> | undefined = undefined
|
||||
let saved = false
|
||||
|
||||
const client = getClient()
|
||||
@ -78,11 +77,14 @@
|
||||
const newAttachments: Set<Ref<Attachment>> = new Set<Ref<Attachment>>()
|
||||
const removedAttachments: Set<Attachment> = new Set<Attachment>()
|
||||
|
||||
$: objectId && draftKey && updateAttachments(objectId, draftKey)
|
||||
$: draftKey && updateAttachments(objectId, $draftsStore[draftKey])
|
||||
|
||||
async function updateAttachments (objectId: Ref<Doc>, draftKey: string) {
|
||||
draftAttachments = $draftsStore[draftKey]
|
||||
async function updateAttachments (
|
||||
objectId: Ref<Doc> | undefined,
|
||||
draftAttachments: Record<Ref<Attachment>, Attachment> | undefined
|
||||
) {
|
||||
if (draftAttachments && shouldSaveDraft) {
|
||||
query.unsubscribe()
|
||||
attachments.clear()
|
||||
newAttachments.clear()
|
||||
Object.entries(draftAttachments).map((file) => {
|
||||
@ -93,7 +95,8 @@
|
||||
})
|
||||
originalAttachments.clear()
|
||||
removedAttachments.clear()
|
||||
} else {
|
||||
attachments = attachments
|
||||
} else if (objectId) {
|
||||
query.query(
|
||||
attachment.class.Attachment,
|
||||
{
|
||||
@ -102,6 +105,7 @@
|
||||
(res) => {
|
||||
originalAttachments = new Set(res.map((p) => p._id))
|
||||
attachments = toIdMap(res)
|
||||
dispatch('attach', { action: 'saved', value: attachments.size })
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -109,7 +113,7 @@
|
||||
|
||||
async function saveDraft () {
|
||||
if (draftKey && shouldSaveDraft) {
|
||||
draftAttachments = Object.fromEntries(attachments)
|
||||
const draftAttachments = Object.fromEntries(attachments)
|
||||
DraftController.save(draftKey, draftAttachments)
|
||||
}
|
||||
}
|
||||
@ -138,6 +142,7 @@
|
||||
attachments = attachments
|
||||
saved = false
|
||||
saveDraft()
|
||||
dispatch('attach', { action: 'saved', value: attachments.size })
|
||||
dispatch('attached', _id)
|
||||
} catch (err: any) {
|
||||
setPlatformStatus(unknownError(err))
|
||||
@ -255,10 +260,6 @@
|
||||
removedAttachments.clear()
|
||||
}
|
||||
|
||||
$: if (attachments.size || newAttachments.size || removedAttachments.size) {
|
||||
dispatch('attach', { action: 'saved', value: attachments.size })
|
||||
}
|
||||
|
||||
function isAllowedPaste (evt: ClipboardEvent) {
|
||||
let t: HTMLElement | null = evt.target as HTMLElement
|
||||
|
||||
|
@ -50,15 +50,15 @@
|
||||
Component,
|
||||
createFocusManager,
|
||||
EditBox,
|
||||
IconFile as FileIcon,
|
||||
FocusHandler,
|
||||
getColorNumberByText,
|
||||
IconFile as FileIcon,
|
||||
IconInfo,
|
||||
Label,
|
||||
showPopup,
|
||||
Spinner
|
||||
} from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import recruit from '../plugin'
|
||||
import FileUpload from './icons/FileUpload.svelte'
|
||||
import YesNo from './YesNo.svelte'
|
||||
@ -81,10 +81,29 @@
|
||||
const empty = {}
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const ignoreKeys = ['onsite', 'remote']
|
||||
const ignoreKeys = ['onsite', 'remote', 'title']
|
||||
|
||||
const draft = shouldSaveDraft ? draftController.get() : undefined
|
||||
let draft = shouldSaveDraft ? ($draftsStore[recruit.mixin.Candidate] as CandidateDraft) : undefined
|
||||
$: draft = shouldSaveDraft ? ($draftsStore[recruit.mixin.Candidate] as CandidateDraft) : undefined
|
||||
let object = draft ?? getEmptyCandidate()
|
||||
|
||||
function draftChange (draft: CandidateDraft | undefined) {
|
||||
if (draft === undefined) {
|
||||
object = getEmptyCandidate()
|
||||
} else {
|
||||
object = draft
|
||||
}
|
||||
}
|
||||
|
||||
function objectChange (object: CandidateDraft, empty: any) {
|
||||
if (shouldSaveDraft) {
|
||||
draftController.save(object, empty)
|
||||
}
|
||||
}
|
||||
|
||||
$: objectChange(object, empty)
|
||||
$: draftChange(draft)
|
||||
|
||||
type resumeFile = {
|
||||
name: string
|
||||
uuid: string
|
||||
@ -113,12 +132,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSaveDraft) {
|
||||
draftController.watch(object, empty)
|
||||
}
|
||||
|
||||
onDestroy(() => draftController.unsubscribe())
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let inputFile: HTMLInputElement
|
||||
@ -643,6 +656,9 @@
|
||||
toClass={contact.class.Contact}
|
||||
{ignoreKeys}
|
||||
extraProps={{ showNavigate: false }}
|
||||
on:update={() => {
|
||||
object = object
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
|
@ -55,7 +55,6 @@
|
||||
} from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { ObjectBox } from '@hcengineering/view-resources'
|
||||
import { onDestroy } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { activeComponent, activeSprint, generateIssueShortLink, getIssueId, updateIssueRelation } from '../issues'
|
||||
import tracker from '../plugin'
|
||||
@ -84,7 +83,8 @@
|
||||
|
||||
const draftController = new DraftController<any>(tracker.ids.IssueDraft)
|
||||
|
||||
const draft: IssueDraft | undefined = shouldSaveDraft ? draftController.get() : undefined
|
||||
let draft = shouldSaveDraft ? ($draftsStore[tracker.ids.IssueDraft] as IssueDraft) : undefined
|
||||
$: draft = shouldSaveDraft ? ($draftsStore[tracker.ids.IssueDraft] as IssueDraft) : undefined
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const parentQuery = createQuery()
|
||||
@ -92,6 +92,24 @@
|
||||
|
||||
let object = draft ?? getDefaultObject()
|
||||
|
||||
function draftChange (draft: IssueDraft | undefined) {
|
||||
if (draft === undefined) {
|
||||
object = getDefaultObject()
|
||||
} else {
|
||||
object = draft
|
||||
descriptionBox?.setContent(object.description)
|
||||
}
|
||||
}
|
||||
|
||||
function objectChange (object: IssueDraft, empty: any) {
|
||||
if (shouldSaveDraft) {
|
||||
draftController.save(object, empty)
|
||||
}
|
||||
}
|
||||
|
||||
$: objectChange(object, empty)
|
||||
$: draftChange(draft)
|
||||
|
||||
$: if (object.parentIssue) {
|
||||
parentQuery.query(
|
||||
tracker.class.Issue,
|
||||
@ -297,12 +315,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: watch(empty)
|
||||
function watch (empty: Record<string, any>): void {
|
||||
if (!shouldSaveDraft) return
|
||||
draftController.watch(object, empty)
|
||||
}
|
||||
|
||||
async function createIssue () {
|
||||
const _id: Ref<Issue> = generateId()
|
||||
if (!canSave || object.status === undefined) {
|
||||
@ -390,6 +402,7 @@
|
||||
draftController.remove()
|
||||
resetObject()
|
||||
descriptionBox?.removeDraft(false)
|
||||
subIssuesComponent.removeChildDraft()
|
||||
}
|
||||
|
||||
async function showMoreActions (ev: Event) {
|
||||
@ -503,6 +516,7 @@
|
||||
if (result === true) {
|
||||
dispatch('close')
|
||||
resetObject()
|
||||
subIssuesComponent.removeChildDraft()
|
||||
draftController.remove()
|
||||
descriptionBox?.removeDraft(true)
|
||||
}
|
||||
@ -511,8 +525,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
onDestroy(() => draftController.unsubscribe())
|
||||
|
||||
$: objectId = object._id
|
||||
</script>
|
||||
|
||||
|
@ -36,7 +36,9 @@
|
||||
let lastProject = project
|
||||
|
||||
let isCollapsed = false
|
||||
let isCreating = $draftsStore[tracker.ids.IssueDraftChild] !== undefined
|
||||
$: isCreatingMode = $draftsStore[tracker.ids.IssueDraftChild] !== undefined
|
||||
let isManualCreating = false
|
||||
$: isCreating = isCreatingMode || isManualCreating
|
||||
|
||||
async function handleIssueSwap (ev: CustomEvent<{ fromIndex: number; toIndex: number }>) {
|
||||
if (subIssues) {
|
||||
@ -170,7 +172,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
export function removeChildDraft () {
|
||||
draftChild?.removeDraft()
|
||||
}
|
||||
|
||||
$: hasSubIssues = subIssues.length > 0
|
||||
|
||||
let draftChild: DraftIssueChildEditor
|
||||
</script>
|
||||
|
||||
<div class="flex-between clear-mins">
|
||||
@ -200,7 +208,7 @@
|
||||
showTooltip={{ label: tracker.string.AddSubIssues, props: { subIssues: 1 } }}
|
||||
on:click={() => {
|
||||
closeTooltip()
|
||||
isCreating = true
|
||||
isManualCreating = true
|
||||
isCollapsed = false
|
||||
}}
|
||||
/>
|
||||
@ -224,12 +232,13 @@
|
||||
{#if isCreating && project}
|
||||
<ExpandCollapse isExpanded={!isCollapsed} on:changeContent>
|
||||
<DraftIssueChildEditor
|
||||
bind:this={draftChild}
|
||||
{project}
|
||||
{component}
|
||||
{sprint}
|
||||
{shouldSaveDraft}
|
||||
on:close={() => {
|
||||
isCreating = false
|
||||
isManualCreating = false
|
||||
}}
|
||||
on:create={(evt) => {
|
||||
if (subIssues === undefined) {
|
||||
|
@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact, { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import { AssigneeBox } from '@hcengineering/contact-resources'
|
||||
import { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import { AssigneeBox, employeeAccountByIdStore } from '@hcengineering/contact-resources'
|
||||
import { AttachedData, Ref } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Issue, IssueDraft, IssueTemplateData } from '@hcengineering/tracker'
|
||||
@ -58,9 +58,9 @@
|
||||
if (hasSpace(issue)) {
|
||||
const project = await client.findOne(tracker.class.Project, { _id: issue.space })
|
||||
if (project !== undefined) {
|
||||
const accounts = await client.findAll(contact.class.EmployeeAccount, {
|
||||
_id: { $in: project.members as Ref<EmployeeAccount>[] }
|
||||
})
|
||||
const accounts = project.members
|
||||
.map((p) => $employeeAccountByIdStore.get(p as Ref<EmployeeAccount>))
|
||||
.filter((p) => p !== undefined) as EmployeeAccount[]
|
||||
members = accounts.map((p) => p.employee)
|
||||
} else {
|
||||
members = []
|
||||
|
@ -15,11 +15,11 @@
|
||||
<script lang="ts">
|
||||
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
|
||||
import { Account, Doc, generateId, Ref } from '@hcengineering/core'
|
||||
import presentation, { DraftController, getClient, KeyedAttribute } from '@hcengineering/presentation'
|
||||
import presentation, { DraftController, draftsStore, getClient, KeyedAttribute } from '@hcengineering/presentation'
|
||||
import tags, { TagElement, TagReference } from '@hcengineering/tags'
|
||||
import { Component as ComponentType, IssueDraft, IssuePriority, Project, Sprint } from '@hcengineering/tracker'
|
||||
import { Button, Component, EditBox } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import tracker from '../../plugin'
|
||||
import AssigneeEditor from '../issues/AssigneeEditor.svelte'
|
||||
import PriorityEditor from '../issues/PriorityEditor.svelte'
|
||||
@ -36,17 +36,28 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
const draftController = new DraftController<IssueDraft>(tracker.ids.IssueDraftChild)
|
||||
const draft = shouldSaveDraft ? draftController.get() : undefined
|
||||
const draft = shouldSaveDraft ? ($draftsStore[tracker.ids.IssueDraftChild] as IssueDraft) : undefined
|
||||
let object = childIssue !== undefined ? childIssue : draft ?? getIssueDefaults()
|
||||
let thisRef: HTMLDivElement
|
||||
let focusIssueTitle: () => void
|
||||
onDestroy(() => draftController.unsubscribe())
|
||||
|
||||
const key: KeyedAttribute = {
|
||||
key: 'labels',
|
||||
attr: client.getHierarchy().getAttribute(tracker.class.IssueTemplate, 'labels')
|
||||
}
|
||||
|
||||
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(),
|
||||
@ -75,10 +86,14 @@
|
||||
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?.()
|
||||
@ -88,8 +103,12 @@
|
||||
return value.trim()
|
||||
}
|
||||
|
||||
function close () {
|
||||
export function removeDraft () {
|
||||
draftController.remove()
|
||||
}
|
||||
|
||||
function close () {
|
||||
removeDraft()
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
@ -100,7 +119,7 @@
|
||||
|
||||
dispatch(childIssue ? 'close' : 'create', object)
|
||||
|
||||
draftController.remove()
|
||||
removeDraft()
|
||||
resetToDefaults()
|
||||
}
|
||||
|
||||
@ -149,6 +168,7 @@
|
||||
<div class="mt-4 clear-mins" id="sub-issue-description">
|
||||
{#key objectId}
|
||||
<AttachmentStyledBox
|
||||
bind:this={descriptionBox}
|
||||
objectId={object._id}
|
||||
space={project._id}
|
||||
_class={tracker.class.Issue}
|
||||
|
Loading…
Reference in New Issue
Block a user