@things-factory/announcement 10.1.248 → 10.1.250
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/announcement-watch.d.ts +6 -0
- package/dist-client/announcement-watch.js +105 -0
- package/dist-client/announcement-watch.js.map +1 -0
- package/dist-client/bootstrap.d.ts +1 -0
- package/dist-client/bootstrap.js +8 -0
- package/dist-client/bootstrap.js.map +1 -0
- package/dist-client/components/announcement-popup.d.ts +20 -0
- package/dist-client/components/announcement-popup.js +98 -0
- package/dist-client/components/announcement-popup.js.map +1 -0
- package/dist-client/components/announcement-receipts.d.ts +30 -0
- package/dist-client/components/announcement-receipts.js +220 -0
- package/dist-client/components/announcement-receipts.js.map +1 -0
- package/dist-client/components/announcement-sheet.d.ts +17 -0
- package/dist-client/components/announcement-sheet.js +224 -0
- package/dist-client/components/announcement-sheet.js.map +1 -0
- package/dist-client/components/audience-picker.d.ts +32 -0
- package/dist-client/components/audience-picker.js +229 -0
- package/dist-client/components/audience-picker.js.map +1 -0
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +2 -0
- package/dist-client/index.js.map +1 -0
- package/dist-client/pages/announcement-editor.d.ts +59 -0
- package/dist-client/pages/announcement-editor.js +523 -0
- package/dist-client/pages/announcement-editor.js.map +1 -0
- package/dist-client/pages/announcement-list.d.ts +54 -0
- package/dist-client/pages/announcement-list.js +209 -0
- package/dist-client/pages/announcement-list.js.map +1 -0
- package/dist-client/pages/announcement-manage-list.d.ts +46 -0
- package/dist-client/pages/announcement-manage-list.js +115 -0
- package/dist-client/pages/announcement-manage-list.js.map +1 -0
- package/dist-client/pages/announcement-view.d.ts +30 -0
- package/dist-client/pages/announcement-view.js +182 -0
- package/dist-client/pages/announcement-view.js.map +1 -0
- package/dist-client/route.d.ts +1 -0
- package/dist-client/route.js +18 -0
- package/dist-client/route.js.map +1 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-client/utils/announcement-api.d.ts +149 -0
- package/dist-client/utils/announcement-api.js +52 -0
- package/dist-client/utils/announcement-api.js.map +1 -0
- package/dist-client/utils/announcement-badge.d.ts +4 -0
- package/dist-client/utils/announcement-badge.js +47 -0
- package/dist-client/utils/announcement-badge.js.map +1 -0
- package/dist-client/utils/announcement-words.d.ts +11 -0
- package/dist-client/utils/announcement-words.js +23 -0
- package/dist-client/utils/announcement-words.js.map +1 -0
- package/dist-server/announcement-read.d.ts +6 -0
- package/dist-server/announcement-read.js +45 -0
- package/dist-server/announcement-read.js.map +1 -0
- package/dist-server/attachment-reader.d.ts +1 -0
- package/dist-server/attachment-reader.js +13 -0
- package/dist-server/attachment-reader.js.map +1 -0
- package/dist-server/index.d.ts +2 -0
- package/dist-server/index.js +20 -0
- package/dist-server/index.js.map +1 -0
- package/dist-server/role-tasks.d.ts +2 -0
- package/dist-server/role-tasks.js +13 -0
- package/dist-server/role-tasks.js.map +1 -0
- package/dist-server/service/announcement/announcement-resolver.d.ts +38 -0
- package/dist-server/service/announcement/announcement-resolver.js +664 -0
- package/dist-server/service/announcement/announcement-resolver.js.map +1 -0
- package/dist-server/service/announcement/announcement-rules.d.ts +150 -0
- package/dist-server/service/announcement/announcement-rules.js +227 -0
- package/dist-server/service/announcement/announcement-rules.js.map +1 -0
- package/dist-server/service/announcement/announcement-service.d.ts +54 -0
- package/dist-server/service/announcement/announcement-service.js +248 -0
- package/dist-server/service/announcement/announcement-service.js.map +1 -0
- package/dist-server/service/announcement/announcement-types.d.ts +54 -0
- package/dist-server/service/announcement/announcement-types.js +203 -0
- package/dist-server/service/announcement/announcement-types.js.map +1 -0
- package/dist-server/service/announcement/announcement.d.ts +124 -0
- package/dist-server/service/announcement/announcement.js +462 -0
- package/dist-server/service/announcement/announcement.js.map +1 -0
- package/dist-server/service/announcement/index.d.ts +4 -0
- package/dist-server/service/announcement/index.js +8 -0
- package/dist-server/service/announcement/index.js.map +1 -0
- package/dist-server/service/index.d.ts +7 -0
- package/dist-server/service/index.js +23 -0
- package/dist-server/service/index.js.map +1 -0
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +8 -8
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AnnouncementResolver = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const GraphQLUpload_js_1 = tslib_1.__importDefault(require("graphql-upload/GraphQLUpload.js"));
|
|
6
|
+
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const typeorm_1 = require("typeorm");
|
|
8
|
+
const attachment_base_1 = require("@things-factory/attachment-base");
|
|
9
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
10
|
+
const organization_1 = require("@things-factory/organization");
|
|
11
|
+
const shell_1 = require("@things-factory/shell");
|
|
12
|
+
const announcement_1 = require("./announcement");
|
|
13
|
+
const announcement_rules_1 = require("./announcement-rules");
|
|
14
|
+
const announcement_service_1 = require("./announcement-service");
|
|
15
|
+
const announcement_types_1 = require("./announcement-types");
|
|
16
|
+
const WRITE = '@privilege(category: "announcement", privilege: "mutation", domainOwnerGranted: true)';
|
|
17
|
+
/** A refusal said in the reader's words, with a code the screen may read. */
|
|
18
|
+
function refuse(context, code, fallback) {
|
|
19
|
+
const message = context.t ? String(context.t(`announcement.refusal.${code}`, { defaultValue: fallback })) : fallback;
|
|
20
|
+
const error = new Error(message);
|
|
21
|
+
error.extensions = { code: `announcement.${code}` };
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
const NOT_FOUND = 'there is no such announcement.';
|
|
25
|
+
/** The announcement the request may see, refused otherwise. */
|
|
26
|
+
async function visibleOrRefuse(id, context, tx) {
|
|
27
|
+
const visible = await (0, announcement_service_1.visibleAnnouncement)(id, context, tx);
|
|
28
|
+
if (!visible)
|
|
29
|
+
refuse(context, 'unknown-announcement', NOT_FOUND);
|
|
30
|
+
return visible;
|
|
31
|
+
}
|
|
32
|
+
/** One the writer may change: any that is not somebody else's draft, and not withdrawn. */
|
|
33
|
+
async function changeable(id, context, tx) {
|
|
34
|
+
const visible = await visibleOrRefuse(id, context, tx);
|
|
35
|
+
if (!visible.writer)
|
|
36
|
+
refuse(context, 'unknown-announcement', NOT_FOUND);
|
|
37
|
+
if (visible.announcement.status === announcement_1.AnnouncementStatus.WITHDRAWN)
|
|
38
|
+
refuse(context, 'withdrawn', 'a withdrawn announcement is not changed.');
|
|
39
|
+
return visible.announcement;
|
|
40
|
+
}
|
|
41
|
+
/** The fields of the input as stored, checked against the rules. */
|
|
42
|
+
function fieldsOf(input, context) {
|
|
43
|
+
const refusal = (0, announcement_rules_1.inputRefusal)(input);
|
|
44
|
+
if (refusal)
|
|
45
|
+
refuse(context, refusal, `the announcement cannot be kept (${refusal}).`);
|
|
46
|
+
const importance = input.importance || announcement_1.AnnouncementImportance.NORMAL;
|
|
47
|
+
const pinned = !!input.pinned;
|
|
48
|
+
return {
|
|
49
|
+
title: input.title.trim(),
|
|
50
|
+
body: input.body ?? null,
|
|
51
|
+
category: input.category || 'GENERAL',
|
|
52
|
+
importance,
|
|
53
|
+
startsAt: input.startsAt ?? null,
|
|
54
|
+
endsAt: input.endsAt ?? null,
|
|
55
|
+
pinned,
|
|
56
|
+
rank: (0, announcement_rules_1.rankOf)({ pinned, importance }),
|
|
57
|
+
requiresAcknowledgement: !!input.requiresAcknowledgement,
|
|
58
|
+
acknowledgeBy: input.requiresAcknowledgement ? (input.acknowledgeBy ?? null) : null,
|
|
59
|
+
popup: !!input.popup,
|
|
60
|
+
sendEmail: !!input.sendEmail,
|
|
61
|
+
links: (input.links ?? []).map(({ label, url }) => ({ label: label.trim(), url: url.trim() }))
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/** Sets the whole audience - each target checked against the domain - and answers whether it changed. */
|
|
65
|
+
async function setAudiences(announcement, wanted, context, tx) {
|
|
66
|
+
const { domain, user } = context.state;
|
|
67
|
+
const scopes = new Set(wanted.map(one => one.scope));
|
|
68
|
+
const departmentIds = scopes.has('DEPARTMENT') ? [...(await (0, organization_1.departmentTreeOf)(domain, tx)).keys()] : [];
|
|
69
|
+
const roleIds = scopes.has('ROLE') ? (await (0, organization_1.domainRolesOf)(domain, undefined, tx)).map(one => one.id) : [];
|
|
70
|
+
const people = scopes.has('USER') ? new Set((await (0, auth_base_1.getDomainAssignees)(domain, tx)).map(one => one.id)) : new Set();
|
|
71
|
+
const byKey = new Map();
|
|
72
|
+
for (const target of wanted) {
|
|
73
|
+
const refusal = (0, organization_1.audienceTargetRefusal)(target, { domainId: domain.id, departmentIds, roleIds }) ?? (target.scope === 'USER' && !people.has(target.targetId) ? 'unknown-person' : undefined);
|
|
74
|
+
if (refusal)
|
|
75
|
+
refuse(context, `audience-${refusal}`, `this target cannot be given (${refusal}).`);
|
|
76
|
+
byKey.set(`${target.scope}:${target.targetId}`, target);
|
|
77
|
+
}
|
|
78
|
+
const repository = (0, shell_1.getRepository)(announcement_1.AnnouncementAudience, tx);
|
|
79
|
+
const current = await (0, announcement_service_1.audiencesOf)(announcement.id, tx);
|
|
80
|
+
const gone = current.filter(one => !byKey.has(`${one.scope}:${one.targetId}`));
|
|
81
|
+
if (gone.length)
|
|
82
|
+
await repository.softRemove(gone);
|
|
83
|
+
let added = 0;
|
|
84
|
+
for (const [key, target] of byKey) {
|
|
85
|
+
if (current.some(one => `${one.scope}:${one.targetId}` === key))
|
|
86
|
+
continue;
|
|
87
|
+
added++;
|
|
88
|
+
await repository.save({ domain, announcement: { id: announcement.id }, scope: target.scope, targetId: target.targetId, targetName: target.targetName?.slice(0, 100), creator: user, updater: user });
|
|
89
|
+
}
|
|
90
|
+
return gone.length + added > 0;
|
|
91
|
+
}
|
|
92
|
+
async function attachFiles(announcementId, attach, remove, context) {
|
|
93
|
+
for (const id of remove ?? []) {
|
|
94
|
+
const file = await (0, shell_1.getRepository)(attachment_base_1.Attachment, context.state.tx).findOne({ where: { id, domain: { id: context.state.domain.id }, refType: announcement_service_1.ANNOUNCEMENT_REF_TYPE, refBy: announcementId } });
|
|
95
|
+
if (file)
|
|
96
|
+
await (0, attachment_base_1.deleteAttachment)(null, { id }, context);
|
|
97
|
+
}
|
|
98
|
+
for (const file of attach ?? []) {
|
|
99
|
+
await (0, attachment_base_1.createAttachment)(null, { attachment: { file, refType: announcement_service_1.ANNOUNCEMENT_REF_TYPE, refBy: announcementId } }, context);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** The reader's own receipts of `ids`, by announcement. */
|
|
103
|
+
async function myReceipts(ids, userId, tx) {
|
|
104
|
+
if (!ids.length)
|
|
105
|
+
return new Map();
|
|
106
|
+
const rows = await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt, tx).find({ where: { announcement: { id: (0, typeorm_1.In)(ids) }, user: { id: userId } } });
|
|
107
|
+
return new Map(rows.map(one => [one.announcementId, one]));
|
|
108
|
+
}
|
|
109
|
+
/** The current announcements addressed to the request's person, with their receipts. */
|
|
110
|
+
async function currentForReader(context) {
|
|
111
|
+
const { domain, user } = context.state;
|
|
112
|
+
const ids = await (0, announcement_service_1.reachingIds)(await (0, announcement_service_1.memberOf)(context));
|
|
113
|
+
if (!ids.length)
|
|
114
|
+
return { items: [], receipts: new Map() };
|
|
115
|
+
const now = new Date();
|
|
116
|
+
const items = await (0, shell_1.getRepository)(announcement_1.Announcement).find({
|
|
117
|
+
where: [
|
|
118
|
+
{ id: (0, typeorm_1.In)(ids), domain: { id: domain.id }, status: announcement_1.AnnouncementStatus.PUBLISHED, endsAt: (0, typeorm_1.IsNull)() },
|
|
119
|
+
{ id: (0, typeorm_1.In)(ids), domain: { id: domain.id }, status: announcement_1.AnnouncementStatus.PUBLISHED, endsAt: (0, typeorm_1.MoreThan)(now) }
|
|
120
|
+
],
|
|
121
|
+
order: { rank: 'ASC', publishedAt: 'DESC' }
|
|
122
|
+
});
|
|
123
|
+
return { items, receipts: await myReceipts(items.map(one => one.id), user.id) };
|
|
124
|
+
}
|
|
125
|
+
let AnnouncementResolver = class AnnouncementResolver {
|
|
126
|
+
/* ---------------------------------------------------------------- reading - the audience */
|
|
127
|
+
async announcements(params, context) {
|
|
128
|
+
const { domain, user } = context.state;
|
|
129
|
+
const { rest, period, states, refusal } = (0, announcement_rules_1.readerNarrowingOf)(params.filters);
|
|
130
|
+
if (refusal)
|
|
131
|
+
refuse(context, refusal, `the list cannot be narrowed so (${refusal}).`);
|
|
132
|
+
let ids = await (0, announcement_service_1.reachingIds)(await (0, announcement_service_1.memberOf)(context));
|
|
133
|
+
if (states && ids.length) {
|
|
134
|
+
const candidates = await (0, shell_1.getRepository)(announcement_1.Announcement).find({ where: { id: (0, typeorm_1.In)(ids), status: announcement_1.AnnouncementStatus.PUBLISHED } });
|
|
135
|
+
const receipts = await myReceipts(candidates.map(one => one.id), user.id);
|
|
136
|
+
ids = candidates.filter(one => states.includes((0, announcement_rules_1.readerStateOf)(one, receipts.get(one.id)))).map(one => one.id);
|
|
137
|
+
}
|
|
138
|
+
if (!ids.length)
|
|
139
|
+
return { items: [], total: 0 };
|
|
140
|
+
const now = new Date();
|
|
141
|
+
const qb = (0, shell_1.getQueryBuilderFromListParams)({
|
|
142
|
+
domain,
|
|
143
|
+
params: { ...params, filters: rest, sortings: [] },
|
|
144
|
+
repository: (0, shell_1.getRepository)(announcement_1.Announcement),
|
|
145
|
+
alias: 'A',
|
|
146
|
+
searchables: ['title', 'body', 'category']
|
|
147
|
+
})
|
|
148
|
+
.andWhere('A.id IN (:...ids)', { ids })
|
|
149
|
+
.andWhere('A.status = :published', { published: announcement_1.AnnouncementStatus.PUBLISHED });
|
|
150
|
+
if (period === 'past')
|
|
151
|
+
qb.andWhere('A.endsAt <= :now', { now });
|
|
152
|
+
if (period === 'current')
|
|
153
|
+
qb.andWhere('(A.endsAt IS NULL OR A.endsAt > :now)', { now }).orderBy('A.rank', 'ASC').addOrderBy('A.publishedAt', 'DESC');
|
|
154
|
+
else
|
|
155
|
+
qb.orderBy('A.publishedAt', 'DESC');
|
|
156
|
+
const [items, total] = await qb.getManyAndCount();
|
|
157
|
+
const receipts = await myReceipts(items.map(one => one.id), user.id);
|
|
158
|
+
for (const one of items)
|
|
159
|
+
one.__mine = receipts.get(one.id) ?? null;
|
|
160
|
+
return { items, total };
|
|
161
|
+
}
|
|
162
|
+
async announcement(id, context) {
|
|
163
|
+
return (await (0, announcement_service_1.visibleAnnouncement)(id, context))?.announcement;
|
|
164
|
+
}
|
|
165
|
+
async announcementSummary(context) {
|
|
166
|
+
const { items, receipts } = await currentForReader(context);
|
|
167
|
+
let unread = 0;
|
|
168
|
+
let toAcknowledge = 0;
|
|
169
|
+
let pending = 0;
|
|
170
|
+
for (const one of items) {
|
|
171
|
+
const state = (0, announcement_rules_1.readerStateOf)(one, receipts.get(one.id));
|
|
172
|
+
if (state === 'unread')
|
|
173
|
+
unread++;
|
|
174
|
+
if (one.requiresAcknowledgement && state !== 'acknowledged')
|
|
175
|
+
toAcknowledge++;
|
|
176
|
+
if (state === 'unread' || state === 'to-acknowledge')
|
|
177
|
+
pending++;
|
|
178
|
+
}
|
|
179
|
+
return { unread, toAcknowledge, pending };
|
|
180
|
+
}
|
|
181
|
+
async announcementPopups(context) {
|
|
182
|
+
const { items, receipts } = await currentForReader(context);
|
|
183
|
+
const now = new Date();
|
|
184
|
+
return items.filter(one => (0, announcement_rules_1.popupDue)(one, receipts.get(one.id), now)).map(one => Object.assign(one, { __mine: receipts.get(one.id) ?? null }));
|
|
185
|
+
}
|
|
186
|
+
async readAnnouncement(id, context) {
|
|
187
|
+
return await this.receive(id, context, false);
|
|
188
|
+
}
|
|
189
|
+
async acknowledgeAnnouncement(id, context) {
|
|
190
|
+
return await this.receive(id, context, true);
|
|
191
|
+
}
|
|
192
|
+
async receive(id, context, acknowledge) {
|
|
193
|
+
const { domain, user, tx } = context.state;
|
|
194
|
+
const visible = await visibleOrRefuse(id, context, tx);
|
|
195
|
+
/* Only its audience reads it into the record - a writer looking at one addressed to others leaves no trace. */
|
|
196
|
+
if (!visible.reader)
|
|
197
|
+
return visible.announcement;
|
|
198
|
+
if (acknowledge && !visible.announcement.requiresAcknowledgement)
|
|
199
|
+
refuse(context, 'no-acknowledgement', 'this announcement does not ask to be acknowledged.');
|
|
200
|
+
const repository = (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt, tx);
|
|
201
|
+
const now = new Date();
|
|
202
|
+
const receipt = await repository.findOne({ where: { announcement: { id }, user: { id: user.id } } });
|
|
203
|
+
const patch = {};
|
|
204
|
+
if (!receipt?.readAt)
|
|
205
|
+
patch.readAt = now;
|
|
206
|
+
if (acknowledge && !receipt?.acknowledgedAt)
|
|
207
|
+
patch.acknowledgedAt = now;
|
|
208
|
+
if (!receipt)
|
|
209
|
+
await repository.save({ domain, announcement: { id }, user: { id: user.id }, listed: false, ...patch, creator: user, updater: user });
|
|
210
|
+
else if (Object.keys(patch).length)
|
|
211
|
+
await repository.update(receipt.id, { ...patch, updater: user });
|
|
212
|
+
return visible.announcement;
|
|
213
|
+
}
|
|
214
|
+
/* ---------------------------------------------------------------- writing and managing */
|
|
215
|
+
async managedAnnouncements(params, context) {
|
|
216
|
+
const { domain, user } = context.state;
|
|
217
|
+
const qb = (0, shell_1.getQueryBuilderFromListParams)({
|
|
218
|
+
domain,
|
|
219
|
+
params,
|
|
220
|
+
repository: (0, shell_1.getRepository)(announcement_1.Announcement),
|
|
221
|
+
alias: 'A',
|
|
222
|
+
searchables: ['title', 'body', 'category']
|
|
223
|
+
}).andWhere('(A.status != :draft OR A.creator = :me)', { draft: announcement_1.AnnouncementStatus.DRAFT, me: user.id });
|
|
224
|
+
if (!params.sortings?.length)
|
|
225
|
+
qb.orderBy('A.updatedAt', 'DESC');
|
|
226
|
+
const [items, total] = await qb.getManyAndCount();
|
|
227
|
+
return { items, total };
|
|
228
|
+
}
|
|
229
|
+
async announcementReceipts(id, context) {
|
|
230
|
+
const visible = await visibleOrRefuse(id, context);
|
|
231
|
+
if (!visible.writer)
|
|
232
|
+
refuse(context, 'unknown-announcement', NOT_FOUND);
|
|
233
|
+
const receipts = await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt).find({ where: { announcement: { id } }, relations: ['user'] });
|
|
234
|
+
return receipts
|
|
235
|
+
.map(one => ({
|
|
236
|
+
userId: one.userId,
|
|
237
|
+
name: one.user?.name,
|
|
238
|
+
email: one.user?.email,
|
|
239
|
+
listed: one.listed,
|
|
240
|
+
notifiedAt: one.notifiedAt,
|
|
241
|
+
readAt: one.readAt,
|
|
242
|
+
acknowledgedAt: one.acknowledgedAt
|
|
243
|
+
}))
|
|
244
|
+
.sort((a, b) => Number(!!a.readAt) - Number(!!b.readAt) || String(a.name ?? '').localeCompare(String(b.name ?? '')));
|
|
245
|
+
}
|
|
246
|
+
async announcementRevisions(id, context) {
|
|
247
|
+
const visible = await visibleOrRefuse(id, context);
|
|
248
|
+
if (!visible.writer)
|
|
249
|
+
refuse(context, 'unknown-announcement', NOT_FOUND);
|
|
250
|
+
return await (0, shell_1.getRepository)(announcement_1.AnnouncementRevision).find({ where: { announcement: { id } }, order: { version: 'DESC' }, relations: ['creator'] });
|
|
251
|
+
}
|
|
252
|
+
async announcementAudienceChoices(context) {
|
|
253
|
+
const domain = context.state.domain;
|
|
254
|
+
const tree = await (0, organization_1.departmentTreeOf)(domain);
|
|
255
|
+
const departments = tree.size ? await (0, shell_1.getRepository)(organization_1.Department).find({ where: { id: (0, typeorm_1.In)([...tree.keys()]) }, order: { name: 'ASC' } }) : [];
|
|
256
|
+
const nameOf = new Map(departments.map(one => [one.id, one.name]));
|
|
257
|
+
return {
|
|
258
|
+
domainId: domain.id,
|
|
259
|
+
domainName: domain.name ?? domain.subdomain ?? domain.id,
|
|
260
|
+
departments: departments.map(one => ({ id: one.id, name: one.name, note: nameOf.get(tree.get(one.id) ?? '') ?? undefined })),
|
|
261
|
+
roles: (await (0, organization_1.domainRolesOf)(domain)).map(one => ({ id: one.id, name: one.name, note: one.description ?? undefined }))
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
async announcementPeople(text, context) {
|
|
265
|
+
const words = (text ?? '').trim().toLowerCase();
|
|
266
|
+
if (!words)
|
|
267
|
+
return [];
|
|
268
|
+
return (await (0, auth_base_1.getDomainAssignees)(context.state.domain))
|
|
269
|
+
.filter(one => `${one.name ?? ''} ${one.email ?? ''}`.toLowerCase().includes(words))
|
|
270
|
+
.slice(0, 20)
|
|
271
|
+
.map(one => ({ id: one.id, name: one.name || one.email, note: one.email }));
|
|
272
|
+
}
|
|
273
|
+
async announcementAudienceSize(audiences, context) {
|
|
274
|
+
return (await (0, organization_1.audienceUserIds)(context.state.domain, audiences ?? [])).length;
|
|
275
|
+
}
|
|
276
|
+
async createAnnouncement(input, attach, context) {
|
|
277
|
+
const { domain, user, tx } = context.state;
|
|
278
|
+
const saved = await (0, shell_1.getRepository)(announcement_1.Announcement, tx).save({ ...fieldsOf(input, context), domain, status: announcement_1.AnnouncementStatus.DRAFT, version: 1, creator: user, updater: user });
|
|
279
|
+
await setAudiences(saved, input.audiences ?? [], context, tx);
|
|
280
|
+
await attachFiles(saved.id, attach, [], context);
|
|
281
|
+
return saved;
|
|
282
|
+
}
|
|
283
|
+
async updateAnnouncement(id, input, attach, remove, notifyAgain, context) {
|
|
284
|
+
const { domain, user, tx } = context.state;
|
|
285
|
+
const announcement = await changeable(id, context, tx);
|
|
286
|
+
const fields = fieldsOf(input, context);
|
|
287
|
+
const out = announcement.status === announcement_1.AnnouncementStatus.PUBLISHED;
|
|
288
|
+
/* Once out, its start is the moment it went out - a start set later would hide it again. */
|
|
289
|
+
if (out)
|
|
290
|
+
fields.startsAt = announcement.startsAt;
|
|
291
|
+
const repository = (0, shell_1.getRepository)(announcement_1.Announcement, tx);
|
|
292
|
+
await repository.update(id, { ...fields, ...(out ? { version: announcement.version + 1 } : {}), updater: user });
|
|
293
|
+
const audienceChanged = await setAudiences(announcement, input.audiences ?? [], context, tx);
|
|
294
|
+
if (out && !(input.audiences ?? []).length)
|
|
295
|
+
refuse(context, 'no-audience', 'an announcement that is out names someone.');
|
|
296
|
+
await attachFiles(id, attach, remove, context);
|
|
297
|
+
const fresh = (await repository.findOneBy({ id }));
|
|
298
|
+
if (!out)
|
|
299
|
+
return fresh;
|
|
300
|
+
await (0, announcement_service_1.keepRevision)(fresh, domain, user, tx);
|
|
301
|
+
const added = audienceChanged ? await (0, announcement_service_1.alignRoster)(fresh, domain, user, tx) : [];
|
|
302
|
+
const receivers = notifyAgain
|
|
303
|
+
? (await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt, tx).find({ where: { announcement: { id }, listed: true } })).map(one => one.userId)
|
|
304
|
+
: added;
|
|
305
|
+
if (notifyAgain)
|
|
306
|
+
await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt, tx).update({ announcement: { id }, listed: true }, { notifiedAt: new Date() });
|
|
307
|
+
/* Told again, everyone hears it - the channel too; people the audience newly names are told one by one. */
|
|
308
|
+
await (0, announcement_service_1.tellWhenCommitted)(context, fresh, notifyAgain ? 'changed' : 'published', receivers.filter(one => one !== user.id), !!notifyAgain);
|
|
309
|
+
return fresh;
|
|
310
|
+
}
|
|
311
|
+
async publishAnnouncement(id, context) {
|
|
312
|
+
const { domain, user, tx } = context.state;
|
|
313
|
+
const announcement = await changeable(id, context, tx);
|
|
314
|
+
const audiences = await (0, announcement_service_1.audiencesOf)(id, tx);
|
|
315
|
+
const refusal = (0, announcement_rules_1.publishRefusal)(announcement.status, announcement, audiences.length);
|
|
316
|
+
if (refusal)
|
|
317
|
+
refuse(context, refusal, `the announcement cannot go out (${refusal}).`);
|
|
318
|
+
const repository = (0, shell_1.getRepository)(announcement_1.Announcement, tx);
|
|
319
|
+
if ((0, announcement_rules_1.publishedStatusOf)(announcement.startsAt) === 'SCHEDULED') {
|
|
320
|
+
await repository.update(id, { status: announcement_1.AnnouncementStatus.SCHEDULED, publisher: user, updater: user });
|
|
321
|
+
return (await repository.findOneBy({ id }));
|
|
322
|
+
}
|
|
323
|
+
const receivers = await (0, announcement_service_1.sendOut)(announcement, domain, user, tx);
|
|
324
|
+
const fresh = (await repository.findOneBy({ id }));
|
|
325
|
+
await (0, announcement_service_1.tellWhenCommitted)(context, fresh, 'published', receivers, true);
|
|
326
|
+
return fresh;
|
|
327
|
+
}
|
|
328
|
+
async withdrawAnnouncement(id, reason, context) {
|
|
329
|
+
const { user, tx } = context.state;
|
|
330
|
+
const announcement = await changeable(id, context, tx);
|
|
331
|
+
if (announcement.status === announcement_1.AnnouncementStatus.DRAFT)
|
|
332
|
+
refuse(context, 'not-out', 'a draft is deleted, not withdrawn.');
|
|
333
|
+
if (!reason?.trim())
|
|
334
|
+
refuse(context, 'no-reason', 'say why it is withdrawn.');
|
|
335
|
+
const repository = (0, shell_1.getRepository)(announcement_1.Announcement, tx);
|
|
336
|
+
await repository.update(id, { status: announcement_1.AnnouncementStatus.WITHDRAWN, withdrawnAt: new Date(), withdrawReason: reason.trim().slice(0, 500), updater: user });
|
|
337
|
+
return (await repository.findOneBy({ id }));
|
|
338
|
+
}
|
|
339
|
+
async deleteAnnouncement(id, context) {
|
|
340
|
+
const { tx } = context.state;
|
|
341
|
+
const announcement = await changeable(id, context, tx);
|
|
342
|
+
if (announcement.status !== announcement_1.AnnouncementStatus.DRAFT)
|
|
343
|
+
refuse(context, 'not-a-draft', 'an announcement that went out is withdrawn, not deleted.');
|
|
344
|
+
await (0, attachment_base_1.deleteAttachmentsByRef)(null, { refBys: [id], refType: announcement_service_1.ANNOUNCEMENT_REF_TYPE }, context);
|
|
345
|
+
await (0, shell_1.getRepository)(announcement_1.Announcement, tx).softDelete(id);
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
async remindAnnouncement(id, context) {
|
|
349
|
+
const { user, tx } = context.state;
|
|
350
|
+
const announcement = await changeable(id, context, tx);
|
|
351
|
+
if (!(0, announcement_rules_1.isCurrent)(announcement))
|
|
352
|
+
refuse(context, 'not-current', 'only a current announcement is reminded.');
|
|
353
|
+
const repository = (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt, tx);
|
|
354
|
+
const owed = (await repository.find({ where: { announcement: { id } } })).filter(one => (0, announcement_rules_1.owedReminder)(announcement, one));
|
|
355
|
+
if (owed.length)
|
|
356
|
+
await repository.update({ id: (0, typeorm_1.In)(owed.map(one => one.id)) }, { notifiedAt: new Date(), updater: user });
|
|
357
|
+
await (0, announcement_service_1.tellWhenCommitted)(context, announcement, 'reminder', owed.map(one => one.userId));
|
|
358
|
+
return owed.length;
|
|
359
|
+
}
|
|
360
|
+
/* ---------------------------------------------------------------- fields */
|
|
361
|
+
async audiences(one) {
|
|
362
|
+
return await (0, announcement_service_1.audiencesOf)(one.id);
|
|
363
|
+
}
|
|
364
|
+
async attachments(one, context) {
|
|
365
|
+
return await (0, shell_1.getRepository)(attachment_base_1.Attachment).find({ where: { domain: { id: context.state.domain.id }, refType: announcement_service_1.ANNOUNCEMENT_REF_TYPE, refBy: one.id }, order: { createdAt: 'ASC' } });
|
|
366
|
+
}
|
|
367
|
+
async mine(one, context) {
|
|
368
|
+
if ('__mine' in one)
|
|
369
|
+
return one.__mine;
|
|
370
|
+
return (await myReceipts([one.id], context.state.user.id)).get(one.id) ?? null;
|
|
371
|
+
}
|
|
372
|
+
async addressed(one, context) {
|
|
373
|
+
return one.status === announcement_1.AnnouncementStatus.PUBLISHED && (await (0, announcement_service_1.reachingIds)(await (0, announcement_service_1.memberOf)(context))).includes(one.id);
|
|
374
|
+
}
|
|
375
|
+
period(one) {
|
|
376
|
+
return (0, announcement_rules_1.periodOf)(one);
|
|
377
|
+
}
|
|
378
|
+
async readerState(one, context) {
|
|
379
|
+
return (0, announcement_rules_1.readerStateOf)(one, (await this.mine(one, context)) ?? undefined);
|
|
380
|
+
}
|
|
381
|
+
async readCount(one, context) {
|
|
382
|
+
if (!(await (0, announcement_service_1.isWriter)(context)))
|
|
383
|
+
return null;
|
|
384
|
+
return await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt).count({ where: { announcement: { id: one.id }, listed: true, readAt: (0, typeorm_1.Not)((0, typeorm_1.IsNull)()) } });
|
|
385
|
+
}
|
|
386
|
+
async acknowledgedCount(one, context) {
|
|
387
|
+
if (!(await (0, announcement_service_1.isWriter)(context)))
|
|
388
|
+
return null;
|
|
389
|
+
return await (0, shell_1.getRepository)(announcement_1.AnnouncementReceipt).count({ where: { announcement: { id: one.id }, listed: true, acknowledgedAt: (0, typeorm_1.Not)((0, typeorm_1.IsNull)()) } });
|
|
390
|
+
}
|
|
391
|
+
async editable(one, context) {
|
|
392
|
+
if (one.status === announcement_1.AnnouncementStatus.WITHDRAWN)
|
|
393
|
+
return false;
|
|
394
|
+
if (one.status === announcement_1.AnnouncementStatus.DRAFT && one.creatorId !== context.state.user.id)
|
|
395
|
+
return false;
|
|
396
|
+
return await (0, announcement_service_1.isWriter)(context);
|
|
397
|
+
}
|
|
398
|
+
async publisher(one) {
|
|
399
|
+
return one.publisherId ? await (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: one.publisherId }) : null;
|
|
400
|
+
}
|
|
401
|
+
async creator(one) {
|
|
402
|
+
return one.creatorId ? await (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: one.creatorId }) : null;
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
exports.AnnouncementResolver = AnnouncementResolver;
|
|
406
|
+
tslib_1.__decorate([
|
|
407
|
+
(0, type_graphql_1.Query)(returns => announcement_types_1.AnnouncementList, {
|
|
408
|
+
description: "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."
|
|
409
|
+
}),
|
|
410
|
+
tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
|
|
411
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
412
|
+
tslib_1.__metadata("design:type", Function),
|
|
413
|
+
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
414
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
415
|
+
], AnnouncementResolver.prototype, "announcements", null);
|
|
416
|
+
tslib_1.__decorate([
|
|
417
|
+
(0, type_graphql_1.Query)(returns => announcement_1.Announcement, { nullable: true, description: 'One announcement - to its audience once it is out, to a writer whatever its status (not somebody else\'s draft).' }),
|
|
418
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
419
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
420
|
+
tslib_1.__metadata("design:type", Function),
|
|
421
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
422
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
423
|
+
], AnnouncementResolver.prototype, "announcement", null);
|
|
424
|
+
tslib_1.__decorate([
|
|
425
|
+
(0, type_graphql_1.Query)(returns => announcement_types_1.AnnouncementSummary, { description: 'How many current announcements addressed to the person are unread, and how many await their acknowledgement.' }),
|
|
426
|
+
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
427
|
+
tslib_1.__metadata("design:type", Function),
|
|
428
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
429
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
430
|
+
], AnnouncementResolver.prototype, "announcementSummary", null);
|
|
431
|
+
tslib_1.__decorate([
|
|
432
|
+
(0, type_graphql_1.Query)(returns => [announcement_1.Announcement], { description: 'The announcements that pop up for the person now - unread popup ones, and those still to be acknowledged.' }),
|
|
433
|
+
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
434
|
+
tslib_1.__metadata("design:type", Function),
|
|
435
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
436
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
437
|
+
], AnnouncementResolver.prototype, "announcementPopups", null);
|
|
438
|
+
tslib_1.__decorate([
|
|
439
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
440
|
+
(0, type_graphql_1.Mutation)(returns => announcement_1.Announcement, { description: 'Records that the person read the announcement - once; reading it again changes nothing.' }),
|
|
441
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
442
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
443
|
+
tslib_1.__metadata("design:type", Function),
|
|
444
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
445
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
446
|
+
], AnnouncementResolver.prototype, "readAnnouncement", null);
|
|
447
|
+
tslib_1.__decorate([
|
|
448
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
449
|
+
(0, type_graphql_1.Mutation)(returns => announcement_1.Announcement, { description: 'Records that the person acknowledged an announcement that asks for it - reading it too.' }),
|
|
450
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
451
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
452
|
+
tslib_1.__metadata("design:type", Function),
|
|
453
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
454
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
455
|
+
], AnnouncementResolver.prototype, "acknowledgeAnnouncement", null);
|
|
456
|
+
tslib_1.__decorate([
|
|
457
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
458
|
+
(0, type_graphql_1.Query)(returns => announcement_types_1.AnnouncementList, { description: "Every announcement of the domain for its writers - all that are out, scheduled or withdrawn, and the writer's own drafts." }),
|
|
459
|
+
tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
|
|
460
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
461
|
+
tslib_1.__metadata("design:type", Function),
|
|
462
|
+
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
463
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
464
|
+
], AnnouncementResolver.prototype, "managedAnnouncements", null);
|
|
465
|
+
tslib_1.__decorate([
|
|
466
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
467
|
+
(0, type_graphql_1.Query)(returns => [announcement_types_1.AnnouncementReceiptRow], { description: 'Who on the roster read and acknowledged it, and who came to it later - for its writers.' }),
|
|
468
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
469
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
470
|
+
tslib_1.__metadata("design:type", Function),
|
|
471
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
472
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
473
|
+
], AnnouncementResolver.prototype, "announcementReceipts", null);
|
|
474
|
+
tslib_1.__decorate([
|
|
475
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
476
|
+
(0, type_graphql_1.Query)(returns => [announcement_1.AnnouncementRevision], { description: 'The versions of an announcement since it went out, newest first - for its writers.' }),
|
|
477
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
478
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
479
|
+
tslib_1.__metadata("design:type", Function),
|
|
480
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
481
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
482
|
+
], AnnouncementResolver.prototype, "announcementRevisions", null);
|
|
483
|
+
tslib_1.__decorate([
|
|
484
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
485
|
+
(0, type_graphql_1.Query)(returns => announcement_types_1.AnnouncementAudienceChoices, { description: 'What an announcement may be addressed to - the domain, its departments and its roles.' }),
|
|
486
|
+
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
487
|
+
tslib_1.__metadata("design:type", Function),
|
|
488
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
489
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
490
|
+
], AnnouncementResolver.prototype, "announcementAudienceChoices", null);
|
|
491
|
+
tslib_1.__decorate([
|
|
492
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
493
|
+
(0, type_graphql_1.Query)(returns => [announcement_types_1.AnnouncementChoice], { description: 'People of the domain an announcement may be addressed to, found by name or e-mail.' }),
|
|
494
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('text')),
|
|
495
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
496
|
+
tslib_1.__metadata("design:type", Function),
|
|
497
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
498
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
499
|
+
], AnnouncementResolver.prototype, "announcementPeople", null);
|
|
500
|
+
tslib_1.__decorate([
|
|
501
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
502
|
+
(0, type_graphql_1.Query)(returns => type_graphql_1.Int, { description: 'How many people an audience names now - shown before it is sent.' }),
|
|
503
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('audiences', type => [announcement_types_1.AnnouncementAudienceInput])),
|
|
504
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
505
|
+
tslib_1.__metadata("design:type", Function),
|
|
506
|
+
tslib_1.__metadata("design:paramtypes", [Array, Object]),
|
|
507
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
508
|
+
], AnnouncementResolver.prototype, "announcementAudienceSize", null);
|
|
509
|
+
tslib_1.__decorate([
|
|
510
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
511
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
512
|
+
(0, type_graphql_1.Mutation)(returns => announcement_1.Announcement, { description: 'Writes a new announcement as a draft, with its files.' }),
|
|
513
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('input', type => announcement_types_1.AnnouncementInput)),
|
|
514
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('attach', type => [GraphQLUpload_js_1.default], { nullable: true })),
|
|
515
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
516
|
+
tslib_1.__metadata("design:type", Function),
|
|
517
|
+
tslib_1.__metadata("design:paramtypes", [announcement_types_1.AnnouncementInput, Array, Object]),
|
|
518
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
519
|
+
], AnnouncementResolver.prototype, "createAnnouncement", null);
|
|
520
|
+
tslib_1.__decorate([
|
|
521
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
522
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
523
|
+
(0, type_graphql_1.Mutation)(returns => announcement_1.Announcement, {
|
|
524
|
+
description: '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.'
|
|
525
|
+
}),
|
|
526
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
527
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('input', type => announcement_types_1.AnnouncementInput)),
|
|
528
|
+
tslib_1.__param(2, (0, type_graphql_1.Arg)('attach', type => [GraphQLUpload_js_1.default], { nullable: true })),
|
|
529
|
+
tslib_1.__param(3, (0, type_graphql_1.Arg)('remove', type => [String], { nullable: true, description: 'Ids of its files to take off.' })),
|
|
530
|
+
tslib_1.__param(4, (0, type_graphql_1.Arg)('notifyAgain', { nullable: true, description: 'Tell everyone on the roster of the change.' })),
|
|
531
|
+
tslib_1.__param(5, (0, type_graphql_1.Ctx)()),
|
|
532
|
+
tslib_1.__metadata("design:type", Function),
|
|
533
|
+
tslib_1.__metadata("design:paramtypes", [String, announcement_types_1.AnnouncementInput, Array, Array, Boolean, Object]),
|
|
534
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
535
|
+
], AnnouncementResolver.prototype, "updateAnnouncement", null);
|
|
536
|
+
tslib_1.__decorate([
|
|
537
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
538
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
539
|
+
(0, type_graphql_1.Mutation)(returns => announcement_1.Announcement, { description: 'Sends a draft out to its audience - at once, or at its start when that is still to come.' }),
|
|
540
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
541
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
542
|
+
tslib_1.__metadata("design:type", Function),
|
|
543
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
544
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
545
|
+
], AnnouncementResolver.prototype, "publishAnnouncement", null);
|
|
546
|
+
tslib_1.__decorate([
|
|
547
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
548
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
549
|
+
(0, type_graphql_1.Mutation)(returns => announcement_1.Announcement, { description: 'Takes back an announcement that is out or scheduled, with the reason. Its audience no longer sees it; its record stays.' }),
|
|
550
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
551
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('reason')),
|
|
552
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
553
|
+
tslib_1.__metadata("design:type", Function),
|
|
554
|
+
tslib_1.__metadata("design:paramtypes", [String, String, Object]),
|
|
555
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
556
|
+
], AnnouncementResolver.prototype, "withdrawAnnouncement", null);
|
|
557
|
+
tslib_1.__decorate([
|
|
558
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
559
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
560
|
+
(0, type_graphql_1.Mutation)(returns => Boolean, { description: "Deletes one's own draft and its files. An announcement that went out is withdrawn instead." }),
|
|
561
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
562
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
563
|
+
tslib_1.__metadata("design:type", Function),
|
|
564
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
565
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
566
|
+
], AnnouncementResolver.prototype, "deleteAnnouncement", null);
|
|
567
|
+
tslib_1.__decorate([
|
|
568
|
+
(0, type_graphql_1.Directive)(WRITE),
|
|
569
|
+
(0, type_graphql_1.Directive)('@transaction'),
|
|
570
|
+
(0, type_graphql_1.Mutation)(returns => type_graphql_1.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.' }),
|
|
571
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
572
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
573
|
+
tslib_1.__metadata("design:type", Function),
|
|
574
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
575
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
576
|
+
], AnnouncementResolver.prototype, "remindAnnouncement", null);
|
|
577
|
+
tslib_1.__decorate([
|
|
578
|
+
(0, type_graphql_1.FieldResolver)(type => [announcement_1.AnnouncementAudience], { description: 'Whom it is addressed to.' }),
|
|
579
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
580
|
+
tslib_1.__metadata("design:type", Function),
|
|
581
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement]),
|
|
582
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
583
|
+
], AnnouncementResolver.prototype, "audiences", null);
|
|
584
|
+
tslib_1.__decorate([
|
|
585
|
+
(0, type_graphql_1.FieldResolver)(type => [attachment_base_1.Attachment], { description: 'Its files.' }),
|
|
586
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
587
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
588
|
+
tslib_1.__metadata("design:type", Function),
|
|
589
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement, Object]),
|
|
590
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
591
|
+
], AnnouncementResolver.prototype, "attachments", null);
|
|
592
|
+
tslib_1.__decorate([
|
|
593
|
+
(0, type_graphql_1.FieldResolver)(type => announcement_1.AnnouncementReceipt, { nullable: true, description: "The request's person's own reading of it." }),
|
|
594
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
595
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
596
|
+
tslib_1.__metadata("design:type", Function),
|
|
597
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement, Object]),
|
|
598
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
599
|
+
], AnnouncementResolver.prototype, "mine", null);
|
|
600
|
+
tslib_1.__decorate([
|
|
601
|
+
(0, type_graphql_1.FieldResolver)(type => Boolean, { description: "Whether it is addressed to the request's person and out - the one who reads and acknowledges it." }),
|
|
602
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
603
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
604
|
+
tslib_1.__metadata("design:type", Function),
|
|
605
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement, Object]),
|
|
606
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
607
|
+
], AnnouncementResolver.prototype, "addressed", null);
|
|
608
|
+
tslib_1.__decorate([
|
|
609
|
+
(0, type_graphql_1.FieldResolver)(type => String, { nullable: true, description: 'Whether it is still current or past - for one that is out.' }),
|
|
610
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
611
|
+
tslib_1.__metadata("design:type", Function),
|
|
612
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement]),
|
|
613
|
+
tslib_1.__metadata("design:returntype", String)
|
|
614
|
+
], AnnouncementResolver.prototype, "period", null);
|
|
615
|
+
tslib_1.__decorate([
|
|
616
|
+
(0, type_graphql_1.FieldResolver)(type => String, { description: "Where it stands for the request's person: unread, read, to-acknowledge or acknowledged." }),
|
|
617
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
618
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
619
|
+
tslib_1.__metadata("design:type", Function),
|
|
620
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement, Object]),
|
|
621
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
622
|
+
], AnnouncementResolver.prototype, "readerState", null);
|
|
623
|
+
tslib_1.__decorate([
|
|
624
|
+
(0, type_graphql_1.FieldResolver)(type => type_graphql_1.Int, { nullable: true, description: 'How many on the roster read it - for its writers.' }),
|
|
625
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
626
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
627
|
+
tslib_1.__metadata("design:type", Function),
|
|
628
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement, Object]),
|
|
629
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
630
|
+
], AnnouncementResolver.prototype, "readCount", null);
|
|
631
|
+
tslib_1.__decorate([
|
|
632
|
+
(0, type_graphql_1.FieldResolver)(type => type_graphql_1.Int, { nullable: true, description: 'How many on the roster acknowledged it - for its writers.' }),
|
|
633
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
634
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
635
|
+
tslib_1.__metadata("design:type", Function),
|
|
636
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement, Object]),
|
|
637
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
638
|
+
], AnnouncementResolver.prototype, "acknowledgedCount", null);
|
|
639
|
+
tslib_1.__decorate([
|
|
640
|
+
(0, type_graphql_1.FieldResolver)(type => Boolean, { description: 'Whether the request may change it.' }),
|
|
641
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
642
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
643
|
+
tslib_1.__metadata("design:type", Function),
|
|
644
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement, Object]),
|
|
645
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
646
|
+
], AnnouncementResolver.prototype, "editable", null);
|
|
647
|
+
tslib_1.__decorate([
|
|
648
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true, description: 'Who published it.' }),
|
|
649
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
650
|
+
tslib_1.__metadata("design:type", Function),
|
|
651
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement]),
|
|
652
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
653
|
+
], AnnouncementResolver.prototype, "publisher", null);
|
|
654
|
+
tslib_1.__decorate([
|
|
655
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true, description: 'Who wrote it.' }),
|
|
656
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
657
|
+
tslib_1.__metadata("design:type", Function),
|
|
658
|
+
tslib_1.__metadata("design:paramtypes", [announcement_1.Announcement]),
|
|
659
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
660
|
+
], AnnouncementResolver.prototype, "creator", null);
|
|
661
|
+
exports.AnnouncementResolver = AnnouncementResolver = tslib_1.__decorate([
|
|
662
|
+
(0, type_graphql_1.Resolver)(announcement_1.Announcement)
|
|
663
|
+
], AnnouncementResolver);
|
|
664
|
+
//# sourceMappingURL=announcement-resolver.js.map
|