Updated navigator layout (#5619)

Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
Alexander Platov
2024-06-05 12:50:13 +07:00
committed by GitHub
parent 07d35f0827
commit a437926f35
79 changed files with 1582 additions and 1012 deletions
@@ -32,7 +32,7 @@
export let documentById: Map<Ref<Document>, Document>
export let selected: Ref<Document> | undefined
export let level = 1
export let level: number = 0
const client = getClient()
const dispatch = createEventDispatcher()
@@ -97,10 +97,12 @@
}}
title={doc.name}
selected={selected === doc._id}
parent={desc.length > 0}
isFold
{level}
empty={desc.length === 0}
actions={getActions(doc)}
moreActions={() => getMoreActions(doc)}
{level}
shouldTooltip
on:click={() => {
handleDocumentSelected(doc._id)
}}
@@ -17,19 +17,7 @@
import { Document } from '@hcengineering/document'
import type { Asset, IntlString } from '@hcengineering/platform'
import type { Action, AnySvelteComponent } from '@hcengineering/ui'
import {
ActionIcon,
Icon,
IconChevronDown,
IconMoreH,
Label,
Menu,
navigate,
showPopup,
getTreeCollapsed,
setTreeCollapsed
} from '@hcengineering/ui'
import { IconMoreH, Menu, navigate, showPopup, NavItem, ButtonIcon } from '@hcengineering/ui'
import { getDocumentLink } from '../../utils'
export let doc: Document
@@ -37,14 +25,16 @@
export let iconProps: Record<string, any> | undefined = undefined
export let label: IntlString | undefined = undefined
export let title: string | undefined = undefined
export let parent: boolean = false
export let collapsed: boolean = getTreeCollapsed(doc._id)
export let selected: boolean = false
export let isFold: boolean = false
export let empty: boolean = false
export let shouldTooltip: boolean = false
export let level: number = 0
export let actions: Action[] = []
export let moreActions: (originalEvent?: MouseEvent) => Promise<Action[]> | undefined = async () => []
export let forciblyСollapsed: boolean = false
let hovered = false
let hovered: boolean = false
async function onMenuClick (ev: MouseEvent): Promise<void> {
showPopup(Menu, { actions: await moreActions(ev), ctx: doc._id }, ev.target as HTMLElement, () => {
hovered = false
@@ -58,59 +48,41 @@
}
const dispatch = createEventDispatcher()
$: collapsed = getTreeCollapsed(doc._id)
$: setTreeCollapsed(doc._id, collapsed)
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
class="antiNav-element tree"
class:selected
class:hovered
class:parent
class:collapsed
style:padding-left={`${level > 0 ? level * 1.25 + 0.125 : 0.75}rem`}
<NavItem
_id={doc._id}
{icon}
{iconProps}
{label}
{title}
{isFold}
{level}
{empty}
{selected}
showMenu={hovered}
{shouldTooltip}
{forciblyСollapsed}
on:click={() => {
selectDocument()
if (selected) {
collapsed = !collapsed
}
dispatch('click')
}}
>
<div
class="an-element__tool arrow"
class:empty={!parent}
on:click|preventDefault|stopPropagation={() => {
if (parent) collapsed = !collapsed
}}
>
{#if parent}<IconChevronDown size={'small'} filled />{/if}
</div>
{#if icon}
<div class="an-element__icon" class:folder={level === 0}>
<Icon {icon} {iconProps} size={'small'} />
</div>
{/if}
<span class="an-element__label">
{#if label}<Label {label} />{:else}{title}{/if}
</span>
<div class="an-element__grow" />
{#each actions as action}
{#if action.icon}
<div class="an-element__tool">
<ActionIcon label={action.label} icon={action.icon} size={'small'} action={(evt) => action.action({}, evt)} />
</div>
{/if}
{/each}
<div class="an-element__tool" class:pressed={hovered} on:click|preventDefault|stopPropagation={onMenuClick}>
<IconMoreH size={'small'} />
</div>
</div>
{#if parent && !collapsed}
<div class="antiNav-element__dropbox"><slot /></div>
{/if}
<svelte:fragment slot="actions">
{#each actions as action}
{#if action.icon}
<ButtonIcon
icon={action.icon}
kind={'tertiary'}
size={'extra-small'}
tooltip={{ label: action.label, direction: 'top' }}
on:click={(evt) => action.action({}, evt)}
/>
{/if}
{/each}
<ButtonIcon icon={IconMoreH} kind={'tertiary'} size={'extra-small'} pressed={hovered} on:click={onMenuClick} />
</svelte:fragment>
<svelte:fragment slot="dropbox">
<slot />
</svelte:fragment>
</NavItem>
@@ -13,25 +13,27 @@
// limitations under the License.
-->
<script lang="ts">
import { Ref, SortingOrder, Space } from '@hcengineering/core'
import { Ref, SortingOrder, Space, generateId } from '@hcengineering/core'
import { Document, Teamspace } from '@hcengineering/document'
import { createQuery } from '@hcengineering/presentation'
import { createQuery, getClient } from '@hcengineering/presentation'
import {
IconWithEmoji,
getTreeCollapsed,
setTreeCollapsed,
IconEdit,
getPlatformColorDef,
getPlatformColorForTextDef,
themeStore,
Action
Action,
IconAdd
} from '@hcengineering/ui'
import view from '@hcengineering/view'
import { TreeNode } from '@hcengineering/view-resources'
import { TreeNode, openDoc, getActions as getContributedActions } from '@hcengineering/view-resources'
import { SpacesNavModel } from '@hcengineering/workbench'
import { getResource } from '@hcengineering/platform'
import document from '../../plugin'
import { getDocumentIdFromFragment } from '../../utils'
import { getDocumentIdFromFragment, createEmptyDocument } from '../../utils'
import DocHierarchy from './DocHierarchy.svelte'
import DocTreeElement from './DocTreeElement.svelte'
export let space: Teamspace
export let model: SpacesNavModel
@@ -40,9 +42,9 @@
export let currentFragment: string | undefined
export let getActions: (space: Space) => Promise<Action[]> = async () => []
export let deselect: boolean = false
export let forciblyСollapsed: boolean = false
let collapsed: boolean = getTreeCollapsed(space._id)
$: setTreeCollapsed(space._id, collapsed)
const client = getClient()
let documents: Ref<Document>[] = []
let documentById: Map<Ref<Document>, Document> = new Map<Ref<Document>, Document>()
@@ -54,6 +56,8 @@
let selected: Ref<Document> | undefined
$: selected = getDocumentIdFromFragment(currentFragment ?? '')
let visibleItem: Document | undefined
$: visibleItem = selected !== undefined ? documentById.get(selected) : undefined
// TODO expand tree until the selected document ?
@@ -84,10 +88,43 @@
}
}
)
function getDocActions (doc: Document): Action[] {
return [
{
icon: IconAdd,
label: document.string.CreateDocument,
action: async (ctx: any, evt: Event) => {
const id: Ref<Document> = generateId()
await createEmptyDocument(client, id, doc.space, doc._id, {})
const object = await client.findOne(document.class.Document, { _id: id })
if (object !== undefined) {
openDoc(client.getHierarchy(), object)
}
}
}
]
}
async function getMoreActions (obj: Document): Promise<Action[]> {
const result: Action[] = []
const extraActions = await getContributedActions(client, obj)
for (const act of extraActions) {
result.push({
icon: act.icon ?? IconEdit,
label: act.label,
action: async (ctx: any, evt: Event) => {
const impl = await getResource(act.action)
await impl(obj, evt, act.actionProps)
}
})
}
return result
}
</script>
<TreeNode
{collapsed}
_id={space?._id}
icon={space?.icon === view.ids.IconWithEmoji ? IconWithEmoji : space?.icon ?? model.icon}
iconProps={space?.icon === view.ids.IconWithEmoji
@@ -99,10 +136,34 @@
: getPlatformColorForTextDef(space.name, $themeStore.dark).icon
}}
title={space.name}
folder
parent={descendants.size > 0}
type={'nested'}
highlighted={currentSpace === space._id}
visible={currentSpace === space._id || forciblyСollapsed}
actions={() => getActions(space)}
on:click={() => (collapsed = !collapsed)}
{forciblyСollapsed}
>
<DocHierarchy {documents} {descendants} {documentById} {selected} />
<svelte:fragment slot="visible">
{#if (selected || forciblyСollapsed) && visibleItem}
{@const item = visibleItem}
<DocTreeElement
doc={item}
icon={item.icon === view.ids.IconWithEmoji ? IconWithEmoji : item.icon ?? document.icon.Document}
iconProps={item.icon === view.ids.IconWithEmoji
? { icon: visibleItem.color }
: {
fill: item.color !== undefined ? getPlatformColorDef(item.color, $themeStore.dark).icon : 'currentColor'
}}
title={item.name}
selected
isFold
empty
shouldTooltip
actions={getDocActions(item)}
moreActions={() => getMoreActions(item)}
forciblyСollapsed
/>
{/if}
</svelte:fragment>
</TreeNode>