mirror of
https://github.com/hcengineering/platform.git
synced 2026-10-01 22:15:04 +02:00
Filters fix (#1808)
Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user