fix navigation handling (#2373)

Signed-off-by: Ruslan Bayandinov <wazsone@ya.ru>
This commit is contained in:
Ruslan Bayandinov 2022-11-12 12:52:16 +07:00 committed by GitHub
parent 5cf3ae7846
commit 2df58960d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 90 additions and 82 deletions

View File

@ -108,32 +108,6 @@
dispatch('row-focus', object) dispatch('row-focus', object)
} }
export const onElementSelected = (offset: 1 | -1 | 0, docObject?: Doc) => {
let position =
(docObject !== undefined ? combinedGroupedIssues.findIndex((x) => x._id === docObject?._id) : selectedRowIndex) ??
-1
position += offset
if (position < 0) {
position = 0
}
if (position >= combinedGroupedIssues.length) {
position = combinedGroupedIssues.length - 1
}
const objectRef = objectRefs[position]
selectedRowIndex = position
handleRowFocused(combinedGroupedIssues[position])
if (objectRef) {
objectRef.scrollIntoView({ behavior: 'auto', block: 'nearest' })
}
}
const handleNewIssueAdded = (event: MouseEvent, category: any) => { const handleNewIssueAdded = (event: MouseEvent, category: any) => {
if (!currentSpace) { if (!currentSpace) {
return return

View File

@ -41,11 +41,7 @@
export let groupedIssues: { [key: string | number | symbol]: Issue[] } = {} export let groupedIssues: { [key: string | number | symbol]: Issue[] } = {}
export let loadingProps: LoadingProps | undefined = undefined export let loadingProps: LoadingProps | undefined = undefined
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => { const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {})
if (dir === 'vertical') {
issuesList.onElementSelected(offset, of)
}
})
let issuesList: IssuesList let issuesList: IssuesList

View File

@ -24,7 +24,6 @@
function updateSearchQuery (search: string): void { function updateSearchQuery (search: string): void {
searchQuery = search === '' ? { ...query } : { ...query, $search: search } searchQuery = search === '' ? { ...query } : { ...query, $search: search }
} }
$: updateSearchQuery(search)
$: if (query) updateSearchQuery(search) $: if (query) updateSearchQuery(search)
let resultQuery: DocumentQuery<Issue> = { ...searchQuery } let resultQuery: DocumentQuery<Issue> = { ...searchQuery }

View File

@ -20,7 +20,7 @@
import { getResource } from '@hcengineering/platform' import { getResource } from '@hcengineering/platform'
import presentation, { createQuery, getClient, MessageViewer } from '@hcengineering/presentation' import presentation, { createQuery, getClient, MessageViewer } from '@hcengineering/presentation'
import setting, { settingId } from '@hcengineering/setting' import setting, { settingId } from '@hcengineering/setting'
import type { Issue, IssueStatus, Team } from '@hcengineering/tracker' import type { Issue, IssuesGrouping, IssuesOrdering, IssueStatus, Team } from '@hcengineering/tracker'
import { import {
Button, Button,
EditBox, EditBox,
@ -34,7 +34,14 @@
showPopup, showPopup,
Spinner Spinner
} from '@hcengineering/ui' } from '@hcengineering/ui'
import { ContextMenu, UpDownNavigator } from '@hcengineering/view-resources' import {
ContextMenu,
focusStore,
ListSelectionProvider,
SelectDirection,
UpDownNavigator,
viewOptionsStore
} from '@hcengineering/view-resources'
import { createEventDispatcher, onDestroy, onMount } from 'svelte' import { createEventDispatcher, onDestroy, onMount } from 'svelte'
import { generateIssueShortLink, getIssueId } from '../../../issues' import { generateIssueShortLink, getIssueId } from '../../../issues'
import tracker from '../../../plugin' import tracker from '../../../plugin'
@ -43,13 +50,15 @@
import CopyToClipboard from './CopyToClipboard.svelte' import CopyToClipboard from './CopyToClipboard.svelte'
import SubIssues from './SubIssues.svelte' import SubIssues from './SubIssues.svelte'
import SubIssueSelector from './SubIssueSelector.svelte' import SubIssueSelector from './SubIssueSelector.svelte'
import { groupBy as groupByFunc, issuesOrderKeyMap, issuesSortOrderMap } from '../../../utils'
import contact from '@hcengineering/contact'
export let _id: Ref<Issue> export let _id: Ref<Issue>
export let _class: Ref<Class<Issue>> export let _class: Ref<Class<Issue>>
let lastId: Ref<Doc> = _id let lastId: Ref<Doc> = _id
let lastClass: Ref<Class<Doc>> = _class let lastClass: Ref<Class<Doc>> = _class
const query = createQuery() const queryClient = createQuery()
const statusesQuery = createQuery() const statusesQuery = createQuery()
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
const client = getClient() const client = getClient()
@ -63,6 +72,14 @@
let isEditing = false let isEditing = false
let descriptionBox: AttachmentStyledBox let descriptionBox: AttachmentStyledBox
let groupBy: IssuesGrouping
let orderBy: IssuesOrdering
let shouldShowSubIssues: boolean
$: ({ groupBy, orderBy, shouldShowSubIssues } = $viewOptionsStore)
$: orderByKey = issuesOrderKeyMap[orderBy]
$: subIssuesQuery = shouldShowSubIssues ? {} : { attachedTo: tracker.ids.NoParent }
$: query = { space: issue?.space }
const notificationClient = getResource(notification.function.GetNotificationClient).then((res) => res()) const notificationClient = getResource(notification.function.GetNotificationClient).then((res) => res())
$: read(_id) $: read(_id)
@ -82,7 +99,7 @@
$: _id && $: _id &&
_class && _class &&
query.query( queryClient.query(
_class, _class,
{ _id }, { _id },
async (result) => { async (result) => {
@ -110,6 +127,72 @@
$: isDescriptionEmpty = !new DOMParser().parseFromString(description, 'text/html').documentElement.innerText?.trim() $: isDescriptionEmpty = !new DOMParser().parseFromString(description, 'text/html').documentElement.innerText?.trim()
$: parentIssue = issue?.$lookup?.attachedTo $: parentIssue = issue?.$lookup?.attachedTo
let issues: WithLookup<Issue>[] = []
let neighbourIssues: Issue[] = []
const issuesQuery = createQuery()
const subIssuesQueryClient = createQuery()
$: if (parentIssue) {
subIssuesQueryClient.query(
tracker.class.Issue,
{ attachedTo: parentIssue?._id },
async (result) => (neighbourIssues = result ?? []),
{
sort: { rank: SortingOrder.Descending }
}
)
} else {
issuesQuery.query(
tracker.class.Issue,
{ ...subIssuesQuery, ...query },
(result) => {
issues = result
},
{
sort: { [orderByKey]: issuesSortOrderMap[orderByKey] },
lookup: {
assignee: contact.class.Employee,
status: tracker.class.IssueStatus,
space: tracker.class.Team,
sprint: tracker.class.Sprint,
_id: {
subIssues: tracker.class.Issue
}
}
}
)
}
$: groupedIssues = groupByFunc(issues, groupBy)
$: flatGroupedIssues = Object.values(groupedIssues ?? {}).flat(1)
$: issuesToNavigate = parentIssue ? neighbourIssues : flatGroupedIssues
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
if (dir === 'vertical') {
if (groupedIssues) {
const selectedRowIndex = listProvider.current($focusStore)
let position =
(of !== undefined ? issuesToNavigate.findIndex((x) => x._id === of?._id) : selectedRowIndex) ?? -1
position -= offset
if (position < 0) {
position = 0
}
if (position >= issuesToNavigate.length) {
position = issuesToNavigate.length - 1
}
listProvider.updateFocus(issuesToNavigate[position])
}
}
})
$: if (issue) listProvider.updateFocus(issue)
$: listProvider.update(issuesToNavigate)
function edit (ev: MouseEvent) { function edit (ev: MouseEvent) {
ev.preventDefault() ev.preventDefault()
@ -265,7 +348,6 @@
{#if currentTeam !== undefined && issueStatuses !== undefined} {#if currentTeam !== undefined && issueStatuses !== undefined}
<SubIssues <SubIssues
{issue} {issue}
{parentIssue}
issueStatuses={new Map([[currentTeam._id, issueStatuses]])} issueStatuses={new Map([[currentTeam._id, issueStatuses]])}
teams={new Map([[currentTeam?._id, currentTeam]])} teams={new Map([[currentTeam?._id, currentTeam]])}
/> />

View File

@ -13,11 +13,10 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { Doc, Ref, SortingOrder, WithLookup } from '@hcengineering/core' import { Ref, SortingOrder, WithLookup } from '@hcengineering/core'
import { createQuery, getClient } from '@hcengineering/presentation' import { createQuery, getClient } from '@hcengineering/presentation'
import { calcRank, Issue, IssueStatus, Team } from '@hcengineering/tracker' import { calcRank, Issue, IssueStatus, Team } from '@hcengineering/tracker'
import { Button, Spinner, ExpandCollapse, closeTooltip, IconAdd } from '@hcengineering/ui' import { Button, Spinner, ExpandCollapse, closeTooltip, IconAdd } from '@hcengineering/ui'
import { focusStore, ListSelectionProvider, SelectDirection } from '@hcengineering/view-resources'
import tracker from '../../../plugin' import tracker from '../../../plugin'
import Collapsed from '../../icons/Collapsed.svelte' import Collapsed from '../../icons/Collapsed.svelte'
import Expanded from '../../icons/Expanded.svelte' import Expanded from '../../icons/Expanded.svelte'
@ -25,7 +24,6 @@
import SubIssueList from './SubIssueList.svelte' import SubIssueList from './SubIssueList.svelte'
export let issue: Issue export let issue: Issue
export let parentIssue: Doc | undefined
export let teams: Map<Ref<Team>, Team> export let teams: Map<Ref<Team>, Team>
export let issueStatuses: Map<Ref<Team>, WithLookup<IssueStatus>[]> export let issueStatuses: Map<Ref<Team>, WithLookup<IssueStatus>[]>
@ -33,7 +31,6 @@
const client = getClient() const client = getClient()
let subIssues: Issue[] | undefined let subIssues: Issue[] | undefined
let neighbourIssues: Issue[] | undefined
let isCollapsed = false let isCollapsed = false
let isCreating = false let isCreating = false
@ -50,42 +47,10 @@
} }
} }
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
if (dir === 'vertical') {
if (neighbourIssues) {
const selectedRowIndex = listProvider.current($focusStore)
let position = (of !== undefined ? neighbourIssues.findIndex((x) => x._id === of?._id) : selectedRowIndex) ?? -1
position += offset
if (position < 0) {
position = 0
}
if (position >= neighbourIssues.length) {
position = neighbourIssues.length - 1
}
listProvider.updateFocus(neighbourIssues[position])
}
}
})
$: hasSubIssues = issue.subIssues > 0 $: hasSubIssues = issue.subIssues > 0
$: subIssuesQuery.query(tracker.class.Issue, { attachedTo: issue._id }, async (result) => (subIssues = result), { $: subIssuesQuery.query(tracker.class.Issue, { attachedTo: issue._id }, async (result) => (subIssues = result), {
sort: { rank: SortingOrder.Ascending } sort: { rank: SortingOrder.Ascending }
}) })
$: if (parentIssue) {
subIssuesQuery.query(
tracker.class.Issue,
{ attachedTo: parentIssue?._id },
async (result) => (neighbourIssues = result),
{
sort: { rank: SortingOrder.Ascending }
}
)
}
$: if (neighbourIssues && neighbourIssues.length > 0) listProvider.update(neighbourIssues)
</script> </script>
<div class="flex-between"> <div class="flex-between">
@ -125,15 +90,7 @@
<ExpandCollapse isExpanded={!isCollapsed} duration={400}> <ExpandCollapse isExpanded={!isCollapsed} duration={400}>
{#if hasSubIssues} {#if hasSubIssues}
<div class="list" class:collapsed={isCollapsed}> <div class="list" class:collapsed={isCollapsed}>
<SubIssueList <SubIssueList issues={subIssues} {issueStatuses} {teams} on:move={handleIssueSwap} />
issues={subIssues}
{issueStatuses}
{teams}
on:move={handleIssueSwap}
on:issue-focus={(event) => {
listProvider.updateFocus(event.detail ?? undefined)
}}
/>
</div> </div>
{/if} {/if}
</ExpandCollapse> </ExpandCollapse>