mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 21:50:34 +03:00
UBERF-4195: fix query after applying viewOptions (#3942)
Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>
This commit is contained in:
parent
67a563d6c7
commit
f8cdaba5f2
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Client } from '..'
|
||||
import { Client, generateId, mergeQueries } from '..'
|
||||
import type { Class, Doc, Obj, Ref } from '../classes'
|
||||
import core from '../component'
|
||||
import { Hierarchy } from '../hierarchy'
|
||||
@ -396,4 +396,39 @@ describe('memdb', () => {
|
||||
expect(e).toEqual(new Error('createDoc cannot be used for objects inherited from AttachedDoc'))
|
||||
}
|
||||
})
|
||||
|
||||
it('mergeQueries', () => {
|
||||
const id1 = generateId()
|
||||
const id2 = generateId()
|
||||
const q1 = {
|
||||
space: id1,
|
||||
unique: 'item',
|
||||
age: { $gt: 10 }
|
||||
} as any
|
||||
const q2 = {
|
||||
space: { $in: [id1, id2] },
|
||||
age: 30
|
||||
} as any
|
||||
const resCompare = {
|
||||
space: id1,
|
||||
unique: 'item',
|
||||
age: { $gt: 30 }
|
||||
} as any
|
||||
expect(mergeQueries(q1, q2)).toEqual(resCompare)
|
||||
expect(mergeQueries(q2, q1)).toEqual(resCompare)
|
||||
|
||||
const q3 = {
|
||||
space: { $nin: [id1] },
|
||||
age: 20
|
||||
} as any
|
||||
const resCompare2 = {
|
||||
space: { $ne: id1 },
|
||||
age: []
|
||||
} as any
|
||||
expect(mergeQueries(q2, q3)).toEqual(resCompare2)
|
||||
expect(mergeQueries(q3, q2)).toEqual(resCompare2)
|
||||
|
||||
expect(mergeQueries({ age: { $lt: 20 } } as any, { age: { $gt: 25 } } as any)).toEqual({ age: { $gt: 25 } })
|
||||
expect(mergeQueries({ age: { $gt: 25 } } as any, { age: { $lt: 20 } } as any)).toEqual({ age: { $lt: 20 } })
|
||||
})
|
||||
})
|
||||
|
@ -16,7 +16,8 @@
|
||||
import { Account, AnyAttribute, Class, Doc, DocData, DocIndexState, IndexKind, Obj, Ref, Space } from './classes'
|
||||
import core from './component'
|
||||
import { Hierarchy } from './hierarchy'
|
||||
import { FindResult } from './storage'
|
||||
import { DocumentQuery, FindResult } from './storage'
|
||||
import { isPredicate } from './predicate'
|
||||
|
||||
function toHex (value: number, chars: number): string {
|
||||
const result = value.toString(16)
|
||||
@ -331,3 +332,64 @@ export class RateLimitter {
|
||||
await await Promise.race(this.processingQueue.values())
|
||||
}
|
||||
}
|
||||
|
||||
export function mergeQueries<T extends Doc> (query1: DocumentQuery<T>, query2: DocumentQuery<T>): DocumentQuery<T> {
|
||||
const q = Object.assign({}, query1)
|
||||
for (const k in query2) {
|
||||
if (!Object.keys(query1).includes(k)) {
|
||||
Object.assign(q, { [k]: query2[k] })
|
||||
continue
|
||||
}
|
||||
Object.assign(q, { [k]: getInNiN(query1[k], query2[k]) })
|
||||
if (isPredicate(query2[k]) || isPredicate(query1[k])) {
|
||||
const toIterate = isPredicate(query2[k]) ? query2[k] : query1[k]
|
||||
for (const x in toIterate) {
|
||||
if (['$lt', '$gt'].includes(x)) {
|
||||
const val1 = isPredicate(query1[k]) ? query1[k][x] : query1[k]
|
||||
const val2 = isPredicate(query2[k]) ? query2[k][x] : query2[k]
|
||||
if (x === '$lt') {
|
||||
Object.assign(q, { [k]: { $lt: val1 < val2 ? val1 : val2 } })
|
||||
continue
|
||||
}
|
||||
if (x === '$gt') {
|
||||
Object.assign(q, { [k]: { $gt: val1 > val2 ? val1 : val2 } })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
function getInNiN (query1: any, query2: any): Object {
|
||||
const aIn =
|
||||
(typeof query1 === 'object' && '$in' in query1 ? query1.$in : undefined) ??
|
||||
(typeof query1 !== 'object' && query1 !== undefined ? [query1] : [])
|
||||
const aNIn =
|
||||
(typeof query1 === 'object' && '$nin' in query1 ? query1.$nin : undefined) ??
|
||||
(typeof query1 === 'object' && query1.$ne !== undefined ? [query1.$ne] : [])
|
||||
const bIn =
|
||||
(typeof query2 === 'object' && '$in' in query2 ? query2.$in : undefined) ??
|
||||
(typeof query2 !== 'object' && query2 !== undefined ? [query2] : [])
|
||||
const bNIn =
|
||||
(typeof query2 === 'object' && '$nin' in query2 ? query2.$nin : undefined) ??
|
||||
(typeof query2 === 'object' && query2.$ne !== undefined ? [query2.$ne] : [])
|
||||
const finalIn =
|
||||
aIn.length - bIn.length < 0 ? bIn.filter((c: any) => aIn.includes(c)) : aIn.filter((c: any) => bIn.includes(c))
|
||||
const finalNin = Array.from(new Set([...aNIn, ...bNIn]))
|
||||
if (finalIn.length === 1 && finalNin.length === 0) {
|
||||
return aIn[0]
|
||||
}
|
||||
if (finalIn.length === 0 && finalNin.length === 1) {
|
||||
return { $ne: finalNin[0] }
|
||||
}
|
||||
const res: any = {}
|
||||
if (finalIn.length > 0) {
|
||||
res.$in = finalIn
|
||||
}
|
||||
if (finalNin.length > 0) {
|
||||
res.$nin = finalNin
|
||||
}
|
||||
if (aIn.length === 1 && bIn.length === 1) return []
|
||||
return res
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Class, Doc, DocumentQuery, Ref, Space, WithLookup } from '@hcengineering/core'
|
||||
import { Class, Doc, DocumentQuery, mergeQueries, Ref, Space, WithLookup } from '@hcengineering/core'
|
||||
import { IntlString, getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Project, ProjectType, ProjectTypeCategory } from '@hcengineering/task'
|
||||
@ -65,7 +65,7 @@
|
||||
$: spacesQ.query(task.class.Project, { type: mode as Ref<ProjectType> }, (result) => {
|
||||
spaces = result
|
||||
})
|
||||
|
||||
let resultQuery: DocumentQuery<Doc>
|
||||
$: query = { ...(baseQuery ?? {}), ...(viewlet?.baseQuery ?? {}), space: { $in: spaces.map((it) => it._id) } }
|
||||
$: searchQuery = search === '' ? query : { ...query, $search: search }
|
||||
$: resultQuery = searchQuery
|
||||
@ -154,7 +154,7 @@
|
||||
query={searchQuery}
|
||||
{viewOptions}
|
||||
on:change={(e) => {
|
||||
resultQuery = { ...query, ...e.detail }
|
||||
resultQuery = mergeQueries(query, e.detail)
|
||||
}}
|
||||
/>
|
||||
<Component
|
||||
|
@ -22,6 +22,7 @@
|
||||
DocumentUpdate,
|
||||
FindOptions,
|
||||
generateId,
|
||||
mergeQueries,
|
||||
Ref
|
||||
} from '@hcengineering/core'
|
||||
import { Item, Kanban as KanbanUI } from '@hcengineering/kanban'
|
||||
@ -87,7 +88,7 @@
|
||||
}
|
||||
|
||||
let resultQuery: DocumentQuery<any> = { ...query }
|
||||
$: getResultQuery(query, viewOptionsConfig, viewOptions).then((p) => (resultQuery = { ...p, ...query }))
|
||||
$: getResultQuery(query, viewOptionsConfig, viewOptions).then((p) => (resultQuery = mergeQueries(p, query)))
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
@ -13,7 +13,16 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { Class, Doc, DocumentQuery, FindOptions, Ref, Space, RateLimitter } from '@hcengineering/core'
|
||||
import core, {
|
||||
Class,
|
||||
Doc,
|
||||
DocumentQuery,
|
||||
FindOptions,
|
||||
Ref,
|
||||
Space,
|
||||
RateLimitter,
|
||||
mergeQueries
|
||||
} from '@hcengineering/core'
|
||||
import { IntlString, getResource } from '@hcengineering/platform'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { AnyComponent, AnySvelteComponent } from '@hcengineering/ui'
|
||||
@ -59,7 +68,7 @@
|
||||
|
||||
let resultQuery: DocumentQuery<Doc> = query
|
||||
$: getResultQuery(query, viewOptionsConfig, viewOptions).then((p) => {
|
||||
resultQuery = { ...query, ...p }
|
||||
resultQuery = mergeQueries(p, query) as DocumentQuery<Doc>
|
||||
})
|
||||
|
||||
$: queryNoLookup = noLookup(resultQuery)
|
||||
|
Loading…
Reference in New Issue
Block a user