mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-25 01:39:53 +00:00
fix navigation handling (#2373)
Signed-off-by: Ruslan Bayandinov <wazsone@ya.ru>
This commit is contained in:
parent
5cf3ae7846
commit
2df58960d2
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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 }
|
||||||
|
|
||||||
|
@ -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]])}
|
||||||
/>
|
/>
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user