Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-09-09 14:43:54 +06:00 committed by GitHub
parent c04b2d47b2
commit a9cd080476
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 118 additions and 25 deletions

View File

@ -19,7 +19,6 @@ import {
DOMAIN_MODEL, DOMAIN_MODEL,
DateRangeMode, DateRangeMode,
Domain, Domain,
FindOptions,
IndexKind, IndexKind,
Markup, Markup,
Ref, Ref,
@ -1518,13 +1517,6 @@ export function createModel (builder: Builder): void {
tracker.completion.IssueCategory tracker.completion.IssueCategory
) )
const statusOptions: FindOptions<IssueStatus> = {
lookup: {
category: core.class.StatusCategory
},
sort: { rank: SortingOrder.Ascending }
}
createAction(builder, { createAction(builder, {
action: view.actionImpl.ShowPopup, action: view.actionImpl.ShowPopup,
actionProps: { actionProps: {
@ -1549,20 +1541,8 @@ export function createModel (builder: Builder): void {
createAction( createAction(
builder, builder,
{ {
action: view.actionImpl.ValueSelector, action: tracker.actionImpl.SelectStatus,
actionPopup: view.component.ValueSelector, actionPopup: tracker.component.StatusSelector,
actionProps: {
attribute: 'status',
_class: tracker.class.IssueStatus,
placeholder: tracker.string.SetStatus,
query: {
ofAttribute: tracker.attribute.IssueStatus
},
fillQuery: {
space: 'space'
},
queryOptions: statusOptions
},
label: tracker.string.Status, label: tracker.string.Status,
icon: tracker.icon.CategoryBacklog, icon: tracker.icon.CategoryBacklog,
keyBinding: ['keyS->keyS'], keyBinding: ['keyS->keyS'],
@ -1577,6 +1557,7 @@ export function createModel (builder: Builder): void {
}, },
tracker.action.SetStatus tracker.action.SetStatus
) )
createAction( createAction(
builder, builder,
{ {

View File

@ -54,7 +54,8 @@ export default mergeIds(trackerId, tracker, {
IssueStatistics: '' as AnyComponent, IssueStatistics: '' as AnyComponent,
TimeSpendReportPopup: '' as AnyComponent, TimeSpendReportPopup: '' as AnyComponent,
NotificationIssuePresenter: '' as AnyComponent, NotificationIssuePresenter: '' as AnyComponent,
MilestoneFilter: '' as AnyComponent MilestoneFilter: '' as AnyComponent,
StatusSelector: '' as AnyComponent
}, },
app: { app: {
Tracker: '' as Ref<Application> Tracker: '' as Ref<Application>
@ -77,6 +78,7 @@ export default mergeIds(trackerId, tracker, {
IssueCategory: '' as Ref<ObjectSearchCategory> IssueCategory: '' as Ref<ObjectSearchCategory>
}, },
actionImpl: { actionImpl: {
SelectStatus: '' as ViewAction,
Move: '' as ViewAction, Move: '' as ViewAction,
CopyToClipboard: '' as ViewAction, CopyToClipboard: '' as ViewAction,
EditWorkflowStatuses: '' as ViewAction, EditWorkflowStatuses: '' as ViewAction,

View File

@ -0,0 +1,104 @@
<script lang="ts">
import core, { DocumentQuery, FindOptions, SortingOrder } from '@hcengineering/core'
import { ObjectPopup, createQuery, getClient } from '@hcengineering/presentation'
import { Issue, IssueStatus, Project } from '@hcengineering/tracker'
import { Label, resizeObserver } from '@hcengineering/ui'
import { ObjectPresenter } from '@hcengineering/view-resources'
import view from '@hcengineering/view-resources/src/plugin'
import { createEventDispatcher } from 'svelte'
import tracker from '../../plugin'
export let value: Issue | Issue[]
const queryOptions: FindOptions<IssueStatus> = {
lookup: {
category: core.class.StatusCategory
},
sort: { category: SortingOrder.Ascending, name: SortingOrder.Ascending }
}
const placeholder = tracker.string.SetStatus
const dispatch = createEventDispatcher()
const client = getClient()
const changeStatus = async (newStatus: any) => {
if (newStatus === undefined) {
dispatch('close', undefined)
return
}
const docs = Array.isArray(value) ? value : [value]
const changed = (d: Issue) => d.status !== newStatus
await Promise.all(
docs.filter(changed).map((it) => {
return client.update(it, { status: newStatus })
})
)
dispatch('close', newStatus)
}
$: current = Array.isArray(value)
? value.every((v) => v.status === (value as Array<Issue>)[0].status)
? (value as Array<Issue>)[0].status
: undefined
: value.status
let finalQuery: DocumentQuery<IssueStatus> = {}
let docMatch = true
$: _space = Array.isArray(value)
? value.every((v) => v.space === (value as Array<Issue>)[0].space)
? (value as Array<Issue>)[0].space
: undefined
: value.space
let project: Project | undefined
const query = createQuery()
$: _space ? query.query(tracker.class.Project, { _id: _space }, (res) => (project = res[0])) : (project = undefined)
function updateQuery (space: Project | undefined): void {
if (space === undefined) {
finalQuery = { ofAttribute: tracker.attribute.IssueStatus }
} else {
finalQuery = { ofAttribute: tracker.attribute.IssueStatus, _id: { $in: space.states } }
}
docMatch = true
}
$: updateQuery(project)
</script>
{#if docMatch}
<ObjectPopup
_class={tracker.class.IssueStatus}
docQuery={finalQuery}
options={queryOptions}
allowDeselect={true}
selected={current}
on:close={(evt) => {
changeStatus(evt.detail === null ? null : evt.detail?._id)
}}
{placeholder}
on:changeContent
>
<svelte:fragment slot="item" let:item>
<div class="flex-row-center flex-grow overflow-label">
<ObjectPresenter
objectId={item._id}
_class={item._class}
value={item}
inline={false}
noUnderline
props={{ disabled: true, inline: false, size: 'small', avatarSize: 'smaller' }}
/>
</div>
</svelte:fragment>
</ObjectPopup>
{:else}
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
<div class="flex-center w-60 h-18">
<Label label={view.string.DontMatchCriteria} />
</div>
</div>
{/if}

View File

@ -75,7 +75,7 @@ import SetDueDateActionPopup from './components/SetDueDateActionPopup.svelte'
import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.svelte' import SetParentIssueActionPopup from './components/SetParentIssueActionPopup.svelte'
import CreateIssueTemplate from './components/templates/CreateIssueTemplate.svelte' import CreateIssueTemplate from './components/templates/CreateIssueTemplate.svelte'
import Statuses from './components/workflow/Statuses.svelte' import Statuses from './components/workflow/Statuses.svelte'
import StatusSelector from './components/issues/StatusSelector.svelte'
import { import {
getIssueId, getIssueId,
getIssueTitle, getIssueTitle,
@ -208,6 +208,10 @@ async function move (issues: Issue | Issue[]): Promise<void> {
showPopup(MoveIssues, { selected: issues }, 'top') showPopup(MoveIssues, { selected: issues }, 'top')
} }
async function selectStatus (doc: Issue | Issue[]): Promise<void> {
showPopup(StatusSelector, { value: doc }, 'top')
}
async function editWorkflowStatuses (project: Project | undefined): Promise<void> { async function editWorkflowStatuses (project: Project | undefined): Promise<void> {
if (project !== undefined) { if (project !== undefined) {
showPopup(Statuses, { projectId: project._id, projectClass: project._class }, 'top') showPopup(Statuses, { projectId: project._id, projectClass: project._class }, 'top')
@ -474,7 +478,8 @@ export default async (): Promise<Resources> => ({
PriorityFilterValuePresenter, PriorityFilterValuePresenter,
StatusFilterValuePresenter, StatusFilterValuePresenter,
ProjectFilterValuePresenter, ProjectFilterValuePresenter,
ComponentFilterValuePresenter ComponentFilterValuePresenter,
StatusSelector
}, },
completion: { completion: {
IssueQuery: async (client: Client, query: string, filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }) => IssueQuery: async (client: Client, query: string, filter?: { in?: RelatedDocument[], nin?: RelatedDocument[] }) =>
@ -497,6 +502,7 @@ export default async (): Promise<Resources> => ({
IsProjectJoined: async (project: Project) => !project.private || project.members.includes(getCurrentAccount()._id) IsProjectJoined: async (project: Project) => !project.private || project.members.includes(getCurrentAccount()._id)
}, },
actionImpl: { actionImpl: {
SelectStatus: selectStatus,
Move: move, Move: move,
EditWorkflowStatuses: editWorkflowStatuses, EditWorkflowStatuses: editWorkflowStatuses,
EditProject: editProject, EditProject: editProject,