mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 11:01:54 +03:00
Inbox keyboard action (#2977)
This commit is contained in:
parent
12974b5bb7
commit
ad4394d541
@ -269,9 +269,10 @@ export function createModel (builder: Builder): void {
|
||||
label: notification.string.Archive,
|
||||
icon: view.icon.Archive,
|
||||
input: 'focus',
|
||||
keyBinding: ['Backspace'],
|
||||
category: notification.category.Notification,
|
||||
target: notification.class.DocUpdates,
|
||||
context: { mode: 'context', application: notification.app.Notification, group: 'edit' }
|
||||
context: { mode: ['context', 'browser'], group: 'edit' }
|
||||
},
|
||||
notification.action.Hide
|
||||
)
|
||||
|
@ -20,6 +20,7 @@
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { AnyComponent, Component, Label, Loading, Scroller } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { ActionContext, ListSelectionProvider, SelectDirection } from '@hcengineering/view-resources'
|
||||
import NotificationView from './NotificationView.svelte'
|
||||
|
||||
export let visibileNav: boolean
|
||||
@ -39,8 +40,11 @@
|
||||
},
|
||||
(res) => {
|
||||
docs = res
|
||||
if (loading && docs.length > 0) {
|
||||
select(docs[0].attachedTo, docs[0].attachedToClass)
|
||||
listProvider.update(docs)
|
||||
if (loading || _id === undefined) {
|
||||
changeSelected(selected)
|
||||
} else if (docs.find((p) => p.attachedTo === _id) === undefined) {
|
||||
changeSelected(selected)
|
||||
}
|
||||
loading = false
|
||||
},
|
||||
@ -51,16 +55,32 @@
|
||||
}
|
||||
)
|
||||
|
||||
function select (objectId: Ref<Doc>, objectClass: Ref<Class<Doc>>) {
|
||||
const targetClass = hierarchy.getClass(objectClass)
|
||||
const panelComponent = hierarchy.as(targetClass, view.mixin.ObjectPanel)
|
||||
component = panelComponent.component ?? view.component.EditDoc
|
||||
_id = objectId
|
||||
_class = objectClass
|
||||
$: changeSelected(selected)
|
||||
|
||||
function changeSelected (index: number) {
|
||||
if (docs[index] !== undefined) {
|
||||
select(docs[index])
|
||||
} else if (docs.length) {
|
||||
if (index < docs.length - 1) {
|
||||
selected++
|
||||
} else {
|
||||
selected--
|
||||
}
|
||||
} else {
|
||||
selected = 0
|
||||
component = undefined
|
||||
_id = undefined
|
||||
_class = undefined
|
||||
}
|
||||
}
|
||||
|
||||
function selectHandler (e: CustomEvent) {
|
||||
select(e.detail._id, e.detail._class)
|
||||
function select (value: DocUpdates) {
|
||||
listProvider.updateFocus(value)
|
||||
const targetClass = hierarchy.getClass(value.attachedToClass)
|
||||
const panelComponent = hierarchy.as(targetClass, view.mixin.ObjectPanel)
|
||||
component = panelComponent.component ?? view.component.EditDoc
|
||||
_id = value.attachedTo
|
||||
_class = value.attachedToClass
|
||||
}
|
||||
|
||||
let component: AnyComponent | undefined
|
||||
@ -69,12 +89,28 @@
|
||||
|
||||
let viewlets: Map<ActivityKey, TxViewlet>
|
||||
|
||||
const listProvider = new ListSelectionProvider((offset: 1 | -1 | 0, of?: Doc, dir?: SelectDirection) => {
|
||||
if (dir === 'vertical') {
|
||||
const value = selected + offset
|
||||
if (docs[value] !== undefined) {
|
||||
selected = value
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const descriptors = createQuery()
|
||||
descriptors.query(activity.class.TxViewlet, {}, (result) => {
|
||||
viewlets = new Map(result.map((r) => [activityKey(r.objectClass, r.txClass), r]))
|
||||
})
|
||||
|
||||
let selected = 0
|
||||
</script>
|
||||
|
||||
<ActionContext
|
||||
context={{
|
||||
mode: 'browser'
|
||||
}}
|
||||
/>
|
||||
<div class="flex h-full">
|
||||
{#if visibileNav}
|
||||
<div class="antiPanel-component border-right filled indent aside">
|
||||
@ -88,8 +124,15 @@
|
||||
{#if loading}
|
||||
<Loading />
|
||||
{:else}
|
||||
{#each docs as doc}
|
||||
<NotificationView value={doc} selected={doc.attachedTo === _id} {viewlets} on:click={selectHandler} />
|
||||
{#each docs as doc, i}
|
||||
<NotificationView
|
||||
value={doc}
|
||||
selected={selected === i}
|
||||
{viewlets}
|
||||
on:click={() => {
|
||||
selected = i
|
||||
}}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
</Scroller>
|
||||
@ -99,9 +142,7 @@
|
||||
{#if component && _id && _class}
|
||||
<Component is={component} props={{ embedded: true, _id, _class }} />
|
||||
{:else}
|
||||
<div class="antiPanel-component filled w-full">
|
||||
<Loading />
|
||||
</div>
|
||||
<div class="antiPanel-component filled w-full" />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
import { AnySvelteComponent, Label, TimeSince, getEventPositionElement, showPopup } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { Menu } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import TxView from './TxView.svelte'
|
||||
|
||||
export let value: DocUpdates
|
||||
@ -60,10 +59,10 @@
|
||||
query.query(contact.class.EmployeeAccount, { _id: tx.modifiedBy as Ref<EmployeeAccount> }, (r) => ([account] = r))
|
||||
$: employee = account && $employeeByIdStore.get(account.employee)
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const docQuery = createQuery()
|
||||
$: docQuery.query(value.attachedToClass, { _id: value.attachedTo }, (res) => ([doc] = res))
|
||||
$: docQuery.query(value.attachedToClass, { _id: value.attachedTo }, (res) => {
|
||||
;[doc] = res
|
||||
})
|
||||
|
||||
$: newTxes = value.txes.length
|
||||
|
||||
@ -74,12 +73,7 @@
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
{#if doc}
|
||||
<div
|
||||
class="container cursor-pointer bottom-divider"
|
||||
class:selected
|
||||
on:contextmenu|preventDefault={showMenu}
|
||||
on:click={() => dispatch('click', { _id: value.attachedTo, _class: value.attachedToClass })}
|
||||
>
|
||||
<div class="container cursor-pointer bottom-divider" class:selected on:contextmenu|preventDefault={showMenu} on:click>
|
||||
<div class="header flex">
|
||||
<Avatar avatar={employee?.avatar} size="medium" />
|
||||
<div class="ml-2 w-full clear-mins">
|
||||
|
@ -133,11 +133,19 @@ export async function unsubscribe (object: DocUpdates): Promise<void> {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function hide (object: DocUpdates): Promise<void> {
|
||||
export async function hide (object: DocUpdates | DocUpdates[]): Promise<void> {
|
||||
const client = getClient()
|
||||
await client.update(object, {
|
||||
hidden: true
|
||||
})
|
||||
if (Array.isArray(object)) {
|
||||
for (const value of object) {
|
||||
await client.update(value, {
|
||||
hidden: true
|
||||
})
|
||||
}
|
||||
} else {
|
||||
await client.update(object, {
|
||||
hidden: true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import { Doc, DocumentQuery, Ref } from '@hcengineering/core'
|
||||
import { Issue, Project } from '@hcengineering/tracker'
|
||||
import { Viewlet, ViewOptions } from '@hcengineering/view'
|
||||
import { ViewOptions, Viewlet } from '@hcengineering/view'
|
||||
import {
|
||||
ActionContext,
|
||||
List,
|
||||
@ -23,7 +23,6 @@
|
||||
SelectDirection,
|
||||
selectionStore
|
||||
} from '@hcengineering/view-resources'
|
||||
import { onDestroy } from 'svelte'
|
||||
import tracker from '../../../plugin'
|
||||
|
||||
export let query: DocumentQuery<Issue> | undefined = undefined
|
||||
@ -43,10 +42,6 @@
|
||||
list.select(offset, of)
|
||||
}
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
ListSelectionProvider.Pop()
|
||||
})
|
||||
</script>
|
||||
|
||||
<ActionContext
|
||||
|
@ -146,13 +146,15 @@ export class ListSelectionProvider implements SelectionFocusProvider {
|
||||
})
|
||||
|
||||
if (this._docs.length > 0) {
|
||||
if (this._current?.focus === undefined) {
|
||||
if (this._current === undefined) {
|
||||
this.delegate(0, undefined, 'vertical')
|
||||
} else {
|
||||
// Check if we don't have object, we need to select first one.
|
||||
this.delegate(0, this._current?.focus, 'vertical')
|
||||
}
|
||||
updateFocus({ focus: this._current?.focus, provider: this })
|
||||
if (this._current?.focus === undefined) {
|
||||
updateFocus({ focus: this._current?.focus, provider: this })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,10 @@ async function CommentCreate (tx: TxCUD<Doc>, control: TriggerControl): Promise<
|
||||
const actualTx = TxProcessor.extractTx(tx)
|
||||
if (actualTx._class !== core.class.TxCreateDoc) return []
|
||||
const doc = TxProcessor.createDoc2Doc(actualTx as TxCreateDoc<Comment>)
|
||||
if (!hierarchy.isDerived(doc._class, chunter.class.Comment)) {
|
||||
if (
|
||||
!hierarchy.isDerived(doc._class, chunter.class.Comment) ||
|
||||
hierarchy.isDerived(doc._class, chunter.class.Backlink)
|
||||
) {
|
||||
return []
|
||||
}
|
||||
const res: Tx[] = []
|
||||
|
@ -94,6 +94,16 @@ export async function OnBacklinkCreate (tx: Tx, control: TriggerControl): Promis
|
||||
}
|
||||
)
|
||||
res.push(collabTx)
|
||||
res = res.concat(
|
||||
await createCollabDocInfo(
|
||||
[receiver._id],
|
||||
tx as TxCUD<Doc>,
|
||||
doc._id,
|
||||
doc._class,
|
||||
control,
|
||||
tx._id as Ref<TxCUD<Doc>>
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
const notifyTx = await createNotificationTxes(
|
||||
|
Loading…
Reference in New Issue
Block a user