mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-23 18:15:03 +02:00
@@ -29,7 +29,7 @@
|
||||
<!-- <Icon icon={tracker.icon.TrackerApplication} size={'medium'} /> -->
|
||||
<FixedColumn key="object-popup-issue-status">
|
||||
{#if st}
|
||||
<IssueStatusIcon value={st} size={'small'} />
|
||||
<IssueStatusIcon value={st} size={'small'} space={value.space} />
|
||||
{/if}
|
||||
</FixedColumn>
|
||||
<span class="ml-2 max-w-120 overflow-label">
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script lang="ts">
|
||||
import presentation, { copyTextToClipboard, createQuery } from '@hcengineering/presentation'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import presentation, { copyTextToClipboard, createQuery } from '@hcengineering/presentation'
|
||||
import { Issue, IssueStatus } from '@hcengineering/tracker'
|
||||
import view from '@hcengineering/view'
|
||||
import {
|
||||
AnySvelteComponent,
|
||||
Button,
|
||||
@@ -15,8 +14,10 @@
|
||||
navigate,
|
||||
parseLocation
|
||||
} from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { fade } from 'svelte/transition'
|
||||
|
||||
import { statusStore } from '@hcengineering/view-resources'
|
||||
import tracker from '../../plugin'
|
||||
import IssuePresenter from './IssuePresenter.svelte'
|
||||
import IssueStatusIcon from './IssueStatusIcon.svelte'
|
||||
@@ -25,7 +26,6 @@
|
||||
export let onRemove: () => void
|
||||
|
||||
const issueQuery = createQuery()
|
||||
const statusQuery = createQuery()
|
||||
|
||||
let issue: Issue | undefined
|
||||
let status: IssueStatus | undefined
|
||||
@@ -42,14 +42,7 @@
|
||||
)
|
||||
|
||||
$: if (issue?.status !== undefined) {
|
||||
statusQuery.query(
|
||||
tracker.class.IssueStatus,
|
||||
{ _id: issue.status },
|
||||
(res) => {
|
||||
status = res[0]
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
status = $statusStore.get(issue.status)
|
||||
}
|
||||
|
||||
const getIcon = (): AnySvelteComponent | undefined => {
|
||||
@@ -107,8 +100,8 @@
|
||||
</div>
|
||||
|
||||
<div class="content flex-row-center flex-wrap gap-2 reverse">
|
||||
{#if status}
|
||||
<IssueStatusIcon value={status} size="small" />
|
||||
{#if status && issue}
|
||||
<IssueStatusIcon value={status} space={issue.space} size="small" />
|
||||
{/if}
|
||||
{#if issue}
|
||||
<IssuePresenter value={issue} />
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
displaySt = result
|
||||
}
|
||||
|
||||
$: updateStatus(txes, $statusStore.getIdMap(), $ticker)
|
||||
$: updateStatus(txes, $statusStore, $ticker)
|
||||
</script>
|
||||
|
||||
<Row>
|
||||
@@ -93,6 +93,6 @@
|
||||
</span>
|
||||
</Row>
|
||||
{#each displaySt as st}
|
||||
<StatusPresenter value={st.status} />
|
||||
<StatusPresenter value={st.status} space={issue.space} />
|
||||
<Duration value={st.duration} />
|
||||
{/each}
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { StatusCategory, WithLookup } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { IssueStatus } from '@hcengineering/tracker'
|
||||
import core, { Ref, StatusCategory, WithLookup } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { getStates } from '@hcengineering/task'
|
||||
import { IssueStatus, Project } from '@hcengineering/tracker'
|
||||
import { IconSize } from '@hcengineering/ui'
|
||||
import { statusStore } from '@hcengineering/view-resources'
|
||||
import tracker from '../../plugin'
|
||||
@@ -23,6 +24,7 @@
|
||||
|
||||
export let value: WithLookup<IssueStatus>
|
||||
export let size: IconSize
|
||||
export let space: Ref<Project> | undefined
|
||||
|
||||
const dynamicFillCategories = [tracker.issueStatusCategory.Started]
|
||||
|
||||
@@ -35,17 +37,16 @@
|
||||
count: number | undefined
|
||||
} = { index: undefined, count: undefined }
|
||||
|
||||
const spaceQuery = createQuery()
|
||||
let _space: Project | undefined = undefined
|
||||
$: space
|
||||
? spaceQuery.query(tracker.class.Project, { _id: space }, (res) => {
|
||||
_space = res[0]
|
||||
})
|
||||
: (_space = undefined)
|
||||
|
||||
$: if (value.category === tracker.issueStatusCategory.Started) {
|
||||
const _s = [
|
||||
...$statusStore.filter(
|
||||
(it) =>
|
||||
it.ofAttribute === value.ofAttribute &&
|
||||
it.category === tracker.issueStatusCategory.Started &&
|
||||
it.space === value.space
|
||||
)
|
||||
]
|
||||
_s.sort((a, b) => a.rank.localeCompare(b.rank))
|
||||
statuses = _s
|
||||
statuses = getStates(_space, $statusStore).filter((p) => p.category === tracker.issueStatusCategory.Started)
|
||||
}
|
||||
|
||||
async function updateCategory (status: WithLookup<IssueStatus>, statuses: IssueStatus[]) {
|
||||
|
||||
@@ -42,8 +42,7 @@
|
||||
$: activeStatusQuery.query(
|
||||
tracker.class.IssueStatus,
|
||||
{
|
||||
category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] },
|
||||
...spaceQuery
|
||||
category: { $in: [tracker.issueStatusCategory.Unstarted, tracker.issueStatusCategory.Started] }
|
||||
},
|
||||
(result) => {
|
||||
active = { status: { $in: result.map(({ _id }) => _id) }, ...spaceQuery }
|
||||
@@ -54,7 +53,7 @@
|
||||
let backlog: DocumentQuery<Issue> = {}
|
||||
$: backlogStatusQuery.query(
|
||||
tracker.class.IssueStatus,
|
||||
{ category: tracker.issueStatusCategory.Backlog, ...spaceQuery },
|
||||
{ category: tracker.issueStatusCategory.Backlog },
|
||||
(result) => {
|
||||
backlog = { status: { $in: result.map(({ _id }) => _id) }, ...spaceQuery }
|
||||
}
|
||||
|
||||
@@ -76,7 +76,13 @@
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</SpaceHeader>
|
||||
<FilterBar _class={tracker.class.Issue} query={searchQuery} {viewOptions} on:change={(e) => (resultQuery = e.detail)} />
|
||||
<FilterBar
|
||||
_class={tracker.class.Issue}
|
||||
{space}
|
||||
query={searchQuery}
|
||||
{viewOptions}
|
||||
on:change={(e) => (resultQuery = e.detail)}
|
||||
/>
|
||||
<slot name="afterHeader" />
|
||||
<div class="popupPanel rowContent">
|
||||
{#if viewlet && viewOptions}
|
||||
|
||||
@@ -196,7 +196,7 @@
|
||||
viewOptions: ViewOptions,
|
||||
viewOptionsModel: ViewOptionModel[] | undefined
|
||||
) {
|
||||
categories = await getCategories(client, _class, docs, groupByKey, viewlet.descriptor)
|
||||
categories = await getCategories(client, _class, space, docs, groupByKey, viewlet.descriptor)
|
||||
for (const viewOption of viewOptionsModel ?? []) {
|
||||
if (viewOption.actionTarget !== 'category') continue
|
||||
const categoryFunc = viewOption as CategoryOption
|
||||
@@ -210,6 +210,7 @@
|
||||
const res = await categoryAction(
|
||||
_class,
|
||||
spaces.length > 0 ? { space: { $in: Array.from(spaces.values()) } } : {},
|
||||
space,
|
||||
groupByKey,
|
||||
update,
|
||||
queryId,
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
import StatusMovePresenter from './move/StatusMovePresenter.svelte'
|
||||
import SelectReplacement from './move/SelectReplacement.svelte'
|
||||
import PriorityEditor from './PriorityEditor.svelte'
|
||||
import { getStates } from '@hcengineering/task'
|
||||
|
||||
export let selected: Issue | Issue[]
|
||||
$: docs = Array.isArray(selected) ? selected : [selected]
|
||||
@@ -48,7 +49,7 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
let currentSpace: Project | undefined
|
||||
let targetProject: Project | undefined
|
||||
let space: Ref<Project>
|
||||
|
||||
$: {
|
||||
@@ -61,32 +62,22 @@
|
||||
let processing = false
|
||||
|
||||
async function createMissingStatus (st: Ref<Status>): Promise<void> {
|
||||
const cur = $statusStore.get(st)
|
||||
const statuses = $statusStore.filter((it) => it.space === currentSpace?._id)
|
||||
if (cur === undefined || currentSpace === undefined || statuses.find((s) => s.name === cur.name) !== undefined) {
|
||||
return
|
||||
if (targetProject) {
|
||||
await client.update(targetProject, { $push: { states: st } })
|
||||
}
|
||||
await client.createDoc(cur._class, currentSpace._id, {
|
||||
name: cur.name,
|
||||
ofAttribute: cur.ofAttribute,
|
||||
category: cur.category,
|
||||
color: cur.color,
|
||||
description: cur.description,
|
||||
rank: cur.rank
|
||||
})
|
||||
}
|
||||
|
||||
async function createMissingComponent (c: Ref<Component>): Promise<void> {
|
||||
const cur = $componentStore.get(c)
|
||||
const components = $componentStore.filter((it) => it.space === currentSpace?._id)
|
||||
const components = $componentStore.filter((it) => it.space === targetProject?._id)
|
||||
if (
|
||||
cur === undefined ||
|
||||
currentSpace === undefined ||
|
||||
targetProject === undefined ||
|
||||
components.find((c) => c.label === cur.label) !== undefined
|
||||
) {
|
||||
return
|
||||
}
|
||||
await client.createDoc(cur._class, currentSpace._id, {
|
||||
await client.createDoc(cur._class, targetProject._id, {
|
||||
label: cur.label,
|
||||
attachments: 0,
|
||||
description: cur.description,
|
||||
@@ -96,7 +87,7 @@
|
||||
}
|
||||
|
||||
const moveAll = async () => {
|
||||
if (currentSpace === undefined) {
|
||||
if (targetProject === undefined) {
|
||||
return
|
||||
}
|
||||
processing = true
|
||||
@@ -133,7 +124,7 @@
|
||||
issueToUpdate.set(issue._id, upd)
|
||||
}
|
||||
|
||||
await moveIssueToSpace(client, docs, currentSpace, issueToUpdate)
|
||||
await moveIssueToSpace(client, docs, targetProject, issueToUpdate)
|
||||
processing = false
|
||||
dispatch('close')
|
||||
}
|
||||
@@ -145,7 +136,7 @@
|
||||
let componentToUpdate: Record<Ref<Component>, ComponentToUpdate | undefined> = {}
|
||||
|
||||
$: targetSpaceQuery.query(tracker.class.Project, { _id: space }, (res) => {
|
||||
;[currentSpace] = res
|
||||
;[targetProject] = res
|
||||
})
|
||||
|
||||
let toMove: Issue[] = []
|
||||
@@ -159,8 +150,8 @@
|
||||
|
||||
$: if (keepOriginalAttribytes) {
|
||||
setOriginalAttributes()
|
||||
} else if (currentSpace !== undefined) {
|
||||
setReplacementAttributres(currentSpace)
|
||||
} else if (targetProject !== undefined) {
|
||||
setReplacementAttributres(targetProject)
|
||||
}
|
||||
|
||||
const componentQuery = createQuery()
|
||||
@@ -175,11 +166,11 @@
|
||||
milestones = res
|
||||
})
|
||||
|
||||
$: statuses = $statusStore.filter((it) => it.space === currentSpace?._id)
|
||||
$: statuses = getStates(targetProject, $statusStore)
|
||||
|
||||
let keepOriginalAttribytes: boolean = false
|
||||
let showManageAttributes: boolean = false
|
||||
$: isManageAttributesAvailable = issueToUpdate.size > 0 && docs[0]?.space !== currentSpace?._id
|
||||
$: isManageAttributesAvailable = issueToUpdate.size > 0 && docs[0]?.space !== targetProject?._id
|
||||
|
||||
function setOriginalAttributes () {
|
||||
for (const issue of toMove) {
|
||||
@@ -225,7 +216,7 @@
|
||||
upd.status = undefined
|
||||
}
|
||||
if (upd.status === undefined) {
|
||||
upd.status = findTargetStatus($statusStore, issue.status, space, true) ?? currentSpace.defaultIssueStatus
|
||||
upd.status = findTargetStatus(issue.status, currentSpace, $statusStore, true) ?? currentSpace.defaultIssueStatus
|
||||
}
|
||||
|
||||
if (issue.component !== undefined) {
|
||||
@@ -268,7 +259,7 @@
|
||||
label={showManageAttributes ? tracker.string.ManageAttributes : tracker.string.MoveIssues}
|
||||
okLabel={view.string.Move}
|
||||
okAction={moveAll}
|
||||
canSave={docs[0]?.space !== currentSpace?._id}
|
||||
canSave={docs[0]?.space !== targetProject?._id}
|
||||
onCancel={() => dispatch('close')}
|
||||
backAction={() => {
|
||||
showManageAttributes = !showManageAttributes
|
||||
@@ -281,7 +272,7 @@
|
||||
hideAttachments
|
||||
numberOfBlocks={showManageAttributes
|
||||
? toMove.length
|
||||
: currentSpace !== undefined && !keepOriginalAttribytes && docs[0]?.space !== currentSpace?._id
|
||||
: targetProject !== undefined && !keepOriginalAttribytes && docs[0]?.space !== targetProject?._id
|
||||
? 1
|
||||
: 0}
|
||||
on:changeContent
|
||||
@@ -306,9 +297,9 @@
|
||||
|
||||
{#if !showManageAttributes}
|
||||
<div class="flex-between">
|
||||
{#if currentSpace !== undefined}
|
||||
{#if targetProject !== undefined}
|
||||
<SpaceSelector
|
||||
_class={currentSpace._class}
|
||||
_class={targetProject._class}
|
||||
label={hierarchy.getClass(tracker.class.Project).label}
|
||||
bind:space
|
||||
kind={'regular'}
|
||||
@@ -337,36 +328,37 @@
|
||||
|
||||
<svelte:fragment slot="blocks" let:block>
|
||||
{#if !showManageAttributes}
|
||||
{#if currentSpace !== undefined && !keepOriginalAttribytes}
|
||||
{#if targetProject !== undefined && !keepOriginalAttribytes}
|
||||
<SelectReplacement
|
||||
currentProject={space}
|
||||
{statuses}
|
||||
{components}
|
||||
targetProject={currentSpace}
|
||||
{targetProject}
|
||||
issues={toMove}
|
||||
bind:statusToUpdate
|
||||
bind:componentToUpdate
|
||||
/>
|
||||
{/if}
|
||||
{:else if toMove.length > 0 && currentSpace}
|
||||
{:else if toMove.length > 0 && targetProject}
|
||||
{@const issue = toMove[block]}
|
||||
{@const upd = issueToUpdate.get(issue._id) ?? {}}
|
||||
{@const originalComponent = components.find((it) => it._id === issue.component)}
|
||||
{@const targetComponent = components.find(
|
||||
(it) => it.space === currentSpace?._id && it.label === originalComponent?.label
|
||||
(it) => it.space === targetProject?._id && it.label === originalComponent?.label
|
||||
)}
|
||||
{#key keepOriginalAttribytes}
|
||||
{#if issue.space !== currentSpace._id && (upd.status !== undefined || upd.component !== undefined)}
|
||||
{#if issue.space !== targetProject._id && (upd.status !== undefined || upd.component !== undefined)}
|
||||
<div class="flex-row-center min-h-9 gap-1-5 content-color">
|
||||
<PriorityEditor value={issue} isEditable={false} kind={'list'} size={'small'} shouldShowLabel={false} />
|
||||
<IssuePresenter value={issue} disabled kind={'list'} />
|
||||
<TitlePresenter disabled value={issue} showParent={false} maxWidth={'7.5rem'} />
|
||||
</div>
|
||||
{#key upd.status}
|
||||
<StatusMovePresenter {issue} bind:issueToUpdate targetProject={currentSpace} {statuses} />
|
||||
<StatusMovePresenter currentProject={space} {issue} bind:issueToUpdate {targetProject} {statuses} />
|
||||
{/key}
|
||||
{#if targetComponent === undefined}
|
||||
{#key upd.component}
|
||||
<ComponentMovePresenter {issue} bind:issueToUpdate targetProject={currentSpace} {components} />
|
||||
<ComponentMovePresenter {issue} bind:issueToUpdate {targetProject} {components} />
|
||||
{/key}
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AttachedData, Ref, StatusManager, WithLookup } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { AttachedData, IdMap, Ref, Status, WithLookup } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Issue, IssueDraft, IssueStatus, Project } from '@hcengineering/tracker'
|
||||
import {
|
||||
ButtonKind,
|
||||
@@ -31,7 +31,6 @@
|
||||
import tracker from '../../plugin'
|
||||
import IssueStatusIcon from './IssueStatusIcon.svelte'
|
||||
import StatusPresenter from './StatusPresenter.svelte'
|
||||
|
||||
type ValueType = Issue | (AttachedData<Issue> & { space: Ref<Project> }) | IssueDraft
|
||||
|
||||
export let value: ValueType
|
||||
@@ -82,11 +81,19 @@
|
||||
)
|
||||
}
|
||||
|
||||
function getStatuses (statusStore: StatusManager, value: ValueType): WithLookup<IssueStatus>[] {
|
||||
return statusStore.filter((it) => it.space === value?.space)
|
||||
let space: Project | undefined = undefined
|
||||
|
||||
const query = createQuery()
|
||||
$: query.query(tracker.class.Project, { _id: value.space }, (res) => {
|
||||
space = res[0]
|
||||
})
|
||||
|
||||
function getStatuses (statuses: IdMap<Status>, space: Project | undefined): IssueStatus[] {
|
||||
if (space === undefined) return []
|
||||
return space.states.map((p) => statuses.get(p) as IssueStatus).filter((p) => p !== undefined)
|
||||
}
|
||||
|
||||
$: statuses = getStatuses($statusStore, value)
|
||||
$: statuses = getStatuses($statusStore, space)
|
||||
|
||||
function getSelectedStatus (
|
||||
statuses: WithLookup<IssueStatus>[] | undefined,
|
||||
@@ -127,7 +134,11 @@
|
||||
on:click={handleStatusEditorOpened}
|
||||
>
|
||||
<div class="flex-center flex-no-shrink square-4">
|
||||
{#if selectedStatus}<IssueStatusIcon value={selectedStatus} size={kind === 'list' ? 'small' : 'medium'} />{/if}
|
||||
{#if selectedStatus}<IssueStatusIcon
|
||||
value={selectedStatus}
|
||||
size={kind === 'list' ? 'small' : 'medium'}
|
||||
space={value.space}
|
||||
/>{/if}
|
||||
</div>
|
||||
{#if selectedStatusLabel}
|
||||
<span
|
||||
@@ -152,7 +163,7 @@
|
||||
>
|
||||
<svelte:fragment slot="icon">
|
||||
{#if selectedStatus}
|
||||
<IssueStatusIcon value={selectedStatus} size={iconSize} />
|
||||
<IssueStatusIcon value={selectedStatus} size={iconSize} space={value.space} />
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="content">
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { IssueStatus } from '@hcengineering/tracker'
|
||||
import { IssueStatus, Project } from '@hcengineering/tracker'
|
||||
import IssueStatusIcon from './IssueStatusIcon.svelte'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import core, { IdMap, Ref, StatusCategory, toIdMap } from '@hcengineering/core'
|
||||
import { statusStore } from '@hcengineering/view-resources'
|
||||
|
||||
export let value: Ref<IssueStatus>[]
|
||||
export let space: Ref<Project> | undefined
|
||||
|
||||
let statuses: IssueStatus[] = []
|
||||
|
||||
@@ -31,7 +32,6 @@
|
||||
|
||||
function sort (value: IssueStatus[], categories: IdMap<StatusCategory>): IssueStatus[] {
|
||||
return value.sort((a, b) => {
|
||||
if (a.category === b.category) return a.rank.localeCompare(b.rank)
|
||||
if (a.category === undefined) return -1
|
||||
if (b.category === undefined) return 1
|
||||
const aCat = categories.get(a.category)
|
||||
@@ -42,14 +42,14 @@
|
||||
})
|
||||
}
|
||||
|
||||
$: statuses = sort(value.map((p) => $statusStore.getIdMap().get(p)) as IssueStatus[], categories)
|
||||
$: statuses = sort(value.map((p) => $statusStore.get(p)) as IssueStatus[], categories)
|
||||
</script>
|
||||
|
||||
<div class="flex-presenter flex-gap-1-5">
|
||||
{#each statuses as value, i}
|
||||
{#if value && i < 5}
|
||||
<div>
|
||||
<IssueStatusIcon {value} size={'small'} />
|
||||
<IssueStatusIcon {space} {value} size={'small'} />
|
||||
</div>
|
||||
{/if}
|
||||
{/each}
|
||||
|
||||
@@ -13,10 +13,12 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { IssueStatus } from '@hcengineering/tracker'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { IssueStatus, Project } from '@hcengineering/tracker'
|
||||
import IssueStatusIcon from './IssueStatusIcon.svelte'
|
||||
|
||||
export let value: IssueStatus | undefined
|
||||
export let space: Ref<Project>
|
||||
export let size: 'small' | 'medium' = 'small'
|
||||
export let kind: 'list-header' | undefined = undefined
|
||||
export let colorInherit: boolean = false
|
||||
@@ -27,7 +29,7 @@
|
||||
{#if value}
|
||||
<div class="flex-presenter cursor-default" style:color={'inherit'}>
|
||||
{#if !inline}
|
||||
<IssueStatusIcon {value} {size} on:accent-color />
|
||||
<IssueStatusIcon {value} {size} {space} on:accent-color />
|
||||
{/if}
|
||||
<span
|
||||
class="overflow-label"
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Ref, Status, StatusValue } from '@hcengineering/core'
|
||||
import { Project } from '@hcengineering/tracker'
|
||||
import { statusStore } from '@hcengineering/view-resources'
|
||||
import StatusPresenter from './StatusPresenter.svelte'
|
||||
|
||||
export let value: Ref<Status> | StatusValue | undefined
|
||||
export let space: Ref<Project>
|
||||
export let size: 'small' | 'medium' = 'medium'
|
||||
export let kind: 'list-header' | undefined = undefined
|
||||
export let colorInherit: boolean = false
|
||||
@@ -27,5 +29,5 @@
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<StatusPresenter value={statusValue} {size} {kind} {colorInherit} {accent} on:accent-color />
|
||||
<StatusPresenter {space} value={statusValue} {size} {kind} {colorInherit} {accent} on:accent-color />
|
||||
{/if}
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
subIssuesQeury.unsubscribe()
|
||||
}
|
||||
|
||||
$: parentStatus = parentIssue ? $statusStore.getIdMap().get(parentIssue.status) : undefined
|
||||
$: parentStatus = parentIssue ? $statusStore.get(parentIssue.status) : undefined
|
||||
</script>
|
||||
|
||||
{#if parentIssue}
|
||||
@@ -132,7 +132,7 @@
|
||||
>
|
||||
{#if parentStatus}
|
||||
<div class="pr-2">
|
||||
<IssueStatusIcon value={parentStatus} size="small" />
|
||||
<IssueStatusIcon space={parentIssue.space} value={parentStatus} size="small" />
|
||||
</div>
|
||||
{/if}
|
||||
{#if issue.$lookup?.space}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Ref, SortingOrder, WithLookup } from '@hcengineering/core'
|
||||
import { Ref, SortingOrder, Status, WithLookup } from '@hcengineering/core'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Issue, Project } from '@hcengineering/tracker'
|
||||
import {
|
||||
@@ -79,13 +79,17 @@
|
||||
}
|
||||
|
||||
$: if (subIssues) {
|
||||
const doneStatuses = $statusStore
|
||||
.getDocs()
|
||||
.filter(
|
||||
(s) =>
|
||||
s.category === tracker.issueStatusCategory.Completed || s.category === tracker.issueStatusCategory.Canceled
|
||||
)
|
||||
.map((p) => p._id)
|
||||
const doneStatuses = project
|
||||
? project.states
|
||||
.map((p) => $statusStore.get(p))
|
||||
.filter((p) => p !== undefined)
|
||||
.filter(
|
||||
(s) =>
|
||||
s?.category === tracker.issueStatusCategory.Completed ||
|
||||
s?.category === tracker.issueStatusCategory.Canceled
|
||||
)
|
||||
.map((p) => (p as Status)._id)
|
||||
: []
|
||||
countComplete = subIssues.filter((si) => doneStatuses.includes(si.status)).length
|
||||
}
|
||||
$: hasSubIssues = (subIssues?.length ?? 0) > 0
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import { statusStore } from '@hcengineering/view-resources'
|
||||
|
||||
import tracker from '../../../plugin'
|
||||
import { ComponentToUpdate, StatusToUpdate, findTargetStatus } from '../../../utils'
|
||||
import { ComponentToUpdate, StatusToUpdate } from '../../../utils'
|
||||
import ComponentPresenter from '../../components/ComponentPresenter.svelte'
|
||||
import ComponentRefPresenter from '../../components/ComponentRefPresenter.svelte'
|
||||
import StatusRefPresenter from '../StatusRefPresenter.svelte'
|
||||
@@ -27,6 +27,7 @@
|
||||
import ComponentReplacementPopup from './ComponentReplacementPopup.svelte'
|
||||
|
||||
export let targetProject: Project
|
||||
export let currentProject: Ref<Project>
|
||||
export let issues: Issue[]
|
||||
export let statuses: IssueStatus[] = []
|
||||
export let components: Component[] = []
|
||||
@@ -36,15 +37,17 @@
|
||||
$: if (targetProject !== undefined) {
|
||||
for (const i of issues) {
|
||||
const status = statusToUpdate[i.status]
|
||||
if (status !== undefined && !status.create) {
|
||||
if ($statusStore.get(status.ref)?.space !== targetProject._id) {
|
||||
statusToUpdate[i.status] = undefined
|
||||
if (status?.create !== true) {
|
||||
if (!targetProject.states.includes(i.status)) {
|
||||
if (status?.ref === undefined) {
|
||||
statusToUpdate[i.status] = { ref: targetProject.defaultIssueStatus }
|
||||
} else if (!targetProject.states.includes(status.ref)) {
|
||||
statusToUpdate[i.status] = { ref: targetProject.defaultIssueStatus }
|
||||
}
|
||||
} else {
|
||||
delete statusToUpdate[i.status]
|
||||
}
|
||||
}
|
||||
if (statusToUpdate[i.status] === undefined) {
|
||||
const targetStatus = findTargetStatus($statusStore, i.status, targetProject._id, true)
|
||||
statusToUpdate[i.status] = { ref: targetStatus ?? targetProject.defaultIssueStatus }
|
||||
}
|
||||
|
||||
if (i.component !== undefined && i.component !== null) {
|
||||
const cur = components.find((it) => it._id === i.component)
|
||||
@@ -95,7 +98,7 @@
|
||||
{#each Object.keys(statusToUpdate) as status}
|
||||
{@const newStatus = statusToUpdate[status]}
|
||||
<div class="flex-between min-h-11">
|
||||
<StatusRefPresenter value={getStatusRef(status)} kind={'list-header'} />
|
||||
<StatusRefPresenter value={getStatusRef(status)} space={currentProject} kind={'list-header'} />
|
||||
<IconArrowRight size={'small'} fill={'var(--theme-halfcontent-color)'} />
|
||||
</div>
|
||||
<div class="flex-row-center min-h-11">
|
||||
@@ -108,6 +111,7 @@
|
||||
StatusReplacementPopup,
|
||||
{
|
||||
statuses,
|
||||
space: targetProject._id,
|
||||
original: $statusStore.get(getStatusRef(status)),
|
||||
selected: getStatusRef(newStatus.ref)
|
||||
},
|
||||
@@ -123,7 +127,7 @@
|
||||
}}
|
||||
>
|
||||
<span slot="content" class="flex-row-center pointer-events-none">
|
||||
<StatusRefPresenter value={getStatusRef(newStatus.ref)} />
|
||||
<StatusRefPresenter space={targetProject._id} value={getStatusRef(newStatus.ref)} />
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
export let issue: Issue
|
||||
export let targetProject: Project
|
||||
export let currentProject: Ref<Project>
|
||||
export let issueToUpdate: Map<Ref<Issue>, IssueToUpdate> = new Map()
|
||||
export let statuses: IssueStatus[]
|
||||
|
||||
@@ -33,7 +34,7 @@
|
||||
|
||||
<Grid rowGap={0.25} topGap>
|
||||
<div class="flex-between min-h-11">
|
||||
<StatusRefPresenter value={issue.status} size={'small'} />
|
||||
<StatusRefPresenter space={currentProject} value={issue.status} size={'small'} />
|
||||
<IconArrowRight size={'small'} fill={'var(--theme-halfcontent-color)'} />
|
||||
</div>
|
||||
<div class="flex-row-center min-h-11">
|
||||
@@ -62,7 +63,7 @@
|
||||
}}
|
||||
>
|
||||
<span slot="content" class="flex-row-center pointer-events-none">
|
||||
<StatusRefPresenter value={replace} />
|
||||
<StatusRefPresenter space={targetProject._id} value={replace} />
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
import { IssueStatus } from '@hcengineering/tracker'
|
||||
import { IssueStatus, Project } from '@hcengineering/tracker'
|
||||
import tracker from '../../../plugin'
|
||||
import { StatusPresenter } from '@hcengineering/view-resources'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
@@ -26,6 +26,7 @@
|
||||
export let statuses: IssueStatus[] | undefined
|
||||
export let original: IssueStatus | undefined
|
||||
export let selected: Ref<IssueStatus>
|
||||
export let space: Ref<Project>
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
@@ -50,7 +51,7 @@
|
||||
<div class="flex-between w-full">
|
||||
<div class="flex-row-center">
|
||||
<div class="pr-2">
|
||||
<IssueStatusIcon value={status} size={'small'} />
|
||||
<IssueStatusIcon value={status} size={'small'} {space} />
|
||||
</div>
|
||||
<StatusPresenter value={status} />
|
||||
</div>
|
||||
@@ -83,7 +84,7 @@
|
||||
<div class="flex-between w-full">
|
||||
<div class="flex-row-center">
|
||||
<div class="pr-2">
|
||||
<IssueStatusIcon value={original} size={'small'} />
|
||||
<IssueStatusIcon value={original} size={'small'} {space} />
|
||||
</div>
|
||||
<StatusPresenter value={original} />
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@
|
||||
export let issue: Issue
|
||||
export let size: 'small' | 'medium' | 'large' = 'small'
|
||||
|
||||
$: status = $statusStore.getIdMap().get(issue.status)
|
||||
$: status = $statusStore.get(issue.status)
|
||||
$: huge = size === 'medium' || size === 'large'
|
||||
$: text = project ? `${getIssueId(project, issue)} ${issue.title}` : issue.title
|
||||
</script>
|
||||
@@ -31,7 +31,7 @@
|
||||
<div class="flex-row-center">
|
||||
{#if status}
|
||||
<div class="icon mr-2">
|
||||
<IssueStatusIcon value={status} {size} />
|
||||
<IssueStatusIcon value={status} {size} space={issue.space} />
|
||||
</div>
|
||||
{/if}
|
||||
<span class="label" class:text-base={huge}>
|
||||
|
||||
@@ -70,8 +70,7 @@
|
||||
}
|
||||
|
||||
$: if (subIssues) {
|
||||
const doneStatuses = $statusStore
|
||||
.getDocs()
|
||||
const doneStatuses = Array.from($statusStore.values())
|
||||
.filter((s) => s.category === tracker.issueStatusCategory.Completed)
|
||||
.map((p) => p._id)
|
||||
countComplete = subIssues.filter((si) => doneStatuses.includes(si.status)).length
|
||||
|
||||
Reference in New Issue
Block a user