mirror of
https://github.com/hcengineering/platform.git
synced 2025-01-03 08:57:14 +03:00
UBER-720: Rework list view to multiple requests (#3578)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
7a9e8f0321
commit
26d8099f1d
@ -541,12 +541,7 @@ export function createModel (builder: Builder): void {
|
||||
displayProps: { key: 'assignee', fixed: 'right' },
|
||||
props: { kind: 'list', shouldShowName: false, avatarSize: 'x-small' }
|
||||
}
|
||||
],
|
||||
options: {
|
||||
lookup: {
|
||||
space: tracker.class.Project
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
tracker.viewlet.IssueList
|
||||
)
|
||||
@ -1052,7 +1047,6 @@ export function createModel (builder: Builder): void {
|
||||
icon: tracker.icon.Issues,
|
||||
component: tracker.component.Issues,
|
||||
componentProps: {
|
||||
baseQuery: { '$lookup.space.archived': false },
|
||||
space: undefined,
|
||||
title: tracker.string.AllIssues,
|
||||
config: [
|
||||
|
@ -59,4 +59,5 @@
|
||||
{disabled}
|
||||
{inline}
|
||||
{accent}
|
||||
on:accent-color
|
||||
/>
|
||||
|
@ -60,13 +60,28 @@
|
||||
}
|
||||
)
|
||||
|
||||
const archivedProjectQuery = createQuery()
|
||||
let archived: Ref<Project>[] = []
|
||||
|
||||
archivedProjectQuery.query(
|
||||
tracker.class.Project,
|
||||
{ archived: true },
|
||||
(res) => {
|
||||
archived = res.map((it) => it._id)
|
||||
},
|
||||
{ projection: { _id: 1 } }
|
||||
)
|
||||
|
||||
$: queries = { all, active, backlog }
|
||||
$: mode = $resolvedLocationStore.query?.mode ?? undefined
|
||||
$: if (mode === undefined || queries[mode] === undefined) {
|
||||
;[[mode]] = config
|
||||
}
|
||||
$: if (mode !== undefined) {
|
||||
query = { ...queries[mode], '$lookup.space.archived': false }
|
||||
query = { ...queries[mode] }
|
||||
if (query?.space === undefined) {
|
||||
query = { ...query, space: { $nin: archived } }
|
||||
}
|
||||
modeSelectorProps = {
|
||||
config,
|
||||
mode,
|
||||
|
@ -18,7 +18,7 @@
|
||||
import { Doc, DocumentQuery, getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import type { IntlString } from '@hcengineering/platform'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import type { Issue } from '@hcengineering/tracker'
|
||||
import type { Issue, Project } from '@hcengineering/tracker'
|
||||
import { resolvedLocationStore } from '@hcengineering/ui'
|
||||
|
||||
import { IModeSelector } from '@hcengineering/ui'
|
||||
@ -50,13 +50,28 @@
|
||||
{ sort: { _id: 1 } }
|
||||
)
|
||||
|
||||
const archivedProjectQuery = createQuery()
|
||||
let archived: Ref<Project>[] = []
|
||||
|
||||
archivedProjectQuery.query(
|
||||
tracker.class.Project,
|
||||
{ archived: true },
|
||||
(res) => {
|
||||
archived = res.map((it) => it._id)
|
||||
},
|
||||
{ projection: { _id: 1 } }
|
||||
)
|
||||
|
||||
$: queries = { assigned, created, subscribed }
|
||||
$: mode = $resolvedLocationStore.query?.mode ?? undefined
|
||||
$: if (mode === undefined || queries[mode] === undefined) {
|
||||
;[[mode]] = config
|
||||
}
|
||||
$: if (mode !== undefined) {
|
||||
query = { ...queries[mode], '$lookup.space.archived': false }
|
||||
query = { ...queries[mode] }
|
||||
if (query?.space === undefined) {
|
||||
query = { ...query, space: { $nin: archived } }
|
||||
}
|
||||
modeSelectorProps = {
|
||||
config,
|
||||
mode,
|
||||
|
@ -46,7 +46,7 @@
|
||||
activeViewlet: Record<string, Ref<Viewlet> | null>,
|
||||
key: string
|
||||
) {
|
||||
if (viewlets.length === 0) return
|
||||
if (viewlets == null || viewlets.length === 0) return
|
||||
const newViewlet = viewlets.find((viewlet) => viewlet?._id === activeViewlet[key]) ?? viewlets[0]
|
||||
if (viewlet?._id !== newViewlet?._id) {
|
||||
viewlet = newViewlet
|
||||
@ -55,7 +55,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: viewslist = viewlets.map((views) => {
|
||||
$: viewslist = viewlets?.map((views) => {
|
||||
return {
|
||||
id: views._id,
|
||||
icon: views.$lookup?.descriptor?.icon,
|
||||
|
@ -73,11 +73,17 @@
|
||||
prefix = attr.attributeOf + '.'
|
||||
}
|
||||
const isDerivedFromSpace = hierarchy.isDerived(_class, core.class.Space)
|
||||
|
||||
const archived =
|
||||
space === undefined || isDerivedFromSpace
|
||||
? []
|
||||
: (await client.findAll(core.class.Space, { archived: true }, { projection: { _id: 1 } })).map((it) => it._id)
|
||||
|
||||
objectsPromise = client.findAll(
|
||||
_class,
|
||||
{
|
||||
...resultQuery,
|
||||
...(space ? { space } : isDerivedFromSpace ? { archived: false } : { '$lookup.space.archived': false })
|
||||
...(space ? { space } : isDerivedFromSpace ? { archived: false } : { space: { $nin: archived } })
|
||||
},
|
||||
{
|
||||
sort: { [filter.key.key]: SortingOrder.Ascending },
|
||||
|
@ -48,6 +48,7 @@
|
||||
$: orderBy = viewOptions.orderBy
|
||||
|
||||
const docsQuery = createQuery()
|
||||
|
||||
$: lookup = buildConfigLookup(client.getHierarchy(), _class, config, options?.lookup)
|
||||
$: resultOptions = { ...options, lookup, ...(orderBy !== undefined ? { sort: { [orderBy[0]]: orderBy[1] } } : {}) }
|
||||
|
||||
@ -59,17 +60,38 @@
|
||||
$: if (documents === undefined) {
|
||||
docsQuery.query(
|
||||
_class,
|
||||
resultQuery,
|
||||
noLookup(resultQuery),
|
||||
(res) => {
|
||||
docs = res
|
||||
},
|
||||
resultOptions
|
||||
{
|
||||
...resultOptions,
|
||||
projection: { ...resultOptions.projection, _id: 1, _class: 1, ...getProjection(viewOptions.groupBy) }
|
||||
}
|
||||
)
|
||||
} else {
|
||||
docsQuery.unsubscribe()
|
||||
docs = documents
|
||||
}
|
||||
|
||||
function getProjection (fields: string[]): Record<string, number> {
|
||||
const res: Record<string, number> = {}
|
||||
for (const f of fields) {
|
||||
res[f] = 1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function noLookup (query: DocumentQuery<Doc>): DocumentQuery<Doc> {
|
||||
const newQuery: DocumentQuery<Doc> = {}
|
||||
for (const [k, v] of Object.entries(query)) {
|
||||
if (!k.startsWith('$lookup.')) {
|
||||
newQuery[k] = v
|
||||
}
|
||||
}
|
||||
return newQuery
|
||||
}
|
||||
|
||||
$: dispatch('content', docs)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
@ -153,6 +175,8 @@
|
||||
select(-2, evt.detail)
|
||||
}}
|
||||
on:collapsed
|
||||
{resultQuery}
|
||||
{resultOptions}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -13,7 +13,17 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { CategoryType, Class, Doc, DocumentQuery, generateId, Lookup, Ref, Space } from '@hcengineering/core'
|
||||
import {
|
||||
CategoryType,
|
||||
Class,
|
||||
Doc,
|
||||
DocumentQuery,
|
||||
FindOptions,
|
||||
generateId,
|
||||
Lookup,
|
||||
Ref,
|
||||
Space
|
||||
} from '@hcengineering/core'
|
||||
import { getResource, IntlString } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { AnyComponent, AnySvelteComponent } from '@hcengineering/ui'
|
||||
@ -68,6 +78,9 @@
|
||||
export let groupPersistKey: string
|
||||
export let compactMode: boolean = false
|
||||
|
||||
export let resultQuery: DocumentQuery<Doc>
|
||||
export let resultOptions: FindOptions<Doc>
|
||||
|
||||
$: groupByKey = viewOptions.groupBy[level] ?? noCategory
|
||||
let categories: CategoryType[] = []
|
||||
$: updateCategories(_class, docs, groupByKey, viewOptions, viewOptionsConfig)
|
||||
@ -348,13 +361,15 @@
|
||||
oneCat={viewOptions.groupBy.length === 1}
|
||||
lastCat={i === categories.length - 1}
|
||||
{category}
|
||||
{items}
|
||||
itemProj={items}
|
||||
{newObjectProps}
|
||||
{createItemDialog}
|
||||
{createItemDialogProps}
|
||||
{createItemLabel}
|
||||
{viewOptionsConfig}
|
||||
{compactMode}
|
||||
{resultQuery}
|
||||
{resultOptions}
|
||||
on:check
|
||||
on:uncheckAll
|
||||
on:row-focus
|
||||
@ -411,6 +426,8 @@
|
||||
{initIndex}
|
||||
{viewOptionsConfig}
|
||||
{listDiv}
|
||||
{resultQuery}
|
||||
{resultOptions}
|
||||
on:dragItem
|
||||
on:check
|
||||
on:uncheckAll
|
||||
|
@ -13,9 +13,20 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AggregateValue, Class, Doc, DocumentUpdate, Lookup, PrimitiveType, Ref, Space } from '@hcengineering/core'
|
||||
import {
|
||||
AggregateValue,
|
||||
Class,
|
||||
Doc,
|
||||
DocumentQuery,
|
||||
DocumentUpdate,
|
||||
FindOptions,
|
||||
Lookup,
|
||||
PrimitiveType,
|
||||
Ref,
|
||||
Space
|
||||
} from '@hcengineering/core'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { DocWithRank, calcRank } from '@hcengineering/task'
|
||||
import {
|
||||
AnyComponent,
|
||||
@ -42,7 +53,7 @@
|
||||
export let groupByKey: string
|
||||
export let space: Ref<Space> | undefined
|
||||
export let baseMenuClass: Ref<Class<Doc>> | undefined
|
||||
export let items: Doc[]
|
||||
export let itemProj: Doc[]
|
||||
export let createItemDialog: AnyComponent | AnySvelteComponent | undefined
|
||||
export let createItemDialogProps: Record<string, any> | undefined
|
||||
export let createItemLabel: IntlString | undefined
|
||||
@ -68,15 +79,34 @@
|
||||
export let index: number
|
||||
export let groupPersistKey: string
|
||||
export let compactMode: boolean = false
|
||||
export let resultQuery: DocumentQuery<Doc>
|
||||
export let resultOptions: FindOptions<Doc>
|
||||
|
||||
$: lastLevel = level + 1 >= viewOptions.groupBy.length
|
||||
|
||||
let items: Doc[] = []
|
||||
|
||||
const docsQuery = createQuery()
|
||||
|
||||
const autoFoldLimit = 20
|
||||
const defaultLimit = 20
|
||||
const singleCategoryLimit = 50
|
||||
$: initialLimit = !lastLevel ? undefined : singleCat ? singleCategoryLimit : defaultLimit
|
||||
$: limit = initialLimit
|
||||
|
||||
$: if (lastLevel) {
|
||||
docsQuery.query(
|
||||
_class,
|
||||
{ ...resultQuery, _id: { $in: itemProj.map((it) => it._id) } },
|
||||
(res) => {
|
||||
items = res
|
||||
},
|
||||
{ ...resultOptions, limit: limit ?? 200 }
|
||||
)
|
||||
} else {
|
||||
docsQuery.unsubscribe()
|
||||
}
|
||||
|
||||
$: categoryCollapseKey = `list_collapsing_${location.pathname}_${groupPersistKey}`
|
||||
$: storedCollapseState = localStorage.getItem(categoryCollapseKey)
|
||||
|
||||
@ -92,7 +122,7 @@
|
||||
|
||||
function initCollapsed (singleCat: boolean, lastLevel: boolean): void {
|
||||
if (localStorage.getItem(categoryCollapseKey) === null) {
|
||||
collapsed = !disableHeader && !singleCat && items.length > (lastLevel ? autoFoldLimit : singleCategoryLimit)
|
||||
collapsed = !disableHeader && !singleCat && itemProj.length > (lastLevel ? autoFoldLimit : singleCategoryLimit)
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,8 +418,9 @@
|
||||
{category}
|
||||
{space}
|
||||
{level}
|
||||
limited={limited.length}
|
||||
{items}
|
||||
limited={lastLevel ? limited.length : itemProj.length}
|
||||
itemsProj={itemProj}
|
||||
items={limited}
|
||||
{headerComponent}
|
||||
{createItemDialog}
|
||||
{createItemDialogProps}
|
||||
@ -423,7 +454,7 @@
|
||||
{#if !lastLevel}
|
||||
<slot
|
||||
name="category"
|
||||
docs={items}
|
||||
docs={itemProj}
|
||||
{_class}
|
||||
{space}
|
||||
{lookup}
|
||||
|
@ -45,6 +45,7 @@
|
||||
export let space: Ref<Space> | undefined
|
||||
export let limited: number
|
||||
export let items: Doc[]
|
||||
export let itemsProj: Doc[]
|
||||
export let flat = false
|
||||
export let collapsed = false
|
||||
export let lastCat = false
|
||||
@ -139,11 +140,11 @@
|
||||
</span>
|
||||
</span>
|
||||
{/if}
|
||||
{#if limited < items.length}
|
||||
{#if limited < itemsProj.length}
|
||||
<div class="antiSection-header__counter flex-row-center mx-2">
|
||||
<span class="caption-color">{limited}</span>
|
||||
<span class="text-xs mx-0-5">/</span>
|
||||
{items.length}
|
||||
{itemsProj.length}
|
||||
</div>
|
||||
<ActionIcon
|
||||
size={'small'}
|
||||
@ -154,7 +155,7 @@
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
<span class="antiSection-header__counter ml-2">{items.length}</span>
|
||||
<span class="antiSection-header__counter ml-2">{itemsProj.length}</span>
|
||||
{/if}
|
||||
<div class="flex-row-center flex-reverse flex-grow mr-2 gap-2 reverse">
|
||||
{#each extraHeaders ?? [] as extra}
|
||||
|
Loading…
Reference in New Issue
Block a user