Fix status filter (#3937)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-11-03 21:31:19 +06:00 committed by GitHub
parent 9f82ec3b7f
commit 66915d29e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 62 additions and 80 deletions

View File

@ -707,7 +707,7 @@ export function createModel (builder: Builder): void {
label: recruit.string.HideArchivedVacancies
}
const applicantViewOptions = (colors: boolean, hides: boolean): ViewOptionsModel => {
const applicantViewOptions = (colors: boolean): ViewOptionsModel => {
const model: ViewOptionsModel = {
groupBy: ['status', 'assignee', 'space', 'createdBy', 'modifiedBy'],
orderBy: [
@ -725,15 +725,14 @@ export function createModel (builder: Builder): void {
actionTarget: 'category',
action: view.function.ShowEmptyGroups,
label: view.string.ShowEmptyGroups
}
},
applicationDoneOption,
vacancyHideOption
]
}
if (colors) {
model.other.push(showColorsViewOption)
}
if (hides) {
model.other.push(...[applicationDoneOption, vacancyHideOption])
}
return model
}
@ -811,7 +810,7 @@ export function createModel (builder: Builder): void {
strict: true,
hiddenKeys: ['name', 'attachedTo']
},
viewOptions: applicantViewOptions(true, true)
viewOptions: applicantViewOptions(true)
},
recruit.viewlet.ListApplicant
)
@ -978,12 +977,8 @@ export function createModel (builder: Builder): void {
attachTo: recruit.class.Applicant,
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
baseQuery: {
isDone: { $ne: true },
'$lookup.space.archived': false
},
viewOptions: {
...applicantViewOptions(false, false),
...applicantViewOptions(false),
groupDepth: 1
},
options: {

View File

@ -412,6 +412,10 @@ export function createModel (builder: Builder): void {
func: task.function.StatusSort
})
builder.mixin(core.class.Status, core.class.Class, view.mixin.AttributeFilter, {
component: task.component.StatusFilter
})
builder.mixin(core.class.Status, core.class.Class, view.mixin.AllValuesFunc, {
func: task.function.GetAllStates
})

View File

@ -753,10 +753,6 @@ export function createModel (builder: Builder): void {
component: view.component.ObjectFilter
})
builder.mixin(core.class.Status, core.class.Class, view.mixin.AttributeFilter, {
component: view.component.StatusFilter
})
builder.mixin(core.class.TypeTimestamp, core.class.Class, view.mixin.AttributeFilter, {
component: view.component.DateFilter,
group: 'bottom'

View File

@ -16,7 +16,7 @@
import core, { Doc, FindResult, IdMap, Ref, RefTo, Space, Status, toIdMap } from '@hcengineering/core'
import { translate } from '@hcengineering/platform'
import presentation, { createQuery, getClient } from '@hcengineering/presentation'
import task, { Project, ProjectType, getStates } from '@hcengineering/task'
import task, { Project, ProjectType } from '@hcengineering/task'
import ui, {
EditWithIcon,
Icon,
@ -30,10 +30,16 @@
themeStore
} from '@hcengineering/ui'
import { Filter } from '@hcengineering/view'
import {
FILTER_DEBOUNCE_MS,
FilterRemovedNotification,
sortFilterValues,
statusStore
} from '@hcengineering/view-resources'
import view from '@hcengineering/view-resources/src/plugin'
import { buildConfigLookup, getPresenter } from '@hcengineering/view-resources/src/utils'
import { createEventDispatcher } from 'svelte'
import { FILTER_DEBOUNCE_MS, FilterRemovedNotification, sortFilterValues, statusStore } from '../..'
import view from '../../plugin'
import { buildConfigLookup, getPresenter } from '../../utils'
import { selectedTypeStore, typeStore } from '..'
export let filter: Filter
export let space: Ref<Space> | undefined = undefined
@ -65,7 +71,12 @@
let filterUpdateTimeout: any | undefined
async function getValues (search: string, typeStore: IdMap<ProjectType>, statusStore: IdMap<Status>): Promise<void> {
async function getValues (
search: string,
selectedType: Ref<ProjectType> | undefined,
typeStore: IdMap<ProjectType>,
statusStore: IdMap<Status>
): Promise<void> {
if (objectsPromise) {
await objectsPromise
}
@ -74,17 +85,15 @@
for (const object of filter.value) {
targets.add(object)
}
if (space !== undefined) {
const _space = await client.findOne(task.class.Project, { _id: space as Ref<Project> })
if (_space) {
values = getStates(_space, typeStore, statusStore)
const type = selectedType ? typeStore.get(selectedType) : undefined
if (type !== undefined) {
values = type?.statuses?.map((p) => statusStore.get(p._id))
for (const value of values) {
targets.add(value?._id)
}
if (search !== '') {
values = values.filter((p) => p?.name.includes(search))
}
}
} else {
const statuses: Status[] = []
for (const status of statusStore.values()) {
@ -162,13 +171,7 @@
const dispatch = createEventDispatcher()
const typesQuery = createQuery()
let types: IdMap<ProjectType> = new Map()
typesQuery.query(task.class.ProjectType, {}, (res) => {
types = toIdMap(res)
})
$: if (targetClass) getValues(search, types, $statusStore.byId)
$: if (targetClass) getValues(search, $selectedTypeStore, $typeStore, $statusStore.byId)
</script>
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>

View File

@ -33,6 +33,8 @@
import { ViewOptions, Viewlet, ViewletDescriptor, ViewletPreference } from '@hcengineering/view'
import { FilterBar, FilterButton, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources'
import task from '../plugin'
import { onDestroy } from 'svelte'
import { selectedTypeStore } from '..'
export let _class: Ref<Class<Doc>>
export let space: Ref<Space> | undefined = undefined
@ -82,6 +84,7 @@
let modeSelectorProps: IModeSelector | undefined = undefined
$: if (mode === undefined && config.length > 0) {
;[[mode]] = config
selectedTypeStore.set(mode as Ref<ProjectType>)
}
$: if (mode !== undefined) {
modeSelectorProps = {
@ -89,9 +92,14 @@
config,
onChange: (_mode: string) => {
mode = _mode
selectedTypeStore.set(mode as Ref<ProjectType>)
}
}
}
onDestroy(() => {
selectedTypeStore.set(undefined)
})
</script>
<div class="ac-header full divide caption-height">

View File

@ -16,21 +16,24 @@
import { Attribute, Class, Doc, DocumentQuery, IdMap, Ref, Status, TxOperations, toIdMap } from '@hcengineering/core'
import { IntlString, Resources } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import task, { Project, ProjectType, Task, calcRank } from '@hcengineering/task'
import { getCurrentLocation, navigate, showPopup } from '@hcengineering/ui'
import { ViewletDescriptor } from '@hcengineering/view'
import { CategoryQuery, statusStore } from '@hcengineering/view-resources'
import { statusStore } from '@hcengineering/view-resources'
import { get, writable } from 'svelte/store'
import AssignedTasks from './components/AssignedTasks.svelte'
import CreateStatePopup from './components/CreateStatePopup.svelte'
import Dashboard from './components/Dashboard.svelte'
import DueDateEditor from './components/DueDateEditor.svelte'
import KanbanTemplatePresenter from './components/KanbanTemplatePresenter.svelte'
import StatusFilter from './components/StatusFilter.svelte'
import StatusSelector from './components/StatusSelector.svelte'
import StatusTableView from './components/StatusTableView.svelte'
import TaskHeader from './components/TaskHeader.svelte'
import TaskPresenter from './components/TaskPresenter.svelte'
import TemplatesIcon from './components/TemplatesIcon.svelte'
import TypesView from './components/TypesView.svelte'
import KanbanView from './components/kanban/KanbanView.svelte'
import ProjectEditor from './components/kanban/ProjectEditor.svelte'
import ProjectTypeSelector from './components/kanban/ProjectTypeSelector.svelte'
@ -41,8 +44,6 @@ import TodoItemPresenter from './components/todos/TodoItemPresenter.svelte'
import TodoItemsPopup from './components/todos/TodoItemsPopup.svelte'
import TodoStatePresenter from './components/todos/TodoStatePresenter.svelte'
import Todos from './components/todos/Todos.svelte'
import TypesView from './components/TypesView.svelte'
import { createQuery, getClient } from '@hcengineering/presentation'
export { default as AssigneePresenter } from './components/AssigneePresenter.svelte'
export { StateRefPresenter }
@ -106,7 +107,8 @@ export default async (): Promise<Resources> => ({
CreateStatePopup,
StatusSelector,
TemplatesIcon,
TypesView
TypesView,
StatusFilter
},
actionImpl: {
EditStatuses: editStatuses,
@ -124,29 +126,14 @@ async function getAllStates (
queryId: Ref<Doc>,
attr: Attribute<Status>
): Promise<any[]> {
const _space = query?.space
if (_space !== undefined) {
const promise = new Promise<Array<Ref<Doc>>>((resolve, reject) => {
let refresh: boolean = false
const lq = CategoryQuery.getLiveQuery(queryId)
refresh = lq.query(task.class.Project, { _id: _space as Ref<Project> }, (res) => {
const typeId = res[0]?.type
const type = get(typeStore).get(typeId)
const typeId = get(selectedTypeStore)
const type = typeId !== undefined ? get(typeStore).get(typeId) : undefined
if (type !== undefined) {
const statusMap = get(statusStore).byId
const statuses = (type?.statuses?.map((p) => statusMap.get(p._id)) as Status[]) ?? []
const result = statuses
const statuses = (type.statuses?.map((p) => statusMap.get(p._id)) as Status[]) ?? []
return statuses
.filter((p) => p?.category !== task.statusCategory.Lost && p?.category !== task.statusCategory.Won)
.map((p) => p?._id)
CategoryQuery.results.set(queryId, result)
resolve(result)
onUpdate()
})
if (!refresh) {
resolve(CategoryQuery.results.get(queryId) ?? [])
}
})
return await promise
}
return get(statusStore)
.array.filter(
@ -162,19 +149,8 @@ async function statusSort (
space: Ref<Project> | undefined,
viewletDescriptorId?: Ref<ViewletDescriptor>
): Promise<Array<Ref<Status>>> {
let type: ProjectType | undefined
if (space !== undefined) {
const _space = await client.findOne(
task.class.Project,
{ _id: space },
{
lookup: {
type: task.class.ProjectType
}
}
)
type = _space?.$lookup?.type
}
const typeId = get(selectedTypeStore)
const type = typeId !== undefined ? get(typeStore).get(typeId) : undefined
const statuses = get(statusStore).byId
if (type !== undefined) {
@ -238,3 +214,5 @@ function fillStores (): void {
}
fillStores()
export const selectedTypeStore = writable<Ref<ProjectType> | undefined>(undefined)

View File

@ -79,6 +79,7 @@ export default mergeIds(taskId, task, {
AssigneeRequired: '' as IntlString
},
component: {
StatusFilter: '' as AnyComponent,
TodoStatePresenter: '' as AnyComponent,
AssignedTasks: '' as AnyComponent,
DueDateEditor: '' as AnyComponent

View File

@ -40,7 +40,6 @@ import FilterTypePopup from './components/filter/FilterTypePopup.svelte'
import ObjectFilter from './components/filter/ObjectFilter.svelte'
import StringFilter from './components/filter/StringFilter.svelte'
import StringFilterPresenter from './components/filter/StringFilterPresenter.svelte'
import StatusFilter from './components/filter/StatusFilter.svelte'
import TimestampFilter from './components/filter/TimestampFilter.svelte'
import ValueFilter from './components/filter/ValueFilter.svelte'
import HTMLEditor from './components/HTMLEditor.svelte'
@ -206,7 +205,6 @@ export default async (): Promise<Resources> => ({
DateFilter,
ValueFilter,
StringFilter,
StatusFilter,
TimestampFilter,
TableBrowser,
SpacePresenter,

View File

@ -25,7 +25,6 @@ export default mergeIds(viewId, view, {
DateFilter: '' as AnyComponent,
ValueFilter: '' as AnyComponent,
ArrayFilter: '' as AnyComponent,
StatusFilter: '' as AnyComponent,
StringFilter: '' as AnyComponent,
TimestampFilter: '' as AnyComponent,
FilterTypePopup: '' as AnyComponent,