diff --git a/models/controlled-documents/src/types.ts b/models/controlled-documents/src/types.ts
index 1efce19690..4294ef30b8 100644
--- a/models/controlled-documents/src/types.ts
+++ b/models/controlled-documents/src/types.ts
@@ -462,11 +462,11 @@ export class TDocumentComment extends TChatMessage implements DocumentComment {
export class TDocumentRequest extends TRequest implements DocumentRequest {}
@Model(documents.class.DocumentReviewRequest, documents.class.DocumentRequest)
-@UX(documents.string.DocumentReviewRequest)
+@UX(documents.string.DocumentReviewRequest, documents.icon.Document)
export class TDocumentReviewRequest extends TDocumentRequest implements DocumentReviewRequest {}
@Model(documents.class.DocumentApprovalRequest, documents.class.DocumentRequest)
-@UX(documents.string.DocumentApprovalRequest)
+@UX(documents.string.DocumentApprovalRequest, documents.icon.Document)
export class TDocumentApprovalRequest extends TDocumentRequest implements DocumentApprovalRequest {}
@Mixin(documents.mixin.DocumentSpaceTypeData, documents.class.DocumentSpace)
diff --git a/models/request/src/index.ts b/models/request/src/index.ts
index 0f695343af..ddaa1a8e1d 100644
--- a/models/request/src/index.ts
+++ b/models/request/src/index.ts
@@ -133,24 +133,56 @@ export function createModel (builder: Builder): void {
field: 'requested',
generated: false,
group: request.ids.RequestNotificationGroup,
- label: request.string.Request,
+ label: request.string.NewRequest,
allowedForAuthor: true,
defaultEnabled: true,
templates: {
- textTemplate: '{sender} sent you a {doc}',
- htmlTemplate: '
{sender} sent you a {doc}
',
+ textTemplate: '{sender} sent you a request for the {doc}',
+ htmlTemplate: '{sender} sent you a request for the {doc}
',
subjectTemplate: '{doc}'
}
},
request.ids.CreateRequestNotification
)
+ builder.createDoc(
+ notification.class.NotificationType,
+ core.space.Model,
+ {
+ hidden: false,
+ objectClass: request.class.Request,
+ txClasses: [core.class.TxUpdateDoc],
+ field: 'requested',
+ generated: false,
+ group: request.ids.RequestNotificationGroup,
+ label: request.string.CancelRequest,
+ allowedForAuthor: true,
+ defaultEnabled: true,
+ templates: {
+ textTemplate: '{sender} canceled the request for the {doc}',
+ htmlTemplate: '{sender} canceled the request for the {doc}
',
+ subjectTemplate: '{doc}'
+ }
+ },
+ request.ids.RemoveRequestNotification
+ )
+
+ builder.createDoc(notification.class.ActivityNotificationViewlet, core.space.Model, {
+ messageMatch: {
+ _class: activity.class.DocUpdateMessage,
+ objectClass: request.class.Request,
+ action: 'update',
+ 'attributeUpdates.attrKey': 'requested'
+ },
+ presenter: request.component.RequestedChangedNotification
+ })
+
generateClassNotificationTypes(
builder,
request.class.Request,
request.ids.RequestNotificationGroup,
['requested'],
- ['comments', 'approved', 'rejected', 'status']
+ ['comments']
)
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
diff --git a/models/request/src/plugin.ts b/models/request/src/plugin.ts
index 2726dc8275..9f539a93ef 100644
--- a/models/request/src/plugin.ts
+++ b/models/request/src/plugin.ts
@@ -24,14 +24,18 @@ import type { NotificationGroup, NotificationType } from '@hcengineering/notific
export default mergeIds(requestId, request, {
component: {
EditRequest: '' as AnyComponent,
- NotificationRequestView: '' as AnyComponent
+ NotificationRequestView: '' as AnyComponent,
+ RequestedChangedNotification: '' as AnyComponent
},
ids: {
RequestNotificationGroup: '' as Ref,
- CreateRequestNotification: '' as Ref
+ CreateRequestNotification: '' as Ref,
+ RemoveRequestNotification: '' as Ref
},
string: {
Status: '' as IntlString,
- Requested: '' as IntlString
+ Requested: '' as IntlString,
+ NewRequest: '' as IntlString,
+ CancelRequest: '' as IntlString
}
})
diff --git a/models/server-request/package.json b/models/server-request/package.json
index 2c2f390b8b..f7cc79d55f 100644
--- a/models/server-request/package.json
+++ b/models/server-request/package.json
@@ -35,6 +35,7 @@
"@hcengineering/server-request": "^0.6.0",
"@hcengineering/server-core": "^0.6.1",
"@hcengineering/model-request": "^0.6.0",
- "@hcengineering/server-notification": "^0.6.1"
+ "@hcengineering/server-notification": "^0.6.1",
+ "@hcengineering/notification": "^0.6.23"
}
}
diff --git a/models/server-request/src/index.ts b/models/server-request/src/index.ts
index 57bf3580f8..4dd79fc6cd 100644
--- a/models/server-request/src/index.ts
+++ b/models/server-request/src/index.ts
@@ -20,6 +20,7 @@ import serverCore from '@hcengineering/server-core'
import serverRequest from '@hcengineering/server-request'
import serverNotification from '@hcengineering/server-notification'
import request from '@hcengineering/model-request'
+import notification from '@hcengineering/notification'
export { serverRequestId } from '@hcengineering/server-request'
@@ -34,4 +35,22 @@ export function createModel (builder: Builder): void {
builder.mixin(request.class.Request, core.class.Class, serverNotification.mixin.TextPresenter, {
presenter: serverRequest.function.RequestTextPresenter
})
+
+ builder.mixin(
+ request.ids.CreateRequestNotification,
+ notification.class.NotificationType,
+ serverNotification.mixin.TypeMatch,
+ {
+ func: serverRequest.function.SendRequestMatch
+ }
+ )
+
+ builder.mixin(
+ request.ids.RemoveRequestNotification,
+ notification.class.NotificationType,
+ serverNotification.mixin.TypeMatch,
+ {
+ func: serverRequest.function.RemoveRequestMatch
+ }
+ )
}
diff --git a/plugins/controlled-documents-resources/src/components/document/EditDocTeam.svelte b/plugins/controlled-documents-resources/src/components/document/EditDocTeam.svelte
index 993b93cdec..dc8c32b27f 100644
--- a/plugins/controlled-documents-resources/src/components/document/EditDocTeam.svelte
+++ b/plugins/controlled-documents-resources/src/components/document/EditDocTeam.svelte
@@ -21,7 +21,7 @@
DocumentReviewRequest,
DocumentState
} from '@hcengineering/controlled-documents'
- import { Ref } from '@hcengineering/core'
+ import { DocumentUpdate, Ref } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { Scroller } from '@hcengineering/ui'
@@ -88,16 +88,51 @@
}
const requiredApprovesCount = users.length
+ const requestedQuery: DocumentUpdate = {}
+ if (addedPersons.size > 0) {
+ requestedQuery.$push = { requested: { $each: Array.from(addedPersons), $position: 0 } }
+ }
+ if (removedPersons.size > 0) {
+ requestedQuery.$pull = { requested: { $in: Array.from(removedPersons) } }
+ }
+
+ if (Object.keys(requestedQuery).length > 0) {
+ await ops.update(request, requestedQuery)
+ }
await ops.update(request, {
- requested: users,
approved,
approvedDates,
requiredApprovesCount
})
}
- await ops.update(controlledDoc, { [type]: users })
+ const added = new Set()
+ const removed = new Set()
+
+ for (const user of users) {
+ if (!controlledDoc[type].includes(user as Ref)) {
+ added.add(user)
+ }
+ }
+
+ for (const user of controlledDoc[type]) {
+ if (!users.includes(user)) {
+ removed.add(user)
+ }
+ }
+
+ const updateQuery: DocumentUpdate = {}
+ if (added.size > 0) {
+ updateQuery.$push = { [type]: { $each: Array.from(added), $position: 0 } }
+ }
+ if (removed.size > 0) {
+ updateQuery.$pull = { [type]: { $in: Array.from(removed) } }
+ }
+
+ if (Object.keys(updateQuery).length > 0) {
+ await ops.update(controlledDoc, updateQuery)
+ }
await ops.commit()
}
diff --git a/plugins/notification-resources/src/components/inbox/ActivityInboxNotificationPresenter.svelte b/plugins/notification-resources/src/components/inbox/ActivityInboxNotificationPresenter.svelte
index 836dc267dc..47bcc9c34a 100644
--- a/plugins/notification-resources/src/components/inbox/ActivityInboxNotificationPresenter.svelte
+++ b/plugins/notification-resources/src/components/inbox/ActivityInboxNotificationPresenter.svelte
@@ -25,7 +25,7 @@
combineActivityMessages,
sortActivityMessages
} from '@hcengineering/activity-resources'
- import { ActivityMessage, DisplayActivityMessage } from '@hcengineering/activity'
+ import activity, { ActivityMessage, DisplayActivityMessage, DocUpdateMessage } from '@hcengineering/activity'
import { Action, Component } from '@hcengineering/ui'
import { getActions } from '@hcengineering/view-resources'
import { getResource } from '@hcengineering/platform'
@@ -55,6 +55,24 @@
$: updateViewlet(viewlets, displayMessage)
+ function matchViewlet (viewlet: ActivityNotificationViewlet, message: DisplayActivityMessage): boolean {
+ const hierarchy = client.getHierarchy()
+ const matched = matchQuery([message], viewlet.messageMatch, message._class, hierarchy, true)[0]
+ if (matched !== undefined) return true
+
+ if (hierarchy.isDerived(message._class, activity.class.DocUpdateMessage)) {
+ const dum = message as DocUpdateMessage
+ const dumUpdated: DocUpdateMessage = {
+ ...dum,
+ objectClass: hierarchy.getParentClass(dum.objectClass)
+ }
+ const matched = matchQuery([dumUpdated], viewlet.messageMatch, message._class, hierarchy, true)[0]
+ return matched !== undefined
+ }
+
+ return false
+ }
+
function updateViewlet (viewlets: ActivityNotificationViewlet[], message?: DisplayActivityMessage): void {
if (viewlets.length === 0 || message === undefined) {
viewlet = undefined
@@ -62,8 +80,8 @@
}
for (const v of viewlets) {
- const matched = matchQuery([message], v.messageMatch, message._class, client.getHierarchy(), true)
- if (matched.length > 0) {
+ const matched = matchViewlet(v, message)
+ if (matched) {
viewlet = v
return
}
diff --git a/plugins/request-assets/lang/cs.json b/plugins/request-assets/lang/cs.json
index 94a27aa89f..2b5b168520 100644
--- a/plugins/request-assets/lang/cs.json
+++ b/plugins/request-assets/lang/cs.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Zadejte prosím zprávu ke komentáři, abyste mohli pokračovat...",
"NoRequests": "Žádné žádosti",
"Cancel": "Zrušit",
- "Cancelled": "Zrušeno"
+ "Cancelled": "Zrušeno",
+ "NewRequest": "Nový požadavek",
+ "CancelRequest": "Zrušit požadavek"
}
}
\ No newline at end of file
diff --git a/plugins/request-assets/lang/de.json b/plugins/request-assets/lang/de.json
index aa2fe46569..48c3503533 100644
--- a/plugins/request-assets/lang/de.json
+++ b/plugins/request-assets/lang/de.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Bitte geben Sie eine Kommentarnachricht ein, um fortzufahren...",
"NoRequests": "Keine Anfragen",
"Cancel": "Abbrechen",
- "Cancelled": "Abgebrochen"
+ "Cancelled": "Abgebrochen",
+ "NewRequest": "Neue Anfrage",
+ "CancelRequest": "Anfrage abbrechen"
}
}
\ No newline at end of file
diff --git a/plugins/request-assets/lang/en.json b/plugins/request-assets/lang/en.json
index adc89bfc37..3645fc67a6 100644
--- a/plugins/request-assets/lang/en.json
+++ b/plugins/request-assets/lang/en.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Please type comment message to continue...",
"NoRequests": "No requests",
"Cancel": "Cancel",
- "Cancelled": "Cancelled"
+ "Cancelled": "Cancelled",
+ "NewRequest": "New Request",
+ "CancelRequest": "Cancel Request"
}
}
\ No newline at end of file
diff --git a/plugins/request-assets/lang/es.json b/plugins/request-assets/lang/es.json
index 6dc7f496d8..6d4562e7ea 100644
--- a/plugins/request-assets/lang/es.json
+++ b/plugins/request-assets/lang/es.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Escriba un mensaje de comentario para continuar...",
"NoRequests": "No hay solicitudes",
"Cancel": "Cancelar",
- "Cancelled": "Cancelado"
+ "Cancelled": "Cancelado",
+ "NewRequest": "Nueva solicitud",
+ "CancelRequest": "Cancelar solicitud"
}
}
\ No newline at end of file
diff --git a/plugins/request-assets/lang/fr.json b/plugins/request-assets/lang/fr.json
index e33cb3e70d..74c2d31aa9 100644
--- a/plugins/request-assets/lang/fr.json
+++ b/plugins/request-assets/lang/fr.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Veuillez taper un message de commentaire pour continuer...",
"NoRequests": "Aucune demande",
"Cancel": "Annuler",
- "Cancelled": "Annulé"
+ "Cancelled": "Annulé",
+ "NewRequest": "Nouvelle demande",
+ "CancelRequest": "Annuler la demande"
}
}
\ No newline at end of file
diff --git a/plugins/request-assets/lang/it.json b/plugins/request-assets/lang/it.json
index bc4d063b83..d1bc06e342 100644
--- a/plugins/request-assets/lang/it.json
+++ b/plugins/request-assets/lang/it.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Per favore, digita un commento per continuare...",
"NoRequests": "Nessuna richiesta",
"Cancel": "Annulla",
- "Cancelled": "Annullato"
+ "Cancelled": "Annullato",
+ "NewRequest": "Nuova richiesta",
+ "CancelRequest": "Annulla richiesta"
}
}
diff --git a/plugins/request-assets/lang/ja.json b/plugins/request-assets/lang/ja.json
index d1629d2aef..cf84bbcfd5 100644
--- a/plugins/request-assets/lang/ja.json
+++ b/plugins/request-assets/lang/ja.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "コメントを入力して続行...",
"NoRequests": "リクエストはありません",
"Cancel": "キャンセル",
- "Cancelled": "キャンセル済み"
+ "Cancelled": "キャンセル済み",
+ "NewRequest": "新しいリクエスト",
+ "CancelRequest": "リクエストをキャンセル"
}
}
diff --git a/plugins/request-assets/lang/pt.json b/plugins/request-assets/lang/pt.json
index 30e45c96b8..891c21ecba 100644
--- a/plugins/request-assets/lang/pt.json
+++ b/plugins/request-assets/lang/pt.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Digite uma mensagem de comentário para continuar...",
"NoRequests": "Sem solicitações",
"Cancel": "Cancelar",
- "Cancelled": "Cancelado"
+ "Cancelled": "Cancelado",
+ "NewRequest": "Nova solicitação",
+ "CancelRequest": "Cancelar solicitação"
}
}
\ No newline at end of file
diff --git a/plugins/request-assets/lang/ru.json b/plugins/request-assets/lang/ru.json
index a0ced6f6cb..d49e785d6f 100644
--- a/plugins/request-assets/lang/ru.json
+++ b/plugins/request-assets/lang/ru.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "Пожалуйста, оставьте комментарий, чтобы продолжить...",
"NoRequests": "Нет запросов",
"Cancel": "Отменить",
- "Cancelled": "Отменен"
+ "Cancelled": "Отменен",
+ "NewRequest": "Новый запрос",
+ "CancelRequest": "Отмена запроса"
}
}
\ No newline at end of file
diff --git a/plugins/request-assets/lang/zh.json b/plugins/request-assets/lang/zh.json
index a6822f649b..c38c3d8c9f 100644
--- a/plugins/request-assets/lang/zh.json
+++ b/plugins/request-assets/lang/zh.json
@@ -18,6 +18,8 @@
"PleaseTypeMessage": "请键入评论消息以继续...",
"NoRequests": "没有请求",
"Cancel": "取消",
- "Cancelled": "已取消"
+ "Cancelled": "已取消",
+ "NewRequest": "新请求",
+ "CancelRequest": "取消请求"
}
}
diff --git a/plugins/request-resources/src/components/RequestedChangedNotification.svelte b/plugins/request-resources/src/components/RequestedChangedNotification.svelte
new file mode 100644
index 0000000000..99e4c45da5
--- /dev/null
+++ b/plugins/request-resources/src/components/RequestedChangedNotification.svelte
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+ {#if isAddedMe}
+
+ {:else if isRemovedMe}
+
+ {:else}
+
+ {/if}
+
+
+
+ :
+
+
+
+
+
+
+
+
diff --git a/plugins/request-resources/src/index.ts b/plugins/request-resources/src/index.ts
index c3d29a048d..96cace24e3 100644
--- a/plugins/request-resources/src/index.ts
+++ b/plugins/request-resources/src/index.ts
@@ -18,6 +18,7 @@ import EditRequest from './components/EditRequest.svelte'
import RequestPresenter from './components/RequestPresenter.svelte'
import RequestView from './components/RequestView.svelte'
import NotificationRequestView from './components/NotificationRequestView.svelte'
+import RequestedChangedNotification from './components/RequestedChangedNotification.svelte'
export { default as RequestStatusPresenter } from './components/RequestStatusPresenter.svelte'
export { default as RequestDetailPopup } from './components/RequestDetailPopup.svelte'
@@ -27,6 +28,7 @@ export default async (): Promise => ({
EditRequest,
RequestPresenter,
RequestView,
- NotificationRequestView
+ NotificationRequestView,
+ RequestedChangedNotification
}
})
diff --git a/server-plugins/request-resources/src/index.ts b/server-plugins/request-resources/src/index.ts
index 50df2bac83..253d5e36b5 100644
--- a/server-plugins/request-resources/src/index.ts
+++ b/server-plugins/request-resources/src/index.ts
@@ -14,8 +14,20 @@
//
import { DocUpdateMessage } from '@hcengineering/activity'
-import core, { Doc, Tx, TxCUD, TxCreateDoc, TxProcessor, TxUpdateDoc, type MeasureContext } from '@hcengineering/core'
-import notification from '@hcengineering/notification'
+import core, {
+ Doc,
+ Tx,
+ TxCUD,
+ TxCreateDoc,
+ TxProcessor,
+ TxUpdateDoc,
+ type MeasureContext,
+ Ref,
+ PersonId,
+ AccountUuid,
+ combineAttributes
+} from '@hcengineering/core'
+import notification, { NotificationType } from '@hcengineering/notification'
import { getResource, translate } from '@hcengineering/platform'
import request, { Request, RequestStatus } from '@hcengineering/request'
import { pushDocUpdateMessages } from '@hcengineering/server-activity-resources'
@@ -28,6 +40,7 @@ import {
getSenderInfo,
getTextPresenter
} from '@hcengineering/server-notification-resources'
+import { Person } from '@hcengineering/contact'
/**
* @public
@@ -191,10 +204,54 @@ export async function requestTextPresenter (doc: Doc, control: TriggerControl):
return title
}
+export const sendRequestMatch = (
+ tx: TxCreateDoc | TxUpdateDoc,
+ doc: Doc,
+ person: Ref,
+ socialIds: PersonId[],
+ type: NotificationType,
+ control: TriggerControl,
+ account: AccountUuid
+): boolean => {
+ if (tx._class === core.class.TxCreateDoc) {
+ const createTx = tx as TxCreateDoc
+ const request = TxProcessor.createDoc2Doc(createTx)
+
+ return request.requested.includes(person)
+ } else if (tx._class === core.class.TxUpdateDoc) {
+ const updateTx = tx as TxUpdateDoc
+ const pushed: Ref[] = combineAttributes([updateTx.operations], 'requested', '$push', '$each') ?? []
+
+ return pushed.includes(person)
+ }
+
+ return false
+}
+
+export const removeRequestMatch = (
+ tx: TxUpdateDoc,
+ doc: Doc,
+ person: Ref,
+ socialIds: PersonId[],
+ type: NotificationType,
+ control: TriggerControl,
+ account: AccountUuid
+): boolean => {
+ if (tx._class === core.class.TxUpdateDoc) {
+ const removed: Ref[] = combineAttributes([tx.operations], 'requested', '$pull', '$in') ?? []
+
+ return removed.includes(person)
+ }
+
+ return false
+}
+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default async () => ({
function: {
- RequestTextPresenter: requestTextPresenter
+ RequestTextPresenter: requestTextPresenter,
+ SendRequestMatch: sendRequestMatch,
+ RemoveRequestMatch: removeRequestMatch
},
trigger: {
OnRequest
diff --git a/server-plugins/request/src/index.ts b/server-plugins/request/src/index.ts
index c575c5b2cc..8be79093a2 100644
--- a/server-plugins/request/src/index.ts
+++ b/server-plugins/request/src/index.ts
@@ -15,7 +15,7 @@
import { Plugin, plugin, Resource } from '@hcengineering/platform'
import type { TriggerFunc } from '@hcengineering/server-core'
-import { Presenter } from '@hcengineering/server-notification'
+import { Presenter, TypeMatchFunc } from '@hcengineering/server-notification'
/**
* @public
@@ -27,7 +27,9 @@ export const serverRequestId = 'server-request' as Plugin
*/
export default plugin(serverRequestId, {
function: {
- RequestTextPresenter: '' as Resource
+ RequestTextPresenter: '' as Resource,
+ SendRequestMatch: '' as TypeMatchFunc,
+ RemoveRequestMatch: '' as TypeMatchFunc
},
trigger: {
OnRequest: '' as Resource