mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
Refactor server side notifications (#2327)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -99,7 +99,7 @@
|
||||
"@hcengineering/server-attachment-resources": "~0.6.0",
|
||||
"@hcengineering/server-contact": "~0.6.1",
|
||||
"@hcengineering/server-contact-resources": "~0.6.0",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-notification-resources": "~0.6.0",
|
||||
"@hcengineering/server-setting": "~0.6.0",
|
||||
"@hcengineering/server-setting-resources": "~0.6.0",
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
"@hcengineering/attachment": "~0.6.1",
|
||||
"@hcengineering/server-contact": "~0.6.1",
|
||||
"@hcengineering/server-contact-resources": "~0.6.0",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-notification-resources": "~0.6.0",
|
||||
"@hcengineering/server-setting": "~0.6.0",
|
||||
"@hcengineering/server-setting-resources": "~0.6.0",
|
||||
|
||||
@@ -128,7 +128,10 @@ export function createModel (builder: Builder): void {
|
||||
notification.class.NotificationType,
|
||||
core.space.Model,
|
||||
{
|
||||
label: calendar.string.Reminder
|
||||
label: calendar.string.Reminder,
|
||||
textTemplate: 'Reminder: {doc}',
|
||||
htmlTemplate: 'Reminder: {doc}',
|
||||
subjectTemplate: 'Reminder: {doc}'
|
||||
},
|
||||
calendar.ids.ReminderNotification
|
||||
)
|
||||
|
||||
@@ -81,6 +81,9 @@ export class TEmaiNotification extends TDoc implements EmailNotification {
|
||||
@Model(notification.class.NotificationType, core.class.Doc, DOMAIN_MODEL)
|
||||
export class TNotificationType extends TDoc implements NotificationType {
|
||||
label!: IntlString
|
||||
textTemplate!: string
|
||||
htmlTemplate!: string
|
||||
subjectTemplate!: string
|
||||
}
|
||||
|
||||
@Model(notification.class.NotificationProvider, core.class.Doc, DOMAIN_MODEL)
|
||||
@@ -126,7 +129,10 @@ export function createModel (builder: Builder): void {
|
||||
notification.class.NotificationType,
|
||||
core.space.Model,
|
||||
{
|
||||
label: notification.string.MentionNotification
|
||||
label: notification.string.MentionNotification,
|
||||
textTemplate: '{sender} mentioned you in {doc} {data}',
|
||||
htmlTemplate: '<p><b>{sender}</b> mentioned you in {doc}</p> {data}',
|
||||
subjectTemplate: 'You was mentioned in {doc}'
|
||||
},
|
||||
notification.ids.MentionNotification
|
||||
)
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
"@hcengineering/server-chunter": "~0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/chunter": "~0.6.1",
|
||||
"@hcengineering/view": "^0.6.1"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@ import { Builder } from '@hcengineering/model'
|
||||
|
||||
import core, { Class, Doc } from '@hcengineering/core'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
import view from '@hcengineering/view'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
import serverCore, { ObjectDDParticipant } from '@hcengineering/server-core'
|
||||
import serverChunter from '@hcengineering/server-chunter'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(chunter.class.Channel, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverChunter.function.ChannelHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(chunter.class.Channel, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverChunter.function.ChannelTextPresenter
|
||||
})
|
||||
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
"@hcengineering/server-contact": "~0.6.1",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/contact": "~0.6.5",
|
||||
"@hcengineering/view": "^0.6.1"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,23 +19,23 @@ import { Builder } from '@hcengineering/model'
|
||||
import serverCore from '@hcengineering/server-core'
|
||||
import core from '@hcengineering/core'
|
||||
import contact from '@hcengineering/contact'
|
||||
import view from '@hcengineering/view'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
import serverContact from '@hcengineering/server-contact'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.mixin(contact.class.Person, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(contact.class.Person, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverContact.function.PersonHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Person, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(contact.class.Person, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverContact.function.PersonTextPresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(contact.class.Organization, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverContact.function.OrganizationHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(contact.class.Organization, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(contact.class.Organization, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverContact.function.OrganizationTextPresenter
|
||||
})
|
||||
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
"@hcengineering/server-inventory": "~0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/inventory": "~0.6.0",
|
||||
"@hcengineering/view": "^0.6.1"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ import { Builder } from '@hcengineering/model'
|
||||
import core from '@hcengineering/core'
|
||||
import inventory from '@hcengineering/inventory'
|
||||
import serverInventory from '@hcengineering/server-inventory'
|
||||
import view from '@hcengineering/view'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.mixin(inventory.class.Product, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(inventory.class.Product, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverInventory.function.ProductHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(inventory.class.Product, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(inventory.class.Product, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverInventory.function.ProductTextPresenter
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
"@hcengineering/server-lead": "~0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/lead": "~0.6.0",
|
||||
"@hcengineering/view": "^0.6.1"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,16 @@ import { Builder } from '@hcengineering/model'
|
||||
|
||||
import core from '@hcengineering/core'
|
||||
import lead from '@hcengineering/lead'
|
||||
import view from '@hcengineering/view'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
import serverLead from '@hcengineering/server-lead'
|
||||
import serverCore from '@hcengineering/server-core'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.mixin(lead.class.Lead, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(lead.class.Lead, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverLead.function.LeadHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(lead.class.Lead, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(lead.class.Lead, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverLead.function.LeadTextPresenter
|
||||
})
|
||||
|
||||
|
||||
@@ -27,8 +27,9 @@
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/model": "~0.6.0",
|
||||
"@hcengineering/model-core": "~0.6.0",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,13 +14,27 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Builder } from '@hcengineering/model'
|
||||
import { Builder, Mixin } from '@hcengineering/model'
|
||||
|
||||
import serverCore from '@hcengineering/server-core'
|
||||
import core from '@hcengineering/core'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
import serverNotification, { HTMLPresenter, TextPresenter, Presenter } from '@hcengineering/server-notification'
|
||||
import { Resource } from '@hcengineering/platform'
|
||||
import { TClass } from '@hcengineering/model-core'
|
||||
|
||||
@Mixin(serverNotification.mixin.HTMLPresenter, core.class.Class)
|
||||
export class THTMLPresenter extends TClass implements HTMLPresenter {
|
||||
presenter!: Resource<Presenter>
|
||||
}
|
||||
|
||||
@Mixin(serverNotification.mixin.TextPresenter, core.class.Class)
|
||||
export class TTextPresenter extends TClass implements TextPresenter {
|
||||
presenter!: Resource<Presenter>
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createModel(THTMLPresenter, TTextPresenter)
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverNotification.trigger.OnBacklinkCreate
|
||||
})
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
"@hcengineering/server-recruit": "~0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/recruit": "~0.6.3",
|
||||
"@hcengineering/view": "^0.6.1"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,24 +17,24 @@ import { Builder } from '@hcengineering/model'
|
||||
|
||||
import core from '@hcengineering/core'
|
||||
import recruit from '@hcengineering/recruit'
|
||||
import view from '@hcengineering/view'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
import serverRecruit from '@hcengineering/server-recruit'
|
||||
import serverCore from '@hcengineering/server-core'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.mixin(recruit.class.Applicant, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(recruit.class.Applicant, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverRecruit.function.ApplicationHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(recruit.class.Applicant, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(recruit.class.Applicant, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverRecruit.function.ApplicationTextPresenter
|
||||
})
|
||||
|
||||
builder.mixin(recruit.class.Vacancy, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(recruit.class.Vacancy, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverRecruit.function.VacancyHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(recruit.class.Vacancy, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(recruit.class.Vacancy, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverRecruit.function.VacancyTextPresenter
|
||||
})
|
||||
|
||||
|
||||
@@ -31,6 +31,6 @@
|
||||
"@hcengineering/server-task": "~0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/task": "~0.6.0",
|
||||
"@hcengineering/view": "^0.6.1"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@ import { Builder } from '@hcengineering/model'
|
||||
import core from '@hcengineering/core'
|
||||
import serverTask from '@hcengineering/server-task'
|
||||
import task from '@hcengineering/task'
|
||||
import view from '@hcengineering/view'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.mixin(task.class.Issue, core.class.Class, view.mixin.HTMLPresenter, {
|
||||
builder.mixin(task.class.Issue, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverTask.function.IssueHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(task.class.Issue, core.class.Class, view.mixin.TextPresenter, {
|
||||
builder.mixin(task.class.Issue, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverTask.function.IssueTextPresenter
|
||||
})
|
||||
}
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/model": "~0.6.0",
|
||||
"@hcengineering/tracker": "^0.6.1",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-tracker": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,18 @@ import { Builder } from '@hcengineering/model'
|
||||
import core from '@hcengineering/core'
|
||||
import serverCore from '@hcengineering/server-core'
|
||||
import serverTracker from '@hcengineering/server-tracker'
|
||||
import tracker from '@hcengineering/tracker'
|
||||
import serverNotification from '@hcengineering/server-notification'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.mixin(tracker.class.Issue, core.class.Class, serverNotification.mixin.HTMLPresenter, {
|
||||
presenter: serverTracker.function.IssueHTMLPresenter
|
||||
})
|
||||
|
||||
builder.mixin(tracker.class.Issue, core.class.Class, serverNotification.mixin.TextPresenter, {
|
||||
presenter: serverTracker.function.IssueTextPresenter
|
||||
})
|
||||
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverTracker.trigger.OnIssueUpdate
|
||||
})
|
||||
|
||||
@@ -581,7 +581,10 @@ export function createModel (builder: Builder): void {
|
||||
notification.class.NotificationType,
|
||||
core.space.Model,
|
||||
{
|
||||
label: task.string.Assigned
|
||||
label: task.string.Assigned,
|
||||
textTemplate: '{doc} was assigned to you by {sender}',
|
||||
htmlTemplate: '<p>{doc} was assigned to you by {sender}</p>',
|
||||
subjectTemplate: '{doc} was assigned to you'
|
||||
},
|
||||
task.ids.AssigneedNotification
|
||||
)
|
||||
|
||||
@@ -17,6 +17,7 @@ import type { Class, Client, Data, Doc, DocumentQuery, Ref, Space } from '@hceng
|
||||
import { DOMAIN_MODEL } from '@hcengineering/core'
|
||||
import { Builder, Mixin, Model } from '@hcengineering/model'
|
||||
import core, { TClass, TDoc } from '@hcengineering/model-core'
|
||||
import preference, { TPreference } from '@hcengineering/model-preference'
|
||||
import type { Asset, IntlString, Resource, Status } from '@hcengineering/platform'
|
||||
import type { AnyComponent } from '@hcengineering/ui'
|
||||
import type {
|
||||
@@ -32,7 +33,6 @@ import type {
|
||||
CollectionPresenter,
|
||||
Filter,
|
||||
FilterMode,
|
||||
HTMLPresenter,
|
||||
IgnoreActions,
|
||||
InlineAttributEditor,
|
||||
KeyBinding,
|
||||
@@ -46,7 +46,6 @@ import type {
|
||||
PreviewPresenter,
|
||||
SpaceHeader,
|
||||
SpaceName,
|
||||
TextPresenter,
|
||||
ViewAction,
|
||||
ViewActionInput,
|
||||
ViewContext,
|
||||
@@ -54,7 +53,6 @@ import type {
|
||||
ViewletDescriptor,
|
||||
ViewletPreference
|
||||
} from '@hcengineering/view'
|
||||
import preference, { TPreference } from '@hcengineering/model-preference'
|
||||
import view from './plugin'
|
||||
|
||||
export { viewOperation } from './migration'
|
||||
@@ -223,16 +221,6 @@ export class TIgnoreActions extends TClass implements IgnoreActions {
|
||||
actions!: Ref<Action>[]
|
||||
}
|
||||
|
||||
@Mixin(view.mixin.HTMLPresenter, core.class.Class)
|
||||
export class THTMLPresenter extends TClass implements HTMLPresenter {
|
||||
presenter!: Resource<(doc: Doc) => string>
|
||||
}
|
||||
|
||||
@Mixin(view.mixin.TextPresenter, core.class.Class)
|
||||
export class TTextPresenter extends TClass implements TextPresenter {
|
||||
presenter!: Resource<(doc: Doc) => string>
|
||||
}
|
||||
|
||||
@Mixin(view.mixin.PreviewPresenter, core.class.Class)
|
||||
export class TPreviewPresenter extends TClass implements PreviewPresenter {
|
||||
presenter!: AnyComponent
|
||||
@@ -291,10 +279,8 @@ export function createModel (builder: Builder): void {
|
||||
TObjectFactory,
|
||||
TObjectTitle,
|
||||
TObjectEditorHeader,
|
||||
THTMLPresenter,
|
||||
TSpaceHeader,
|
||||
TSpaceName,
|
||||
TTextPresenter,
|
||||
TIgnoreActions,
|
||||
TPreviewPresenter,
|
||||
TLinkPresenter,
|
||||
|
||||
@@ -29,6 +29,15 @@ export interface LastView extends AttachedDoc {
|
||||
user: Ref<Account>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface NotificationAction {
|
||||
component: AnyComponent
|
||||
objectId: Ref<Doc>
|
||||
objectClass: Ref<Class<Doc>>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@@ -39,11 +48,7 @@ export interface Notification extends AttachedDoc {
|
||||
type: Ref<NotificationType>
|
||||
|
||||
// Defined to open particular item if required.
|
||||
action?: {
|
||||
component: AnyComponent
|
||||
objectId: Ref<Doc>
|
||||
objectClass: Ref<Class<Doc>>
|
||||
}
|
||||
action?: NotificationAction
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,6 +77,9 @@ export enum NotificationStatus {
|
||||
*/
|
||||
export interface NotificationType extends Doc {
|
||||
label: IntlString
|
||||
textTemplate: string
|
||||
htmlTemplate: string
|
||||
subjectTemplate: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -306,20 +306,6 @@ export interface IgnoreActions extends Class<Doc> {
|
||||
actions: Ref<Action>[]
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface HTMLPresenter extends Class<Doc> {
|
||||
presenter: Resource<(doc: Doc) => string>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TextPresenter extends Class<Doc> {
|
||||
presenter: Resource<(doc: Doc) => string>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@@ -420,8 +406,6 @@ const view = plugin(viewId, {
|
||||
SpaceHeader: '' as Ref<Mixin<SpaceHeader>>,
|
||||
SpaceName: '' as Ref<Mixin<SpaceName>>,
|
||||
IgnoreActions: '' as Ref<Mixin<IgnoreActions>>,
|
||||
HTMLPresenter: '' as Ref<Mixin<HTMLPresenter>>,
|
||||
TextPresenter: '' as Ref<Mixin<TextPresenter>>,
|
||||
PreviewPresenter: '' as Ref<Mixin<PreviewPresenter>>
|
||||
},
|
||||
class: {
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
"@hcengineering/server-attachment-resources": "~0.6.0",
|
||||
"@hcengineering/server-contact": "~0.6.1",
|
||||
"@hcengineering/server-contact-resources": "~0.6.0",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-notification-resources": "~0.6.0",
|
||||
"@hcengineering/server-setting": "~0.6.0",
|
||||
"@hcengineering/server-setting-resources": "~0.6.0",
|
||||
|
||||
@@ -38,16 +38,16 @@ import { workbenchId } from '@hcengineering/workbench'
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function channelHTMLPresenter (doc: Doc): string {
|
||||
export async function channelHTMLPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const channel = doc as ChunterSpace
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${chunterId}/${channel._id}">${channel.name}</a>`
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${chunterId}/${channel._id}">${channel.name}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function channelTextPresenter (doc: Doc): string {
|
||||
export async function channelTextPresenter (doc: Doc): Promise<string> {
|
||||
const channel = doc as ChunterSpace
|
||||
return `${channel.name}`
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Class, Doc, DocumentQuery, FindOptions, FindResult, Hierarchy, Ref } fr
|
||||
import type { Plugin, Resource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import { TriggerFunc } from '@hcengineering/server-core'
|
||||
import { Presenter } from '@hcengineering/server-notification'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -42,7 +43,7 @@ export default plugin(serverChunterId, {
|
||||
) => Promise<FindResult<T>>
|
||||
) => Promise<Doc[]>
|
||||
>,
|
||||
ChannelHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
ChannelTextPresenter: '' as Resource<(doc: Doc) => string>
|
||||
ChannelHTMLPresenter: '' as Resource<Presenter>,
|
||||
ChannelTextPresenter: '' as Resource<Presenter>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -67,10 +67,10 @@ export async function OnContactDelete (tx: Tx, { findAll, hierarchy, storageFx }
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function personHTMLPresenter (doc: Doc): string {
|
||||
export function personHTMLPresenter (doc: Doc, control: TriggerControl): string {
|
||||
const person = doc as Person
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${contactId}#${view.component.EditDoc}|${person._id}|${
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${contactId}#${view.component.EditDoc}|${person._id}|${
|
||||
person._class
|
||||
}">${formatName(person.name)}</a>`
|
||||
}
|
||||
@@ -86,10 +86,10 @@ export function personTextPresenter (doc: Doc): string {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function organizationHTMLPresenter (doc: Doc): string {
|
||||
export function organizationHTMLPresenter (doc: Doc, control: TriggerControl): string {
|
||||
const organization = doc as Organization
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${contactId}#${view.component.EditDoc}|${organization._id}|${organization._class}">${organization.name}</a>`
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${contactId}#${view.component.EditDoc}|${organization._id}|${organization._class}">${organization.name}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import type { Resource, Plugin } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import type { TriggerFunc } from '@hcengineering/server-core'
|
||||
import { Doc } from '@hcengineering/core'
|
||||
import { Presenter } from '@hcengineering/server-notification'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -32,9 +32,9 @@ export default plugin(serverContactId, {
|
||||
OnContactDelete: '' as Resource<TriggerFunc>
|
||||
},
|
||||
function: {
|
||||
PersonHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
PersonTextPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
OrganizationHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
OrganizationTextPresenter: '' as Resource<(doc: Doc) => string>
|
||||
PersonHTMLPresenter: '' as Resource<Presenter>,
|
||||
PersonTextPresenter: '' as Resource<Presenter>,
|
||||
OrganizationHTMLPresenter: '' as Resource<Presenter>,
|
||||
OrganizationTextPresenter: '' as Resource<Presenter>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/inventory": "~0.6.0",
|
||||
"@hcengineering/view": "^0.6.1",
|
||||
"@hcengineering/login": "~0.6.1",
|
||||
|
||||
@@ -17,22 +17,23 @@ import { Doc } from '@hcengineering/core'
|
||||
import { inventoryId, Product } from '@hcengineering/inventory'
|
||||
import login from '@hcengineering/login'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import { TriggerControl } from '@hcengineering/server-core'
|
||||
import view from '@hcengineering/view'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function productHTMLPresenter (doc: Doc): string {
|
||||
export async function productHTMLPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const product = doc as Product
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${inventoryId}/Products/#${view.component.EditDoc}|${product._id}|${product._class}">${product.name}</a>`
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${inventoryId}/Products/#${view.component.EditDoc}|${product._id}|${product._class}">${product.name}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function productTextPresenter (doc: Doc): string {
|
||||
export async function productTextPresenter (doc: Doc): Promise<string> {
|
||||
const product = doc as Product
|
||||
return `${product.name}`
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Doc } from '@hcengineering/core'
|
||||
import type { Plugin, Resource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import { Presenter } from '@hcengineering/server-notification'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -27,7 +27,7 @@ export const serverInventoryId = 'server-inventory' as Plugin
|
||||
*/
|
||||
export default plugin(serverInventoryId, {
|
||||
function: {
|
||||
ProductHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
ProductTextPresenter: '' as Resource<(doc: Doc) => string>
|
||||
ProductHTMLPresenter: '' as Resource<Presenter>,
|
||||
ProductTextPresenter: '' as Resource<Presenter>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -34,16 +34,16 @@ import { addAssigneeNotification } from '@hcengineering/server-task-resources'
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function leadHTMLPresenter (doc: Doc): string {
|
||||
export async function leadHTMLPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const lead = doc as Lead
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${leadId}/${lead.space}/#${view.component.EditDoc}|${lead._id}|${lead._class}">${lead.title}</a>`
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${leadId}/${lead.space}/#${view.component.EditDoc}|${lead._id}|${lead._class}">${lead.title}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function leadTextPresenter (doc: Doc): string {
|
||||
export async function leadTextPresenter (doc: Doc): Promise<string> {
|
||||
const lead = doc as Lead
|
||||
return `LEAD-${lead.number}`
|
||||
}
|
||||
@@ -77,7 +77,6 @@ async function handleLeadCreate (control: TriggerControl, cud: TxCUD<Doc>, res:
|
||||
control,
|
||||
res,
|
||||
leadValue,
|
||||
leadTextPresenter(leadValue),
|
||||
leadValue.assignee,
|
||||
tx as TxCollectionCUD<Lead, AttachedDoc>
|
||||
)
|
||||
@@ -96,7 +95,6 @@ async function handleLeadUpdate (control: TriggerControl, cud: TxCUD<Doc>, res:
|
||||
control,
|
||||
res,
|
||||
leadValue,
|
||||
leadTextPresenter(leadValue),
|
||||
leadValue.assignee,
|
||||
tx as TxCollectionCUD<Lead, AttachedDoc>
|
||||
)
|
||||
|
||||
@@ -27,10 +27,8 @@
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/contact": "~0.6.5",
|
||||
"@hcengineering/server-task-resources": "~0.6.0"
|
||||
"@hcengineering/server-notification": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Doc } from '@hcengineering/core'
|
||||
import type { Plugin, Resource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import { TriggerFunc } from '@hcengineering/server-core'
|
||||
import { Presenter } from '@hcengineering/server-notification'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -28,8 +28,8 @@ export const serverLeadId = 'server-lead' as Plugin
|
||||
*/
|
||||
export default plugin(serverLeadId, {
|
||||
function: {
|
||||
LeadHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
LeadTextPresenter: '' as Resource<(doc: Doc) => string>
|
||||
LeadHTMLPresenter: '' as Resource<Presenter>,
|
||||
LeadTextPresenter: '' as Resource<Presenter>
|
||||
},
|
||||
trigger: {
|
||||
OnLeadUpdate: '' as Resource<TriggerFunc>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/notification": "~0.6.0",
|
||||
"@hcengineering/chunter": "~0.6.1",
|
||||
"@hcengineering/view": "^0.6.1",
|
||||
|
||||
@@ -36,14 +36,24 @@ import core, {
|
||||
} from '@hcengineering/core'
|
||||
import notification, {
|
||||
EmailNotification,
|
||||
NotificationAction,
|
||||
Notification,
|
||||
NotificationProvider,
|
||||
NotificationStatus
|
||||
NotificationStatus,
|
||||
NotificationType
|
||||
} from '@hcengineering/notification'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import type { TriggerControl } from '@hcengineering/server-core'
|
||||
import { createLastViewTx, getUpdateLastViewTx } from '@hcengineering/server-notification'
|
||||
import view, { HTMLPresenter, TextPresenter } from '@hcengineering/view'
|
||||
import serverNotification, {
|
||||
HTMLPresenter,
|
||||
TextPresenter,
|
||||
createLastViewTx,
|
||||
getEmployeeAccount,
|
||||
getEmployeeAccountById,
|
||||
getUpdateLastViewTx
|
||||
} from '@hcengineering/server-notification'
|
||||
import { replaceAll } from './utils'
|
||||
import { Content } from './types'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -54,33 +64,21 @@ export async function OnBacklinkCreate (tx: Tx, control: TriggerControl): Promis
|
||||
|
||||
if (!checkTx(ptx, hierarchy)) return []
|
||||
|
||||
const result: Tx[] = []
|
||||
|
||||
const receiver = await getReceiver(ptx, control)
|
||||
const receiver = await getEmployeeAccount(ptx.objectId as Ref<Employee>, control)
|
||||
if (receiver === undefined) return []
|
||||
const sender = await getSender(ptx, control)
|
||||
const sender = await getEmployeeAccountById(ptx.modifiedBy, control)
|
||||
if (sender === undefined) return []
|
||||
const backlink = getBacklink(ptx)
|
||||
const doc = await getBacklinkDoc(backlink, control)
|
||||
const textPart = doc !== undefined ? await getTextPart(doc, hierarchy) : undefined
|
||||
const htmlPart = doc !== undefined ? await getHtmlPart(doc, hierarchy) : undefined
|
||||
|
||||
const createNotificationTx = await getPlatformNotificationTx(ptx, backlink, textPart, sender)
|
||||
|
||||
if (createNotificationTx !== undefined) {
|
||||
result.push(createNotificationTx)
|
||||
}
|
||||
|
||||
if (
|
||||
sender !== undefined &&
|
||||
textPart !== undefined &&
|
||||
(await isAllowed(control, receiver, notification.ids.EmailNotification))
|
||||
) {
|
||||
const emailTx = await getEmailTx(ptx, backlink, sender, textPart, htmlPart, receiver)
|
||||
if (emailTx !== undefined) {
|
||||
result.push(emailTx)
|
||||
}
|
||||
}
|
||||
return result
|
||||
return await createNotificationTxes(
|
||||
control,
|
||||
ptx,
|
||||
notification.ids.MentionNotification,
|
||||
doc,
|
||||
sender,
|
||||
receiver,
|
||||
backlink.message
|
||||
)
|
||||
}
|
||||
|
||||
function checkTx (ptx: TxCollectionCUD<Doc, Backlink>, hierarchy: Hierarchy): boolean {
|
||||
@@ -98,6 +96,202 @@ function checkTx (ptx: TxCollectionCUD<Doc, Backlink>, hierarchy: Hierarchy): bo
|
||||
return true
|
||||
}
|
||||
|
||||
async function isAllowed (
|
||||
control: TriggerControl,
|
||||
receiver: EmployeeAccount,
|
||||
providerId: Ref<NotificationProvider>
|
||||
): Promise<boolean> {
|
||||
const setting = (
|
||||
await control.findAll(
|
||||
notification.class.NotificationSetting,
|
||||
{
|
||||
provider: providerId,
|
||||
type: notification.ids.MentionNotification,
|
||||
space: receiver._id as unknown as Ref<Space>
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
if (setting !== undefined) {
|
||||
return setting.enabled
|
||||
}
|
||||
const provider = (
|
||||
await control.modelDb.findAll(notification.class.NotificationProvider, {
|
||||
_id: providerId
|
||||
})
|
||||
)[0]
|
||||
if (provider === undefined) return false
|
||||
return provider.default
|
||||
}
|
||||
|
||||
async function getTextPart (doc: Doc, control: TriggerControl): Promise<string | undefined> {
|
||||
const TextPresenter = getTextPresenter(doc._class, control.hierarchy)
|
||||
if (TextPresenter === undefined) return
|
||||
return await (
|
||||
await getResource(TextPresenter.presenter)
|
||||
)(doc, control)
|
||||
}
|
||||
|
||||
async function getHtmlPart (doc: Doc, control: TriggerControl): Promise<string | undefined> {
|
||||
const HTMLPresenter = getHTMLPresenter(doc._class, control.hierarchy)
|
||||
const htmlPart =
|
||||
HTMLPresenter !== undefined ? await (await getResource(HTMLPresenter.presenter))(doc, control) : undefined
|
||||
return htmlPart
|
||||
}
|
||||
|
||||
function getHTMLPresenter (_class: Ref<Class<Doc>>, hierarchy: Hierarchy): HTMLPresenter | undefined {
|
||||
let clazz: Ref<Class<Obj>> | undefined = _class
|
||||
while (clazz !== undefined) {
|
||||
const _class = hierarchy.getClass(clazz)
|
||||
const presenter = hierarchy.as(_class, serverNotification.mixin.HTMLPresenter)
|
||||
if (presenter.presenter != null) return presenter
|
||||
clazz = _class.extends
|
||||
}
|
||||
}
|
||||
|
||||
function getTextPresenter (_class: Ref<Class<Doc>>, hierarchy: Hierarchy): TextPresenter | undefined {
|
||||
let clazz: Ref<Class<Obj>> | undefined = _class
|
||||
while (clazz !== undefined) {
|
||||
const _class = hierarchy.getClass(clazz)
|
||||
const presenter = hierarchy.as(_class, serverNotification.mixin.TextPresenter)
|
||||
if (presenter.presenter != null) return presenter
|
||||
clazz = _class.extends
|
||||
}
|
||||
}
|
||||
|
||||
function fillTemplate (template: string, sender: string, doc: string, data: string): string {
|
||||
let res = replaceAll(template, '{sender}', sender)
|
||||
res = replaceAll(res, '{doc}', doc)
|
||||
res = replaceAll(res, '{data}', data)
|
||||
return res
|
||||
}
|
||||
|
||||
async function getContent (
|
||||
doc: Doc | undefined,
|
||||
sender: string,
|
||||
type: Ref<NotificationType>,
|
||||
control: TriggerControl,
|
||||
data: string
|
||||
): Promise<Content | undefined> {
|
||||
if (doc === undefined) return
|
||||
const notificationType = control.modelDb.getObject(type)
|
||||
|
||||
const textPart = await getTextPart(doc, control)
|
||||
if (textPart === undefined) return
|
||||
const text = fillTemplate(notificationType.textTemplate, sender, textPart, data)
|
||||
const htmlPart = await getHtmlPart(doc, control)
|
||||
const html = fillTemplate(notificationType.htmlTemplate, sender, htmlPart ?? textPart, data)
|
||||
const subject = fillTemplate(notificationType.subjectTemplate, sender, textPart, data)
|
||||
return {
|
||||
text,
|
||||
html,
|
||||
subject
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function createNotificationTxes (
|
||||
control: TriggerControl,
|
||||
ptx: TxCollectionCUD<Doc, AttachedDoc>,
|
||||
type: Ref<NotificationType>,
|
||||
doc: Doc | undefined,
|
||||
sender: EmployeeAccount,
|
||||
receiver: EmployeeAccount,
|
||||
data: string = '',
|
||||
action?: NotificationAction
|
||||
): Promise<Tx[]> {
|
||||
const res: Tx[] = []
|
||||
|
||||
const senderName = formatName(sender.name)
|
||||
|
||||
const content = await getContent(doc, senderName, type, control, data)
|
||||
|
||||
if (await isAllowed(control, receiver, notification.ids.PlatformNotification)) {
|
||||
const createNotificationTx = await getPlatformNotificationTx(ptx, type, content?.text, action)
|
||||
|
||||
res.push(createNotificationTx)
|
||||
}
|
||||
|
||||
if (content !== undefined && (await isAllowed(control, receiver, notification.ids.EmailNotification))) {
|
||||
const emailTx = await getEmailNotificationTx(ptx, senderName, content.text, content.html, content.subject, receiver)
|
||||
if (emailTx !== undefined) {
|
||||
res.push(emailTx)
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
async function getPlatformNotificationTx (
|
||||
ptx: TxCollectionCUD<Doc, AttachedDoc>,
|
||||
type: Ref<NotificationType>,
|
||||
text?: string,
|
||||
action?: NotificationAction
|
||||
): Promise<TxCollectionCUD<Doc, Notification>> {
|
||||
const createTx: TxCreateDoc<Notification> = {
|
||||
objectClass: notification.class.Notification,
|
||||
objectSpace: notification.space.Notifications,
|
||||
objectId: generateId(),
|
||||
modifiedOn: ptx.modifiedOn,
|
||||
modifiedBy: ptx.modifiedBy,
|
||||
space: ptx.space,
|
||||
_id: generateId(),
|
||||
_class: core.class.TxCreateDoc,
|
||||
attributes: {
|
||||
tx: ptx._id,
|
||||
status: NotificationStatus.New,
|
||||
type
|
||||
} as unknown as Data<Notification>
|
||||
}
|
||||
|
||||
if (text !== undefined) {
|
||||
createTx.attributes.text = text
|
||||
}
|
||||
|
||||
if (action !== undefined) {
|
||||
createTx.attributes.action = action
|
||||
}
|
||||
|
||||
const createNotificationTx: TxCollectionCUD<Doc, Notification> = {
|
||||
...ptx,
|
||||
_id: generateId(),
|
||||
collection: 'notifications',
|
||||
tx: createTx
|
||||
}
|
||||
|
||||
return createNotificationTx
|
||||
}
|
||||
|
||||
async function getEmailNotificationTx (
|
||||
ptx: TxCollectionCUD<Doc, AttachedDoc>,
|
||||
sender: string,
|
||||
text: string,
|
||||
html: string,
|
||||
subject: string,
|
||||
receiver: EmployeeAccount
|
||||
): Promise<TxCreateDoc<EmailNotification> | undefined> {
|
||||
return {
|
||||
_id: generateId(),
|
||||
objectId: generateId(),
|
||||
_class: core.class.TxCreateDoc,
|
||||
space: core.space.DerivedTx,
|
||||
objectClass: notification.class.EmailNotification,
|
||||
objectSpace: notification.space.Notifications,
|
||||
modifiedOn: ptx.modifiedOn,
|
||||
modifiedBy: ptx.modifiedBy,
|
||||
attributes: {
|
||||
status: 'new',
|
||||
sender,
|
||||
receivers: [receiver.email],
|
||||
subject,
|
||||
text,
|
||||
html
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getUpdateLastViewTxes (
|
||||
doc: Doc,
|
||||
_id: Ref<Doc>,
|
||||
@@ -197,86 +391,6 @@ export async function UpdateLastView (tx: Tx, control: TriggerControl): Promise<
|
||||
return result
|
||||
}
|
||||
|
||||
async function getReceiver (
|
||||
ptx: TxCollectionCUD<Doc, Backlink>,
|
||||
control: TriggerControl
|
||||
): Promise<EmployeeAccount | undefined> {
|
||||
return (
|
||||
await control.modelDb.findAll(
|
||||
contact.class.EmployeeAccount,
|
||||
{
|
||||
employee: ptx.objectId as Ref<Employee>
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
}
|
||||
|
||||
async function isAllowed (
|
||||
control: TriggerControl,
|
||||
receiver: EmployeeAccount,
|
||||
providerId: Ref<NotificationProvider>
|
||||
): Promise<boolean> {
|
||||
const setting = (
|
||||
await control.findAll(
|
||||
notification.class.NotificationSetting,
|
||||
{
|
||||
provider: providerId,
|
||||
type: notification.ids.MentionNotification,
|
||||
space: receiver._id as unknown as Ref<Space>
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
if (setting !== undefined) {
|
||||
return setting.enabled
|
||||
}
|
||||
const provider = (
|
||||
await control.modelDb.findAll(notification.class.NotificationProvider, {
|
||||
_id: providerId
|
||||
})
|
||||
)[0]
|
||||
if (provider === undefined) return false
|
||||
return provider.default
|
||||
}
|
||||
|
||||
async function getPlatformNotificationTx (
|
||||
ptx: TxCollectionCUD<Doc, Backlink>,
|
||||
backlink: Backlink,
|
||||
textPart: string | undefined,
|
||||
sender: string | undefined
|
||||
): Promise<TxCollectionCUD<Doc, Notification> | undefined> {
|
||||
const createTx: TxCreateDoc<Notification> = {
|
||||
objectClass: notification.class.Notification,
|
||||
objectSpace: notification.space.Notifications,
|
||||
objectId: generateId(),
|
||||
modifiedOn: ptx.modifiedOn,
|
||||
modifiedBy: ptx.modifiedBy,
|
||||
space: ptx.space,
|
||||
_id: generateId(),
|
||||
_class: core.class.TxCreateDoc,
|
||||
attributes: {
|
||||
tx: ptx._id,
|
||||
status: NotificationStatus.New,
|
||||
type: notification.ids.MentionNotification
|
||||
} as unknown as Data<Notification>
|
||||
}
|
||||
|
||||
if (sender !== undefined && textPart !== undefined) {
|
||||
const text = `${sender} mentioned you in ${textPart} ${backlink.message}`
|
||||
createTx.attributes.text = text
|
||||
}
|
||||
|
||||
const createNotificationTx: TxCollectionCUD<Doc, Notification> = {
|
||||
...ptx,
|
||||
_id: generateId(),
|
||||
collection: 'notifications',
|
||||
tx: createTx
|
||||
}
|
||||
|
||||
return createNotificationTx
|
||||
}
|
||||
|
||||
function getBacklink (ptx: TxCollectionCUD<Doc, Backlink>): Backlink {
|
||||
return TxProcessor.createDoc2Doc(ptx.tx as TxCreateDoc<Backlink>)
|
||||
}
|
||||
@@ -293,85 +407,6 @@ async function getBacklinkDoc (backlink: Backlink, control: TriggerControl): Pro
|
||||
)[0]
|
||||
}
|
||||
|
||||
async function getTextPart (doc: Doc, hierarchy: Hierarchy): Promise<string | undefined> {
|
||||
const TextPresenter = getTextPresenter(doc._class, hierarchy)
|
||||
if (TextPresenter === undefined) return
|
||||
return (await getResource(TextPresenter.presenter))(doc)
|
||||
}
|
||||
|
||||
async function getHtmlPart (doc: Doc, hierarchy: Hierarchy): Promise<string | undefined> {
|
||||
const HTMLPresenter = getHTMLPresenter(doc._class, hierarchy)
|
||||
const htmlPart = HTMLPresenter !== undefined ? (await getResource(HTMLPresenter.presenter))(doc) : undefined
|
||||
return htmlPart
|
||||
}
|
||||
|
||||
async function getSender (ptx: TxCollectionCUD<Doc, Backlink>, control: TriggerControl): Promise<string | undefined> {
|
||||
const account = (
|
||||
await control.modelDb.findAll(
|
||||
contact.class.EmployeeAccount,
|
||||
{
|
||||
_id: ptx.modifiedBy as Ref<EmployeeAccount>
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
if (account === undefined) return undefined
|
||||
|
||||
return formatName(account.name)
|
||||
}
|
||||
|
||||
async function getEmailTx (
|
||||
ptx: TxCollectionCUD<Doc, Backlink>,
|
||||
backlink: Backlink,
|
||||
sender: string,
|
||||
textPart: string,
|
||||
htmlPart: string | undefined,
|
||||
receiver: EmployeeAccount
|
||||
): Promise<TxCreateDoc<EmailNotification> | undefined> {
|
||||
const html = `<p><b>${sender}</b> mentioned you in ${htmlPart !== undefined ? htmlPart : textPart}</p> ${
|
||||
backlink.message
|
||||
}`
|
||||
const text = `${sender} mentioned you in ${textPart}`
|
||||
return {
|
||||
_id: generateId(),
|
||||
objectId: generateId(),
|
||||
_class: core.class.TxCreateDoc,
|
||||
space: core.space.DerivedTx,
|
||||
objectClass: notification.class.EmailNotification,
|
||||
objectSpace: notification.space.Notifications,
|
||||
modifiedOn: ptx.modifiedOn,
|
||||
modifiedBy: ptx.modifiedBy,
|
||||
attributes: {
|
||||
status: 'new',
|
||||
sender,
|
||||
receivers: [receiver.email],
|
||||
subject: `You was mentioned in ${textPart}`,
|
||||
text,
|
||||
html
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getHTMLPresenter (_class: Ref<Class<Doc>>, hierarchy: Hierarchy): HTMLPresenter | undefined {
|
||||
let clazz: Ref<Class<Obj>> | undefined = _class
|
||||
while (clazz !== undefined) {
|
||||
const _class = hierarchy.getClass(clazz)
|
||||
const presenter = hierarchy.as(_class, view.mixin.HTMLPresenter)
|
||||
if (presenter.presenter != null) return presenter
|
||||
clazz = _class.extends
|
||||
}
|
||||
}
|
||||
|
||||
function getTextPresenter (_class: Ref<Class<Doc>>, hierarchy: Hierarchy): TextPresenter | undefined {
|
||||
let clazz: Ref<Class<Obj>> | undefined = _class
|
||||
while (clazz !== undefined) {
|
||||
const _class = hierarchy.getClass(clazz)
|
||||
const presenter = hierarchy.as(_class, view.mixin.TextPresenter)
|
||||
if (presenter.presenter != null) return presenter
|
||||
clazz = _class.extends
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export default async () => ({
|
||||
trigger: {
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface Content {
|
||||
text: string
|
||||
html: string
|
||||
subject: string
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
function escapeRegExp (str: string): string {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
}
|
||||
|
||||
export function replaceAll (str: string, find: string, replace: string): string {
|
||||
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace)
|
||||
}
|
||||
@@ -30,6 +30,7 @@
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/notification": "~0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/contact": "~0.6.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import core, { Account, Class, Doc, Ref, TxCreateDoc, TxFactory, TxUpdateDoc } from '@hcengineering/core'
|
||||
import type { Resource, Plugin } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import type { TriggerControl, TriggerFunc } from '@hcengineering/server-core'
|
||||
import contact, { Employee, EmployeeAccount } from '@hcengineering/contact'
|
||||
import core, { Account, Class, Doc, Mixin, Ref, TxCreateDoc, TxFactory, TxUpdateDoc } from '@hcengineering/core'
|
||||
import notification, { LastView } from '@hcengineering/notification'
|
||||
import { Plugin, plugin, Resource } from '@hcengineering/platform'
|
||||
import type { TriggerControl, TriggerFunc } from '@hcengineering/server-core'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -69,6 +69,60 @@ export async function getUpdateLastViewTx (
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function getEmployeeAccount (
|
||||
employee: Ref<Employee>,
|
||||
control: TriggerControl
|
||||
): Promise<EmployeeAccount | undefined> {
|
||||
const account = (
|
||||
await control.modelDb.findAll(
|
||||
contact.class.EmployeeAccount,
|
||||
{
|
||||
employee: employee
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
return account
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function getEmployeeAccountById (
|
||||
_id: Ref<Account>,
|
||||
control: TriggerControl
|
||||
): Promise<EmployeeAccount | undefined> {
|
||||
const account = (
|
||||
await control.modelDb.findAll(
|
||||
contact.class.EmployeeAccount,
|
||||
{
|
||||
_id: _id as Ref<EmployeeAccount>
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
return account
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function getEmployee (employee: Ref<Employee>, control: TriggerControl): Promise<Employee | undefined> {
|
||||
const account = (
|
||||
await control.findAll(
|
||||
contact.class.Employee,
|
||||
{
|
||||
_id: employee
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
return account
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@@ -103,10 +157,33 @@ export async function createLastViewTx (
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type Presenter = (doc: Doc, control: TriggerControl) => Promise<string>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface HTMLPresenter extends Class<Doc> {
|
||||
presenter: Resource<Presenter>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TextPresenter extends Class<Doc> {
|
||||
presenter: Resource<Presenter>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export default plugin(serverNotificationId, {
|
||||
mixin: {
|
||||
HTMLPresenter: '' as Ref<Mixin<HTMLPresenter>>,
|
||||
TextPresenter: '' as Ref<Mixin<TextPresenter>>
|
||||
},
|
||||
trigger: {
|
||||
OnBacklinkCreate: '' as Resource<TriggerFunc>,
|
||||
UpdateLastView: '' as Resource<TriggerFunc>
|
||||
|
||||
@@ -36,16 +36,16 @@ import { workbenchId } from '@hcengineering/workbench'
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function vacancyHTMLPresenter (doc: Doc): string {
|
||||
export async function vacancyHTMLPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const vacancy = doc as Vacancy
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${recruitId}/${vacancy._id}/#${recruit.component.EditVacancy}|${vacancy._id}|${vacancy._class}">${vacancy.name}</a>`
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${recruitId}/${vacancy._id}/#${recruit.component.EditVacancy}|${vacancy._id}|${vacancy._class}">${vacancy.name}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function vacancyTextPresenter (doc: Doc): string {
|
||||
export async function vacancyTextPresenter (doc: Doc): Promise<string> {
|
||||
const vacancy = doc as Vacancy
|
||||
return `${vacancy.name}`
|
||||
}
|
||||
@@ -53,16 +53,16 @@ export function vacancyTextPresenter (doc: Doc): string {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function applicationHTMLPresenter (doc: Doc): string {
|
||||
export async function applicationHTMLPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const applicant = doc as Applicant
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${recruitId}/${applicant.space}/#${view.component.EditDoc}|${applicant._id}|${applicant._class}">APP-${applicant.number}</a>`
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${recruitId}/${applicant.space}/#${view.component.EditDoc}|${applicant._id}|${applicant._class}">APP-${applicant.number}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function applicationTextPresenter (doc: Doc): string {
|
||||
export async function applicationTextPresenter (doc: Doc): Promise<string> {
|
||||
const applicant = doc as Applicant
|
||||
return `APP-${applicant.number}`
|
||||
}
|
||||
@@ -185,7 +185,6 @@ async function handleApplicantUpdate (control: TriggerControl, cud: TxCUD<Doc>,
|
||||
control,
|
||||
res,
|
||||
applicant,
|
||||
applicationTextPresenter(applicant),
|
||||
applicant.assignee,
|
||||
tx as TxCollectionCUD<Applicant, AttachedDoc>
|
||||
)
|
||||
@@ -203,7 +202,6 @@ async function handleApplicantCreate (control: TriggerControl, cud: TxCUD<Doc>,
|
||||
control,
|
||||
res,
|
||||
applicant,
|
||||
applicationTextPresenter(applicant),
|
||||
applicant.assignee,
|
||||
tx as TxCollectionCUD<Applicant, AttachedDoc>
|
||||
)
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Resource, Plugin } from '@hcengineering/platform'
|
||||
import type { Plugin, Resource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import { Doc } from '@hcengineering/core'
|
||||
import { TriggerFunc } from '@hcengineering/server-core'
|
||||
import { Presenter } from '@hcengineering/server-notification'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -28,10 +28,10 @@ export const serverRecruitId = 'server-recruit' as Plugin
|
||||
*/
|
||||
export default plugin(serverRecruitId, {
|
||||
function: {
|
||||
ApplicationHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
ApplicationTextPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
VacancyHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
VacancyTextPresenter: '' as Resource<(doc: Doc) => string>
|
||||
ApplicationHTMLPresenter: '' as Resource<Presenter>,
|
||||
ApplicationTextPresenter: '' as Resource<Presenter>,
|
||||
VacancyHTMLPresenter: '' as Resource<Presenter>,
|
||||
VacancyTextPresenter: '' as Resource<Presenter>
|
||||
},
|
||||
trigger: {
|
||||
OnRecruitUpdate: '' as Resource<TriggerFunc>
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-notification-resources": "~0.6.0",
|
||||
"@hcengineering/task": "~0.6.0",
|
||||
"@hcengineering/view": "^0.6.1",
|
||||
"@hcengineering/login": "~0.6.1",
|
||||
|
||||
@@ -13,25 +13,19 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import contact, { Employee, EmployeeAccount, formatName } from '@hcengineering/contact'
|
||||
import core, {
|
||||
Account,
|
||||
AttachedDoc,
|
||||
Data,
|
||||
Doc,
|
||||
generateId,
|
||||
Ref,
|
||||
Tx,
|
||||
TxCollectionCUD,
|
||||
TxCreateDoc,
|
||||
TxProcessor,
|
||||
TxUpdateDoc
|
||||
} from '@hcengineering/core'
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import core, { AttachedDoc, Doc, Ref, Tx, TxCollectionCUD, TxProcessor, TxUpdateDoc } from '@hcengineering/core'
|
||||
import login from '@hcengineering/login'
|
||||
import notification, { Notification, NotificationStatus } from '@hcengineering/notification'
|
||||
import { NotificationAction } from '@hcengineering/notification'
|
||||
import { getMetadata, Resource } from '@hcengineering/platform'
|
||||
import { TriggerControl } from '@hcengineering/server-core'
|
||||
import { getUpdateLastViewTx } from '@hcengineering/server-notification'
|
||||
import {
|
||||
getEmployee,
|
||||
getEmployeeAccount,
|
||||
getEmployeeAccountById,
|
||||
getUpdateLastViewTx
|
||||
} from '@hcengineering/server-notification'
|
||||
import { createNotificationTxes } from '@hcengineering/server-notification-resources'
|
||||
import task, { Issue, Task, taskId } from '@hcengineering/task'
|
||||
import view from '@hcengineering/view'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
@@ -39,52 +33,20 @@ import { workbenchId } from '@hcengineering/workbench'
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function issueHTMLPresenter (doc: Doc): string {
|
||||
export async function issueHTMLPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const issue = doc as Issue
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${taskId}/${issue.space}/#${view.component.EditDoc}|${issue._id}|${issue._class}">Task-${issue.number}</a>`
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${taskId}/${issue.space}/#${view.component.EditDoc}|${issue._id}|${issue._class}">Task-${issue.number}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function issueTextPresenter (doc: Doc): string {
|
||||
export async function issueTextPresenter (doc: Doc): Promise<string> {
|
||||
const issue = doc as Issue
|
||||
return `Task-${issue.number}`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function getEmployeeAccount (
|
||||
employee: Ref<Account>,
|
||||
control: TriggerControl
|
||||
): Promise<EmployeeAccount | undefined> {
|
||||
const account = (
|
||||
await control.modelDb.findAll(
|
||||
contact.class.EmployeeAccount,
|
||||
{
|
||||
_id: employee as Ref<EmployeeAccount>
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
return account
|
||||
}
|
||||
|
||||
async function getEmployee (employee: Ref<Employee>, control: TriggerControl): Promise<Employee | undefined> {
|
||||
const account = (
|
||||
await control.findAll(
|
||||
contact.class.Employee,
|
||||
{
|
||||
_id: employee
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
)[0]
|
||||
return account
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@@ -92,12 +54,11 @@ export async function addAssigneeNotification (
|
||||
control: TriggerControl,
|
||||
res: Tx[],
|
||||
issue: Doc,
|
||||
issueName: string,
|
||||
assignee: Ref<Employee>,
|
||||
ptx: TxCollectionCUD<AttachedDoc, AttachedDoc>,
|
||||
component?: Resource<string>
|
||||
): Promise<void> {
|
||||
const sender = await getEmployeeAccount(ptx.modifiedBy, control)
|
||||
const sender = await getEmployeeAccountById(ptx.modifiedBy, control)
|
||||
if (sender === undefined) {
|
||||
return
|
||||
}
|
||||
@@ -107,29 +68,30 @@ export async function addAssigneeNotification (
|
||||
return
|
||||
}
|
||||
|
||||
const createTx: TxCreateDoc<Notification> = {
|
||||
objectClass: notification.class.Notification,
|
||||
objectSpace: notification.space.Notifications,
|
||||
objectId: generateId(),
|
||||
modifiedOn: ptx.modifiedOn,
|
||||
modifiedBy: ptx.modifiedBy,
|
||||
space: ptx.space,
|
||||
_id: generateId(),
|
||||
_class: core.class.TxCreateDoc,
|
||||
attributes: {
|
||||
tx: ptx._id,
|
||||
status: NotificationStatus.New,
|
||||
type: task.ids.AssigneedNotification,
|
||||
text: `${issueName} was assigned to you by ${formatName(sender.name)}`,
|
||||
action: {
|
||||
component: component ?? view.component.EditDoc,
|
||||
objectId: issue._id,
|
||||
objectClass: issue._class
|
||||
}
|
||||
} as unknown as Data<Notification>
|
||||
const receiver = await getEmployeeAccount(assignee, control)
|
||||
if (receiver === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
res.push(control.txFactory.createTxCollectionCUD(target._class, target._id, target.space, 'notifications', createTx))
|
||||
// eslint-disable-next-line
|
||||
const action: NotificationAction = {
|
||||
component: component ?? view.component.EditDoc,
|
||||
objectId: issue._id,
|
||||
objectClass: issue._class
|
||||
} as NotificationAction
|
||||
|
||||
const result = await createNotificationTxes(
|
||||
control,
|
||||
ptx,
|
||||
task.ids.AssigneedNotification,
|
||||
issue,
|
||||
sender,
|
||||
receiver,
|
||||
undefined,
|
||||
action
|
||||
)
|
||||
|
||||
res.push(...result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.17",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Doc } from '@hcengineering/core'
|
||||
import type { Plugin, Resource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import { Presenter } from '@hcengineering/server-notification'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -27,7 +27,7 @@ export const serverTaskId = 'server-task' as Plugin
|
||||
*/
|
||||
export default plugin(serverTaskId, {
|
||||
function: {
|
||||
IssueHTMLPresenter: '' as Resource<(doc: Doc) => string>,
|
||||
IssueTextPresenter: '' as Resource<(doc: Doc) => string>
|
||||
IssueHTMLPresenter: '' as Resource<Presenter>,
|
||||
IssueTextPresenter: '' as Resource<Presenter>
|
||||
}
|
||||
})
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
"@hcengineering/contact": "~0.6.5",
|
||||
"@hcengineering/notification": "~0.6.0",
|
||||
"@hcengineering/task": "~0.6.0",
|
||||
"@hcengineering/view": "^0.6.1",
|
||||
"@hcengineering/login": "~0.6.1",
|
||||
"@hcengineering/workbench": "~0.6.1",
|
||||
"@hcengineering/server-task-resources": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import { Employee } from '@hcengineering/contact'
|
||||
import core, {
|
||||
AttachedDoc,
|
||||
Doc,
|
||||
DocumentUpdate,
|
||||
Ref,
|
||||
Space,
|
||||
@@ -28,10 +29,13 @@ import core, {
|
||||
TxUpdateDoc,
|
||||
WithLookup
|
||||
} from '@hcengineering/core'
|
||||
import login from '@hcengineering/login'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import { Resource } from '@hcengineering/platform/lib/platform'
|
||||
import { TriggerControl } from '@hcengineering/server-core'
|
||||
import { addAssigneeNotification } from '@hcengineering/server-task-resources'
|
||||
import tracker, { Issue, IssueParentInfo, TimeSpendReport } from '@hcengineering/tracker'
|
||||
import tracker, { Issue, IssueParentInfo, TimeSpendReport, trackerId } from '@hcengineering/tracker'
|
||||
|
||||
async function updateSubIssues (
|
||||
updateTx: TxUpdateDoc<Issue>,
|
||||
@@ -46,6 +50,29 @@ async function updateSubIssues (
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function issueHTMLPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const issue = doc as Issue
|
||||
const team = (await control.findAll(tracker.class.Team, { _id: issue.space })).shift()
|
||||
const issueName = `${team?.identifier ?? '?'}-${issue.number}`
|
||||
|
||||
const front = getMetadata(login.metadata.FrontUrl) ?? ''
|
||||
return `<a href="${front}/${workbenchId}/${control.workspace}/${trackerId}/${issue.space}/#${tracker.component.EditIssue}|${issue._id}|${issue._class}">${issueName}</a>`
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function issueTextPresenter (doc: Doc, control: TriggerControl): Promise<string> {
|
||||
const issue = doc as Issue
|
||||
const team = (await control.findAll(tracker.class.Team, { _id: issue.space })).shift()
|
||||
const issueName = `${team?.identifier ?? '?'}-${issue.number}`
|
||||
|
||||
return issueName
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@@ -56,14 +83,10 @@ export async function addTrackerAssigneeNotification (
|
||||
assignee: Ref<Employee>,
|
||||
ptx: TxCollectionCUD<Issue, AttachedDoc>
|
||||
): Promise<void> {
|
||||
const team = (await control.findAll(tracker.class.Team, { _id: issue.space })).shift()
|
||||
const issueName = `${team?.identifier ?? '?'}-${issue.number}`
|
||||
|
||||
await addAssigneeNotification(
|
||||
control,
|
||||
res,
|
||||
issue,
|
||||
issueName,
|
||||
assignee,
|
||||
ptx,
|
||||
tracker.component.EditIssue as unknown as Resource<string>
|
||||
@@ -142,6 +165,10 @@ export async function OnIssueUpdate (tx: Tx, control: TriggerControl): Promise<T
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export default async () => ({
|
||||
function: {
|
||||
IssueHTMLPresenter: issueHTMLPresenter,
|
||||
IssueTextPresenter: issueTextPresenter
|
||||
},
|
||||
trigger: {
|
||||
OnIssueUpdate
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/platform": "^0.6.7",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-core": "~0.6.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import type { Plugin, Resource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import { TriggerFunc } from '@hcengineering/server-core'
|
||||
import { Presenter } from '@hcengineering/server-notification'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -26,6 +27,10 @@ export const serverTrackerId = 'server-tracker' as Plugin
|
||||
* @public
|
||||
*/
|
||||
export default plugin(serverTrackerId, {
|
||||
function: {
|
||||
IssueHTMLPresenter: '' as Resource<Presenter>,
|
||||
IssueTextPresenter: '' as Resource<Presenter>
|
||||
},
|
||||
trigger: {
|
||||
OnIssueUpdate: '' as Resource<TriggerFunc>
|
||||
}
|
||||
|
||||
@@ -408,6 +408,7 @@ class TServerStorage implements ServerStorage {
|
||||
...(await ctx.with('process-move', { _class }, () => this.processMove(ctx, tx))),
|
||||
...(await ctx.with('process-triggers', {}, (ctx) =>
|
||||
this.triggers.apply(tx.modifiedBy, tx, {
|
||||
workspace: this.workspace,
|
||||
fx: triggerFx.fx,
|
||||
fulltextFx: (f) => triggerFx.fx(() => f(this.fulltextAdapter)),
|
||||
storageFx: (f) => {
|
||||
|
||||
@@ -98,6 +98,7 @@ export interface Pipeline extends LowLevelStorage {
|
||||
* @public
|
||||
*/
|
||||
export interface TriggerControl {
|
||||
workspace: string
|
||||
txFactory: TxFactory
|
||||
findAll: Storage['findAll']
|
||||
hierarchy: Hierarchy
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"minio": "^7.0.26",
|
||||
"@hcengineering/server-contact": "~0.6.1",
|
||||
"@hcengineering/server-contact-resources": "~0.6.0",
|
||||
"@hcengineering/server-notification": "~0.6.0",
|
||||
"@hcengineering/server-notification": "^0.6.0",
|
||||
"@hcengineering/server-notification-resources": "~0.6.0",
|
||||
"@hcengineering/server-setting": "~0.6.0",
|
||||
"@hcengineering/server-setting-resources": "~0.6.0",
|
||||
|
||||
Reference in New Issue
Block a user