TSK-924: Follow proper order for Tracker Kanban (#2815)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2023-03-23 12:41:27 +07:00 committed by GitHub
parent a48012037d
commit 26052dca3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 68 additions and 29 deletions

View File

@ -523,7 +523,7 @@ export function createModel (builder: Builder): void {
key: 'shouldShowSubIssues',
type: 'toggle',
defaultValue: false,
actionTartget: 'query',
actionTarget: 'query',
action: tracker.function.SubIssueQuery,
label: tracker.string.SubIssues
},
@ -531,7 +531,7 @@ export function createModel (builder: Builder): void {
key: 'shouldShowAll',
type: 'toggle',
defaultValue: false,
actionTartget: 'category',
actionTarget: 'category',
action: view.function.ShowEmptyGroups,
label: view.string.ShowEmptyGroups
}

View File

@ -20,7 +20,7 @@ import { IntlString, mergeIds, Resource } from '@hcengineering/platform'
import { trackerId } from '@hcengineering/tracker'
import tracker from '@hcengineering/tracker-resources/src/plugin'
import type { AnyComponent } from '@hcengineering/ui/src/types'
import { Action, ViewAction, Viewlet, ViewletDescriptor } from '@hcengineering/view'
import { Action, ViewAction, Viewlet } from '@hcengineering/view'
import { Application } from '@hcengineering/workbench'
export default mergeIds(trackerId, tracker, {
@ -51,9 +51,7 @@ export default mergeIds(trackerId, tracker, {
IssueList: '' as Ref<Viewlet>,
IssueTemplateList: '' as Ref<Viewlet>,
IssueKanban: '' as Ref<Viewlet>,
SprintList: '' as Ref<Viewlet>,
List: '' as Ref<ViewletDescriptor>,
Kanban: '' as Ref<ViewletDescriptor>
SprintList: '' as Ref<Viewlet>
},
completion: {
IssueQuery: '' as Resource<ObjectSearchFactory>,

View File

@ -41,7 +41,7 @@
showPopup,
tooltip
} from '@hcengineering/ui'
import { CategoryOption, ViewOptionModel, ViewOptions, ViewQueryOption } from '@hcengineering/view'
import { CategoryOption, Viewlet, ViewOptionModel, ViewOptions, ViewQueryOption } from '@hcengineering/view'
import {
ActionContext,
focusStore,
@ -52,6 +52,7 @@
SelectDirection,
selectionStore
} from '@hcengineering/view-resources'
import { sortCategories } from '@hcengineering/view-resources/src/utils'
import { onMount } from 'svelte'
import tracker from '../../plugin'
import { issuesGroupBySorting, mapKanbanCategories } from '../../utils'
@ -71,6 +72,7 @@
export let query: DocumentQuery<Issue> = {}
export let viewOptionsConfig: ViewOptionModel[] | undefined
export let viewOptions: ViewOptions
export let viewlet: Viewlet
$: currentSpace = space || tracker.project.DefaultProject
$: groupBy = (viewOptions.groupBy[0] ?? noCategory) as IssuesGrouping
@ -99,7 +101,7 @@
if (viewOptions === undefined) return query
let result = hierarchy.clone(query)
for (const viewOption of viewOptions) {
if (viewOption.actionTartget !== 'query') continue
if (viewOption.actionTarget !== 'query') continue
const queryOption = viewOption as ViewQueryOption
const f = await getResource(queryOption.action)
result = f(viewOptionsStore[queryOption.key] ?? queryOption.defaultValue, query)
@ -234,9 +236,9 @@
sprints: Sprint[],
assignee: Employee[]
) {
let categories = await getCategories(client, _class, docs, groupByKey)
let categories = await getCategories(client, _class, docs, groupByKey, viewlet.descriptor)
for (const viewOption of viewOptionsModel ?? []) {
if (viewOption.actionTartget !== 'category') continue
if (viewOption.actionTarget !== 'category') continue
const categoryFunc = viewOption as CategoryOption
if (viewOptions[viewOption.key] ?? viewOption.defaultValue) {
const f = await getResource(categoryFunc.action)
@ -247,7 +249,8 @@
res.push(category)
}
}
categories = res
categories = await sortCategories(client, _class, res, groupByKey, viewlet.descriptor)
break
}
}

View File

@ -17,12 +17,14 @@ import type { IntlString, Metadata, Resource } from '@hcengineering/platform'
import { mergeIds } from '@hcengineering/platform'
import { IssueDraft } from '@hcengineering/tracker'
import { AnyComponent, Location } from '@hcengineering/ui'
import { SortFunc, Viewlet, ViewQueryAction } from '@hcengineering/view'
import { SortFunc, Viewlet, ViewletDescriptor, ViewQueryAction } from '@hcengineering/view'
import tracker, { trackerId } from '../../tracker/lib'
export default mergeIds(trackerId, tracker, {
viewlet: {
SubIssues: '' as Ref<Viewlet>
SubIssues: '' as Ref<Viewlet>,
List: '' as Ref<ViewletDescriptor>,
Kanban: '' as Ref<ViewletDescriptor>
},
string: {
More: '' as IntlString,

View File

@ -33,6 +33,8 @@ import { TypeState } from '@hcengineering/kanban'
import { Asset, IntlString, translate } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import {
Component,
ComponentStatus,
Issue,
IssuePriority,
IssuesDateModificationPeriod,
@ -40,11 +42,9 @@ import {
IssuesOrdering,
IssueStatus,
IssueTemplateData,
Component,
ComponentStatus,
Project,
Sprint,
SprintStatus,
Project,
TimeReportDayType
} from '@hcengineering/tracker'
import {
@ -55,10 +55,11 @@ import {
isWeekend,
MILLISECONDS_IN_WEEK
} from '@hcengineering/ui'
import { ViewletDescriptor } from '@hcengineering/view'
import { CategoryQuery, ListSelectionProvider, SelectDirection } from '@hcengineering/view-resources'
import { writable } from 'svelte/store'
import tracker from './plugin'
import { defaultPriorities, defaultComponentStatuses, defaultSprintStatuses, issuePriorities } from './types'
import { defaultComponentStatuses, defaultPriorities, defaultSprintStatuses, issuePriorities } from './types'
export * from './types'
@ -331,11 +332,33 @@ const listIssueStatusOrder = [
tracker.issueStatusCategory.Canceled
] as const
export async function issueStatusSort (value: Array<Ref<IssueStatus>>): Promise<Array<Ref<IssueStatus>>> {
const listIssueKanbanStatusOrder = [
tracker.issueStatusCategory.Backlog,
tracker.issueStatusCategory.Unstarted,
tracker.issueStatusCategory.Started,
tracker.issueStatusCategory.Completed,
tracker.issueStatusCategory.Canceled
] as const
export async function issueStatusSort (
value: Array<Ref<IssueStatus>>,
viewletDescriptorId?: Ref<ViewletDescriptor>
): Promise<Array<Ref<IssueStatus>>> {
return await new Promise((resolve) => {
// TODO: How we track category updates.
const query = createQuery(true)
query.query(tracker.class.IssueStatus, { _id: { $in: value } }, (res) => {
res.sort((a, b) => listIssueStatusOrder.indexOf(a.category) - listIssueStatusOrder.indexOf(b.category))
if (viewletDescriptorId === tracker.viewlet.Kanban) {
res.sort((a, b) => {
const res = listIssueKanbanStatusOrder.indexOf(a.category) - listIssueKanbanStatusOrder.indexOf(b.category)
if (res === 0) {
return a.rank.localeCompare(b.rank)
}
return res
})
} else {
res.sort((a, b) => listIssueStatusOrder.indexOf(a.category) - listIssueStatusOrder.indexOf(b.category))
}
resolve(res.map((p) => p._id))
query.unsubscribe()
})

View File

@ -86,7 +86,7 @@
if (viewOptions === undefined) return query
let result = hierarchy.clone(query)
for (const viewOption of viewOptions) {
if (viewOption.actionTartget !== 'query') continue
if (viewOption.actionTarget !== 'query') continue
const queryOption = viewOption as ViewQueryOption
const f = await getResource(queryOption.action)
result = f(viewOptionsStore[queryOption.key] ?? queryOption.defaultValue, query)

View File

@ -74,7 +74,7 @@
categories = await getCategories(client, _class, docs, groupByKey)
if (level === 0) {
for (const viewOption of viewOptionsModel ?? []) {
if (viewOption.actionTartget !== 'category') continue
if (viewOption.actionTarget !== 'category') continue
const categoryFunc = viewOption as CategoryOption
if (viewOptions[viewOption.key] ?? viewOption.defaultValue) {
const f = await getResource(categoryFunc.action)

View File

@ -43,7 +43,7 @@ import {
Location,
locationToUrl
} from '@hcengineering/ui'
import type { BuildModelOptions, Viewlet } from '@hcengineering/view'
import type { BuildModelOptions, Viewlet, ViewletDescriptor } from '@hcengineering/view'
import view, { AttributeModel, BuildModelKey } from '@hcengineering/view'
import { writable } from 'svelte/store'
import plugin from './plugin'
@ -528,11 +528,24 @@ export async function getCategories (
client: TxOperations,
_class: Ref<Class<Doc>>,
docs: Doc[],
key: string
key: string,
viewletDescriptorId?: Ref<ViewletDescriptor>
): Promise<any[]> {
if (key === noCategory) return [undefined]
const existingCategories = Array.from(new Set(docs.map((x: any) => x[key] ?? undefined)))
return await sortCategories(client, _class, existingCategories, key, viewletDescriptorId)
}
export async function sortCategories (
client: TxOperations,
_class: Ref<Class<Doc>>,
existingCategories: any[],
key: string,
viewletDescriptorId?: Ref<ViewletDescriptor>
): Promise<any[]> {
if (key === noCategory) return [undefined]
const hierarchy = client.getHierarchy()
const existingCategories = Array.from(new Set(docs.map((x: any) => x[key] ?? undefined)))
const attr = hierarchy.getAttribute(_class, key)
if (attr === undefined) return existingCategories
const attrClass = getAttributePresenterClass(hierarchy, attr).attrClass
@ -541,7 +554,7 @@ export async function getCategories (
if (sortFunc?.func === undefined) return existingCategories
const f = await getResource(sortFunc.func)
return await f(existingCategories)
return await f(existingCategories, viewletDescriptorId)
}
export function getKeyLabel<T extends Doc> (

View File

@ -236,7 +236,7 @@ export interface ListHeaderExtra extends Class<Doc> {
/**
* @public
*/
export type SortFunc = Resource<(values: any[]) => Promise<any[]>>
export type SortFunc = Resource<(values: any[], viewletDescriptorId?: Ref<ViewletDescriptor>) => Promise<any[]>>
/**
* @public
@ -483,7 +483,7 @@ export interface ViewOption {
defaultValue: any
label: IntlString
hidden?: (viewOptions: ViewOptions) => boolean
actionTartget?: 'query' | 'category'
actionTarget?: 'query' | 'category'
action?: Resource<(value: any, ...params: any) => any>
}
@ -504,7 +504,7 @@ export type ViewCategoryAction = Resource<
* @public
*/
export interface CategoryOption extends ViewOption {
actionTartget: 'category'
actionTarget: 'category'
action: ViewCategoryAction
}
@ -517,7 +517,7 @@ export type ViewQueryAction = Resource<(value: any, query: DocumentQuery<Doc>) =
* @public
*/
export interface ViewQueryOption extends ViewOption {
actionTartget: 'query'
actionTarget: 'query'
action: ViewQueryAction
}