@things-factory/announcement 10.1.270 → 10.1.272

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/announcement",
3
- "version": "10.1.270",
3
+ "version": "10.1.272",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -36,18 +36,18 @@
36
36
  "@operato/shell": "^10.29.69",
37
37
  "@operato/styles": "^10.29.1",
38
38
  "@operato/utils": "^10.0.0",
39
- "@things-factory/ai-assistant": "^10.1.270",
40
- "@things-factory/attachment-base": "^10.1.270",
41
- "@things-factory/auth-base": "^10.1.270",
39
+ "@things-factory/ai-assistant": "^10.1.272",
40
+ "@things-factory/attachment-base": "^10.1.271",
41
+ "@things-factory/auth-base": "^10.1.271",
42
42
  "@things-factory/env": "^10.1.149",
43
- "@things-factory/i18n-base": "^10.1.270",
44
- "@things-factory/notification": "^10.1.270",
45
- "@things-factory/organization": "^10.1.270",
43
+ "@things-factory/i18n-base": "^10.1.271",
44
+ "@things-factory/notification": "^10.1.272",
45
+ "@things-factory/organization": "^10.1.272",
46
46
  "@things-factory/shell": "^10.1.270",
47
47
  "graphql-scalars": "^1.22.0",
48
48
  "graphql-tag": "^2.12.6",
49
49
  "graphql-upload": "^15.0.2",
50
50
  "lit": "^3.1.2"
51
51
  },
52
- "gitHead": "9fb23e57702302f1a6c6572d9f0f37ef6f12b446"
52
+ "gitHead": "f87fefe0687eedf52a25cda1c54d59efabaf3dc2"
53
53
  }
@@ -19,6 +19,7 @@ import { Announcement, AnnouncementAudience, AnnouncementImportance, Announcemen
19
19
  import { inputRefusal, isCurrent, owedReminder, periodOf, popupDue, publishedStatusOf, publishRefusal, rankOf, readerNarrowingOf, readerStateOf } from './announcement-rules'
20
20
  import {
21
21
  alignRoster,
22
+ announcementNoticeKey,
22
23
  ANNOUNCEMENT_REF_TYPE,
23
24
  audiencesOf,
24
25
  isWriter,
@@ -39,6 +40,7 @@ import {
39
40
  AnnouncementReceiptRow,
40
41
  AnnouncementSummary
41
42
  } from './announcement-types'
43
+ import { closeNotices } from '@things-factory/notification'
42
44
 
43
45
  const WRITE = '@privilege(category: "announcement", privilege: "mutation", domainOwnerGranted: true)'
44
46
 
@@ -247,6 +249,8 @@ export class AnnouncementResolver {
247
249
  if (!Object.keys(patch).length) return visible.announcement
248
250
  if (!receipt) await repository.save({ domain, announcement: { id }, user: { id: user.id }, listed: false, ...patch, creator: user, updater: user } as any)
249
251
  else await repository.update(receipt.id, { ...patch, updater: user })
252
+ /* Read: its notice is read too, on every device and screen (ADR-0164 amendment 1) - one reading, not two. */
253
+ if (patch.readAt) await closeNotices(tx, domain, 'announcement', announcementNoticeKey(id), [user.id])
250
254
  /* The reader's other windows - their badge asks again. */
251
255
  tellChange(context as any, { kind: 'announcement', id, userIds: [user.id] })
252
256
  return visible.announcement
@@ -147,6 +147,9 @@ async function receiversOf(userIds: string[], tx?: EntityManager) {
147
147
  return people.filter(one => one.status === UserStatus.ACTIVATED).map(one => ({ id: one.id, email: one.email, locale: (one as any).locale }))
148
148
  }
149
149
 
150
+ /** What an announcement's notices tell of - a reader's are closed once they read it. */
151
+ export const announcementNoticeKey = (id: string) => `announcement:${id}`
152
+
150
153
  /**
151
154
  * The notice of an announcement (notification ADR-0164): in the app and by web push always - the `announcement` type is
152
155
  * what pops it up - and by mail when the announcement asks for it and the domain has mail on.
@@ -159,6 +162,8 @@ function noticeOf(one: Announcement, kind: NoticeKind, receivers: Notice['receiv
159
162
  words: lng => noticeWordsOf(one, kind, sayIn(lng)),
160
163
  address: viewAddressOf(one.id),
161
164
  link,
165
+ /* closed for a person once they read it (`readAnnouncement`) */
166
+ key: announcementNoticeKey(one.id),
162
167
  label: `announcement ${kind} ${one.id}`,
163
168
  /* The mail carries the whole body, drawn from its Markdown; the inbox and push show the summary. */
164
169
  format: 'markdown',
@@ -16,6 +16,9 @@ const { DataSource } = require('typeorm')
16
16
  const told: { domain: any; notice: any }[] = []
17
17
  jest.mock('@things-factory/notification', () => ({
18
18
  ...jest.requireActual('@things-factory/notification/dist-server/controllers/notice/notice-delivery-record.js'),
19
+ /* a reader's notice is closed as they read (ADR-0164 amendment 1) - the real closing, on the kept notices */
20
+ closeNotices: jest.requireActual('@things-factory/notification/dist-server/service/notification/notice-service.js').closeNotices,
21
+ Notification: jest.requireActual('@things-factory/notification/dist-server/service/notification/notification.js').Notification,
19
22
  sendNotice: async (domain: any, notice: any) => {
20
23
  told.push({ domain, notice })
21
24
  return { receivers: notice.receivers.length, email: { sent: notice.channels?.email ? notice.receivers.length : 0, failed: 0 }, teams: { sent: 0, failed: 0 } }
@@ -26,6 +29,7 @@ jest.mock('@things-factory/notification', () => ({
26
29
 
27
30
  const shell = require('@things-factory/shell')
28
31
  const authBase = require('@things-factory/auth-base')
32
+ const notification = require('@things-factory/notification')
29
33
  const contact = require('@things-factory/contact')
30
34
  const bizBase = require('@things-factory/biz-base')
31
35
  const attachmentBase = require('@things-factory/attachment-base')
@@ -55,7 +59,7 @@ beforeAll(async () => {
55
59
  synchronize: true,
56
60
  dropSchema: true,
57
61
  namingStrategy: new shell.NamingStrategy(),
58
- entities: [...shell.entities, ...authBase.entities, ...bizBase.entities, ...contact.entities, ...organization.entities, ...attachmentBase.entities, Announcement, AnnouncementAudience, AnnouncementReceipt, AnnouncementRevision],
62
+ entities: [...shell.entities, ...authBase.entities, ...bizBase.entities, ...contact.entities, ...organization.entities, ...attachmentBase.entities, Announcement, AnnouncementAudience, AnnouncementReceipt, AnnouncementRevision, notification.Notification],
59
63
  logging: false
60
64
  })
61
65
  await dataSource.initialize()