diff --git a/models/notification/src/index.ts b/models/notification/src/index.ts
index e630099cba..9244fba8f9 100644
--- a/models/notification/src/index.ts
+++ b/models/notification/src/index.ts
@@ -146,7 +146,7 @@ export function createModel (builder: Builder): void {
core.space.Model,
{
label: notification.string.BrowserNotification,
- default: false
+ default: true
},
notification.ids.BrowserNotification
)
diff --git a/models/server-lead/src/index.ts b/models/server-lead/src/index.ts
index bf7c0a07e4..d245da5be4 100644
--- a/models/server-lead/src/index.ts
+++ b/models/server-lead/src/index.ts
@@ -19,6 +19,7 @@ import core from '@anticrm/core'
import lead from '@anticrm/lead'
import view from '@anticrm/view'
import serverLead from '@anticrm/server-lead'
+import serverCore from '@anticrm/server-core'
export function createModel (builder: Builder): void {
builder.mixin(lead.class.Lead, core.class.Class, view.mixin.HTMLPresenter, {
@@ -28,4 +29,8 @@ export function createModel (builder: Builder): void {
builder.mixin(lead.class.Lead, core.class.Class, view.mixin.TextPresenter, {
presenter: serverLead.function.LeadTextPresenter
})
+
+ builder.createDoc(serverCore.class.Trigger, core.space.Model, {
+ trigger: serverLead.trigger.OnLeadUpdate
+ })
}
diff --git a/models/server-recruit/src/index.ts b/models/server-recruit/src/index.ts
index fb6b467f4b..566dd73da1 100644
--- a/models/server-recruit/src/index.ts
+++ b/models/server-recruit/src/index.ts
@@ -39,6 +39,6 @@ export function createModel (builder: Builder): void {
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
- trigger: serverRecruit.trigger.OnVacancyUpdate
+ trigger: serverRecruit.trigger.OnRecruitUpdate
})
}
diff --git a/models/task/src/index.ts b/models/task/src/index.ts
index bd0e9d5895..683b35d633 100644
--- a/models/task/src/index.ts
+++ b/models/task/src/index.ts
@@ -565,4 +565,13 @@ export function createModel (builder: Builder): void {
},
task.action.ArchiveState
)
+
+ builder.createDoc(
+ notification.class.NotificationType,
+ core.space.Model,
+ {
+ label: task.string.Assigned
+ },
+ task.ids.AssigneedNotification
+ )
}
diff --git a/packages/platform/src/status.ts b/packages/platform/src/status.ts
index 47cdf105d0..24fc52a8c6 100644
--- a/packages/platform/src/status.ts
+++ b/packages/platform/src/status.ts
@@ -36,7 +36,7 @@ export enum Severity {
* Status of an operation
* @public
*/
-export class Status
{
+export class Status
= {}> {
readonly severity: Severity
readonly code: StatusCode
readonly params: P
diff --git a/packages/theme/styles/popups.scss b/packages/theme/styles/popups.scss
index 62f7ca206a..fbde2f8fc8 100644
--- a/packages/theme/styles/popups.scss
+++ b/packages/theme/styles/popups.scss
@@ -418,8 +418,8 @@
width: max-content;
height: max-content;
padding-bottom: 0.5rem;
- min-width: 32rem;
- max-width: 32rem;
+ min-width: 42rem;
+ max-width: 42rem;
min-height: 22rem;
max-height: 22rem;
background: var(--popup-bg-color);
diff --git a/packages/ui/src/components/ActionIcon.svelte b/packages/ui/src/components/ActionIcon.svelte
index 65851711bc..851c1e1460 100644
--- a/packages/ui/src/components/ActionIcon.svelte
+++ b/packages/ui/src/components/ActionIcon.svelte
@@ -23,6 +23,7 @@
export let labelProps: any = undefined
export let direction: TooltipAlignment | undefined = undefined
export let icon: Asset | AnySvelteComponent
+ export let iconProps: any | undefined = undefined
export let size: 'small' | 'medium' | 'large'
export let action: (ev: MouseEvent) => Promise | void = async () => {}
export let invisible: boolean = false
@@ -35,7 +36,7 @@
on:click|stopPropagation|preventDefault={action}
>
-
+
diff --git a/packages/ui/src/components/Icon.svelte b/packages/ui/src/components/Icon.svelte
index f4feb8182b..d4bc835ab5 100644
--- a/packages/ui/src/components/Icon.svelte
+++ b/packages/ui/src/components/Icon.svelte
@@ -19,6 +19,7 @@
export let icon: Asset | AnySvelteComponent
export let size: IconSize
export let fill = 'currentColor'
+ export let iconProps: any | undefined = undefined
function isAsset (icon: Asset | AnySvelteComponent): boolean {
return typeof icon === 'string'
@@ -36,6 +37,6 @@
-{:else}
-
+{:else if typeof icon !== 'string'}
+
{/if}
diff --git a/packages/ui/src/components/icons/Back.svelte b/packages/ui/src/components/icons/Back.svelte
index ee1c593aaa..5db2cc6e70 100644
--- a/packages/ui/src/components/icons/Back.svelte
+++ b/packages/ui/src/components/icons/Back.svelte
@@ -16,8 +16,17 @@
-
+{#if kind === 'strong'}
+
+{:else if kind === 'curve'}
+
+{/if}
diff --git a/plugins/activity-resources/src/components/TxView.svelte b/plugins/activity-resources/src/components/TxView.svelte
index d074b178be..5fda4e5d80 100644
--- a/plugins/activity-resources/src/components/TxView.svelte
+++ b/plugins/activity-resources/src/components/TxView.svelte
@@ -42,6 +42,7 @@
export let viewlets: Map
export let showIcon: boolean = true
export let isNew: boolean = false
+ export let showDocument = false
let ptx: DisplayTx | undefined
@@ -212,8 +213,8 @@
{/if}
1}>
- {#each value.added as value}
-
+ {#each value.added as cvalue}
+
{/each}
@@ -231,8 +232,8 @@
{/if}
1}>
- {#each value.removed as value}
-
+ {#each value.removed as cvalue}
+
{/each}
diff --git a/plugins/calendar-resources/src/components/EventPresenter.svelte b/plugins/calendar-resources/src/components/EventPresenter.svelte
index 593161c967..9389b844ff 100644
--- a/plugins/calendar-resources/src/components/EventPresenter.svelte
+++ b/plugins/calendar-resources/src/components/EventPresenter.svelte
@@ -18,17 +18,20 @@
import view from '@anticrm/view'
export let value: Event
+ export let inline: boolean = false
function click (): void {
showPanel(view.component.EditDoc, value._id, value._class, 'content')
}
-
+
{#if value}
{value.title}
-
+ {#if !inline}
+
+ {/if}
{/if}
diff --git a/plugins/calendar-resources/src/components/activity/ReminderViewlet.svelte b/plugins/calendar-resources/src/components/activity/ReminderViewlet.svelte
index 89446a5718..0393fec168 100644
--- a/plugins/calendar-resources/src/components/activity/ReminderViewlet.svelte
+++ b/plugins/calendar-resources/src/components/activity/ReminderViewlet.svelte
@@ -37,11 +37,13 @@
{#await getEvent(tx.objectId) then event}
{#if event}
{
click(event)
- }}>{event.title} 
+ }}
+ >{event.title}
+
+  
{/if}
{/await}
diff --git a/plugins/notification-assets/lang/en.json b/plugins/notification-assets/lang/en.json
index 74064664d1..67448d896c 100644
--- a/plugins/notification-assets/lang/en.json
+++ b/plugins/notification-assets/lang/en.json
@@ -9,6 +9,10 @@
"PlatformNotification": "in platform",
"Track": "Track",
"DontTrack": "Don't track",
- "BrowserNotification": "in browser"
+ "BrowserNotification": "in browser",
+ "Remove": "Delete notification",
+ "RemoveAll": "Delete all notifications",
+ "MarkAllAsRead": "Mark all notifications as read",
+ "MarkAsRead": "Mark as read"
}
}
\ No newline at end of file
diff --git a/plugins/notification-assets/lang/ru.json b/plugins/notification-assets/lang/ru.json
index 37d64f395f..16efc694d5 100644
--- a/plugins/notification-assets/lang/ru.json
+++ b/plugins/notification-assets/lang/ru.json
@@ -9,6 +9,10 @@
"PlatformNotification": "в системе",
"Track": "Отслеживать",
"DontTrack": "Не отслеживать",
- "BrowserNotification": "в браузере"
+ "BrowserNotification": "в браузере",
+ "Remove": "Удалить нотификацию",
+ "RemoveAll": "Удалить все нотификации",
+ "MarkAllAsRead": "Отметить все нотификации как прочитанные",
+ "MarkAsRead": "Отметить нотификация прочитанной"
}
}
\ No newline at end of file
diff --git a/plugins/notification-resources/package.json b/plugins/notification-resources/package.json
index e092653da3..aab630a7bd 100644
--- a/plugins/notification-resources/package.json
+++ b/plugins/notification-resources/package.json
@@ -39,6 +39,7 @@
"@anticrm/activity-resources": "~0.6.0",
"@anticrm/activity": "~0.6.0",
"@anticrm/contact": "~0.6.5",
- "@anticrm/core": "~0.6.16"
+ "@anticrm/core": "~0.6.16",
+ "@anticrm/view": "~0.6.0"
}
}
diff --git a/plugins/notification-resources/src/components/BrowserNotificatator.svelte b/plugins/notification-resources/src/components/BrowserNotificatator.svelte
index 665734f26d..13ca6422d1 100644
--- a/plugins/notification-resources/src/components/BrowserNotificatator.svelte
+++ b/plugins/notification-resources/src/components/BrowserNotificatator.svelte
@@ -23,6 +23,7 @@
NotificationType
} from '@anticrm/notification'
import { createQuery } from '@anticrm/presentation'
+ import { getCurrentLocation } from '@anticrm/ui'
import notification from '../plugin'
import { NotificationClientImpl } from '../utils'
@@ -39,7 +40,7 @@
let settings: Map
[, NotificationSetting> = new Map][, NotificationSetting>()
let provider: NotificationProvider | undefined
- const enabled = 'Notification' in window && Notification.permission !== 'denied'
+ $: enabled = 'Notification' in window && Notification?.permission !== 'denied'
$: enabled &&
providersQuery.query(
@@ -66,6 +67,8 @@
}
)
+ const alreadyShown = new Set][>()
+
$: enabled &&
settingsReceived &&
provider !== undefined &&
@@ -76,7 +79,12 @@
status: NotificationStatus.New
},
(res) => {
- process(res)
+ process(res.reverse())
+ },
+ {
+ sort: {
+ modifiedOn: 1
+ }
}
)
@@ -93,25 +101,40 @@
const enabled = setting?.enabled ?? provider?.default
if (!enabled) return
if ((setting?.modifiedOn ?? notification.modifiedOn) < 0) return
- if (Notification.permission === 'granted') {
+
+ if (Notification?.permission !== 'granted') {
+ await Notification?.requestPermission()
+ }
+
+ if (Notification?.permission === 'granted') {
await notify(text, notification)
- } else if (Notification.permission !== 'denied') {
- const permission = await Notification.requestPermission()
- if (permission === 'granted') {
- await notify(text, notification)
- }
}
}
- async function notify (text: string, notification: PlatformNotification): Promise {
+ let clearTimer: number | undefined
+
+ async function notify (text: string, notifyInstance: PlatformNotification): Promise {
+ if (alreadyShown.has(notifyInstance._id)) {
+ return
+ }
+ alreadyShown.add(notifyInstance._id)
+
+ if (clearTimer) {
+ clearTimeout(clearTimer)
+ }
+
+ clearTimer = setTimeout(() => {
+ alreadyShown.clear()
+ }, 5000)
+
const lastView = $lastViews.get(lastViewId)
- if ((lastView ?? notification.modifiedOn) > 0) {
+ if ((lastView ?? notifyInstance.modifiedOn) > 0) {
// eslint-disable-next-line
- new Notification(text, { tag: notification._id })
+ new Notification(getCurrentLocation().path[1], { tag: notifyInstance._id, icon: '/favicon.png', body: text })
await notificationClient.updateLastView(
lastViewId,
contact.class.Employee,
- notification.modifiedOn,
+ notifyInstance.modifiedOn,
lastView === undefined
)
}
diff --git a/plugins/notification-resources/src/components/NotificationView.svelte b/plugins/notification-resources/src/components/NotificationView.svelte
index 72f2d89e9f..83e9603900 100644
--- a/plugins/notification-resources/src/components/NotificationView.svelte
+++ b/plugins/notification-resources/src/components/NotificationView.svelte
@@ -16,46 +16,82 @@
-{#await getDisplayTx(notification) then displayTx}
- {#if displayTx}
-
- ] {
- read(notification)
- }}
- >
+{#if displayTx}
+ {@const isNew = notification.status === NotificationStatus.New}
+
+
+
+
+
+
+
+
+
+
+
{
+ client.remove(notification)
+ }}
+ />
+ {
+ changeState(notification, isNew ? NotificationStatus.Read : NotificationStatus.New)
+ }}
+ />
+
+
+
- {/if}
-{/await}
+
+{/if}
diff --git a/plugins/notification-resources/src/components/NotificationsPopup.svelte b/plugins/notification-resources/src/components/NotificationsPopup.svelte
index 31ddedf098..6315896f6f 100644
--- a/plugins/notification-resources/src/components/NotificationsPopup.svelte
+++ b/plugins/notification-resources/src/components/NotificationsPopup.svelte
@@ -17,16 +17,17 @@
import activity, { TxViewlet } from '@anticrm/activity'
import { activityKey, ActivityKey } from '@anticrm/activity-resources'
import { EmployeeAccount } from '@anticrm/contact'
- import { getCurrentAccount, SortingOrder } from '@anticrm/core'
- import type { Notification } from '@anticrm/notification'
- import { createQuery } from '@anticrm/presentation'
- import { Scroller } from '@anticrm/ui'
+ import core, { getCurrentAccount, WithLookup } from '@anticrm/core'
+ import { Notification, NotificationStatus } from '@anticrm/notification'
+ import { createQuery, getClient } from '@anticrm/presentation'
+ import { ActionIcon, IconCheck, IconDelete, Scroller } from '@anticrm/ui'
import Label from '@anticrm/ui/src/components/Label.svelte'
import notification from '../plugin'
import NotificationView from './NotificationView.svelte'
const query = createQuery()
- let notifications: Notification[] = []
+ let notifications: WithLookup
[] = []
+ const client = getClient()
$: query.query(
notification.class.Notification,
@@ -37,7 +38,13 @@
notifications = res
},
{
- sort: { status: SortingOrder.Ascending, modifiedOn: SortingOrder.Descending }
+ sort: {
+ '$lookup.tx.modifiedOn': -1
+ },
+ limit: 30,
+ lookup: {
+ tx: core.class.TxCUD
+ }
}
)
@@ -47,16 +54,51 @@
$: descriptors.query(activity.class.TxViewlet, {}, (result) => {
viewlets = new Map(result.map((r) => [activityKey(r.objectClass, r.txClass), r]))
})
+
+ const deleteNotifications = async () => {
+ const allNotifications = await client.findAll(notification.class.Notification, {
+ attachedTo: (getCurrentAccount() as EmployeeAccount).employee
+ })
+ for (const n of allNotifications) {
+ await client.remove(n)
+ }
+ }
+ const markAsReadNotifications = async () => {
+ const allNotifications = await client.findAll(notification.class.Notification, {
+ attachedTo: (getCurrentAccount() as EmployeeAccount).employee
+ })
+ for (const n of allNotifications) {
+ if (n.status !== NotificationStatus.Read) {
+ await client.updateDoc(n._class, n.space, n._id, {
+ status: NotificationStatus.Read
+ })
+ }
+ }
+ }