2022-05-23 07:24:15 +00:00
|
|
|
<!--
|
|
|
|
// Copyright © 2022 Hardcore Engineering Inc.
|
|
|
|
//
|
|
|
|
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License. You may
|
|
|
|
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
//
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
-->
|
|
|
|
<script lang="ts">
|
2023-04-04 06:11:49 +00:00
|
|
|
import core, { AttachedData, FindOptions, Ref, SortingOrder } from '@hcengineering/core'
|
2022-09-21 08:08:25 +00:00
|
|
|
import { getClient, ObjectPopup } from '@hcengineering/presentation'
|
2023-03-24 10:23:44 +00:00
|
|
|
import { calcRank, Issue, IssueDraft } from '@hcengineering/tracker'
|
2022-05-23 07:24:15 +00:00
|
|
|
import { createEventDispatcher } from 'svelte'
|
|
|
|
import tracker from '../plugin'
|
2022-06-30 03:46:46 +00:00
|
|
|
import { getIssueId } from '../issues'
|
2022-07-05 05:00:54 +00:00
|
|
|
import IssueStatusIcon from './issues/IssueStatusIcon.svelte'
|
2022-05-23 07:24:15 +00:00
|
|
|
|
2023-03-24 10:23:44 +00:00
|
|
|
export let value: Issue | AttachedData<Issue> | Issue[] | IssueDraft
|
2022-06-24 12:36:08 +00:00
|
|
|
export let width: 'medium' | 'large' | 'full' = 'large'
|
2022-05-23 07:24:15 +00:00
|
|
|
|
|
|
|
const client = getClient()
|
|
|
|
const dispatch = createEventDispatcher()
|
|
|
|
const options: FindOptions<Issue> = {
|
2022-07-05 05:00:54 +00:00
|
|
|
lookup: {
|
2023-03-17 06:17:53 +00:00
|
|
|
space: tracker.class.Project,
|
2023-04-04 06:11:49 +00:00
|
|
|
status: [tracker.class.IssueStatus, { category: core.class.StatusCategory }]
|
2022-07-05 05:00:54 +00:00
|
|
|
},
|
2022-05-23 07:24:15 +00:00
|
|
|
sort: { modifiedOn: SortingOrder.Descending }
|
|
|
|
}
|
|
|
|
|
|
|
|
async function onClose ({ detail: parentIssue }: CustomEvent<Issue | undefined | null>) {
|
2022-06-24 12:36:08 +00:00
|
|
|
const vv = Array.isArray(value) ? value : [value]
|
|
|
|
for (const docValue of vv) {
|
2022-06-27 06:04:26 +00:00
|
|
|
if (
|
2023-03-24 10:23:44 +00:00
|
|
|
'_class' in docValue &&
|
2022-06-27 06:04:26 +00:00
|
|
|
parentIssue !== undefined &&
|
|
|
|
parentIssue?._id !== docValue.attachedTo &&
|
|
|
|
parentIssue?._id !== docValue._id
|
|
|
|
) {
|
2022-06-24 12:36:08 +00:00
|
|
|
let rank: string | null = null
|
2022-06-10 15:51:31 +00:00
|
|
|
|
2022-06-24 12:36:08 +00:00
|
|
|
if (parentIssue) {
|
|
|
|
const lastAttachedIssue = await client.findOne<Issue>(
|
|
|
|
tracker.class.Issue,
|
|
|
|
{ attachedTo: parentIssue._id },
|
|
|
|
{ sort: { rank: SortingOrder.Descending } }
|
|
|
|
)
|
2022-06-10 15:51:31 +00:00
|
|
|
|
2022-06-24 12:36:08 +00:00
|
|
|
rank = calcRank(lastAttachedIssue, undefined)
|
|
|
|
}
|
2022-06-10 15:51:31 +00:00
|
|
|
|
2022-06-24 12:36:08 +00:00
|
|
|
await client.update(docValue, {
|
|
|
|
attachedTo: parentIssue === null ? tracker.ids.NoParent : parentIssue._id,
|
|
|
|
...(rank ? { rank } : {})
|
|
|
|
})
|
|
|
|
}
|
2022-05-23 07:24:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dispatch('close', parentIssue)
|
|
|
|
}
|
|
|
|
|
2022-06-24 12:36:08 +00:00
|
|
|
$: selected = !Array.isArray(value) ? ('attachedTo' in value ? value.attachedTo : undefined) : undefined
|
|
|
|
$: ignoreObjects = !Array.isArray(value) ? ('_id' in value ? [value._id] : []) : undefined
|
2022-06-27 06:04:26 +00:00
|
|
|
$: docQuery = {
|
|
|
|
'parents.parentId': {
|
|
|
|
$nin: [
|
|
|
|
...new Set(
|
|
|
|
(Array.isArray(value) ? value : [value])
|
|
|
|
.map((issue) => ('_id' in issue ? issue._id : null))
|
|
|
|
.filter((x): x is Ref<Issue> => x !== null)
|
|
|
|
)
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
2022-05-23 07:24:15 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<ObjectPopup
|
|
|
|
_class={tracker.class.Issue}
|
|
|
|
{options}
|
2022-06-27 06:04:26 +00:00
|
|
|
{docQuery}
|
2022-06-10 15:51:31 +00:00
|
|
|
{selected}
|
2022-05-23 07:24:15 +00:00
|
|
|
multiSelect={false}
|
|
|
|
allowDeselect={true}
|
|
|
|
placeholder={tracker.string.SetParent}
|
|
|
|
create={undefined}
|
|
|
|
{ignoreObjects}
|
|
|
|
shadows={true}
|
2022-06-24 12:36:08 +00:00
|
|
|
{width}
|
2023-02-22 07:27:58 +00:00
|
|
|
noSearchField
|
2022-05-23 07:24:15 +00:00
|
|
|
on:update
|
|
|
|
on:close={onClose}
|
|
|
|
>
|
|
|
|
<svelte:fragment slot="item" let:item={issue}>
|
2022-06-24 12:36:08 +00:00
|
|
|
{@const issueId = getIssueId(issue.$lookup.space, issue)}
|
2022-07-05 05:00:54 +00:00
|
|
|
{#if issueId}
|
2022-05-23 07:24:15 +00:00
|
|
|
<div class="flex-center clear-mins w-full h-9">
|
2022-07-05 05:00:54 +00:00
|
|
|
{#if issue?.$lookup?.status}
|
|
|
|
<div class="icon mr-4 h-8">
|
2023-09-04 17:06:34 +00:00
|
|
|
<IssueStatusIcon value={issue.$lookup.status} space={issue.space} size="small" />
|
2022-07-05 05:00:54 +00:00
|
|
|
</div>
|
|
|
|
{/if}
|
2022-05-23 07:24:15 +00:00
|
|
|
<span class="overflow-label flex-no-shrink mr-3">{issueId}</span>
|
2023-03-10 00:08:04 +00:00
|
|
|
<span class="overflow-label w-full content-color">{issue.title}</span>
|
2022-05-23 07:24:15 +00:00
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
</svelte:fragment>
|
|
|
|
</ObjectPopup>
|