TSK-1404 Improve sprint filter (#3164)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov
2023-05-11 14:26:17 +07:00
committed by GitHub
parent 2e6181acf1
commit bbf81ada7c
11 changed files with 339 additions and 74 deletions
@@ -25,7 +25,7 @@
showPopup,
Submenu
} from '@hcengineering/ui'
import { ClassFilters, Filter, KeyFilter } from '@hcengineering/view'
import { ClassFilters, Filter, KeyFilter, KeyFilterPreset } from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
import { buildFilterKey, FilterQuery } from '../../filter'
import view from '../../plugin'
@@ -36,6 +36,7 @@
export let filter: Filter | undefined
export let index: number
export let onChange: (e: Filter) => void
export let nestedFrom: KeyFilter | undefined = undefined
const client = getClient()
const hierarchy = client.getHierarchy()
@@ -43,7 +44,7 @@
function getFilters (_class: Ref<Class<Doc>>, mixin: ClassFilters): KeyFilter[] {
if (mixin.filters === undefined) return []
const filters = mixin.filters.map((p) => {
return typeof p === 'string' ? buildFilterFromKey(_class, p) : p
return typeof p === 'string' ? buildFilterFromKey(_class, p) : buildFilterFromPreset(p)
})
const result: KeyFilter[] = []
for (const filter of filters) {
@@ -52,6 +53,19 @@
return result
}
function buildFilterFromPreset (p: KeyFilterPreset): KeyFilter | undefined {
if (p.key !== '') {
const attribute = hierarchy.getAttribute(p._class, p.key)
const clazz = hierarchy.getClass(p._class)
return {
...p,
attribute,
label: p.label ?? attribute.label,
icon: p.icon ?? attribute.icon ?? clazz.icon ?? view.icon.Setting
}
}
}
function buildFilterFromKey (_class: Ref<Class<Doc>>, key: string): KeyFilter | undefined {
const attribute = hierarchy.getAttribute(_class, key)
return buildFilterKey(hierarchy, _class, key, attribute)
@@ -69,7 +83,7 @@
return
}
const value = getValue(attribute.name, attribute.type)
if (result.findIndex((p) => p.attribute.name === value) !== -1) {
if (result.findIndex((p) => p.attribute?.name === value) !== -1) {
return
}
const filter = buildFilterKey(hierarchy, _class, value, attribute)
@@ -93,7 +107,20 @@
}
}
function getTypes (_class: Ref<Class<Doc>>): KeyFilter[] {
function getTypes (_class: Ref<Class<Doc>>, nestedFrom: KeyFilter | undefined): KeyFilter[] {
if (nestedFrom !== undefined) {
return getNestedTypes(nestedFrom)
} else {
return getOwnTypes(_class)
}
}
function getNestedTypes (type: KeyFilter): KeyFilter[] {
const targetClass = (hierarchy.getAttribute(type._class, type.key).type as RefTo<Doc>).to
return getOwnTypes(targetClass)
}
function getOwnTypes (_class: Ref<Class<Doc>>): KeyFilter[] {
const clazz = hierarchy.getClass(_class)
const mixin = hierarchy.as(clazz, view.mixin.ClassFilters)
const result = getFilters(_class, mixin)
@@ -159,24 +186,48 @@
closePopup()
closeTooltip()
showPopup(
type.component,
{
_class,
space,
filter: filter || {
key: type,
value: [],
index
if (nestedFrom !== undefined && type !== nestedFrom) {
const change = (e: Filter | undefined) => {
if (nestedFrom) {
setNestedFilter(nestedFrom, e)
}
}
const targetClass = (hierarchy.getAttribute(nestedFrom._class, nestedFrom.key).type as RefTo<Doc>).to
showPopup(
type.component,
{
_class: targetClass,
space,
filter: filter || {
key: type,
value: [],
index
},
onChange: change
},
onChange
},
target
)
target
)
} else {
showPopup(
type.component,
{
_class,
space,
filter: filter || {
key: type,
value: [],
index
},
onChange
},
target
)
}
}
function hasNested (type: KeyFilter): boolean {
const targetClass = (hierarchy.getAttribute(type._class, type.key).type as RefTo<Doc>).to
if (targetClass === undefined) return false
const clazz = hierarchy.getClass(targetClass)
return hierarchy.hasMixin(clazz, view.mixin.ClassFilters)
}
@@ -199,38 +250,51 @@
dispatch('close')
}
function getNestedProps (type: KeyFilter): any {
const targetClass = (hierarchy.getAttribute(type._class, type.key).type as RefTo<Doc>).to
return {
_class: targetClass,
space,
index,
target,
onChange: (e: Filter | undefined) => {
setNestedFilter(type, e)
}
}
}
const elements: HTMLElement[] = []
</script>
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
<Scroller>
{#each getTypes(_class) as type, i}
{#if filter === undefined && type.component === view.component.ObjectFilter && hasNested(type)}
{#if nestedFrom}
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
<button
class="menu-item withIcon"
on:keydown={(event) => keyDown(event, -1)}
on:mouseover={(event) => {
event.currentTarget.focus()
}}
on:click={() => {
if (nestedFrom) {
click(nestedFrom)
}
}}
>
<div class="icon mr-3">
{#if nestedFrom.icon}
<Icon icon={nestedFrom.icon} size={'small'} />
{/if}
</div>
<div class="overflow-label pr-1"><Label label={nestedFrom.label} /></div>
</button>
{/if}
{#each getTypes(_class, nestedFrom) as type, i}
{#if filter === undefined && hasNested(type)}
<Submenu
bind:element={elements[i]}
on:keydown={(event) => keyDown(event, i)}
on:mouseover={() => {
elements[i]?.focus()
}}
on:click={() => {
click(type)
}}
icon={type.icon}
label={type.label}
props={getNestedProps(type)}
props={{
_class,
space,
index,
target,
onChange,
nestedFrom: type
}}
options={{ component: view.component.FilterTypePopup }}
withHover
/>
+19 -2
View File
@@ -7,7 +7,8 @@ import core, {
FindResult,
Hierarchy,
ObjQueryType,
Ref
Ref,
RefTo
} from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import { LiveQuery, createQuery, getClient } from '@hcengineering/presentation'
@@ -198,12 +199,28 @@ export function buildFilterKey (
key: string,
attribute: AnyAttribute
): KeyFilter | undefined {
const attrOf = hierarchy.getClass(attribute.attributeOf)
const isRef = hierarchy.isDerived(attribute.type._class, core.class.RefTo)
if (isRef) {
const targetClass = (attribute.type as RefTo<Doc>).to
const filter = hierarchy.classHierarchyMixin(targetClass, view.mixin.AttributeFilter)
if (filter?.component !== undefined) {
return {
_class,
key,
attribute,
label: attribute.label,
icon: attribute.icon ?? filter.icon ?? attrOf.icon ?? view.icon.Setting,
component: filter.component
}
}
}
const isCollection = hierarchy.isDerived(attribute.type._class, core.class.Collection)
const targetClass = isCollection ? (attribute.type as Collection<AttachedDoc>).of : attribute.type._class
const clazz = hierarchy.getClass(targetClass)
const filter = hierarchy.as(clazz, view.mixin.AttributeFilter)
const attrOf = hierarchy.getClass(attribute.attributeOf)
if (filter.component === undefined) return undefined
return {
_class,