diff --git a/packages/kanban/src/components/Kanban.svelte b/packages/kanban/src/components/Kanban.svelte
index 8e04fb415a..159c308129 100644
--- a/packages/kanban/src/components/Kanban.svelte
+++ b/packages/kanban/src/components/Kanban.svelte
@@ -210,7 +210,7 @@
}
export function select (offset: 1 | -1 | 0, of?: Doc, dir?: 'vertical' | 'horizontal'): void {
- let pos = (of !== undefined ? objects.findIndex((it) => it._id === of._id) : selection) ?? -1
+ let pos = (of != null ? objects.findIndex((it) => it._id === of._id) : selection) ?? -1
if (pos === -1) {
for (const st of categories) {
const stateObjs = getGroupByValues(groupByDocs, st) ?? []
@@ -237,7 +237,7 @@
if (objState === -1) {
return
}
- const stateObjs = getGroupByValues(groupByDocs, categories.indexOf(objState)) ?? []
+ const stateObjs = getGroupByValues(groupByDocs, categories[objState]) ?? []
const statePos = stateObjs.findIndex((it) => it._id === obj._id)
if (statePos === undefined) {
return
diff --git a/packages/kanban/src/components/KanbanRow.svelte b/packages/kanban/src/components/KanbanRow.svelte
index c01b59e8a6..d5fda1741a 100644
--- a/packages/kanban/src/components/KanbanRow.svelte
+++ b/packages/kanban/src/components/KanbanRow.svelte
@@ -14,7 +14,7 @@
-->
(space ? { space } : {})}
- {elementByIndex}
- {indexById}
{docs}
{_class}
{space}
+ {selection}
query={resultQuery}
{lookup}
loadingPropsLength={getLoadingElementsLength(loadingProps, options)}
{baseMenuClass}
{config}
{viewOptions}
- {docByIndex}
{viewOptionsConfig}
{selectedObjectIds}
level={0}
@@ -167,6 +145,9 @@
{props}
{listDiv}
bind:dragItem
+ on:select={(evt) => {
+ select(0, evt.detail)
+ }}
/>
diff --git a/plugins/view-resources/src/components/list/ListCategories.svelte b/plugins/view-resources/src/components/list/ListCategories.svelte
index 713db288e2..11a4136fb3 100644
--- a/plugins/view-resources/src/components/list/ListCategories.svelte
+++ b/plugins/view-resources/src/components/list/ListCategories.svelte
@@ -18,7 +18,7 @@
import { getClient, statusStore } from '@hcengineering/presentation'
import { AnyComponent } from '@hcengineering/ui'
import { AttributeModel, BuildModelKey, CategoryOption, ViewOptionModel, ViewOptions } from '@hcengineering/view'
- import { createEventDispatcher, onDestroy } from 'svelte'
+ import { createEventDispatcher, onDestroy, SvelteComponentTyped } from 'svelte'
import {
buildModel,
concatCategories,
@@ -31,8 +31,6 @@
import { CategoryQuery, noCategory } from '../../viewOptions'
import ListCategory from './ListCategory.svelte'
- export let elementByIndex: Map
- export let indexById: Map[, number>
export let docs: Doc[]
export let _class: Ref>
export let space: Ref | undefined
@@ -51,13 +49,13 @@
export let level: number
export let initIndex = 0
export let newObjectProps: (doc: Doc) => Record | undefined
- export let docByIndex: Map
export let viewOptionsConfig: ViewOptionModel[] | undefined
export let dragItem: {
doc?: Doc
revert?: () => void
}
export let listDiv: HTMLDivElement
+ export let selection: number | undefined = undefined
$: groupByKey = viewOptions.groupBy[level] ?? noCategory
let categories: CategoryType[] = []
@@ -129,25 +127,118 @@
$: extraHeaders = getAdditionalHeader(client, _class)
const dispatch = createEventDispatcher()
+
+ function getState (doc: Doc): number {
+ let pos = 0
+ for (const st of categories) {
+ const stateObjs = getGroupByValues(groupByDocs, st) ?? []
+ if (stateObjs.findIndex((it) => it._id === doc._id) !== -1) {
+ return pos
+ }
+ pos++
+ }
+ return -1
+ }
+
+ export function select (offset: 1 | -1 | 0, of?: Doc, dir?: 'vertical' | 'horizontal'): void {
+ let pos = (of != null ? docs.findIndex((it) => it._id === of._id) : selection) ?? -1
+ if (pos === -1) {
+ for (const st of categories) {
+ const stateObjs = getGroupByValues(groupByDocs, st) ?? []
+ if (stateObjs.length > 0) {
+ pos = docs.findIndex((it) => it._id === stateObjs[0]._id)
+ break
+ }
+ }
+ }
+
+ if (pos < 0) {
+ pos = 0
+ }
+ if (pos >= docs.length) {
+ pos = docs.length - 1
+ }
+
+ const obj = docs[pos]
+ if (obj === undefined) {
+ return
+ }
+
+ // We found group
+ const objState = getState(obj)
+ if (objState === -1) {
+ return
+ }
+
+ if (level + 1 >= viewOptions.groupBy.length) {
+ const stateObjs = getGroupByValues(groupByDocs, categories[objState]) ?? []
+
+ const statePos = stateObjs.findIndex((it) => it._id === obj._id)
+ if (statePos === undefined) {
+ return
+ }
+
+ console.log(statePos, objState, offset)
+ if (offset === -1) {
+ if (dir === undefined || dir === 'vertical') {
+ if (statePos - 1 < 0 && objState > 0) {
+ const pstateObjs = getGroupByValues(groupByDocs, categories[objState - 1]) ?? []
+ dispatch('select', pstateObjs[pstateObjs.length - 1])
+ } else {
+ const obj = stateObjs[statePos - 1] ?? stateObjs[0]
+ scrollInto(objState, obj)
+ dispatch('row-focus', obj)
+ }
+ return
+ }
+ }
+ if (offset === 1) {
+ if (dir === undefined || dir === 'vertical') {
+ if (statePos + 1 >= stateObjs.length && objState < categories.length) {
+ const pstateObjs = getGroupByValues(groupByDocs, categories[objState + 1]) ?? []
+ if (pstateObjs[0] !== undefined) {
+ dispatch('select', pstateObjs[0])
+ }
+ } else {
+ const obj = stateObjs[statePos + 1] ?? stateObjs[stateObjs.length - 1]
+ scrollInto(objState, obj)
+ dispatch('row-focus', obj)
+ }
+ return
+ }
+ }
+ if (offset === 0) {
+ // scrollInto(objState, obj)
+ dispatch('row-focus', obj)
+ }
+ } else {
+ listCategory[objState]?.select(offset, of, dir)
+ }
+ }
+ function scrollInto (statePos: number, obj: Doc): void {
+ // listCategory[statePos]?.scrollIntoView({ behavior: 'auto', block: 'nearest' })
+ listListCategory[statePos]?.scroll(obj)
+ listCategory[statePos]?.scroll(obj)
+ }
+
+ const listCategory: SvelteComponentTyped[] = []
+ const listListCategory: ListCategory[] = []
{#each categories as category, i (typeof category === 'object' ? category.name : category)}
{@const items = groupByKey === noCategory ? docs : getGroupByValues(groupByDocs, category)}
{
+ select(0, evt.detail)
+ }}
/>
diff --git a/plugins/view-resources/src/components/list/ListCategory.svelte b/plugins/view-resources/src/components/list/ListCategory.svelte
index 1c6e87ada5..1723369209 100644
--- a/plugins/view-resources/src/components/list/ListCategory.svelte
+++ b/plugins/view-resources/src/components/list/ListCategory.svelte
@@ -16,17 +16,18 @@
import { Class, Doc, DocumentUpdate, Lookup, PrimitiveType, Ref, Space, StatusValue } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { getClient } from '@hcengineering/presentation'
- import { calcRank, DocWithRank } from '@hcengineering/task'
+ import { DocWithRank, calcRank } from '@hcengineering/task'
import {
AnyComponent,
CheckBox,
ExpandCollapse,
+ Spinner,
getEventPositionElement,
- showPopup,
- Spinner
+ mouseAttractor,
+ showPopup
} from '@hcengineering/ui'
import { AttributeModel, BuildModelKey, ViewOptionModel, ViewOptions } from '@hcengineering/view'
- import { createEventDispatcher } from 'svelte'
+ import { createEventDispatcher, tick } from 'svelte'
import { FocusSelection, focusStore } from '../../selection'
import Menu from '../Menu.svelte'
import ListHeader from './ListHeader.svelte'
@@ -39,7 +40,6 @@
export let space: Ref | undefined
export let baseMenuClass: Ref> | undefined
export let items: Doc[]
- export let initIndex: number
export let createItemDialog: AnyComponent | undefined
export let createItemLabel: IntlString | undefined
export let loadingPropsLength: number | undefined
@@ -50,14 +50,11 @@
export let disableHeader = false
export let props: Record = {}
export let level: number
- export let elementByIndex: Map
- export let indexById: Map][, number>
export let lookup: Lookup
export let _class: Ref>
export let config: (string | BuildModelKey)[]
export let viewOptions: ViewOptions
export let newObjectProps: (doc: Doc) => Record | undefined
- export let docByIndex: Map
export let viewOptionsConfig: ViewOptionModel[] | undefined
export let dragItem: {
doc?: Doc
@@ -92,7 +89,7 @@
dispatch('row-focus', object)
}
- const handleMenuOpened = async (event: MouseEvent, object: Doc, rowIndex: number) => {
+ const handleMenuOpened = async (event: MouseEvent, object: Doc) => {
event.preventDefault()
handleRowFocused(object)
@@ -300,6 +297,24 @@
index: i
})
}
+ export function scroll (item: Doc): void {
+ const pos = items.findIndex((it) => it._id === item._id)
+ if (pos >= 0) {
+ if (collapsed) {
+ collapsed = false
+ tick().then(() => scroll(item))
+ return
+ }
+ if (pos >= limited.length) {
+ limit = (limit ?? 0) + 20
+
+ tick().then(() => scroll(item))
+ } else {
+ listItems[pos]?.scroll()
+ }
+ }
+ }
+ const listItems: ListItem[] = []
]
dragover(e, i)}
on:drop={dropItemHandle}
on:check={(ev) => dispatch('check', { docs: ev.detail.docs, value: ev.detail.value })}
- on:contextmenu={(event) => handleMenuOpened(event, docObject, initIndex + i)}
+ on:contextmenu={(event) => handleMenuOpened(event, docObject)}
on:focus={() => {}}
- on:mouseover={() => handleRowFocused(docObject)}
+ on:mouseover={mouseAttractor(() => handleRowFocused(docObject))}
{props}
/>
{/each}
diff --git a/plugins/view-resources/src/components/list/ListItem.svelte b/plugins/view-resources/src/components/list/ListItem.svelte
index 60b5564fa5..d0f5533874 100644
--- a/plugins/view-resources/src/components/list/ListItem.svelte
+++ b/plugins/view-resources/src/components/list/ListItem.svelte
@@ -13,25 +13,25 @@
// limitations under the License.
-->