mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-28 04:25:03 +02:00
Notification presenter (#1055)
Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/chunter": "~0.6.0",
|
||||
"@anticrm/presentation": "~0.6.2",
|
||||
"@anticrm/activity": "~0.6.0"
|
||||
"@anticrm/activity": "~0.6.0",
|
||||
"@anticrm/notification": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
<script lang="ts">
|
||||
import activity from '@anticrm/activity'
|
||||
import type { Doc } from '@anticrm/core'
|
||||
import notification from '@anticrm/notification'
|
||||
import type { Asset } from '@anticrm/platform'
|
||||
import type { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
|
||||
import { Icon, IconClose, IconExpand, IconMoreH, Component, ActionIcon, Scroller } from '@anticrm/ui'
|
||||
import { ActionIcon,AnyComponent,AnySvelteComponent,Component,Icon,IconClose,IconExpand,IconMoreH,Scroller } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let title: string
|
||||
@@ -43,7 +43,7 @@
|
||||
{#if subtitle }<span class="ac-header__description">{subtitle}</span>{/if}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <ActionIcon icon={IconMoreH} size={'medium'} /> -->
|
||||
<Component is={notification.component.LastViewEditor} props={{ value: object }} />
|
||||
</div>
|
||||
{#if $$slots.subtitle}
|
||||
<div class="ac-subtitle">
|
||||
@@ -68,7 +68,7 @@
|
||||
{#if subtitle }<span class="ac-header__description">{subtitle}</span>{/if}
|
||||
</div>
|
||||
</div>
|
||||
<ActionIcon icon={IconMoreH} size={'medium'} />
|
||||
<Component is={notification.component.LastViewEditor} props={{ value: object }} />
|
||||
</div>
|
||||
{#if $$slots.subtitle}
|
||||
<div class="ac-subtitle">
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
btn.focus()
|
||||
if (!opened) {
|
||||
opened = true
|
||||
showPopup(DropdownPopup, { title: label, caption: 'suggested', items }, container, (result) => {
|
||||
showPopup(DropdownPopup, { title: label, items }, container, (result) => {
|
||||
if (result) selected = result
|
||||
opened = false
|
||||
})
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
config={descr.config}
|
||||
options={descr.options}
|
||||
query={ resultQuery }
|
||||
enableChecking
|
||||
showNotification
|
||||
/>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
config={descr.config}
|
||||
options={descr.options}
|
||||
query={resultQuery}
|
||||
enableChecking
|
||||
showNotification
|
||||
/>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
"@anticrm/view-resources": "~0.6.0",
|
||||
"@anticrm/attachment-resources": "~0.6.0",
|
||||
"@anticrm/contact-resources": "~0.6.0",
|
||||
"@anticrm/chunter-resources": "~0.6.0"
|
||||
"@anticrm/chunter-resources": "~0.6.0",
|
||||
"@anticrm/notification": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
config={descr.config}
|
||||
options={descr.options}
|
||||
query={ resultQuery }
|
||||
enableChecking
|
||||
showNotification
|
||||
/>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
@@ -19,10 +19,11 @@
|
||||
import { ContactPresenter } from '@anticrm/contact-resources'
|
||||
import type { WithLookup } from '@anticrm/core'
|
||||
import type { Lead } from '@anticrm/lead'
|
||||
import { ActionIcon, IconMoreH, showPanel, showPopup } from '@anticrm/ui'
|
||||
import { ActionIcon, Component, IconMoreH, showPanel, showPopup } from '@anticrm/ui'
|
||||
import view from '@anticrm/view'
|
||||
import { ContextMenu } from '@anticrm/view-resources'
|
||||
import lead from '../plugin'
|
||||
import notification from '@anticrm/notification'
|
||||
|
||||
export let object: WithLookup<Lead>
|
||||
export let draggable: boolean
|
||||
@@ -37,16 +38,27 @@
|
||||
</script>
|
||||
|
||||
<div class="card-container" {draggable} class:draggable on:dragstart on:dragend>
|
||||
<div class="content">
|
||||
<div class="flex-between mb-4">
|
||||
<div class="flex-col">
|
||||
<div class="fs-title cursor-pointer" on:click={showLead}>{object.title}</div>
|
||||
</div>
|
||||
<div class="flex-row-center">
|
||||
<div class="flex-col ml-2">
|
||||
<div class="fs-title cursor-pointer" on:click={showLead}>{object.title}</div>
|
||||
<div class="mr-2">
|
||||
<Component is={notification.component.NotificationPresenter} props={{ value: object }} />
|
||||
</div>
|
||||
<ActionIcon
|
||||
label={lead.string.More}
|
||||
action={(evt) => {
|
||||
showMenu(evt)
|
||||
}}
|
||||
icon={IconMoreH}
|
||||
size={'small'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-between">
|
||||
{#if object.$lookup?.attachedTo}
|
||||
<ContactPresenter value={object.$lookup?.attachedTo} />
|
||||
<ContactPresenter value={object.$lookup.attachedTo} />
|
||||
{/if}
|
||||
<div class="flex-row-center">
|
||||
{#if (object.attachments ?? 0) > 0}
|
||||
@@ -55,16 +67,6 @@
|
||||
{#if (object.comments ?? 0) > 0}
|
||||
<div class="step-lr75"><CommentsPresenter value={object} /></div>
|
||||
{/if}
|
||||
<div class="step-lr75">
|
||||
<ActionIcon
|
||||
label={lead.string.More}
|
||||
action={(evt) => {
|
||||
showMenu(evt)
|
||||
}}
|
||||
icon={IconMoreH}
|
||||
size={'small'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -79,11 +81,6 @@
|
||||
user-select: none;
|
||||
backdrop-filter: blur(10px);
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
&.draggable {
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
@@ -2,4 +2,12 @@
|
||||
<symbol id="notification" viewBox="0 0 24 24">
|
||||
<path d="M9.78261 18.7959C9.78261 20.0132 10.7754 21 12 21C13.2246 21 14.2174 20.0132 14.2174 18.7959M19.3905 14.7551C18.7778 14.7551 18.2826 14.2631 18.2826 13.6524V9.24462C18.2826 5.79553 15.4703 3 12 3C8.52965 3 5.71739 5.79481 5.71739 9.24462V13.6524C5.71739 14.2609 5.2205 14.7551 4.60947 14.7551C3.99732 14.7551 3.5 15.2496 3.5 15.8571C3.5 16.4658 3.99753 16.9592 4.61235 16.9592H19.3876C20.0015 16.9592 20.5 16.4646 20.5 15.8571C20.5 15.2497 20.0014 14.7551 19.3905 14.7551Z"/>
|
||||
</symbol>
|
||||
<symbol id="track" viewBox="0 0 24 24">
|
||||
<path d="M9.78261 18.7959C9.78261 20.0132 10.7754 21 12 21C13.2246 21 14.2174 20.0132 14.2174 18.7959M19.3905 14.7551C18.7778 14.7551 18.2826 14.2631 18.2826 13.6524V9.24462C18.2826 5.79553 15.4703 3 12 3C8.52965 3 5.71739 5.79481 5.71739 9.24462V13.6524C5.71739 14.2609 5.2205 14.7551 4.60947 14.7551C3.99732 14.7551 3.5 15.2496 3.5 15.8571C3.5 16.4658 3.99753 16.9592 4.61235 16.9592H19.3876C20.0015 16.9592 20.5 16.4646 20.5 15.8571C20.5 15.2497 20.0014 14.7551 19.3905 14.7551Z" fill="none"
|
||||
stroke="currentColor"/>
|
||||
</symbol>
|
||||
<symbol id="donttrack" viewBox="0 0 24 24">
|
||||
<path stroke="currentColor" fill="none" d="m9.78261,18.7959c0,1.2173 0.99279,2.2041 2.21739,2.2041c1.2246,0 2.2174,-0.9868 2.2174,-2.2041m5.1731,-4.0408c-0.6127,0 -1.1079,-0.492 -1.1079,-1.1027l0,-4.40778c0,-3.44909 -2.8123,-6.24462 -6.2826,-6.24462c-3.47035,0 -6.28261,2.79481 -6.28261,6.24462l0,4.40778c0,0.6085 -0.49689,1.1027 -1.10792,1.1027c-0.61215,0 -1.10947,0.4945 -1.10947,1.102c0,0.6087 0.49753,1.1021 1.11235,1.1021l14.77525,0c0.6139,0 1.1124,-0.4946 1.1124,-1.1021c0,-0.6074 -0.4986,-1.102 -1.1095,-1.102z" id="svg_1"/>
|
||||
<line id="svg_2" y2="2.59025" x2="21.49529" y1="21.40975" x1="2.6758" stroke="currentColor" fill="none"/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 621 B After Width: | Height: | Size: 1.9 KiB |
@@ -6,6 +6,8 @@
|
||||
"NoNotifications": "No notifications",
|
||||
"MentionNotification": "Mentioned",
|
||||
"EmailNotification": "by email",
|
||||
"PlatformNotification": "in platform"
|
||||
"PlatformNotification": "in platform",
|
||||
"Track": "Track",
|
||||
"DontTrack": "Don't track"
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@
|
||||
"NoNotifications": "Нет уведомлений",
|
||||
"MentionNotification": "Упомянул",
|
||||
"EmailNotification": "по email",
|
||||
"PlatformNotification": "в системе"
|
||||
"PlatformNotification": "в системе",
|
||||
"Track": "Отслеживать",
|
||||
"DontTrack": "Не отслеживать"
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,9 @@ import notification, { notificationId } from '@anticrm/notification'
|
||||
|
||||
const icons = require('../assets/icons.svg') as string // eslint-disable-line
|
||||
loadMetadata(notification.icon, {
|
||||
Notifications: `${icons}#notification`
|
||||
Notifications: `${icons}#notification`,
|
||||
Track: `${icons}#track`,
|
||||
DontTrack: `${icons}#donttrack`
|
||||
})
|
||||
|
||||
addStringsLoader(notificationId, async (lang: string) => await import(`../lang/${lang}.json`))
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<!--
|
||||
// Copyright © 2022 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Doc } from '@anticrm/core'
|
||||
import { ActionIcon } from '@anticrm/ui'
|
||||
import notification from '../plugin'
|
||||
import { NotificationClient } from '../utils'
|
||||
|
||||
export let value: Doc
|
||||
|
||||
const notificationClient = NotificationClient.getClient()
|
||||
const lastViews = notificationClient.getLastViews()
|
||||
$: subscribed = $lastViews.has(value._id)
|
||||
|
||||
</script>
|
||||
|
||||
{#if !subscribed}
|
||||
<ActionIcon size='medium' label={notification.string.Track} icon={notification.icon.Track} action={() => { notificationClient.updateLastView(value._id, value._class, undefined, true) }} />
|
||||
{:else}
|
||||
<ActionIcon size='medium' label={notification.string.DontTrack} icon={notification.icon.DontTrack} action={() => { notificationClient.unsubscribe(value._id) }} />
|
||||
{/if}
|
||||
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
// Copyright © 2022 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Doc } from '@anticrm/core'
|
||||
import { getPlatformColor } from '@anticrm/ui'
|
||||
import { NotificationClient } from '../utils'
|
||||
|
||||
export let value: Doc
|
||||
|
||||
const notificationClient = NotificationClient.getClient()
|
||||
const lastViews = notificationClient.getLastViews()
|
||||
|
||||
$: lastView = $lastViews.get(value._id)
|
||||
$: hasNotification = lastView !== undefined && lastView < value.modifiedOn
|
||||
</script>
|
||||
|
||||
{#if hasNotification}
|
||||
<div class="color" style="background-color: {getPlatformColor(11)}" />
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.color {
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
border-radius: .5rem;
|
||||
}
|
||||
</style>
|
||||
@@ -17,12 +17,16 @@
|
||||
import { Resources } from '@anticrm/platform'
|
||||
import NotificationsPopup from './components/NotificationsPopup.svelte'
|
||||
import NotificationSettings from './components/NotificationSettings.svelte'
|
||||
import NotificationPresenter from './components/NotificationPresenter.svelte'
|
||||
import LastViewEditor from './components/LastViewEditor.svelte'
|
||||
|
||||
export * from './utils'
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
NotificationsPopup,
|
||||
NotificationSettings
|
||||
NotificationPresenter,
|
||||
NotificationSettings,
|
||||
LastViewEditor
|
||||
}
|
||||
})
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
// limitations under the License.
|
||||
*/
|
||||
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import type { Asset, IntlString } from '@anticrm/platform'
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
|
||||
import notification, { notificationId } from '@anticrm/notification'
|
||||
|
||||
export default mergeIds(notificationId, notification, {
|
||||
string: {
|
||||
NoNotifications: '' as IntlString
|
||||
NoNotifications: '' as IntlString,
|
||||
Track: '' as IntlString,
|
||||
DontTrack: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
||||
@@ -24,7 +24,7 @@ import { writable, Writable } from 'svelte/store'
|
||||
*/
|
||||
export class NotificationClient {
|
||||
protected static _instance: NotificationClient | undefined = undefined
|
||||
private readonly lastViews = new Map<Ref<Doc>, LastView>()
|
||||
private lastViews = new Map<Ref<Doc>, LastView>()
|
||||
private readonly lastViewsStore = writable(new Map<Ref<Doc>, Timestamp>())
|
||||
|
||||
private readonly lastViewQuery = createQuery()
|
||||
@@ -32,10 +32,12 @@ export class NotificationClient {
|
||||
private constructor () {
|
||||
this.lastViewQuery.query(notification.class.LastView, { user: getCurrentAccount()._id }, (result) => {
|
||||
const res: Map<Ref<Doc>, Timestamp> = new Map<Ref<Doc>, Timestamp>()
|
||||
const lastViews: Map<Ref<Doc>, LastView> = new Map<Ref<Doc>, LastView>()
|
||||
result.forEach((p) => {
|
||||
res.set(p.attachedTo, p.lastView)
|
||||
this.lastViews.set(p.attachedTo, p)
|
||||
lastViews.set(p.attachedTo, p)
|
||||
})
|
||||
this.lastViews = lastViews
|
||||
this.lastViewsStore.set(res)
|
||||
})
|
||||
}
|
||||
@@ -59,6 +61,9 @@ export class NotificationClient {
|
||||
): Promise<void> {
|
||||
const client = getClient()
|
||||
const user = getCurrentAccount()._id
|
||||
console.log('SUBSCRIBE')
|
||||
console.log('USER')
|
||||
console.log(user)
|
||||
const lastView = time ?? new Date().getTime()
|
||||
const current = this.lastViews.get(_id)
|
||||
if (current !== undefined) {
|
||||
@@ -85,6 +90,9 @@ export class NotificationClient {
|
||||
async unsubscribe (_id: Ref<Doc>): Promise<void> {
|
||||
const client = getClient()
|
||||
const user = getCurrentAccount()._id
|
||||
console.log('UNSUBSCRIBE')
|
||||
console.log('USER')
|
||||
console.log(user)
|
||||
const current = await client.findOne(notification.class.LastView, { attachedTo: _id, user })
|
||||
if (current !== undefined) {
|
||||
await client.removeDoc(current._class, current.space, current._id)
|
||||
|
||||
@@ -102,10 +102,14 @@ const notification = plugin(notificationId, {
|
||||
NotificationSettings: '' as Ref<Doc>
|
||||
},
|
||||
component: {
|
||||
NotificationsPopup: '' as AnyComponent
|
||||
NotificationsPopup: '' as AnyComponent,
|
||||
NotificationPresenter: '' as AnyComponent,
|
||||
LastViewEditor: '' as AnyComponent
|
||||
},
|
||||
icon: {
|
||||
Notifications: '' as Asset
|
||||
Notifications: '' as Asset,
|
||||
Track: '' as Asset,
|
||||
DontTrack: '' as Asset
|
||||
},
|
||||
space: {
|
||||
Notifications: '' as Ref<Space>
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
"@anticrm/task-resources": "~0.6.0",
|
||||
"@anticrm/contact-resources": "~0.6.0",
|
||||
"@anticrm/rekoni": "~0.6.0",
|
||||
"@anticrm/notification": "~0.6.0",
|
||||
"@anticrm/tags": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
config={descr.config}
|
||||
options={descr.options}
|
||||
query={ resultQuery }
|
||||
enableChecking
|
||||
showNotification
|
||||
/>
|
||||
{/if}
|
||||
{/await}
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
import type { WithLookup } from '@anticrm/core'
|
||||
import { Avatar } from '@anticrm/presentation'
|
||||
import type { Applicant } from '@anticrm/recruit'
|
||||
import { ActionIcon, IconMoreH, showPanel } from '@anticrm/ui'
|
||||
import { ActionIcon, Component, IconMoreH, showPanel } from '@anticrm/ui'
|
||||
import view from '@anticrm/view'
|
||||
import ApplicationPresenter from './ApplicationPresenter.svelte'
|
||||
import notification from '@anticrm/notification'
|
||||
|
||||
export let object: WithLookup<Applicant>
|
||||
export let draggable: boolean
|
||||
@@ -33,14 +34,21 @@
|
||||
|
||||
<div class="card-container" {draggable} class:draggable on:dragstart on:dragend>
|
||||
<div class="flex-between mb-3">
|
||||
<Avatar avatar={object.$lookup?.attachedTo?.avatar} size={'medium'} />
|
||||
<div class="flex-grow flex-col min-w-0 ml-2">
|
||||
<div class="fs-title over-underline lines-limit-2" on:click={showCandidate}>
|
||||
{formatName(object.$lookup?.attachedTo?.name)}
|
||||
<div class="flex-row-center">
|
||||
<Avatar avatar={object.$lookup?.attachedTo?.avatar} size={'medium'} />
|
||||
<div class="flex-grow flex-col min-w-0 ml-2">
|
||||
<div class="fs-title over-underline lines-limit-2" on:click={showCandidate}>
|
||||
{formatName(object.$lookup?.attachedTo?.name)}
|
||||
</div>
|
||||
<div class="text-sm lines-limit-2">{object.$lookup?.attachedTo?.title ?? ''}</div>
|
||||
</div>
|
||||
<div class="text-sm lines-limit-2">{object.$lookup?.attachedTo?.title ?? ''}</div>
|
||||
</div>
|
||||
<div class="tool"><ActionIcon label={undefined} icon={IconMoreH} size={'small'} /></div>
|
||||
<div class="tool mr-1 flex-row-center">
|
||||
<div class="mr-2">
|
||||
<Component is={notification.component.NotificationPresenter} props={{ value: object }} />
|
||||
</div>
|
||||
<ActionIcon label={undefined} icon={IconMoreH} size={'small'} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-between">
|
||||
<div class="flex-row-center">
|
||||
|
||||
@@ -101,6 +101,6 @@
|
||||
]}
|
||||
options={opt}
|
||||
query={resultQuery}
|
||||
enableChecking
|
||||
showNotification
|
||||
/>
|
||||
</Scroller>
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
"@anticrm/login": "~0.6.1",
|
||||
"@anticrm/attachment-resources": "~0.6.0",
|
||||
"@anticrm/chunter-resources": "~0.6.0",
|
||||
"@anticrm/workbench": "~0.6.1"
|
||||
"@anticrm/workbench": "~0.6.1",
|
||||
"@anticrm/notification": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
import type { WithLookup } from '@anticrm/core'
|
||||
import { Avatar } from '@anticrm/presentation'
|
||||
import type { Issue } from '@anticrm/task'
|
||||
import { ActionIcon, IconMoreH, showPopup } from '@anticrm/ui'
|
||||
import { ActionIcon, Component, IconMoreH, showPopup } from '@anticrm/ui'
|
||||
import { ContextMenu } from '@anticrm/view-resources'
|
||||
import task from '../plugin'
|
||||
import TaskPresenter from './TaskPresenter.svelte'
|
||||
import notification from '@anticrm/notification'
|
||||
|
||||
export let object: WithLookup<Issue>
|
||||
export let draggable: boolean
|
||||
@@ -34,7 +35,12 @@
|
||||
<div class="card-container" {draggable} class:draggable on:dragstart on:dragend>
|
||||
<div class="flex-between mb-2">
|
||||
<TaskPresenter value={object} />
|
||||
<ActionIcon label={task.string.More} action={(evt) => { showMenu(evt) }} icon={IconMoreH} size={'small'} />
|
||||
<div class="flex-row-center">
|
||||
<div class="mr-2">
|
||||
<Component is={notification.component.NotificationPresenter} props={{ value: object }} />
|
||||
</div>
|
||||
<ActionIcon label={task.string.More} action={(evt) => { showMenu(evt) }} icon={IconMoreH} size={'small'} />
|
||||
</div>
|
||||
</div>
|
||||
<div class="caption-color mb-3 lines-limit-4">{object.name}</div>
|
||||
<!-- <div class="text-sm lines-limit-2">{object.description}</div> -->
|
||||
@@ -47,9 +53,7 @@
|
||||
<div class="step-lr75"><CommentsPresenter value={object} /></div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if object.$lookup?.assignee}
|
||||
<Avatar avatar={object.$lookup?.assignee?.avatar} size={'x-small'} />
|
||||
{/if}
|
||||
<Avatar avatar={object.$lookup?.assignee?.avatar} size={'x-small'} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@
|
||||
</div>
|
||||
<div class="statustableview-container">
|
||||
<ScrollBox vertical stretch noShift>
|
||||
<Table {_class} {query} config={resConfig} {options} enableChecking />
|
||||
<Table {_class} {query} config={resConfig} {options} showNotification />
|
||||
</ScrollBox>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -31,5 +31,5 @@
|
||||
</script>
|
||||
|
||||
<div class="sm-tool-icon" on:click={show}>
|
||||
<span class="icon"><Icon icon={task.icon.Task} size={'small'} /></span>{#if shortLabel}<Label label={shortLabel} />-{/if}-{value.number}
|
||||
<span class="icon"><Icon icon={task.icon.Task} size={'small'} /></span>{#if shortLabel}<Label label={shortLabel} />-{/if}{value.number}
|
||||
</div>
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"@anticrm/view": "~0.6.0",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/notification": "~0.6.0",
|
||||
"@anticrm/presentation": "~0.6.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,17 @@
|
||||
import type { Class, Doc, DocumentQuery, FindOptions, Ref } from '@anticrm/core'
|
||||
import { SortingOrder } from '@anticrm/core'
|
||||
import { createQuery, getClient } from '@anticrm/presentation'
|
||||
import { CheckBox, IconDown, IconUp, Label, Loading, showPopup, Spinner } from '@anticrm/ui'
|
||||
import { Component, CheckBox, IconDown, IconUp, Label, Loading, showPopup, Spinner } from '@anticrm/ui'
|
||||
import { BuildModelKey } from '@anticrm/view'
|
||||
import { buildModel, LoadingProps } from '../utils'
|
||||
import MoreV from './icons/MoreV.svelte'
|
||||
import Menu from './Menu.svelte'
|
||||
import notification from '@anticrm/notification'
|
||||
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let query: DocumentQuery<Doc>
|
||||
export let enableChecking: boolean = false
|
||||
export let showNotification: boolean = false
|
||||
export let options: FindOptions<Doc> | undefined = undefined
|
||||
export let baseMenuClass: Ref<Class<Doc>> | undefined = undefined
|
||||
export let config: (BuildModelKey | string)[]
|
||||
@@ -123,23 +125,26 @@
|
||||
<Loading />
|
||||
{/if}
|
||||
{:then model}
|
||||
<table class="table-body" class:enableChecking>
|
||||
<table class="table-body" class:enableChecking class:showNotification>
|
||||
<thead class="scroller-thead">
|
||||
<tr class="tr-head scroller-thead__tr">
|
||||
{#each model as attribute, cellHead}
|
||||
{#if enableChecking && !cellHead}
|
||||
<th>
|
||||
<div class="checkCell" class:checkall={checked.size > 0}>
|
||||
<CheckBox
|
||||
symbol={'minus'}
|
||||
checked={objects?.length === checked.size && objects?.length > 0}
|
||||
on:change={(e) => {
|
||||
objects.map((o) => check(o._id, e))
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</th>
|
||||
{/if}
|
||||
{#if enableChecking}
|
||||
<th>
|
||||
<div class="checkCell" class:checkall={checked.size > 0}>
|
||||
<CheckBox
|
||||
symbol={'minus'}
|
||||
checked={objects?.length === checked.size && objects?.length > 0}
|
||||
on:change={(e) => {
|
||||
objects.map((o) => check(o._id, e))
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</th>
|
||||
{/if}
|
||||
{#if showNotification}
|
||||
<th></th>
|
||||
{/if}
|
||||
{#each model as attribute}
|
||||
<th
|
||||
class:sortable={attribute.sortingKey}
|
||||
class:sorted={attribute.sortingKey === sortKey}
|
||||
@@ -179,6 +184,11 @@
|
||||
</div>
|
||||
</td>
|
||||
{/if}
|
||||
{#if showNotification}
|
||||
<td class="notificationCell">
|
||||
<Component is={notification.component.NotificationPresenter} props={{ value: object }} />
|
||||
</td>
|
||||
{/if}
|
||||
<td>
|
||||
<div class="firstCell">
|
||||
<svelte:component
|
||||
@@ -237,6 +247,12 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.notificationCell {
|
||||
padding: 0.5rem;
|
||||
padding-left: 1rem !important;
|
||||
padding-right: 0rem;
|
||||
}
|
||||
|
||||
.firstCell {
|
||||
display: flex;
|
||||
// justify-content: space-between;
|
||||
@@ -268,7 +284,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.enableChecking {
|
||||
.enableChecking, .showNotification {
|
||||
th,
|
||||
td {
|
||||
&:first-child {
|
||||
|
||||
@@ -30,5 +30,5 @@
|
||||
</script>
|
||||
|
||||
<Scroller>
|
||||
<Table {_class} {config} {options} query={resultQuery} {baseMenuClass} enableChecking />
|
||||
<Table {_class} {config} {options} query={resultQuery} {baseMenuClass} showNotification/>
|
||||
</Scroller>
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
"@anticrm/login": "~0.6.1",
|
||||
"@anticrm/setting": "~0.6.0",
|
||||
"@anticrm/notification": "~0.6.0",
|
||||
"@anticrm/notification-resources": "~0.6.0",
|
||||
"@anticrm/contact": "~0.6.2",
|
||||
"@anticrm/view-resources": "~0.6.0"
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@
|
||||
_class={spaceSample._class}
|
||||
config={['name', 'company', 'location', 'modifiedOn']}
|
||||
options={{}}
|
||||
enableChecking={true}
|
||||
baseMenuClass={core.class.Space}
|
||||
query={{
|
||||
_class: { $in: model?.spaces.map(x => x.spaceClass) ?? [] },
|
||||
|
||||
@@ -42,10 +42,12 @@
|
||||
import Navigator from './Navigator.svelte'
|
||||
import SpaceView from './SpaceView.svelte'
|
||||
import notification, { NotificationStatus } from '@anticrm/notification'
|
||||
import { NotificationClient } from '@anticrm/notification-resources'
|
||||
|
||||
export let client: Client
|
||||
|
||||
setClient(client)
|
||||
NotificationClient.getClient()
|
||||
|
||||
let currentApp: Ref<Application> | undefined
|
||||
let currentSpace: Ref<Space> | undefined
|
||||
|
||||
Reference in New Issue
Block a user