Fix UpDownNavigator (#2311)

Signed-off-by: Ruslan Bayandinov <wazsone@ya.ru>
This commit is contained in:
Ruslan Bayandinov 2022-10-20 09:42:18 +07:00 committed by GitHub
parent 9fc7c33372
commit 39b8454317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 21 deletions

View File

@ -264,6 +264,7 @@
{#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,16 +13,10 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { Doc, Ref, WithLookup } from '@hcengineering/core' import { Ref, WithLookup } from '@hcengineering/core'
import { Issue, IssueStatus, Team } from '@hcengineering/tracker' import { Issue, IssueStatus, Team } from '@hcengineering/tracker'
import { getEventPositionElement, showPanel, showPopup } from '@hcengineering/ui' import { getEventPositionElement, showPanel, showPopup } from '@hcengineering/ui'
import { import { ActionContext, ContextMenu, FixedColumn } from '@hcengineering/view-resources'
ActionContext,
ContextMenu,
FixedColumn,
ListSelectionProvider,
SelectDirection
} from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { flip } from 'svelte/animate' import { flip } from 'svelte/animate'
import { getIssueId } from '../../../issues' import { getIssueId } from '../../../issues'
@ -45,6 +39,7 @@
let hoveringIndex: number | null = null let hoveringIndex: number | null = null
function openIssue (target: Issue) { function openIssue (target: Issue) {
dispatch('issue-focus', target)
showPanel(tracker.component.EditIssue, target._id, target._class, 'content') showPanel(tracker.component.EditIssue, target._id, target._class, 'content')
} }
@ -75,8 +70,6 @@
showPopup(ContextMenu, { object }, getEventPositionElement(ev)) showPopup(ContextMenu, { object }, getEventPositionElement(ev))
} }
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {})
let varsStyle: string = '' let varsStyle: string = ''
const propsWidth: Record<string, number> = { issue: 0 } const propsWidth: Record<string, number> = { issue: 0 }
$: if (propsWidth) { $: if (propsWidth) {
@ -96,6 +89,7 @@
{#each issues as issue, index (issue._id)} {#each issues as issue, index (issue._id)}
{@const currentTeam = teams.get(issue.space)} {@const currentTeam = teams.get(issue.space)}
{@const openIssueCall = () => openIssue(issue)}
<div <div
class="flex-between row" class="flex-between row"
class:is-dragging={index === draggingIndex} class:is-dragging={index === draggingIndex}
@ -104,26 +98,20 @@
style={varsStyle} style={varsStyle}
animate:flip={{ duration: 400 }} animate:flip={{ duration: 400 }}
draggable={true} draggable={true}
on:click|self={() => openIssue(issue)} on:click|self={openIssueCall}
on:contextmenu|preventDefault={(ev) => showContextMenu(ev, issue)} on:contextmenu|preventDefault={(ev) => showContextMenu(ev, issue)}
on:dragstart={(ev) => handleDragStart(ev, index)} on:dragstart={(ev) => handleDragStart(ev, index)}
on:dragover|preventDefault={() => false} on:dragover|preventDefault={() => false}
on:dragenter={() => (hoveringIndex = index)} on:dragenter={() => (hoveringIndex = index)}
on:drop|preventDefault={(ev) => handleDrop(ev, index)} on:drop|preventDefault={(ev) => handleDrop(ev, index)}
on:dragend={resetDrag} on:dragend={resetDrag}
on:mouseover={() => {
listProvider.updateFocus(issue)
}}
on:focus={() => {
listProvider.updateFocus(issue)
}}
> >
<div class="draggable-container"> <div class="draggable-container">
<div class="draggable-mark"><Circles /></div> <div class="draggable-mark"><Circles /></div>
</div> </div>
<div class="flex-row-center ml-6 clear-mins gap-2"> <div class="flex-row-center ml-6 clear-mins gap-2">
<PriorityEditor value={issue} isEditable kind={'list'} size={'small'} justify={'center'} /> <PriorityEditor value={issue} isEditable kind={'list'} size={'small'} justify={'center'} />
<span class="issuePresenter" on:click={() => openIssue(issue)}> <span class="issuePresenter" on:click={openIssueCall}>
<FixedColumn <FixedColumn
width={propsWidth.issue} width={propsWidth.issue}
key={'issue'} key={'issue'}
@ -143,7 +131,7 @@
size={'small'} size={'small'}
tooltipAlignment="bottom" tooltipAlignment="bottom"
/> />
<span class="text name" title={issue.title} on:click={() => openIssue(issue)}> <span class="text name" title={issue.title} on:click={openIssueCall}>
{issue.title} {issue.title}
</span> </span>
</div> </div>

View File

@ -13,10 +13,11 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { Ref, SortingOrder, WithLookup } from '@hcengineering/core' import { Doc, 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'
@ -24,6 +25,7 @@
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>[]>
@ -31,6 +33,7 @@
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
@ -47,10 +50,42 @@
} }
} }
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">
@ -90,7 +125,15 @@
<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 issues={subIssues} {issueStatuses} {teams} on:move={handleIssueSwap} /> <SubIssueList
issues={subIssues}
{issueStatuses}
{teams}
on:move={handleIssueSwap}
on:issue-focus={(event) => {
listProvider.updateFocus(event.detail ?? undefined)
}}
/>
</div> </div>
{/if} {/if}
</ExpandCollapse> </ExpandCollapse>