@things-factory/announcement 10.1.265 → 10.1.269

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.
@@ -205,10 +205,14 @@ let AnnouncementResolver = class AnnouncementResolver {
205
205
  patch.readAt = now;
206
206
  if (acknowledge && !receipt?.acknowledgedAt)
207
207
  patch.acknowledgedAt = now;
208
+ if (!Object.keys(patch).length)
209
+ return visible.announcement;
208
210
  if (!receipt)
209
211
  await repository.save({ domain, announcement: { id }, user: { id: user.id }, listed: false, ...patch, creator: user, updater: user });
210
- else if (Object.keys(patch).length)
212
+ else
211
213
  await repository.update(receipt.id, { ...patch, updater: user });
214
+ /* The reader's other windows - their badge asks again. */
215
+ (0, shell_1.tellChange)(context, { kind: 'announcement', id, userIds: [user.id] });
212
216
  return visible.announcement;
213
217
  }
214
218
  /* ---------------------------------------------------------------- writing and managing */
@@ -306,6 +310,7 @@ let AnnouncementResolver = class AnnouncementResolver {
306
310
  await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt, tx).update({ announcement: { id }, listed: true }, { notifiedAt: new Date() });
307
311
  /* Told again, everyone hears it - the channel too; people the audience newly names are told one by one. */
308
312
  await (0, announcement_service_1.tellWhenCommitted)(context, fresh, notifyAgain ? 'changed' : 'published', receivers.filter(one => one !== user.id), !!notifyAgain);
313
+ await (0, announcement_service_1.tellRosterChange)(context, id, tx);
309
314
  return fresh;
310
315
  }
