@things-factory/announcement 10.1.270 → 10.1.271
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/announcement/announcement-resolver.js +4 -0
- package/dist-server/service/announcement/announcement-resolver.js.map +1 -1
- package/dist-server/service/announcement/announcement-service.d.ts +2 -0
- package/dist-server/service/announcement/announcement-service.js +6 -1
- package/dist-server/service/announcement/announcement-service.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/server/service/announcement/announcement-resolver.ts +4 -0
- package/server/service/announcement/announcement-service.ts +5 -0
- package/test/announcement-persistence.test.ts +5 -1
|
@@ -13,6 +13,7 @@ const announcement_1 = require("./announcement");
|
|
|
13
13
|
const announcement_rules_1 = require("./announcement-rules");
|
|
14
14
|
const announcement_service_1 = require("./announcement-service");
|
|
15
15
|
const announcement_types_1 = require("./announcement-types");
|
|
16
|
+
const notification_1 = require("@things-factory/notification");
|
|
16
17
|
const WRITE = '@privilege(category: "announcement", privilege: "mutation", domainOwnerGranted: true)';
|
|
17
18
|
/** A refusal said in the reader's words, with a code the screen may read. */
|
|
18
19
|
function refuse(context, code, fallback) {
|
|
@@ -211,6 +212,9 @@ let AnnouncementResolver = class AnnouncementResolver {
|
|
|
211
212
|
await repository.save({ domain, announcement: { id }, user: { id: user.id }, listed: false, ...patch, creator: user, updater: user });
|
|
212
213
|
else
|
|
213
214
|
await repository.update(receipt.id, { ...patch, updater: user });
|
|
215
|
+
/* Read: its notice is read too, on every device and screen (ADR-0164 amendment 1) - one reading, not two. */
|
|
216
|
+
if (patch.readAt)
|
|
217
|
+
await (0, notification_1.closeNotices)(tx, domain, 'announcement', (0, announcement_service_1.announcementNoticeKey)(id), [user.id]);
|
|
214
218
|
/* The reader's other windows - their badge asks again. */
|
|
215
219
|
(0, shell_1.tellChange)(context, { kind: 'announcement', id, userIds: [user.id] });
|
|
216
220
|
return visible.announcement;
|
|
@@ -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, 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"]}
|
|
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 announcementNoticeKey,\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'\nimport { closeNotices } from '@things-factory/notification'\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 /* Read: its notice is read too, on every device and screen (ADR-0164 amendment 1) - one reading, not two. */\n if (patch.readAt) await closeNotices(tx, domain, 'announcement', announcementNoticeKey(id), [user.id])\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"]}
|
|
@@ -39,6 +39,8 @@ export declare function keepRevision(announcement: Announcement, domain: Domain,
|
|
|
39
39
|
export declare function sendOut(announcement: Announcement, domain: Domain, by: {
|
|
40
40
|
id: string;
|
|
41
41
|
}, tx: EntityManager): Promise<string[]>;
|
|
42
|
+
/** What an announcement's notices tell of - a reader's are closed once they read it. */
|
|
43
|
+
export declare const announcementNoticeKey: (id: string) => string;
|
|
42
44
|
/**
|
|
43
45
|
* Tells `userIds` of it once the request's transaction has committed - a reader told before it would not find it yet -
|
|
44
46
|
* and keeps what went out. A notice that does not arrive does not undo the announcement: its list, badge and popup
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ANNOUNCEMENT_REF_TYPE = void 0;
|
|
3
|
+
exports.announcementNoticeKey = exports.ANNOUNCEMENT_REF_TYPE = void 0;
|
|
4
4
|
exports.isWriter = isWriter;
|
|
5
5
|
exports.memberOf = memberOf;
|
|
6
6
|
exports.reachingIds = reachingIds;
|
|
@@ -154,6 +154,9 @@ async function receiversOf(userIds, tx) {
|
|
|
154
154
|
const people = await (0, shell_1.getRepository)(auth_base_1.User, tx).find({ where: { id: (0, typeorm_1.In)(userIds) } });
|
|
155
155
|
return people.filter(one => one.status === auth_base_1.UserStatus.ACTIVATED).map(one => ({ id: one.id, email: one.email, locale: one.locale }));
|
|
156
156
|
}
|
|
157
|
+
/** What an announcement's notices tell of - a reader's are closed once they read it. */
|
|
158
|
+
const announcementNoticeKey = (id) => `announcement:${id}`;
|
|
159
|
+
exports.announcementNoticeKey = announcementNoticeKey;
|
|
157
160
|
/**
|
|
158
161
|
* The notice of an announcement (notification ADR-0164): in the app and by web push always - the `announcement` type is
|
|
159
162
|
* what pops it up - and by mail when the announcement asks for it and the domain has mail on.
|
|
@@ -166,6 +169,8 @@ function noticeOf(one, kind, receivers, broadcast, link) {
|
|
|
166
169
|
words: lng => (0, announcement_rules_1.noticeWordsOf)(one, kind, sayIn(lng)),
|
|
167
170
|
address: (0, announcement_rules_1.viewAddressOf)(one.id),
|
|
168
171
|
link,
|
|
172
|
+
/* closed for a person once they read it (`readAnnouncement`) */
|
|
173
|
+
key: (0, exports.announcementNoticeKey)(one.id),
|
|
169
174
|
label: `announcement ${kind} ${one.id}`,
|
|
170
175
|
/* The mail carries the whole body, drawn from its Markdown; the inbox and push show the summary. */
|
|
171
176
|
format: 'markdown',
|
|
@@ -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 { 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"]}
|
|
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/** What an announcement's notices tell of - a reader's are closed once they read it. */\nexport const announcementNoticeKey = (id: string) => `announcement:${id}`\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 /* closed for a person once they read it (`readAnnouncement`) */\n key: announcementNoticeKey(one.id),\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"]}
|