Filters fix (#1808)

Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
Denis Bykhov
2022-05-20 14:17:57 +07:00
committed by GitHub
parent fcea07cba5
commit 06867083d1
7 changed files with 174 additions and 114 deletions
@@ -13,10 +13,10 @@
// limitations under the License.
-->
<script lang="ts">
import { Class, Doc, DocumentQuery, getObjectValue, Ref } from '@anticrm/core'
import { Class, Doc, DocumentQuery, getObjectValue, Ref, RefTo } from '@anticrm/core'
import { translate } from '@anticrm/platform'
import presentation, { getClient } from '@anticrm/presentation'
import { CheckBox } from '@anticrm/ui'
import ui, { CheckBox, Label } from '@anticrm/ui'
import { Filter } from '@anticrm/view'
import { onMount } from 'svelte'
import { buildConfigLookup, getPresenter } from '../../utils'
@@ -57,33 +57,37 @@
}
]
let values: Set<Doc> = new Set<Doc>()
let values: (Doc | undefined | null)[] = []
$: getValues(search)
const targets = new Map<any, number>()
async function getValues (search: string): Promise<void> {
const attrib = await promise
const resultQuery =
search !== ''
? {
[attrib.sortingKey]: { $like: '%' + search + '%' },
...query
}
: query
const res = await client.findAll(_class, resultQuery, { lookup })
const objects = []
const set: Set<any> = new Set<any>()
for (const obj of res) {
const value = (obj as any)[filter.key.key]
if (set.has(value)) continue
objects.push(obj)
set.add(value)
targets.clear()
const baseObjects = await client.findAll(_class, query, { projection: { [filter.key.key]: 1 } })
for (const object of baseObjects) {
const value = getObjectValue(filter.key.key, object) ?? undefined
targets.set(value, (targets.get(value) ?? 0) + 1)
}
const targetClass = (hierarchy.getAttribute(_class, filter.key.key).type as RefTo<Doc>).to
const clazz = hierarchy.getClass(targetClass)
const resultQuery =
search !== '' && clazz.sortingKey
? {
[clazz.sortingKey]: { $like: '%' + search + '%' },
_id: { $in: Array.from(targets.keys()) }
}
: {
_id: { $in: Array.from(targets.keys()) }
}
values = await client.findAll(targetClass, resultQuery, { projection: { _id: 1 } })
if (targets.has(undefined)) {
values.unshift(undefined)
}
values = new Set(objects.map((obj) => getObjectValue(tkey, obj)))
}
function isSelected (value: Doc, values: any[]): boolean {
return values.includes(value?._id ?? '')
function isSelected (value: Doc | undefined | null, values: any[]): boolean {
return values.includes(value?._id ?? value)
}
function checkMode () {
@@ -92,11 +96,15 @@
filter.mode = newMode !== undefined ? newMode : filter.mode
}
function toggle (value: Doc): void {
function toggle (value: Doc | undefined | null): void {
if (isSelected(value, filter.value)) {
filter.value = filter.value.filter((p) => p !== value._id)
filter.value = filter.value.filter((p) => (value ? p !== value._id : p != null))
} else {
filter.value = [...filter.value, value._id]
if (value) {
filter.value = [...filter.value, value._id]
} else {
filter.value = [...filter.value, undefined]
}
}
checkMode()
onChange(filter)
@@ -128,17 +136,28 @@
<div class="scroll">
<div class="box">
{#await promise then attribute}
{#each Array.from(values) as value}
{#each values as value}
<button
class="menu-item"
on:click={() => {
toggle(value)
}}
>
<div class="check pointer-events-none">
<CheckBox checked={isSelected(value, filter.value)} primary />
<div class="flex-between w-full">
<div class="flex">
<div class="check pointer-events-none">
<CheckBox checked={isSelected(value, filter.value)} primary />
</div>
{#if value}
<svelte:component this={attribute.presenter} {value} {...attribute.props} />
{:else}
<Label label={ui.string.NotSelected} />
{/if}
</div>
<div class="content-trans-color">
{targets.get(value?._id)}
</div>
</div>
<svelte:component this={attribute.presenter} {value} {...attribute.props} />
</button>
{/each}
{/await}
@@ -16,7 +16,7 @@
import { Class, Doc, DocumentQuery, getObjectValue, Ref } from '@anticrm/core'
import { translate } from '@anticrm/platform'
import presentation, { getClient } from '@anticrm/presentation'
import { CheckBox } from '@anticrm/ui'
import ui, { CheckBox, Label } from '@anticrm/ui'
import { Filter } from '@anticrm/view'
import { onMount } from 'svelte'
import { getPresenter } from '../../utils'
@@ -55,11 +55,15 @@
const key = { key: filter.key.key }
const promise = getPresenter(client, _class, key, key)
let values: Set<any> = new Set<any>()
let values = new Map<any, number>()
let selectedValues: Set<any> = new Set<any>()
const realValues = new Map<any, Set<any>>()
$: getValues(search)
async function getValues (search: string): Promise<void> {
values.clear()
realValues.clear()
const resultQuery =
search !== ''
? {
@@ -67,12 +71,18 @@
...query
}
: query
const res = await client.findAll(_class, resultQuery)
values = new Set(res.map((obj) => getObjectValue(filter.key.key, obj)))
const res = await client.findAll(_class, resultQuery, { projection: { [filter.key.key]: 1 } })
for (const object of res) {
const realValue = getObjectValue(filter.key.key, object)
const value = typeof realValue === 'string' ? realValue.trim().toUpperCase() : realValue ?? undefined
values.set(value, (values.get(value) ?? 0) + 1)
realValues.set(value, (realValues.get(value) ?? new Set()).add(realValue))
}
values = values
}
function isSelected (value: any, values: any[]): boolean {
return values.includes(value)
function isSelected (value: any, values: Set<any>): boolean {
return values.has(value)
}
function checkMode () {
@@ -82,11 +92,15 @@
}
function toggle (value: any): void {
if (isSelected(value, filter.value)) {
filter.value = filter.value.filter((p) => p !== value)
if (isSelected(value, selectedValues)) {
selectedValues.delete(value)
} else {
filter.value = [...filter.value, value]
selectedValues.add(value)
}
selectedValues = selectedValues
filter.value = Array.from(selectedValues.values())
.map((p) => Array.from(realValues.get(p) ?? []))
.flat()
checkMode()
onChange(filter)
}
@@ -117,17 +131,28 @@
<div class="scroll">
<div class="box">
{#await promise then attribute}
{#each Array.from(values) as value}
{#each Array.from(values.keys()) as value}
<button
class="menu-item"
on:click={() => {
toggle(value)
}}
>
<div class="check pointer-events-none">
<CheckBox checked={isSelected(value, filter.value)} primary />
<div class="flex-between w-full">
<div class="flex">
<div class="check pointer-events-none">
<CheckBox checked={isSelected(value, selectedValues)} primary />
</div>
{#if value}
<svelte:component this={attribute.presenter} {value} {...attribute.props} />
{:else}
<Label label={ui.string.NotSelected} />
{/if}
</div>
<div class="content-trans-color">
{values.get(value)}
</div>
</div>
<svelte:component this={attribute.presenter} {value} {...attribute.props} />
</button>
{/each}
{/await}