311
316
  async publishAnnouncement(id, context) {
@@ -323,6 +328,7 @@ let AnnouncementResolver = class AnnouncementResolver {
323
328
  const receivers = await (0, announcement_service_1.sendOut)(announcement, domain, user, tx);
324
329
  const fresh = (await repository.findOneBy({ id }));
325
330
  await (0, announcement_service_1.tellWhenCommitted)(context, fresh, 'published', receivers, true);
331
+ await (0, announcement_service_1.tellRosterChange)(context, id, tx);
326
332
  return fresh;
327
333
  }
328
334
  async withdrawAnnouncement(id, reason, context) {
@@ -334,6 +340,7 @@ let AnnouncementResolver = class AnnouncementResolver {
334
340
  refuse(context, 'no-reason', 'say why it is withdrawn.');
335
341
  const repository = (0, shell_1.getRepository)(announcement_1.Announcement, tx);
336
342
  await repository.update(id, { status: announcement_1.AnnouncementStatus.WITHDRAWN, withdrawnAt: new Date(), withdrawReason: reason.trim().slice(0, 500), updater: user });
343
+ await (0, announcement_service_1.tellRosterChange)(context, id, tx);
337
344
  return (await repository.findOneBy({ id }));
338
345
  }
339
346
  async deleteAnnouncement(id, context) {
@@ -1 +1 @@
1
- {"version":3,"file":"announcement-resolver.js","sourceRoot":"","sources":["../../../server/service/announcement/announcement-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The doors of announcements (ADR-0163 decisions 2-5).\n *\n * Reading is not a privilege: an announcement is read by the people it names, so the reader's doors are open to anyone\n * signed in to the domain and each asks the audience itself (announcement-service.ts). Writing, managing and the\n * reading record of others are `announcement:mutation` - the module's task `announcement.writing`.\n */\nimport type { FileUpload } from 'graphql-upload/GraphQLUpload.js'\nimport GraphQLUpload from 'graphql-upload/GraphQLUpload.js'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Int, Mutation, Query, Resolver, Root } from 'type-graphql'\nimport { In, IsNull, MoreThan, Not } from 'typeorm'\n\nimport { Attachment, createAttachment, deleteAttachment, deleteAttachmentsByRef } from '@things-factory/attachment-base'\nimport { getDomainAssignees, User } from '@things-factory/auth-base'\nimport { audienceTargetRefusal, audienceUserIds, Department, departmentTreeOf, domainRolesOf } from '@things-factory/organization'\nimport { getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { Announcement, AnnouncementAudience, AnnouncementImportance, AnnouncementReceipt, AnnouncementRevision, AnnouncementStatus } from './announcement'\nimport { inputRefusal, isCurrent, owedReminder, periodOf, popupDue, publishedStatusOf, publishRefusal, rankOf, readerNarrowingOf, readerStateOf } from './announcement-rules'\nimport {\n alignRoster,\n ANNOUNCEMENT_REF_TYPE,\n audiencesOf,\n isWriter,\n keepRevision,\n memberOf,\n reachingIds,\n sendOut,\n tellWhenCommitted,\n visibleAnnouncement\n} from './announcement-service'\nimport {\n AnnouncementAudienceChoices,\n AnnouncementAudienceInput,\n AnnouncementChoice,\n AnnouncementInput,\n AnnouncementList,\n AnnouncementReceiptRow,\n AnnouncementSummary\n} from './announcement-types'\n\nconst WRITE = '@privilege(category: \"announcement\", privilege: \"mutation\", domainOwnerGranted: true)'\n\n/** A refusal said in the reader's words, with a code the screen may read. */\nfunction refuse(context: ResolverContext, code: string, fallback: string): never {\n const message = context.t ? String(context.t(`announcement.refusal.${code}`, { defaultValue: fallback })) : fallback\n const error: any = new Error(message)\n error.extensions = { code: `announcement.${code}` }\n throw error\n}\n\nconst NOT_FOUND = 'there is no such announcement.'\n\n/** The announcement the request may see, refused otherwise. */\nasync function visibleOrRefuse(id: string, context: ResolverContext, tx?: any) {\n const visible = await visibleAnnouncement(id, context, tx)\n if (!visible) refuse(context, 'unknown-announcement', NOT_FOUND)\n return visible\n}\n\n/** One the writer may change: any that is not somebody else's draft, and not withdrawn. */\nasync function changeable(id: string, context: ResolverContext, tx: any): Promise<Announcement> {\n const visible = await visibleOrRefuse(id, context, tx)\n if (!visible.writer) refuse(context, 'unknown-announcement', NOT_FOUND)\n if (visible.announcement.status === AnnouncementStatus.WITHDRAWN) refuse(context, 'withdrawn', 'a withdrawn announcement is not changed.')\n return visible.announcement\n}\n\n/** The fields of the input as stored, checked against the rules. */\nfunction fieldsOf(input: AnnouncementInput, context: ResolverContext) {\n const refusal = inputRefusal(input)\n if (refusal) refuse(context, refusal, `the announcement cannot be kept (${refusal}).`)\n const importance = (input.importance as AnnouncementImportance) || AnnouncementImportance.NORMAL\n const pinned = !!input.pinned\n return {\n title: input.title.trim(),\n body: input.body ?? null,\n category: input.category || 'GENERAL',\n importance,\n startsAt: input.startsAt ?? null,\n endsAt: input.endsAt ?? null,\n pinned,\n rank: rankOf({ pinned, importance }),\n requiresAcknowledgement: !!input.requiresAcknowledgement,\n acknowledgeBy: input.requiresAcknowledgement ? (input.acknowledgeBy ?? null) : null,\n popup: !!input.popup,\n sendEmail: !!input.sendEmail,\n links: (input.links ?? []).map(({ label, url }) => ({ label: label.trim(), url: url.trim() }))\n }\n}\n\n/** Sets the whole audience - each target checked against the domain - and answers whether it changed. */\nasync function setAudiences(announcement: Announcement, wanted: AnnouncementAudienceInput[], context: ResolverContext, tx: any): Promise<boolean> {\n const { domain, user } = context.state\n const scopes = new Set(wanted.map(one => one.scope))\n const departmentIds = scopes.has('DEPARTMENT') ? [...(await departmentTreeOf(domain, tx)).keys()] : []\n const roleIds = scopes.has('ROLE') ? (await domainRolesOf(domain, undefined, tx)).map(one => one.id) : []\n const people = scopes.has('USER') ? new Set((await getDomainAssignees(domain as any, tx)).map(one => one.id)) : new Set<string>()\n const byKey = new Map<string, AnnouncementAudienceInput>()\n for (const target of wanted) {\n const refusal = audienceTargetRefusal(target, { domainId: domain.id, departmentIds, roleIds }) ?? (target.scope === 'USER' && !people.has(target.targetId) ? 'unknown-person' : undefined)\n if (refusal) refuse(context, `audience-${refusal}`, `this target cannot be given (${refusal}).`)\n byKey.set(`${target.scope}:${target.targetId}`, target)\n }\n const repository = getRepository(AnnouncementAudience, tx)\n const current = await audiencesOf(announcement.id, tx)\n const gone = current.filter(one => !byKey.has(`${one.scope}:${one.targetId}`))\n if (gone.length) await repository.softRemove(gone)\n let added = 0\n for (const [key, target] of byKey) {\n if (current.some(one => `${one.scope}:${one.targetId}` === key)) continue\n added++\n await repository.save({ domain, announcement: { id: announcement.id }, scope: target.scope, targetId: target.targetId, targetName: target.targetName?.slice(0, 100), creator: user, updater: user } as any)\n }\n return gone.length + added > 0\n}\n\nasync function attachFiles(announcementId: string, attach: FileUpload[] | undefined, remove: string[] | undefined, context: ResolverContext) {\n for (const id of remove ?? []) {\n const file = await getRepository(Attachment, context.state.tx).findOne({ where: { id, domain: { id: context.state.domain.id }, refType: ANNOUNCEMENT_REF_TYPE, refBy: announcementId } as any })\n if (file) await deleteAttachment(null, { id }, context)\n }\n for (const file of attach ?? []) {\n await createAttachment(null, { attachment: { file, refType: ANNOUNCEMENT_REF_TYPE, refBy: announcementId } } as any, context)\n }\n}\n\n/** The reader's own receipts of `ids`, by announcement. */\nasync function myReceipts(ids: string[], userId: string, tx?: any): Promise<Map<string, AnnouncementReceipt>> {\n if (!ids.length) return new Map()\n const rows = await getRepository(AnnouncementReceipt, tx).find({ where: { announcement: { id: In(ids) }, user: { id: userId } } as any })\n return new Map(rows.map(one => [one.announcementId!, one]))\n}\n\n/** The current announcements addressed to the request's person, with their receipts. */\nasync function currentForReader(context: ResolverContext) {\n const { domain, user } = context.state\n const ids = await reachingIds(await memberOf(context))\n if (!ids.length) return { items: [] as Announcement[], receipts: new Map<string, AnnouncementReceipt>() }\n const now = new Date()\n const items = await getRepository(Announcement).find({\n where: [\n { id: In(ids), domain: { id: domain.id }, status: AnnouncementStatus.PUBLISHED, endsAt: IsNull() },\n { id: In(ids), domain: { id: domain.id }, status: AnnouncementStatus.PUBLISHED, endsAt: MoreThan(now) }\n ] as any,\n order: { rank: 'ASC', publishedAt: 'DESC' } as any\n })\n return { items, receipts: await myReceipts(items.map(one => one.id), user.id) }\n}\n\n@Resolver(Announcement)\nexport class AnnouncementResolver {\n /* ---------------------------------------------------------------- reading - the audience */\n\n @Query(returns => AnnouncementList, {\n description:\n \"The announcements addressed to the request's person that are out. Two filters are the reader's own: `period` (current | past) and `readerState` (unread, read, to-acknowledge, acknowledged - one or several, with `in`). The current ones come pinned, urgent and important first; otherwise the newest first.\"\n })\n async announcements(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AnnouncementList> {\n const { domain, user } = context.state\n const { rest, period, states, refusal } = readerNarrowingOf(params.filters as any)\n if (refusal) refuse(context, refusal, `the list cannot be narrowed so (${refusal}).`)\n let ids = await reachingIds(await memberOf(context))\n if (states && ids.length) {\n const candidates = await getRepository(Announcement).find({ where: { id: In(ids), status: AnnouncementStatus.PUBLISHED } as any })\n const receipts = await myReceipts(\n candidates.map(one => one.id),\n user.id\n )\n ids = candidates.filter(one => states.includes(readerStateOf(one, receipts.get(one.id)))).map(one => one.id)\n }\n if (!ids.length) return { items: [], total: 0 }\n const now = new Date()\n const qb = getQueryBuilderFromListParams({\n domain,\n params: { ...params, filters: rest as any, sortings: [] },\n repository: getRepository(Announcement),\n alias: 'A',\n searchables: ['title', 'body', 'category']\n })\n .andWhere('A.id IN (:...ids)', { ids })\n .andWhere('A.status = :published', { published: AnnouncementStatus.PUBLISHED })\n if (period === 'past') qb.andWhere('A.endsAt <= :now', { now })\n if (period === 'current') qb.andWhere('(A.endsAt IS NULL OR A.endsAt > :now)', { now }).orderBy('A.rank', 'ASC').addOrderBy('A.publishedAt', 'DESC')\n else qb.orderBy('A.publishedAt', 'DESC')\n const [items, total] = await qb.getManyAndCount()\n const receipts = await myReceipts(\n items.map(one => one.id),\n user.id\n )\n for (const one of items) (one as any).__mine = receipts.get(one.id) ?? null\n return { items, total }\n }\n\n @Query(returns => Announcement, { nullable: true, description: 'One announcement - to its audience once it is out, to a writer whatever its status (not somebody else\\'s draft).' })\n async announcement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement | undefined> {\n return (await visibleAnnouncement(id, context))?.announcement\n }\n\n @Query(returns => AnnouncementSummary, { description: 'How many current announcements addressed to the person are unread, and how many await their acknowledgement.' })\n async announcementSummary(@Ctx() context: ResolverContext): Promise<AnnouncementSummary> {\n const { items, receipts } = await currentForReader(context)\n let unread = 0\n let toAcknowledge = 0\n let pending = 0\n for (const one of items) {\n const state = readerStateOf(one, receipts.get(one.id))\n if (state === 'unread') unread++\n if (one.requiresAcknowledgement && state !== 'acknowledged') toAcknowledge++\n if (state === 'unread' || state === 'to-acknowledge') pending++\n }\n return { unread, toAcknowledge, pending }\n }\n\n @Query(returns => [Announcement], { description: 'The announcements that pop up for the person now - unread popup ones, and those still to be acknowledged.' })\n async announcementPopups(@Ctx() context: ResolverContext): Promise<Announcement[]> {\n const { items, receipts } = await currentForReader(context)\n const now = new Date()\n return items.filter(one => popupDue(one, receipts.get(one.id), now)).map(one => Object.assign(one, { __mine: receipts.get(one.id) ?? null }))\n }\n\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Records that the person read the announcement - once; reading it again changes nothing.' })\n async readAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n return await this.receive(id, context, false)\n }\n\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Records that the person acknowledged an announcement that asks for it - reading it too.' })\n async acknowledgeAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n return await this.receive(id, context, true)\n }\n\n private async receive(id: string, context: ResolverContext, acknowledge: boolean): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const visible = await visibleOrRefuse(id, context, tx)\n /* Only its audience reads it into the record - a writer looking at one addressed to others leaves no trace. */\n if (!visible.reader) return visible.announcement\n if (acknowledge && !visible.announcement.requiresAcknowledgement) refuse(context, 'no-acknowledgement', 'this announcement does not ask to be acknowledged.')\n const repository = getRepository(AnnouncementReceipt, tx)\n const now = new Date()\n const receipt = await repository.findOne({ where: { announcement: { id }, user: { id: user.id } } as any })\n const patch: any = {}\n if (!receipt?.readAt) patch.readAt = now\n if (acknowledge && !receipt?.acknowledgedAt) patch.acknowledgedAt = now\n if (!receipt) await repository.save({ domain, announcement: { id }, user: { id: user.id }, listed: false, ...patch, creator: user, updater: user } as any)\n else if (Object.keys(patch).length) await repository.update(receipt.id, { ...patch, updater: user })\n return visible.announcement\n }\n\n /* ---------------------------------------------------------------- writing and managing */\n\n @Directive(WRITE)\n @Query(returns => AnnouncementList, { description: \"Every announcement of the domain for its writers - all that are out, scheduled or withdrawn, and the writer's own drafts.\" })\n async managedAnnouncements(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AnnouncementList> {\n const { domain, user } = context.state\n const qb = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(Announcement),\n alias: 'A',\n searchables: ['title', 'body', 'category']\n }).andWhere('(A.status != :draft OR A.creator = :me)', { draft: AnnouncementStatus.DRAFT, me: user.id })\n if (!params.sortings?.length) qb.orderBy('A.updatedAt', 'DESC')\n const [items, total] = await qb.getManyAndCount()\n return { items, total }\n }\n\n @Directive(WRITE)\n @Query(returns => [AnnouncementReceiptRow], { description: 'Who on the roster read and acknowledged it, and who came to it later - for its writers.' })\n async announcementReceipts(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<AnnouncementReceiptRow[]> {\n const visible = await visibleOrRefuse(id, context)\n if (!visible.writer) refuse(context, 'unknown-announcement', NOT_FOUND)\n const receipts = await getRepository(AnnouncementReceipt).find({ where: { announcement: { id } } as any, relations: ['user'] })\n return receipts\n .map(one => ({\n userId: one.userId!,\n name: one.user?.name,\n email: one.user?.email,\n listed: one.listed,\n notifiedAt: one.notifiedAt,\n readAt: one.readAt,\n acknowledgedAt: one.acknowledgedAt\n }))\n .sort((a, b) => Number(!!a.readAt) - Number(!!b.readAt) || String(a.name ?? '').localeCompare(String(b.name ?? '')))\n }\n\n @Directive(WRITE)\n @Query(returns => [AnnouncementRevision], { description: 'The versions of an announcement since it went out, newest first - for its writers.' })\n async announcementRevisions(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<AnnouncementRevision[]> {\n const visible = await visibleOrRefuse(id, context)\n if (!visible.writer) refuse(context, 'unknown-announcement', NOT_FOUND)\n return await getRepository(AnnouncementRevision).find({ where: { announcement: { id } } as any, order: { version: 'DESC' } as any, relations: ['creator'] })\n }\n\n @Directive(WRITE)\n @Query(returns => AnnouncementAudienceChoices, { description: 'What an announcement may be addressed to - the domain, its departments and its roles.' })\n async announcementAudienceChoices(@Ctx() context: ResolverContext): Promise<AnnouncementAudienceChoices> {\n const domain: any = context.state.domain\n const tree = await departmentTreeOf(domain)\n const departments = tree.size ? await getRepository(Department).find({ where: { id: In([...tree.keys()]) } as any, order: { name: 'ASC' } as any }) : []\n const nameOf = new Map(departments.map(one => [one.id, one.name]))\n return {\n domainId: domain.id,\n domainName: domain.name ?? domain.subdomain ?? domain.id,\n departments: departments.map(one => ({ id: one.id, name: one.name, note: nameOf.get(tree.get(one.id) ?? '') ?? undefined })),\n roles: (await domainRolesOf(domain)).map(one => ({ id: one.id, name: one.name, note: one.description ?? undefined }))\n }\n }\n\n @Directive(WRITE)\n @Query(returns => [AnnouncementChoice], { description: 'People of the domain an announcement may be addressed to, found by name or e-mail.' })\n async announcementPeople(@Arg('text') text: string, @Ctx() context: ResolverContext): Promise<AnnouncementChoice[]> {\n const words = (text ?? '').trim().toLowerCase()\n if (!words) return []\n return (await getDomainAssignees(context.state.domain as any))\n .filter(one => `${one.name ?? ''} ${one.email ?? ''}`.toLowerCase().includes(words))\n .slice(0, 20)\n .map(one => ({ id: one.id, name: one.name || one.email, note: one.email }))\n }\n\n @Directive(WRITE)\n @Query(returns => Int, { description: 'How many people an audience names now - shown before it is sent.' })\n async announcementAudienceSize(@Arg('audiences', type => [AnnouncementAudienceInput]) audiences: AnnouncementAudienceInput[], @Ctx() context: ResolverContext): Promise<number> {\n return (await audienceUserIds(context.state.domain, audiences ?? [])).length\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Writes a new announcement as a draft, with its files.' })\n async createAnnouncement(\n @Arg('input', type => AnnouncementInput) input: AnnouncementInput,\n @Arg('attach', type => [GraphQLUpload], { nullable: true }) attach: FileUpload[],\n @Ctx() context: ResolverContext\n ): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const saved = await getRepository(Announcement, tx).save({ ...fieldsOf(input, context), domain, status: AnnouncementStatus.DRAFT, version: 1, creator: user, updater: user } as any)\n await setAudiences(saved, input.audiences ?? [], context, tx)\n await attachFiles(saved.id, attach, [], context)\n return saved\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, {\n description:\n 'Changes an announcement. Once out, each change is a new version; people the audience now names who were not told are told, and `notifyAgain` tells everyone on the roster again.'\n })\n async updateAnnouncement(\n @Arg('id') id: string,\n @Arg('input', type => AnnouncementInput) input: AnnouncementInput,\n @Arg('attach', type => [GraphQLUpload], { nullable: true }) attach: FileUpload[],\n @Arg('remove', type => [String], { nullable: true, description: 'Ids of its files to take off.' }) remove: string[],\n @Arg('notifyAgain', { nullable: true, description: 'Tell everyone on the roster of the change.' }) notifyAgain: boolean,\n @Ctx() context: ResolverContext\n ): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n const fields = fieldsOf(input, context)\n const out = announcement.status === AnnouncementStatus.PUBLISHED\n /* Once out, its start is the moment it went out - a start set later would hide it again. */\n if (out) fields.startsAt = announcement.startsAt\n const repository = getRepository(Announcement, tx)\n await repository.update(id, { ...fields, ...(out ? { version: announcement.version + 1 } : {}), updater: user } as any)\n const audienceChanged = await setAudiences(announcement, input.audiences ?? [], context, tx)\n if (out && !(input.audiences ?? []).length) refuse(context, 'no-audience', 'an announcement that is out names someone.')\n await attachFiles(id, attach, remove, context)\n const fresh = (await repository.findOneBy({ id }))!\n if (!out) return fresh\n await keepRevision(fresh, domain, user, tx)\n const added = audienceChanged ? await alignRoster(fresh, domain, user, tx) : []\n const receivers = notifyAgain\n ? (await getRepository(AnnouncementReceipt, tx).find({ where: { announcement: { id }, listed: true } as any })).map(one => one.userId!)\n : added\n if (notifyAgain) await getRepository(AnnouncementReceipt, tx).update({ announcement: { id }, listed: true } as any, { notifiedAt: new Date() } as any)\n /* Told again, everyone hears it - the channel too; people the audience newly names are told one by one. */\n await tellWhenCommitted(context, fresh, notifyAgain ? 'changed' : 'published', receivers.filter(one => one !== user.id), !!notifyAgain)\n return fresh\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Sends a draft out to its audience - at once, or at its start when that is still to come.' })\n async publishAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n const audiences = await audiencesOf(id, tx)\n const refusal = publishRefusal(announcement.status, announcement, audiences.length)\n if (refusal) refuse(context, refusal, `the announcement cannot go out (${refusal}).`)\n const repository = getRepository(Announcement, tx)\n if (publishedStatusOf(announcement.startsAt) === 'SCHEDULED') {\n await repository.update(id, { status: AnnouncementStatus.SCHEDULED, publisher: user, updater: user } as any)\n return (await repository.findOneBy({ id }))!\n }\n const receivers = await sendOut(announcement, domain, user, tx)\n const fresh = (await repository.findOneBy({ id }))!\n await tellWhenCommitted(context, fresh, 'published', receivers, true)\n return fresh\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Takes back an announcement that is out or scheduled, with the reason. Its audience no longer sees it; its record stays.' })\n async withdrawAnnouncement(@Arg('id') id: string, @Arg('reason') reason: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n const { user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n if (announcement.status === AnnouncementStatus.DRAFT) refuse(context, 'not-out', 'a draft is deleted, not withdrawn.')\n if (!reason?.trim()) refuse(context, 'no-reason', 'say why it is withdrawn.')\n const repository = getRepository(Announcement, tx)\n await repository.update(id, { status: AnnouncementStatus.WITHDRAWN, withdrawnAt: new Date(), withdrawReason: reason.trim().slice(0, 500), updater: user } as any)\n return (await repository.findOneBy({ id }))!\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: \"Deletes one's own draft and its files. An announcement that went out is withdrawn instead.\" })\n async deleteAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n if (announcement.status !== AnnouncementStatus.DRAFT) refuse(context, 'not-a-draft', 'an announcement that went out is withdrawn, not deleted.')\n await deleteAttachmentsByRef(null, { refBys: [id], refType: ANNOUNCEMENT_REF_TYPE }, context)\n await getRepository(Announcement, tx).softDelete(id)\n return true\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Int, { description: 'Tells again those on the roster who have not read it - or not acknowledged it, when it asks for that. Answers how many were told.' })\n async remindAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<number> {\n const { user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n if (!isCurrent(announcement)) refuse(context, 'not-current', 'only a current announcement is reminded.')\n const repository = getRepository(AnnouncementReceipt, tx)\n const owed = (await repository.find({ where: { announcement: { id } } as any })).filter(one => owedReminder(announcement, one))\n if (owed.length) await repository.update({ id: In(owed.map(one => one.id)) } as any, { notifiedAt: new Date(), updater: user } as any)\n await tellWhenCommitted(\n context,\n announcement,\n 'reminder',\n owed.map(one => one.userId!)\n )\n return owed.length\n }\n\n /* ---------------------------------------------------------------- fields */\n\n @FieldResolver(type => [AnnouncementAudience], { description: 'Whom it is addressed to.' })\n async audiences(@Root() one: Announcement): Promise<AnnouncementAudience[]> {\n return await audiencesOf(one.id)\n }\n\n @FieldResolver(type => [Attachment], { description: 'Its files.' })\n async attachments(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<Attachment[]> {\n return await getRepository(Attachment).find({ where: { domain: { id: context.state.domain.id }, refType: ANNOUNCEMENT_REF_TYPE, refBy: one.id } as any, order: { createdAt: 'ASC' } as any })\n }\n\n @FieldResolver(type => AnnouncementReceipt, { nullable: true, description: \"The request's person's own reading of it.\" })\n async mine(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<AnnouncementReceipt | null> {\n if ('__mine' in (one as any)) return (one as any).__mine\n return (await myReceipts([one.id], context.state.user.id)).get(one.id) ?? null\n }\n\n @FieldResolver(type => Boolean, { description: \"Whether it is addressed to the request's person and out - the one who reads and acknowledges it.\" })\n async addressed(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<boolean> {\n return one.status === AnnouncementStatus.PUBLISHED && (await reachingIds(await memberOf(context))).includes(one.id)\n }\n\n @FieldResolver(type => String, { nullable: true, description: 'Whether it is still current or past - for one that is out.' })\n period(@Root() one: Announcement): string | undefined {\n return periodOf(one)\n }\n\n @FieldResolver(type => String, { description: \"Where it stands for the request's person: unread, read, to-acknowledge or acknowledged.\" })\n async readerState(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<string> {\n return readerStateOf(one, (await this.mine(one, context)) ?? undefined)\n }\n\n @FieldResolver(type => Int, { nullable: true, description: 'How many on the roster read it - for its writers.' })\n async readCount(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<number | null> {\n if (!(await isWriter(context))) return null\n return await getRepository(AnnouncementReceipt).count({ where: { announcement: { id: one.id }, listed: true, readAt: Not(IsNull()) } as any })\n }\n\n @FieldResolver(type => Int, { nullable: true, description: 'How many on the roster acknowledged it - for its writers.' })\n async acknowledgedCount(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<number | null> {\n if (!(await isWriter(context))) return null\n return await getRepository(AnnouncementReceipt).count({ where: { announcement: { id: one.id }, listed: true, acknowledgedAt: Not(IsNull()) } as any })\n }\n\n @FieldResolver(type => Boolean, { description: 'Whether the request may change it.' })\n async editable(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<boolean> {\n if (one.status === AnnouncementStatus.WITHDRAWN) return false\n if (one.status === AnnouncementStatus.DRAFT && one.creatorId !== context.state.user.id) return false\n return await isWriter(context)\n }\n\n @FieldResolver(type => User, { nullable: true, description: 'Who published it.' })\n async publisher(@Root() one: Announcement): Promise<User | null> {\n return one.publisherId ? await getRepository(User).findOneBy({ id: one.publisherId }) : null\n }\n\n @FieldResolver(type => User, { nullable: true, description: 'Who wrote it.' })\n async creator(@Root() one: Announcement): Promise<User | null> {\n return one.creatorId ? await getRepository(User).findOneBy({ id: one.creatorId }) : null\n }\n}\n"]}
1
+ {"version":3,"file":"announcement-resolver.js","sourceRoot":"","sources":["../../../server/service/announcement/announcement-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The doors of announcements (ADR-0163 decisions 2-5).\n *\n * Reading is not a privilege: an announcement is read by the people it names, so the reader's doors are open to anyone\n * signed in to the domain and each asks the audience itself (announcement-service.ts). Writing, managing and the\n * reading record of others are `announcement:mutation` - the module's task `announcement.writing`.\n */\nimport type { FileUpload } from 'graphql-upload/GraphQLUpload.js'\nimport GraphQLUpload from 'graphql-upload/GraphQLUpload.js'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Int, Mutation, Query, Resolver, Root } from 'type-graphql'\nimport { In, IsNull, MoreThan, Not } from 'typeorm'\n\nimport { Attachment, createAttachment, deleteAttachment, deleteAttachmentsByRef } from '@things-factory/attachment-base'\nimport { getDomainAssignees, User } from '@things-factory/auth-base'\nimport { audienceTargetRefusal, audienceUserIds, Department, departmentTreeOf, domainRolesOf } from '@things-factory/organization'\nimport { getQueryBuilderFromListParams, getRepository, ListParam, tellChange } from '@things-factory/shell'\n\nimport { Announcement, AnnouncementAudience, AnnouncementImportance, AnnouncementReceipt, AnnouncementRevision, AnnouncementStatus } from './announcement'\nimport { inputRefusal, isCurrent, owedReminder, periodOf, popupDue, publishedStatusOf, publishRefusal, rankOf, readerNarrowingOf, readerStateOf } from './announcement-rules'\nimport {\n alignRoster,\n ANNOUNCEMENT_REF_TYPE,\n audiencesOf,\n isWriter,\n keepRevision,\n memberOf,\n reachingIds,\n sendOut,\n tellRosterChange,\n tellWhenCommitted,\n visibleAnnouncement\n} from './announcement-service'\nimport {\n AnnouncementAudienceChoices,\n AnnouncementAudienceInput,\n AnnouncementChoice,\n AnnouncementInput,\n AnnouncementList,\n AnnouncementReceiptRow,\n AnnouncementSummary\n} from './announcement-types'\n\nconst WRITE = '@privilege(category: \"announcement\", privilege: \"mutation\", domainOwnerGranted: true)'\n\n/** A refusal said in the reader's words, with a code the screen may read. */\nfunction refuse(context: ResolverContext, code: string, fallback: string): never {\n const message = context.t ? String(context.t(`announcement.refusal.${code}`, { defaultValue: fallback })) : fallback\n const error: any = new Error(message)\n error.extensions = { code: `announcement.${code}` }\n throw error\n}\n\nconst NOT_FOUND = 'there is no such announcement.'\n\n/** The announcement the request may see, refused otherwise. */\nasync function visibleOrRefuse(id: string, context: ResolverContext, tx?: any) {\n const visible = await visibleAnnouncement(id, context, tx)\n if (!visible) refuse(context, 'unknown-announcement', NOT_FOUND)\n return visible\n}\n\n/** One the writer may change: any that is not somebody else's draft, and not withdrawn. */\nasync function changeable(id: string, context: ResolverContext, tx: any): Promise<Announcement> {\n const visible = await visibleOrRefuse(id, context, tx)\n if (!visible.writer) refuse(context, 'unknown-announcement', NOT_FOUND)\n if (visible.announcement.status === AnnouncementStatus.WITHDRAWN) refuse(context, 'withdrawn', 'a withdrawn announcement is not changed.')\n return visible.announcement\n}\n\n/** The fields of the input as stored, checked against the rules. */\nfunction fieldsOf(input: AnnouncementInput, context: ResolverContext) {\n const refusal = inputRefusal(input)\n if (refusal) refuse(context, refusal, `the announcement cannot be kept (${refusal}).`)\n const importance = (input.importance as AnnouncementImportance) || AnnouncementImportance.NORMAL\n const pinned = !!input.pinned\n return {\n title: input.title.trim(),\n body: input.body ?? null,\n category: input.category || 'GENERAL',\n importance,\n startsAt: input.startsAt ?? null,\n endsAt: input.endsAt ?? null,\n pinned,\n rank: rankOf({ pinned, importance }),\n requiresAcknowledgement: !!input.requiresAcknowledgement,\n acknowledgeBy: input.requiresAcknowledgement ? (input.acknowledgeBy ?? null) : null,\n popup: !!input.popup,\n sendEmail: !!input.sendEmail,\n links: (input.links ?? []).map(({ label, url }) => ({ label: label.trim(), url: url.trim() }))\n }\n}\n\n/** Sets the whole audience - each target checked against the domain - and answers whether it changed. */\nasync function setAudiences(announcement: Announcement, wanted: AnnouncementAudienceInput[], context: ResolverContext, tx: any): Promise<boolean> {\n const { domain, user } = context.state\n const scopes = new Set(wanted.map(one => one.scope))\n const departmentIds = scopes.has('DEPARTMENT') ? [...(await departmentTreeOf(domain, tx)).keys()] : []\n const roleIds = scopes.has('ROLE') ? (await domainRolesOf(domain, undefined, tx)).map(one => one.id) : []\n const people = scopes.has('USER') ? new Set((await getDomainAssignees(domain as any, tx)).map(one => one.id)) : new Set<string>()\n const byKey = new Map<string, AnnouncementAudienceInput>()\n for (const target of wanted) {\n const refusal = audienceTargetRefusal(target, { domainId: domain.id, departmentIds, roleIds }) ?? (target.scope === 'USER' && !people.has(target.targetId) ? 'unknown-person' : undefined)\n if (refusal) refuse(context, `audience-${refusal}`, `this target cannot be given (${refusal}).`)\n byKey.set(`${target.scope}:${target.targetId}`, target)\n }\n const repository = getRepository(AnnouncementAudience, tx)\n const current = await audiencesOf(announcement.id, tx)\n const gone = current.filter(one => !byKey.has(`${one.scope}:${one.targetId}`))\n if (gone.length) await repository.softRemove(gone)\n let added = 0\n for (const [key, target] of byKey) {\n if (current.some(one => `${one.scope}:${one.targetId}` === key)) continue\n added++\n await repository.save({ domain, announcement: { id: announcement.id }, scope: target.scope, targetId: target.targetId, targetName: target.targetName?.slice(0, 100), creator: user, updater: user } as any)\n }\n return gone.length + added > 0\n}\n\nasync function attachFiles(announcementId: string, attach: FileUpload[] | undefined, remove: string[] | undefined, context: ResolverContext) {\n for (const id of remove ?? []) {\n const file = await getRepository(Attachment, context.state.tx).findOne({ where: { id, domain: { id: context.state.domain.id }, refType: ANNOUNCEMENT_REF_TYPE, refBy: announcementId } as any })\n if (file) await deleteAttachment(null, { id }, context)\n }\n for (const file of attach ?? []) {\n await createAttachment(null, { attachment: { file, refType: ANNOUNCEMENT_REF_TYPE, refBy: announcementId } } as any, context)\n }\n}\n\n/** The reader's own receipts of `ids`, by announcement. */\nasync function myReceipts(ids: string[], userId: string, tx?: any): Promise<Map<string, AnnouncementReceipt>> {\n if (!ids.length) return new Map()\n const rows = await getRepository(AnnouncementReceipt, tx).find({ where: { announcement: { id: In(ids) }, user: { id: userId } } as any })\n return new Map(rows.map(one => [one.announcementId!, one]))\n}\n\n/** The current announcements addressed to the request's person, with their receipts. */\nasync function currentForReader(context: ResolverContext) {\n const { domain, user } = context.state\n const ids = await reachingIds(await memberOf(context))\n if (!ids.length) return { items: [] as Announcement[], receipts: new Map<string, AnnouncementReceipt>() }\n const now = new Date()\n const items = await getRepository(Announcement).find({\n where: [\n { id: In(ids), domain: { id: domain.id }, status: AnnouncementStatus.PUBLISHED, endsAt: IsNull() },\n { id: In(ids), domain: { id: domain.id }, status: AnnouncementStatus.PUBLISHED, endsAt: MoreThan(now) }\n ] as any,\n order: { rank: 'ASC', publishedAt: 'DESC' } as any\n })\n return { items, receipts: await myReceipts(items.map(one => one.id), user.id) }\n}\n\n@Resolver(Announcement)\nexport class AnnouncementResolver {\n /* ---------------------------------------------------------------- reading - the audience */\n\n @Query(returns => AnnouncementList, {\n description:\n \"The announcements addressed to the request's person that are out. Two filters are the reader's own: `period` (current | past) and `readerState` (unread, read, to-acknowledge, acknowledged - one or several, with `in`). The current ones come pinned, urgent and important first; otherwise the newest first.\"\n })\n async announcements(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AnnouncementList> {\n const { domain, user } = context.state\n const { rest, period, states, refusal } = readerNarrowingOf(params.filters as any)\n if (refusal) refuse(context, refusal, `the list cannot be narrowed so (${refusal}).`)\n let ids = await reachingIds(await memberOf(context))\n if (states && ids.length) {\n const candidates = await getRepository(Announcement).find({ where: { id: In(ids), status: AnnouncementStatus.PUBLISHED } as any })\n const receipts = await myReceipts(\n candidates.map(one => one.id),\n user.id\n )\n ids = candidates.filter(one => states.includes(readerStateOf(one, receipts.get(one.id)))).map(one => one.id)\n }\n if (!ids.length) return { items: [], total: 0 }\n const now = new Date()\n const qb = getQueryBuilderFromListParams({\n domain,\n params: { ...params, filters: rest as any, sortings: [] },\n repository: getRepository(Announcement),\n alias: 'A',\n searchables: ['title', 'body', 'category']\n })\n .andWhere('A.id IN (:...ids)', { ids })\n .andWhere('A.status = :published', { published: AnnouncementStatus.PUBLISHED })\n if (period === 'past') qb.andWhere('A.endsAt <= :now', { now })\n if (period === 'current') qb.andWhere('(A.endsAt IS NULL OR A.endsAt > :now)', { now }).orderBy('A.rank', 'ASC').addOrderBy('A.publishedAt', 'DESC')\n else qb.orderBy('A.publishedAt', 'DESC')\n const [items, total] = await qb.getManyAndCount()\n const receipts = await myReceipts(\n items.map(one => one.id),\n user.id\n )\n for (const one of items) (one as any).__mine = receipts.get(one.id) ?? null\n return { items, total }\n }\n\n @Query(returns => Announcement, { nullable: true, description: 'One announcement - to its audience once it is out, to a writer whatever its status (not somebody else\\'s draft).' })\n async announcement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement | undefined> {\n return (await visibleAnnouncement(id, context))?.announcement\n }\n\n @Query(returns => AnnouncementSummary, { description: 'How many current announcements addressed to the person are unread, and how many await their acknowledgement.' })\n async announcementSummary(@Ctx() context: ResolverContext): Promise<AnnouncementSummary> {\n const { items, receipts } = await currentForReader(context)\n let unread = 0\n let toAcknowledge = 0\n let pending = 0\n for (const one of items) {\n const state = readerStateOf(one, receipts.get(one.id))\n if (state === 'unread') unread++\n if (one.requiresAcknowledgement && state !== 'acknowledged') toAcknowledge++\n if (state === 'unread' || state === 'to-acknowledge') pending++\n }\n return { unread, toAcknowledge, pending }\n }\n\n @Query(returns => [Announcement], { description: 'The announcements that pop up for the person now - unread popup ones, and those still to be acknowledged.' })\n async announcementPopups(@Ctx() context: ResolverContext): Promise<Announcement[]> {\n const { items, receipts } = await currentForReader(context)\n const now = new Date()\n return items.filter(one => popupDue(one, receipts.get(one.id), now)).map(one => Object.assign(one, { __mine: receipts.get(one.id) ?? null }))\n }\n\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Records that the person read the announcement - once; reading it again changes nothing.' })\n async readAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n return await this.receive(id, context, false)\n }\n\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Records that the person acknowledged an announcement that asks for it - reading it too.' })\n async acknowledgeAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n return await this.receive(id, context, true)\n }\n\n private async receive(id: string, context: ResolverContext, acknowledge: boolean): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const visible = await visibleOrRefuse(id, context, tx)\n /* Only its audience reads it into the record - a writer looking at one addressed to others leaves no trace. */\n if (!visible.reader) return visible.announcement\n if (acknowledge && !visible.announcement.requiresAcknowledgement) refuse(context, 'no-acknowledgement', 'this announcement does not ask to be acknowledged.')\n const repository = getRepository(AnnouncementReceipt, tx)\n const now = new Date()\n const receipt = await repository.findOne({ where: { announcement: { id }, user: { id: user.id } } as any })\n const patch: any = {}\n if (!receipt?.readAt) patch.readAt = now\n if (acknowledge && !receipt?.acknowledgedAt) patch.acknowledgedAt = now\n if (!Object.keys(patch).length) return visible.announcement\n if (!receipt) await repository.save({ domain, announcement: { id }, user: { id: user.id }, listed: false, ...patch, creator: user, updater: user } as any)\n else await repository.update(receipt.id, { ...patch, updater: user })\n /* The reader's other windows - their badge asks again. */\n tellChange(context as any, { kind: 'announcement', id, userIds: [user.id] })\n return visible.announcement\n }\n\n /* ---------------------------------------------------------------- writing and managing */\n\n @Directive(WRITE)\n @Query(returns => AnnouncementList, { description: \"Every announcement of the domain for its writers - all that are out, scheduled or withdrawn, and the writer's own drafts.\" })\n async managedAnnouncements(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AnnouncementList> {\n const { domain, user } = context.state\n const qb = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(Announcement),\n alias: 'A',\n searchables: ['title', 'body', 'category']\n }).andWhere('(A.status != :draft OR A.creator = :me)', { draft: AnnouncementStatus.DRAFT, me: user.id })\n if (!params.sortings?.length) qb.orderBy('A.updatedAt', 'DESC')\n const [items, total] = await qb.getManyAndCount()\n return { items, total }\n }\n\n @Directive(WRITE)\n @Query(returns => [AnnouncementReceiptRow], { description: 'Who on the roster read and acknowledged it, and who came to it later - for its writers.' })\n async announcementReceipts(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<AnnouncementReceiptRow[]> {\n const visible = await visibleOrRefuse(id, context)\n if (!visible.writer) refuse(context, 'unknown-announcement', NOT_FOUND)\n const receipts = await getRepository(AnnouncementReceipt).find({ where: { announcement: { id } } as any, relations: ['user'] })\n return receipts\n .map(one => ({\n userId: one.userId!,\n name: one.user?.name,\n email: one.user?.email,\n listed: one.listed,\n notifiedAt: one.notifiedAt,\n readAt: one.readAt,\n acknowledgedAt: one.acknowledgedAt\n }))\n .sort((a, b) => Number(!!a.readAt) - Number(!!b.readAt) || String(a.name ?? '').localeCompare(String(b.name ?? '')))\n }\n\n @Directive(WRITE)\n @Query(returns => [AnnouncementRevision], { description: 'The versions of an announcement since it went out, newest first - for its writers.' })\n async announcementRevisions(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<AnnouncementRevision[]> {\n const visible = await visibleOrRefuse(id, context)\n if (!visible.writer) refuse(context, 'unknown-announcement', NOT_FOUND)\n return await getRepository(AnnouncementRevision).find({ where: { announcement: { id } } as any, order: { version: 'DESC' } as any, relations: ['creator'] })\n }\n\n @Directive(WRITE)\n @Query(returns => AnnouncementAudienceChoices, { description: 'What an announcement may be addressed to - the domain, its departments and its roles.' })\n async announcementAudienceChoices(@Ctx() context: ResolverContext): Promise<AnnouncementAudienceChoices> {\n const domain: any = context.state.domain\n const tree = await departmentTreeOf(domain)\n const departments = tree.size ? await getRepository(Department).find({ where: { id: In([...tree.keys()]) } as any, order: { name: 'ASC' } as any }) : []\n const nameOf = new Map(departments.map(one => [one.id, one.name]))\n return {\n domainId: domain.id,\n domainName: domain.name ?? domain.subdomain ?? domain.id,\n departments: departments.map(one => ({ id: one.id, name: one.name, note: nameOf.get(tree.get(one.id) ?? '') ?? undefined })),\n roles: (await domainRolesOf(domain)).map(one => ({ id: one.id, name: one.name, note: one.description ?? undefined }))\n }\n }\n\n @Directive(WRITE)\n @Query(returns => [AnnouncementChoice], { description: 'People of the domain an announcement may be addressed to, found by name or e-mail.' })\n async announcementPeople(@Arg('text') text: string, @Ctx() context: ResolverContext): Promise<AnnouncementChoice[]> {\n const words = (text ?? '').trim().toLowerCase()\n if (!words) return []\n return (await getDomainAssignees(context.state.domain as any))\n .filter(one => `${one.name ?? ''} ${one.email ?? ''}`.toLowerCase().includes(words))\n .slice(0, 20)\n .map(one => ({ id: one.id, name: one.name || one.email, note: one.email }))\n }\n\n @Directive(WRITE)\n @Query(returns => Int, { description: 'How many people an audience names now - shown before it is sent.' })\n async announcementAudienceSize(@Arg('audiences', type => [AnnouncementAudienceInput]) audiences: AnnouncementAudienceInput[], @Ctx() context: ResolverContext): Promise<number> {\n return (await audienceUserIds(context.state.domain, audiences ?? [])).length\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Writes a new announcement as a draft, with its files.' })\n async createAnnouncement(\n @Arg('input', type => AnnouncementInput) input: AnnouncementInput,\n @Arg('attach', type => [GraphQLUpload], { nullable: true }) attach: FileUpload[],\n @Ctx() context: ResolverContext\n ): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const saved = await getRepository(Announcement, tx).save({ ...fieldsOf(input, context), domain, status: AnnouncementStatus.DRAFT, version: 1, creator: user, updater: user } as any)\n await setAudiences(saved, input.audiences ?? [], context, tx)\n await attachFiles(saved.id, attach, [], context)\n return saved\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, {\n description:\n 'Changes an announcement. Once out, each change is a new version; people the audience now names who were not told are told, and `notifyAgain` tells everyone on the roster again.'\n })\n async updateAnnouncement(\n @Arg('id') id: string,\n @Arg('input', type => AnnouncementInput) input: AnnouncementInput,\n @Arg('attach', type => [GraphQLUpload], { nullable: true }) attach: FileUpload[],\n @Arg('remove', type => [String], { nullable: true, description: 'Ids of its files to take off.' }) remove: string[],\n @Arg('notifyAgain', { nullable: true, description: 'Tell everyone on the roster of the change.' }) notifyAgain: boolean,\n @Ctx() context: ResolverContext\n ): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n const fields = fieldsOf(input, context)\n const out = announcement.status === AnnouncementStatus.PUBLISHED\n /* Once out, its start is the moment it went out - a start set later would hide it again. */\n if (out) fields.startsAt = announcement.startsAt\n const repository = getRepository(Announcement, tx)\n await repository.update(id, { ...fields, ...(out ? { version: announcement.version + 1 } : {}), updater: user } as any)\n const audienceChanged = await setAudiences(announcement, input.audiences ?? [], context, tx)\n if (out && !(input.audiences ?? []).length) refuse(context, 'no-audience', 'an announcement that is out names someone.')\n await attachFiles(id, attach, remove, context)\n const fresh = (await repository.findOneBy({ id }))!\n if (!out) return fresh\n await keepRevision(fresh, domain, user, tx)\n const added = audienceChanged ? await alignRoster(fresh, domain, user, tx) : []\n const receivers = notifyAgain\n ? (await getRepository(AnnouncementReceipt, tx).find({ where: { announcement: { id }, listed: true } as any })).map(one => one.userId!)\n : added\n if (notifyAgain) await getRepository(AnnouncementReceipt, tx).update({ announcement: { id }, listed: true } as any, { notifiedAt: new Date() } as any)\n /* Told again, everyone hears it - the channel too; people the audience newly names are told one by one. */\n await tellWhenCommitted(context, fresh, notifyAgain ? 'changed' : 'published', receivers.filter(one => one !== user.id), !!notifyAgain)\n await tellRosterChange(context, id, tx)\n return fresh\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Sends a draft out to its audience - at once, or at its start when that is still to come.' })\n async publishAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n const { domain, user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n const audiences = await audiencesOf(id, tx)\n const refusal = publishRefusal(announcement.status, announcement, audiences.length)\n if (refusal) refuse(context, refusal, `the announcement cannot go out (${refusal}).`)\n const repository = getRepository(Announcement, tx)\n if (publishedStatusOf(announcement.startsAt) === 'SCHEDULED') {\n await repository.update(id, { status: AnnouncementStatus.SCHEDULED, publisher: user, updater: user } as any)\n return (await repository.findOneBy({ id }))!\n }\n const receivers = await sendOut(announcement, domain, user, tx)\n const fresh = (await repository.findOneBy({ id }))!\n await tellWhenCommitted(context, fresh, 'published', receivers, true)\n await tellRosterChange(context, id, tx)\n return fresh\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Announcement, { description: 'Takes back an announcement that is out or scheduled, with the reason. Its audience no longer sees it; its record stays.' })\n async withdrawAnnouncement(@Arg('id') id: string, @Arg('reason') reason: string, @Ctx() context: ResolverContext): Promise<Announcement> {\n const { user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n if (announcement.status === AnnouncementStatus.DRAFT) refuse(context, 'not-out', 'a draft is deleted, not withdrawn.')\n if (!reason?.trim()) refuse(context, 'no-reason', 'say why it is withdrawn.')\n const repository = getRepository(Announcement, tx)\n await repository.update(id, { status: AnnouncementStatus.WITHDRAWN, withdrawnAt: new Date(), withdrawReason: reason.trim().slice(0, 500), updater: user } as any)\n await tellRosterChange(context, id, tx)\n return (await repository.findOneBy({ id }))!\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: \"Deletes one's own draft and its files. An announcement that went out is withdrawn instead.\" })\n async deleteAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n if (announcement.status !== AnnouncementStatus.DRAFT) refuse(context, 'not-a-draft', 'an announcement that went out is withdrawn, not deleted.')\n await deleteAttachmentsByRef(null, { refBys: [id], refType: ANNOUNCEMENT_REF_TYPE }, context)\n await getRepository(Announcement, tx).softDelete(id)\n return true\n }\n\n @Directive(WRITE)\n @Directive('@transaction')\n @Mutation(returns => Int, { description: 'Tells again those on the roster who have not read it - or not acknowledged it, when it asks for that. Answers how many were told.' })\n async remindAnnouncement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<number> {\n const { user, tx } = context.state as any\n const announcement = await changeable(id, context, tx)\n if (!isCurrent(announcement)) refuse(context, 'not-current', 'only a current announcement is reminded.')\n const repository = getRepository(AnnouncementReceipt, tx)\n const owed = (await repository.find({ where: { announcement: { id } } as any })).filter(one => owedReminder(announcement, one))\n if (owed.length) await repository.update({ id: In(owed.map(one => one.id)) } as any, { notifiedAt: new Date(), updater: user } as any)\n await tellWhenCommitted(\n context,\n announcement,\n 'reminder',\n owed.map(one => one.userId!)\n )\n return owed.length\n }\n\n /* ---------------------------------------------------------------- fields */\n\n @FieldResolver(type => [AnnouncementAudience], { description: 'Whom it is addressed to.' })\n async audiences(@Root() one: Announcement): Promise<AnnouncementAudience[]> {\n return await audiencesOf(one.id)\n }\n\n @FieldResolver(type => [Attachment], { description: 'Its files.' })\n async attachments(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<Attachment[]> {\n return await getRepository(Attachment).find({ where: { domain: { id: context.state.domain.id }, refType: ANNOUNCEMENT_REF_TYPE, refBy: one.id } as any, order: { createdAt: 'ASC' } as any })\n }\n\n @FieldResolver(type => AnnouncementReceipt, { nullable: true, description: \"The request's person's own reading of it.\" })\n async mine(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<AnnouncementReceipt | null> {\n if ('__mine' in (one as any)) return (one as any).__mine\n return (await myReceipts([one.id], context.state.user.id)).get(one.id) ?? null\n }\n\n @FieldResolver(type => Boolean, { description: \"Whether it is addressed to the request's person and out - the one who reads and acknowledges it.\" })\n async addressed(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<boolean> {\n return one.status === AnnouncementStatus.PUBLISHED && (await reachingIds(await memberOf(context))).includes(one.id)\n }\n\n @FieldResolver(type => String, { nullable: true, description: 'Whether it is still current or past - for one that is out.' })\n period(@Root() one: Announcement): string | undefined {\n return periodOf(one)\n }\n\n @FieldResolver(type => String, { description: \"Where it stands for the request's person: unread, read, to-acknowledge or acknowledged.\" })\n async readerState(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<string> {\n return readerStateOf(one, (await this.mine(one, context)) ?? undefined)\n }\n\n @FieldResolver(type => Int, { nullable: true, description: 'How many on the roster read it - for its writers.' })\n async readCount(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<number | null> {\n if (!(await isWriter(context))) return null\n return await getRepository(AnnouncementReceipt).count({ where: { announcement: { id: one.id }, listed: true, readAt: Not(IsNull()) } as any })\n }\n\n @FieldResolver(type => Int, { nullable: true, description: 'How many on the roster acknowledged it - for its writers.' })\n async acknowledgedCount(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<number | null> {\n if (!(await isWriter(context))) return null\n return await getRepository(AnnouncementReceipt).count({ where: { announcement: { id: one.id }, listed: true, acknowledgedAt: Not(IsNull()) } as any })\n }\n\n @FieldResolver(type => Boolean, { description: 'Whether the request may change it.' })\n async editable(@Root() one: Announcement, @Ctx() context: ResolverContext): Promise<boolean> {\n if (one.status === AnnouncementStatus.WITHDRAWN) return false\n if (one.status === AnnouncementStatus.DRAFT && one.creatorId !== context.state.user.id) return false\n return await isWriter(context)\n }\n\n @FieldResolver(type => User, { nullable: true, description: 'Who published it.' })\n async publisher(@Root() one: Announcement): Promise<User | null> {\n return one.publisherId ? await getRepository(User).findOneBy({ id: one.publisherId }) : null\n }\n\n @FieldResolver(type => User, { nullable: true, description: 'Who wrote it.' })\n async creator(@Root() one: Announcement): Promise<User | null> {\n return one.creatorId ? await getRepository(User).findOneBy({ id: one.creatorId }) : null\n }\n}\n"]}
@@ -45,10 +45,24 @@ export declare function sendOut(announcement: Announcement, domain: Domain, by:
45
45
  * still reach them.
46
46
  */
47
47
  export declare function tellWhenCommitted(context: any, one: Announcement, kind: NoticeKind, userIds: string[], toEveryone?: boolean): Promise<void>;
48
+ /**
49
+ * Tells everyone on its roster - those it names now and those it named before - that it changed, so their badge and
50
+ * list ask again (shell's myChange). No notice and no words: a notice is only for what people are to be told of.
51
+ * `context` is a request's, or `{ state: { domain } }` outside one.
52
+ */
53
+ export declare function tellRosterChange(context: any, announcementId: string, tx?: EntityManager): Promise<void>;
48
54
  /**
49
55
  * Publishes the scheduled announcements whose start has come. Each is taken by one update from SCHEDULED, so a server
50
56
  * among several that loses the race does not send it twice.
51
57
  */
52
58
  export declare function publishDue(now?: Date): Promise<number>;
53
- /** Looks for scheduled announcements every minute. The timer never keeps the process alive. */
59
+ /**
60
+ * Tells the rosters of the announcements whose period ended after `since` and by `now` - nothing else moves their
61
+ * badge then. Each server that runs it tells them; a second telling only asks the count again.
62
+ */
63
+ export declare function tellEnded(since: Date, now?: Date): Promise<number>;
64
+ /**
65
+ * Every minute, publishes the scheduled announcements whose start has come and tells the rosters of those whose period
66
+ * ended. The timer never keeps the process alive.
67
+ */
54
68
  export declare function schedulePublishing(): void;
@@ -10,7 +10,9 @@ exports.alignRoster = alignRoster;
10
10
  exports.keepRevision = keepRevision;
11
11
  exports.sendOut = sendOut;
12
12
  exports.tellWhenCommitted = tellWhenCommitted;
13
+ exports.tellRosterChange = tellRosterChange;
13
14
  exports.publishDue = publishDue;
15
+ exports.tellEnded = tellEnded;
14
16
  exports.schedulePublishing = schedulePublishing;
15
17
  /*
16
18
  * What the doors of announcements do with the database (ADR-0163 decisions 1-5): who may read one, who is on its roster,
@@ -184,6 +186,15 @@ async function tellWhenCommitted(context, one, kind, userIds, toEveryone = false
184
186
  const broadcast = toEveryone && (0, announcement_rules_1.broadcastOf)(await audiencesOf(one.id, context.state.tx), context.state.domain?.id);
185
187
  (0, notification_1.sendNoticeWhenCommitted)(context, noticeOf(one, kind, receivers, broadcast, (0, notification_1.noticeLinkOf)(context, (0, announcement_rules_1.viewAddressOf)(one.id))), result => (0, notification_1.keepNoticeDelivery)(announcement_1.Announcement, one.id, 'deliveries', (0, notification_1.noticeDeliveryOf)(kind, result, receivers.length)));
186
188
  }
189
+ /**
190
+ * Tells everyone on its roster - those it names now and those it named before - that it changed, so their badge and
191
+ * list ask again (shell's myChange). No notice and no words: a notice is only for what people are to be told of.
192
+ * `context` is a request's, or `{ state: { domain } }` outside one.
193
+ */
194
+ async function tellRosterChange(context, announcementId, tx) {
195
+ const receipts = await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt, tx).find({ where: { announcement: { id: announcementId } } });
196
+ (0, shell_1.tellChange)(context, { kind: 'announcement', id: announcementId, userIds: receipts.map(one => one.userId) });
197
+ }
187
198
  /**
188
199
  * Publishes the scheduled announcements whose start has come. Each is taken by one update from SCHEDULED, so a server
189
200
  * among several that loses the race does not send it twice.
@@ -207,6 +218,7 @@ async function publishDue(now = new Date()) {
207
218
  if (!receivers)
208
219
  continue;
209
220
  published++;
221
+ await tellRosterChange({ state: { domain: one.domain } }, one.id);
210
222
  /* No request, so no address to put on a mail button - the mail says where to find it instead. */
211
223
  const people = await receiversOf(receivers);
212
224
  const broadcast = (0, announcement_rules_1.broadcastOf)(await audiencesOf(one.id), one.domain?.id);
@@ -219,12 +231,34 @@ async function publishDue(now = new Date()) {
219
231
  }
220
232
  return published;
221
233
  }
234
+ /**
235
+ * Tells the rosters of the announcements whose period ended after `since` and by `now` - nothing else moves their
236
+ * badge then. Each server that runs it tells them; a second telling only asks the count again.
237
+ */
238
+ async function tellEnded(since, now = new Date()) {
239
+ const ended = await (0, shell_1.getRepository)(announcement_1.Announcement).find({
240
+ where: { status: announcement_1.AnnouncementStatus.PUBLISHED, endsAt: (0, typeorm_1.Between)(new Date(since.getTime() + 1), now), deletedAt: (0, typeorm_1.IsNull)() },
241
+ relations: ['domain']
242
+ });
243
+ for (const one of ended)
244
+ await tellRosterChange({ state: { domain: one.domain } }, one.id);
245
+ return ended.length;
246
+ }
222
247
  let timer;
223
- /** Looks for scheduled announcements every minute. The timer never keeps the process alive. */
248
+ /**
249
+ * Every minute, publishes the scheduled announcements whose start has come and tells the rosters of those whose period
250
+ * ended. The timer never keeps the process alive.
251
+ */
224
252
  function schedulePublishing() {
225
253
  if (timer)
226
254
  return;
227
- timer = setInterval(() => void publishDue().catch(error => env_1.logger.error('scheduled announcements', error)), 60 * 1000);
255
+ let since = new Date();
256
+ timer = setInterval(() => {
257
+ const now = new Date();
258
+ void publishDue(now).catch(error => env_1.logger.error('scheduled announcements', error));
259
+ void tellEnded(since, now).catch(error => env_1.logger.error('ended announcements', error));
260
+ since = now;
261
+ }, 60 * 1000);
228
262
  timer.unref?.();
229
263
  }
230
264
  //# sourceMappingURL=announcement-service.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"announcement-service.js","sourceRoot":"","sources":["../../../server/service/announcement/announcement-service.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the doors of announcements do with the database (ADR-0163 decisions 1-5): who may read one, who is on its roster,\n * sending it out, telling people of it, and publishing the scheduled ones when their start comes.\n */\nimport { EntityManager, In, IsNull, LessThanOrEqual } from 'typeorm'\n\nimport { requestHolds, User, UserStatus } from '@things-factory/auth-base'\nimport { logger } from '@things-factory/env'\nimport { translatorFor } from '@things-factory/i18n-base/translator'\nimport { keepNoticeDelivery, noticeDeliveryOf, noticeLinkOf, sendNotice, sendNoticeWhenCommitted, type Notice } from '@things-factory/notification'\nimport { audienceMemberOf, audienceUserIds, type AudienceMember } from '@things-factory/organization'\nimport { Domain, getDataSource, getRepository } from '@things-factory/shell'\n\nimport { Announcement, AnnouncementAudience, AnnouncementReceipt, AnnouncementRevision, AnnouncementStatus } from './announcement'\nimport { broadcastOf, noticeWordsOf, viewAddressOf, type NoticeKind, type Say } from './announcement-rules'\n\n/** The attachments of an announcement hang on it under this `refType` (attachment-base). */\nexport const ANNOUNCEMENT_REF_TYPE = 'Announcement'\n\n/** Whether the request writes announcements - the one privilege of the module (`announcement.writing`). */\nexport async function isWriter(context: any): Promise<boolean> {\n return await requestHolds(context, 'announcement', 'mutation')\n}\n\n/** The request's person as an audience sees them - asked once per request. */\nexport async function memberOf(context: any): Promise<AudienceMember> {\n const state = context.state\n if (!state.__announcementMember) {\n const { ownDepartments, ...member } = await audienceMemberOf(state.domain, state.user ?? {})\n state.__announcementMember = member\n }\n return state.__announcementMember\n}\n\n/** The announcements of the domain whose audience names `member` - by their targets, whatever their status. */\nexport async function reachingIds(member: AudienceMember, tx?: EntityManager): Promise<string[]> {\n if (!member.userId || !member.domainId) return []\n const domain = { id: member.domainId }\n const rows = await getRepository(AnnouncementAudience, tx).find({\n where: [\n { domain, scope: 'DOMAIN', targetId: member.domainId },\n { domain, scope: 'USER', targetId: member.userId },\n ...(member.departmentIds.length ? [{ domain, scope: 'DEPARTMENT', targetId: In([...member.departmentIds]) }] : []),\n ...(member.roleIds.length ? [{ domain, scope: 'ROLE', targetId: In([...member.roleIds]) }] : [])\n ] as any\n })\n return [...new Set(rows.map(one => one.announcementId!))]\n}\n\nexport async function audiencesOf(announcementId: string, tx?: EntityManager): Promise<AnnouncementAudience[]> {\n return await getRepository(AnnouncementAudience, tx).find({ where: { announcement: { id: announcementId } } as any, order: { createdAt: 'ASC' } as any })\n}\n\n/**\n * The announcement as the request may see it, or nothing - one answer for \"none\", \"not yours\" and \"not out yet\".\n * Its audience reads it once it is out; a writer reads every one that is not somebody else's draft.\n */\nexport async function visibleAnnouncement(id: string, context: any, tx?: EntityManager): Promise<{ announcement: Announcement; reader: boolean; writer: boolean } | undefined> {\n const { domain, user } = context?.state ?? {}\n if (!id || !domain || !user || !/^[0-9a-f-]{36}$/i.test(id)) return undefined\n const announcement = await getRepository(Announcement, tx).findOne({ where: { id, domain: { id: domain.id } } as any })\n if (!announcement) return undefined\n const reader = announcement.status === AnnouncementStatus.PUBLISHED && (await reachingIds(await memberOf(context), tx)).includes(id)\n const writer = (announcement.status !== AnnouncementStatus.DRAFT || announcement.creatorId === user.id) && (await isWriter(context))\n return reader || writer ? { announcement, reader, writer } : undefined\n}\n\n/**\n * Puts the roster in line with the audience as it stands: everyone it names now is listed, one it no longer names is\n * not (their reading stays). Answers those newly listed - the ones not yet told.\n */\nexport async function alignRoster(announcement: Announcement, domain: Domain, by: { id: string }, tx: EntityManager): Promise<string[]> {\n const named = await audienceUserIds(domain, await audiencesOf(announcement.id, tx), tx)\n const repository = getRepository(AnnouncementReceipt, tx)\n const receipts = await repository.find({ where: { announcement: { id: announcement.id } } as any })\n const byUser = new Map(receipts.map(one => [one.userId, one]))\n const now = new Date()\n const added: string[] = []\n for (const userId of named) {\n const receipt = byUser.get(userId)\n if (receipt?.listed) continue\n added.push(userId)\n if (receipt) await repository.update(receipt.id, { listed: true, notifiedAt: now, updater: by } as any)\n else await repository.save({ domain, announcement: { id: announcement.id }, user: { id: userId }, listed: true, notifiedAt: now, creator: by, updater: by } as any)\n }\n const gone = receipts.filter(one => one.listed && !named.includes(one.userId!))\n if (gone.length) await repository.update({ id: In(gone.map(one => one.id)) } as any, { listed: false, updater: by } as any)\n await getRepository(Announcement, tx).update(announcement.id, { audienceSize: named.length } as any)\n return added\n}\n\n/** The version as it stands, kept - the one that went out, and each change after. */\nexport async function keepRevision(announcement: Announcement, domain: Domain, by: { id: string }, tx: EntityManager): Promise<void> {\n const audiences = await audiencesOf(announcement.id, tx)\n const { title, body, category, importance, startsAt, endsAt, pinned, requiresAcknowledgement, acknowledgeBy, popup, links } = announcement\n await getRepository(AnnouncementRevision, tx).save({\n domain,\n announcement: { id: announcement.id },\n version: announcement.version,\n title,\n body,\n rest: {\n category,\n importance,\n startsAt,\n endsAt,\n pinned,\n requiresAcknowledgement,\n acknowledgeBy,\n popup,\n links,\n audiences: audiences.map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName }))\n },\n creator: by,\n updater: by\n } as any)\n}\n\n/**\n * Sends it out: published now, the roster counted, this version kept. Answers the people to tell - the publisher is not\n * told of their own announcement.\n */\nexport async function sendOut(announcement: Announcement, domain: Domain, by: { id: string }, tx: EntityManager): Promise<string[]> {\n const now = new Date()\n await getRepository(Announcement, tx).update(announcement.id, {\n status: AnnouncementStatus.PUBLISHED,\n publishedAt: now,\n startsAt: announcement.startsAt ?? now,\n publisher: by,\n updater: by\n } as any)\n const fresh = await getRepository(Announcement, tx).findOneBy({ id: announcement.id })\n await keepRevision(fresh!, domain, by, tx)\n return (await alignRoster(fresh!, domain, by, tx)).filter(id => id !== by.id)\n}\n\n/** The sentences in `lng` from this module's translations, the English one where `lng` has none. */\nconst sayIn =\n (lng: string): Say =>\n (key, english, params = {}) =>\n translatorFor(lng)(key, { ...params, defaultValue: english.replace(/\\{(\\w+)\\}/g, (_, name) => String(params[name] ?? '')) })\n\n/** The people to tell, as notification takes them - only those who can sign in, each with their mail and language. */\nasync function receiversOf(userIds: string[], tx?: EntityManager) {\n if (!userIds.length) return []\n const people = await getRepository(User, tx).find({ where: { id: In(userIds) } as any })\n return people.filter(one => one.status === UserStatus.ACTIVATED).map(one => ({ id: one.id, email: one.email, locale: (one as any).locale }))\n}\n\n/**\n * The notice of an announcement (notification ADR-0164): in the app and by web push always - the `announcement` type is\n * what pops it up - and by mail when the announcement asks for it and the domain has mail on.\n */\nfunction noticeOf(one: Announcement, kind: NoticeKind, receivers: Notice['receivers'], broadcast: boolean, link?: string): Notice {\n return {\n type: 'announcement',\n level: one.importance === 'URGENT' ? 'warn' : 'info',\n receivers,\n words: lng => noticeWordsOf(one, kind, sayIn(lng)),\n address: viewAddressOf(one.id),\n link,\n label: `announcement ${kind} ${one.id}`,\n /* The mail carries the whole body, drawn from its Markdown; the inbox and push show the summary. */\n format: 'markdown',\n channels: { email: !!one.sendEmail },\n /* Said once to the domain's Teams channel too - only what is addressed to everyone, and only when it goes out or all are told again. */\n ...(broadcast ? { broadcast: true } : {})\n }\n}\n\n/**\n * Tells `userIds` of it once the request's transaction has committed - a reader told before it would not find it yet -\n * and keeps what went out. A notice that does not arrive does not undo the announcement: its list, badge and popup\n * still reach them.\n */\nexport async function tellWhenCommitted(context: any, one: Announcement, kind: NoticeKind, userIds: string[], toEveryone = false): Promise<void> {\n const receivers = await receiversOf(userIds, context.state.tx)\n if (!receivers.length) return\n const broadcast = toEveryone && broadcastOf(await audiencesOf(one.id, context.state.tx), context.state.domain?.id)\n sendNoticeWhenCommitted(context, noticeOf(one, kind, receivers, broadcast, noticeLinkOf(context, viewAddressOf(one.id))), result =>\n keepNoticeDelivery(Announcement, one.id, 'deliveries', noticeDeliveryOf(kind, result, receivers.length))\n )\n}\n\n/**\n * Publishes the scheduled announcements whose start has come. Each is taken by one update from SCHEDULED, so a server\n * among several that loses the race does not send it twice.\n */\nexport async function publishDue(now = new Date()): Promise<number> {\n const due = await getRepository(Announcement).find({\n where: { status: AnnouncementStatus.SCHEDULED, startsAt: LessThanOrEqual(now), deletedAt: IsNull() } as any,\n relations: ['domain', 'publisher', 'creator'],\n take: 50\n })\n let published = 0\n for (const one of due) {\n try {\n const by = { id: one.publisherId ?? one.creatorId! }\n const receivers = await getDataSource().transaction(async tx => {\n const taken = await tx.getRepository(Announcement).update({ id: one.id, status: AnnouncementStatus.SCHEDULED } as any, { status: AnnouncementStatus.DRAFT } as any)\n if (!taken.affected) return undefined\n return await sendOut({ ...one, status: AnnouncementStatus.DRAFT } as Announcement, one.domain!, by, tx)\n })\n if (!receivers) continue\n published++\n /* No request, so no address to put on a mail button - the mail says where to find it instead. */\n const people = await receiversOf(receivers)\n const broadcast = broadcastOf(await audiencesOf(one.id), one.domain?.id)\n if (people.length) await keepNoticeDelivery(Announcement, one.id, 'deliveries', noticeDeliveryOf('published', await sendNotice(one.domain, noticeOf(one, 'published', people, broadcast)), people.length))\n } catch (error) {\n logger.error(`announcement ${one.id}: publishing at its start failed`, error)\n }\n }\n return published\n}\n\nlet timer: ReturnType<typeof setInterval> | undefined\n\n/** Looks for scheduled announcements every minute. The timer never keeps the process alive. */\nexport function schedulePublishing(): void {\n if (timer) return\n timer = setInterval(() => void publishDue().catch(error => logger.error('scheduled announcements', error)), 60 * 1000)\n timer.unref?.()\n}\n"]}
1
+ {"version":3,"file":"announcement-service.js","sourceRoot":"","sources":["../../../server/service/announcement/announcement-service.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * What the doors of announcements do with the database (ADR-0163 decisions 1-5): who may read one, who is on its roster,\n * sending it out, telling people of it, and publishing the scheduled ones when their start comes.\n */\nimport { Between, EntityManager, In, IsNull, LessThanOrEqual } from 'typeorm'\n\nimport { requestHolds, User, UserStatus } from '@things-factory/auth-base'\nimport { logger } from '@things-factory/env'\nimport { translatorFor } from '@things-factory/i18n-base/translator'\nimport { keepNoticeDelivery, noticeDeliveryOf, noticeLinkOf, sendNotice, sendNoticeWhenCommitted, type Notice } from '@things-factory/notification'\nimport { audienceMemberOf, audienceUserIds, type AudienceMember } from '@things-factory/organization'\nimport { Domain, getDataSource, getRepository, tellChange } from '@things-factory/shell'\n\nimport { Announcement, AnnouncementAudience, AnnouncementReceipt, AnnouncementRevision, AnnouncementStatus } from './announcement'\nimport { broadcastOf, noticeWordsOf, viewAddressOf, type NoticeKind, type Say } from './announcement-rules'\n\n/** The attachments of an announcement hang on it under this `refType` (attachment-base). */\nexport const ANNOUNCEMENT_REF_TYPE = 'Announcement'\n\n/** Whether the request writes announcements - the one privilege of the module (`announcement.writing`). */\nexport async function isWriter(context: any): Promise<boolean> {\n return await requestHolds(context, 'announcement', 'mutation')\n}\n\n/** The request's person as an audience sees them - asked once per request. */\nexport async function memberOf(context: any): Promise<AudienceMember> {\n const state = context.state\n if (!state.__announcementMember) {\n const { ownDepartments, ...member } = await audienceMemberOf(state.domain, state.user ?? {})\n state.__announcementMember = member\n }\n return state.__announcementMember\n}\n\n/** The announcements of the domain whose audience names `member` - by their targets, whatever their status. */\nexport async function reachingIds(member: AudienceMember, tx?: EntityManager): Promise<string[]> {\n if (!member.userId || !member.domainId) return []\n const domain = { id: member.domainId }\n const rows = await getRepository(AnnouncementAudience, tx).find({\n where: [\n { domain, scope: 'DOMAIN', targetId: member.domainId },\n { domain, scope: 'USER', targetId: member.userId },\n ...(member.departmentIds.length ? [{ domain, scope: 'DEPARTMENT', targetId: In([...member.departmentIds]) }] : []),\n ...(member.roleIds.length ? [{ domain, scope: 'ROLE', targetId: In([...member.roleIds]) }] : [])\n ] as any\n })\n return [...new Set(rows.map(one => one.announcementId!))]\n}\n\nexport async function audiencesOf(announcementId: string, tx?: EntityManager): Promise<AnnouncementAudience[]> {\n return await getRepository(AnnouncementAudience, tx).find({ where: { announcement: { id: announcementId } } as any, order: { createdAt: 'ASC' } as any })\n}\n\n/**\n * The announcement as the request may see it, or nothing - one answer for \"none\", \"not yours\" and \"not out yet\".\n * Its audience reads it once it is out; a writer reads every one that is not somebody else's draft.\n */\nexport async function visibleAnnouncement(id: string, context: any, tx?: EntityManager): Promise<{ announcement: Announcement; reader: boolean; writer: boolean } | undefined> {\n const { domain, user } = context?.state ?? {}\n if (!id || !domain || !user || !/^[0-9a-f-]{36}$/i.test(id)) return undefined\n const announcement = await getRepository(Announcement, tx).findOne({ where: { id, domain: { id: domain.id } } as any })\n if (!announcement) return undefined\n const reader = announcement.status === AnnouncementStatus.PUBLISHED && (await reachingIds(await memberOf(context), tx)).includes(id)\n const writer = (announcement.status !== AnnouncementStatus.DRAFT || announcement.creatorId === user.id) && (await isWriter(context))\n return reader || writer ? { announcement, reader, writer } : undefined\n}\n\n/**\n * Puts the roster in line with the audience as it stands: everyone it names now is listed, one it no longer names is\n * not (their reading stays). Answers those newly listed - the ones not yet told.\n */\nexport async function alignRoster(announcement: Announcement, domain: Domain, by: { id: string }, tx: EntityManager): Promise<string[]> {\n const named = await audienceUserIds(domain, await audiencesOf(announcement.id, tx), tx)\n const repository = getRepository(AnnouncementReceipt, tx)\n const receipts = await repository.find({ where: { announcement: { id: announcement.id } } as any })\n const byUser = new Map(receipts.map(one => [one.userId, one]))\n const now = new Date()\n const added: string[] = []\n for (const userId of named) {\n const receipt = byUser.get(userId)\n if (receipt?.listed) continue\n added.push(userId)\n if (receipt) await repository.update(receipt.id, { listed: true, notifiedAt: now, updater: by } as any)\n else await repository.save({ domain, announcement: { id: announcement.id }, user: { id: userId }, listed: true, notifiedAt: now, creator: by, updater: by } as any)\n }\n const gone = receipts.filter(one => one.listed && !named.includes(one.userId!))\n if (gone.length) await repository.update({ id: In(gone.map(one => one.id)) } as any, { listed: false, updater: by } as any)\n await getRepository(Announcement, tx).update(announcement.id, { audienceSize: named.length } as any)\n return added\n}\n\n/** The version as it stands, kept - the one that went out, and each change after. */\nexport async function keepRevision(announcement: Announcement, domain: Domain, by: { id: string }, tx: EntityManager): Promise<void> {\n const audiences = await audiencesOf(announcement.id, tx)\n const { title, body, category, importance, startsAt, endsAt, pinned, requiresAcknowledgement, acknowledgeBy, popup, links } = announcement\n await getRepository(AnnouncementRevision, tx).save({\n domain,\n announcement: { id: announcement.id },\n version: announcement.version,\n title,\n body,\n rest: {\n category,\n importance,\n startsAt,\n endsAt,\n pinned,\n requiresAcknowledgement,\n acknowledgeBy,\n popup,\n links,\n audiences: audiences.map(({ scope, targetId, targetName }) => ({ scope, targetId, targetName }))\n },\n creator: by,\n updater: by\n } as any)\n}\n\n/**\n * Sends it out: published now, the roster counted, this version kept. Answers the people to tell - the publisher is not\n * told of their own announcement.\n */\nexport async function sendOut(announcement: Announcement, domain: Domain, by: { id: string }, tx: EntityManager): Promise<string[]> {\n const now = new Date()\n await getRepository(Announcement, tx).update(announcement.id, {\n status: AnnouncementStatus.PUBLISHED,\n publishedAt: now,\n startsAt: announcement.startsAt ?? now,\n publisher: by,\n updater: by\n } as any)\n const fresh = await getRepository(Announcement, tx).findOneBy({ id: announcement.id })\n await keepRevision(fresh!, domain, by, tx)\n return (await alignRoster(fresh!, domain, by, tx)).filter(id => id !== by.id)\n}\n\n/** The sentences in `lng` from this module's translations, the English one where `lng` has none. */\nconst sayIn =\n (lng: string): Say =>\n (key, english, params = {}) =>\n translatorFor(lng)(key, { ...params, defaultValue: english.replace(/\\{(\\w+)\\}/g, (_, name) => String(params[name] ?? '')) })\n\n/** The people to tell, as notification takes them - only those who can sign in, each with their mail and language. */\nasync function receiversOf(userIds: string[], tx?: EntityManager) {\n if (!userIds.length) return []\n const people = await getRepository(User, tx).find({ where: { id: In(userIds) } as any })\n return people.filter(one => one.status === UserStatus.ACTIVATED).map(one => ({ id: one.id, email: one.email, locale: (one as any).locale }))\n}\n\n/**\n * The notice of an announcement (notification ADR-0164): in the app and by web push always - the `announcement` type is\n * what pops it up - and by mail when the announcement asks for it and the domain has mail on.\n */\nfunction noticeOf(one: Announcement, kind: NoticeKind, receivers: Notice['receivers'], broadcast: boolean, link?: string): Notice {\n return {\n type: 'announcement',\n level: one.importance === 'URGENT' ? 'warn' : 'info',\n receivers,\n words: lng => noticeWordsOf(one, kind, sayIn(lng)),\n address: viewAddressOf(one.id),\n link,\n label: `announcement ${kind} ${one.id}`,\n /* The mail carries the whole body, drawn from its Markdown; the inbox and push show the summary. */\n format: 'markdown',\n channels: { email: !!one.sendEmail },\n /* Said once to the domain's Teams channel too - only what is addressed to everyone, and only when it goes out or all are told again. */\n ...(broadcast ? { broadcast: true } : {})\n }\n}\n\n/**\n * Tells `userIds` of it once the request's transaction has committed - a reader told before it would not find it yet -\n * and keeps what went out. A notice that does not arrive does not undo the announcement: its list, badge and popup\n * still reach them.\n */\nexport async function tellWhenCommitted(context: any, one: Announcement, kind: NoticeKind, userIds: string[], toEveryone = false): Promise<void> {\n const receivers = await receiversOf(userIds, context.state.tx)\n if (!receivers.length) return\n const broadcast = toEveryone && broadcastOf(await audiencesOf(one.id, context.state.tx), context.state.domain?.id)\n sendNoticeWhenCommitted(context, noticeOf(one, kind, receivers, broadcast, noticeLinkOf(context, viewAddressOf(one.id))), result =>\n keepNoticeDelivery(Announcement, one.id, 'deliveries', noticeDeliveryOf(kind, result, receivers.length))\n )\n}\n\n/**\n * Tells everyone on its roster - those it names now and those it named before - that it changed, so their badge and\n * list ask again (shell's myChange). No notice and no words: a notice is only for what people are to be told of.\n * `context` is a request's, or `{ state: { domain } }` outside one.\n */\nexport async function tellRosterChange(context: any, announcementId: string, tx?: EntityManager): Promise<void> {\n const receipts = await getRepository(AnnouncementReceipt, tx).find({ where: { announcement: { id: announcementId } } as any })\n tellChange(context, { kind: 'announcement', id: announcementId, userIds: receipts.map(one => one.userId) })\n}\n\n/**\n * Publishes the scheduled announcements whose start has come. Each is taken by one update from SCHEDULED, so a server\n * among several that loses the race does not send it twice.\n */\nexport async function publishDue(now = new Date()): Promise<number> {\n const due = await getRepository(Announcement).find({\n where: { status: AnnouncementStatus.SCHEDULED, startsAt: LessThanOrEqual(now), deletedAt: IsNull() } as any,\n relations: ['domain', 'publisher', 'creator'],\n take: 50\n })\n let published = 0\n for (const one of due) {\n try {\n const by = { id: one.publisherId ?? one.creatorId! }\n const receivers = await getDataSource().transaction(async tx => {\n const taken = await tx.getRepository(Announcement).update({ id: one.id, status: AnnouncementStatus.SCHEDULED } as any, { status: AnnouncementStatus.DRAFT } as any)\n if (!taken.affected) return undefined\n return await sendOut({ ...one, status: AnnouncementStatus.DRAFT } as Announcement, one.domain!, by, tx)\n })\n if (!receivers) continue\n published++\n await tellRosterChange({ state: { domain: one.domain } }, one.id)\n /* No request, so no address to put on a mail button - the mail says where to find it instead. */\n const people = await receiversOf(receivers)\n const broadcast = broadcastOf(await audiencesOf(one.id), one.domain?.id)\n if (people.length) await keepNoticeDelivery(Announcement, one.id, 'deliveries', noticeDeliveryOf('published', await sendNotice(one.domain, noticeOf(one, 'published', people, broadcast)), people.length))\n } catch (error) {\n logger.error(`announcement ${one.id}: publishing at its start failed`, error)\n }\n }\n return published\n}\n\n/**\n * Tells the rosters of the announcements whose period ended after `since` and by `now` - nothing else moves their\n * badge then. Each server that runs it tells them; a second telling only asks the count again.\n */\nexport async function tellEnded(since: Date, now = new Date()): Promise<number> {\n const ended = await getRepository(Announcement).find({\n where: { status: AnnouncementStatus.PUBLISHED, endsAt: Between(new Date(since.getTime() + 1), now), deletedAt: IsNull() } as any,\n relations: ['domain']\n })\n for (const one of ended) await tellRosterChange({ state: { domain: one.domain } }, one.id)\n return ended.length\n}\n\nlet timer: ReturnType<typeof setInterval> | undefined\n\n/**\n * Every minute, publishes the scheduled announcements whose start has come and tells the rosters of those whose period\n * ended. The timer never keeps the process alive.\n */\nexport function schedulePublishing(): void {\n if (timer) return\n let since = new Date()\n timer = setInterval(() => {\n const now = new Date()\n void publishDue(now).catch(error => logger.error('scheduled announcements', error))\n void tellEnded(since, now).catch(error => logger.error('ended announcements', error))\n since = now\n }, 60 * 1000)\n timer.unref?.()\n}\n"]}
@@ -79,6 +79,7 @@ async function announce(context, of) {
79
79
  const receivers = await (0, announcement_service_1.sendOut)(saved, domain, user, tx);
80
80
  const fresh = (await repository.findOneBy({ id: saved.id }));
81
81
  await (0, announcement_service_1.tellWhenCommitted)(context, fresh, 'published', receivers, true);
82
+ await (0, announcement_service_1.tellRosterChange)(context, saved.id, tx);
82
83
  return fresh;
83
84
  }
84
85
  /** The announcements of a record, newest first - drafts too, the record's keepers read where it stands. */
@@ -1 +1 @@
1
- {"version":3,"file":"announcement-trigger.js","sourceRoot":"","sources":["../../../server/service/announcement/announcement-trigger.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * 계기 (ADR-0163 decision 7, the least of it) - a module tells of a fact of its own as an announcement: a company rule\n * adopted, a training scheduled. The module names the trigger and gives the words and the record; the application says,\n * once at boot, how an announcement of that trigger goes out (its kind, its weight, who reads it, draft or out at once).\n * A trigger with no rule writes nothing - an application that has not decided tells nobody.\n *\n * The announcement keeps its trigger and record (`trigger`, `sourceKind`, `sourceId`), so the record finds the\n * announcements of it and their readings - the reading is kept here once, never again by the module.\n */\nimport { EntityManager, In } from 'typeorm'\n\nimport { logger } from '@things-factory/env'\nimport { getRepository } from '@things-factory/shell'\n\nimport { Announcement, AnnouncementAudience, AnnouncementImportance, AnnouncementReceipt, AnnouncementStatus } from './announcement'\nimport { ANNOUNCEMENT_CATEGORIES, rankOf } from './announcement-rules'\nimport { sendOut, tellWhenCommitted } from './announcement-service'\n\nexport interface AnnouncementTrigger {\n /** `compliance.regulation-adopted` - the module's name, a dot, the fact. */\n name: string\n description: string\n}\n\nexport interface AnnouncementTriggerRule {\n category?: (typeof ANNOUNCEMENT_CATEGORIES)[number]\n importance?: AnnouncementImportance | 'NORMAL' | 'IMPORTANT' | 'URGENT'\n requiresAcknowledgement?: boolean\n popup?: boolean\n sendEmail?: boolean\n /** Who reads it when the trigger names nobody: the whole domain, or nobody (the trigger must name them). */\n audience?: 'DOMAIN' | 'GIVEN'\n /** Out at once; otherwise written as a draft for its writer to look over and send (ADR-0187 정한 것 2). */\n publish?: boolean\n}\n\nexport interface AnnouncementOfTrigger {\n trigger: string\n sourceKind: string\n sourceId: string\n title: string\n body?: string\n links?: { label: string; url: string }[]\n audiences?: { scope: 'DOMAIN' | 'DEPARTMENT' | 'ROLE' | 'USER'; targetId: string; targetName?: string }[]\n /** The day by which the readers are asked to acknowledge it, where the rule asks for that. */\n acknowledgeBy?: Date | null\n}\n\nconst TRIGGERS = new Map<string, AnnouncementTrigger>()\nconst RULES = new Map<string, AnnouncementTriggerRule>()\n\n/** What a module calls at load to declare a trigger of its own. */\nexport function registerAnnouncementTrigger(trigger: AnnouncementTrigger): void {\n TRIGGERS.set(trigger.name, trigger)\n}\n\n/** What an application calls at boot: how announcements of a trigger go out. */\nexport function configureAnnouncementTrigger(name: string, rule: AnnouncementTriggerRule): void {\n RULES.set(name, rule)\n}\n\nexport function announcementTriggers(): (AnnouncementTrigger & { rule?: AnnouncementTriggerRule })[] {\n return [...TRIGGERS.values()].map(one => ({ ...one, rule: RULES.get(one.name) }))\n}\n\n/**\n * Writes the announcement of a trigger in the request's transaction, its writer the request's person. Answers it, or\n * nothing where the application set no rule for the trigger.\n */\nexport async function announce(context: any, of: AnnouncementOfTrigger): Promise<Announcement | null> {\n const { domain, user, tx } = context.state as { domain: any; user: any; tx: EntityManager }\n if (!TRIGGERS.has(of.trigger)) throw new Error(`announcement trigger '${of.trigger}' is not registered`)\n const rule = RULES.get(of.trigger)\n if (!rule) {\n logger.info(`[Announcement] ${domain?.subdomain}: no rule for '${of.trigger}' - nothing written`)\n return null\n }\n const importance = (rule.importance as AnnouncementImportance) ?? AnnouncementImportance.NORMAL\n const requiresAcknowledgement = !!rule.requiresAcknowledgement\n const repository = getRepository(Announcement, tx)\n const saved = await repository.save({\n domain,\n title: of.title.trim().slice(0, 200),\n body: of.body ?? null,\n category: rule.category ?? 'GENERAL',\n importance,\n pinned: false,\n rank: rankOf({ pinned: false, importance }),\n requiresAcknowledgement,\n acknowledgeBy: requiresAcknowledgement ? (of.acknowledgeBy ?? null) : null,\n popup: !!rule.popup,\n sendEmail: !!rule.sendEmail,\n links: (of.links ?? []).slice(0, 10),\n trigger: of.trigger,\n sourceKind: of.sourceKind,\n sourceId: of.sourceId,\n status: AnnouncementStatus.DRAFT,\n version: 1,\n creator: user,\n updater: user\n } as any)\n const audiences = of.audiences?.length ? of.audiences : rule.audience === 'GIVEN' ? [] : [{ scope: 'DOMAIN' as const, targetId: domain.id, targetName: domain.name }]\n for (const target of audiences)\n await getRepository(AnnouncementAudience, tx).save({ domain, announcement: { id: saved.id }, scope: target.scope, targetId: target.targetId, targetName: target.targetName?.slice(0, 100), creator: user, updater: user } as any)\n if (!rule.publish || !audiences.length) return saved\n const receivers = await sendOut(saved, domain, user, tx)\n const fresh = (await repository.findOneBy({ id: saved.id }))!\n await tellWhenCommitted(context, fresh, 'published', receivers, true)\n return fresh\n}\n\n/** The announcements of a record, newest first - drafts too, the record's keepers read where it stands. */\nexport async function announcementsOfSource(domain: { id: string }, sourceKind: string, sourceIds: string[], tx?: EntityManager): Promise<Announcement[]> {\n if (!sourceIds.length) return []\n return await getRepository(Announcement, tx).find({ where: { domain: { id: domain.id }, sourceKind, sourceId: In(sourceIds) } as any, order: { createdAt: 'DESC' } as any })\n}\n\n/** A person's readings of announcements, by announcement. */\nexport async function receiptsOf(announcementIds: string[], userId: string, tx?: EntityManager): Promise<Map<string, AnnouncementReceipt>> {\n if (!announcementIds.length) return new Map()\n const rows = await getRepository(AnnouncementReceipt, tx).find({ where: { announcement: { id: In(announcementIds) }, user: { id: userId } } as any })\n return new Map(rows.map(one => [one.announcementId!, one]))\n}\n"]}
1
+ {"version":3,"file":"announcement-trigger.js","sourceRoot":"","sources":["../../../server/service/announcement/announcement-trigger.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * 계기 (ADR-0163 decision 7, the least of it) - a module tells of a fact of its own as an announcement: a company rule\n * adopted, a training scheduled. The module names the trigger and gives the words and the record; the application says,\n * once at boot, how an announcement of that trigger goes out (its kind, its weight, who reads it, draft or out at once).\n * A trigger with no rule writes nothing - an application that has not decided tells nobody.\n *\n * The announcement keeps its trigger and record (`trigger`, `sourceKind`, `sourceId`), so the record finds the\n * announcements of it and their readings - the reading is kept here once, never again by the module.\n */\nimport { EntityManager, In } from 'typeorm'\n\nimport { logger } from '@things-factory/env'\nimport { getRepository } from '@things-factory/shell'\n\nimport { Announcement, AnnouncementAudience, AnnouncementImportance, AnnouncementReceipt, AnnouncementStatus } from './announcement'\nimport { ANNOUNCEMENT_CATEGORIES, rankOf } from './announcement-rules'\nimport { sendOut, tellRosterChange, tellWhenCommitted } from './announcement-service'\n\nexport interface AnnouncementTrigger {\n /** `compliance.regulation-adopted` - the module's name, a dot, the fact. */\n name: string\n description: string\n}\n\nexport interface AnnouncementTriggerRule {\n category?: (typeof ANNOUNCEMENT_CATEGORIES)[number]\n importance?: AnnouncementImportance | 'NORMAL' | 'IMPORTANT' | 'URGENT'\n requiresAcknowledgement?: boolean\n popup?: boolean\n sendEmail?: boolean\n /** Who reads it when the trigger names nobody: the whole domain, or nobody (the trigger must name them). */\n audience?: 'DOMAIN' | 'GIVEN'\n /** Out at once; otherwise written as a draft for its writer to look over and send (ADR-0187 정한 것 2). */\n publish?: boolean\n}\n\nexport interface AnnouncementOfTrigger {\n trigger: string\n sourceKind: string\n sourceId: string\n title: string\n body?: string\n links?: { label: string; url: string }[]\n audiences?: { scope: 'DOMAIN' | 'DEPARTMENT' | 'ROLE' | 'USER'; targetId: string; targetName?: string }[]\n /** The day by which the readers are asked to acknowledge it, where the rule asks for that. */\n acknowledgeBy?: Date | null\n}\n\nconst TRIGGERS = new Map<string, AnnouncementTrigger>()\nconst RULES = new Map<string, AnnouncementTriggerRule>()\n\n/** What a module calls at load to declare a trigger of its own. */\nexport function registerAnnouncementTrigger(trigger: AnnouncementTrigger): void {\n TRIGGERS.set(trigger.name, trigger)\n}\n\n/** What an application calls at boot: how announcements of a trigger go out. */\nexport function configureAnnouncementTrigger(name: string, rule: AnnouncementTriggerRule): void {\n RULES.set(name, rule)\n}\n\nexport function announcementTriggers(): (AnnouncementTrigger & { rule?: AnnouncementTriggerRule })[] {\n return [...TRIGGERS.values()].map(one => ({ ...one, rule: RULES.get(one.name) }))\n}\n\n/**\n * Writes the announcement of a trigger in the request's transaction, its writer the request's person. Answers it, or\n * nothing where the application set no rule for the trigger.\n */\nexport async function announce(context: any, of: AnnouncementOfTrigger): Promise<Announcement | null> {\n const { domain, user, tx } = context.state as { domain: any; user: any; tx: EntityManager }\n if (!TRIGGERS.has(of.trigger)) throw new Error(`announcement trigger '${of.trigger}' is not registered`)\n const rule = RULES.get(of.trigger)\n if (!rule) {\n logger.info(`[Announcement] ${domain?.subdomain}: no rule for '${of.trigger}' - nothing written`)\n return null\n }\n const importance = (rule.importance as AnnouncementImportance) ?? AnnouncementImportance.NORMAL\n const requiresAcknowledgement = !!rule.requiresAcknowledgement\n const repository = getRepository(Announcement, tx)\n const saved = await repository.save({\n domain,\n title: of.title.trim().slice(0, 200),\n body: of.body ?? null,\n category: rule.category ?? 'GENERAL',\n importance,\n pinned: false,\n rank: rankOf({ pinned: false, importance }),\n requiresAcknowledgement,\n acknowledgeBy: requiresAcknowledgement ? (of.acknowledgeBy ?? null) : null,\n popup: !!rule.popup,\n sendEmail: !!rule.sendEmail,\n links: (of.links ?? []).slice(0, 10),\n trigger: of.trigger,\n sourceKind: of.sourceKind,\n sourceId: of.sourceId,\n status: AnnouncementStatus.DRAFT,\n version: 1,\n creator: user,\n updater: user\n } as any)\n const audiences = of.audiences?.length ? of.audiences : rule.audience === 'GIVEN' ? [] : [{ scope: 'DOMAIN' as const, targetId: domain.id, targetName: domain.name }]\n for (const target of audiences)\n await getRepository(AnnouncementAudience, tx).save({ domain, announcement: { id: saved.id }, scope: target.scope, targetId: target.targetId, targetName: target.targetName?.slice(0, 100), creator: user, updater: user } as any)\n if (!rule.publish || !audiences.length) return saved\n const receivers = await sendOut(saved, domain, user, tx)\n const fresh = (await repository.findOneBy({ id: saved.id }))!\n await tellWhenCommitted(context, fresh, 'published', receivers, true)\n await tellRosterChange(context, saved.id, tx)\n return fresh\n}\n\n/** The announcements of a record, newest first - drafts too, the record's keepers read where it stands. */\nexport async function announcementsOfSource(domain: { id: string }, sourceKind: string, sourceIds: string[], tx?: EntityManager): Promise<Announcement[]> {\n if (!sourceIds.length) return []\n return await getRepository(Announcement, tx).find({ where: { domain: { id: domain.id }, sourceKind, sourceId: In(sourceIds) } as any, order: { createdAt: 'DESC' } as any })\n}\n\n/** A person's readings of announcements, by announcement. */\nexport async function receiptsOf(announcementIds: string[], userId: string, tx?: EntityManager): Promise<Map<string, AnnouncementReceipt>> {\n if (!announcementIds.length) return new Map()\n const rows = await getRepository(AnnouncementReceipt, tx).find({ where: { announcement: { id: In(announcementIds) }, user: { id: userId } } as any })\n return new Map(rows.map(one => [one.announcementId!, one]))\n}\n"]}