@terreno/announcements 57.4.0
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/LICENSE +21 -0
- package/README.md +50 -0
- package/biome.jsonc +20 -0
- package/bunfig.toml +2 -0
- package/dist/announcementsApp.d.ts +9 -0
- package/dist/announcementsApp.js +820 -0
- package/dist/help.d.ts +30 -0
- package/dist/help.js +72 -0
- package/dist/helpRoutes.d.ts +8 -0
- package/dist/helpRoutes.js +233 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +34 -0
- package/dist/models/announcement.d.ts +3 -0
- package/dist/models/announcement.js +214 -0
- package/dist/models/announcementAcknowledgement.d.ts +2 -0
- package/dist/models/announcementAcknowledgement.js +41 -0
- package/dist/models/announcementClickEvent.d.ts +3 -0
- package/dist/models/announcementClickEvent.js +56 -0
- package/dist/models/announcementImpression.d.ts +3 -0
- package/dist/models/announcementImpression.js +50 -0
- package/dist/overview.d.ts +14 -0
- package/dist/overview.js +310 -0
- package/dist/pending.d.ts +64 -0
- package/dist/pending.js +242 -0
- package/dist/types.d.ts +135 -0
- package/dist/types.js +2 -0
- package/package.json +57 -0
- package/src/announcementsApp.ts +722 -0
- package/src/help.ts +98 -0
- package/src/helpRoutes.ts +160 -0
- package/src/index.ts +45 -0
- package/src/models/announcement.ts +189 -0
- package/src/models/announcementAcknowledgement.ts +50 -0
- package/src/models/announcementClickEvent.ts +68 -0
- package/src/models/announcementImpression.ts +62 -0
- package/src/overview.ts +228 -0
- package/src/pending.ts +286 -0
- package/src/tests/announcementsApp.test.ts +844 -0
- package/src/tests/bunSetup.ts +9 -0
- package/src/tests/help.test.ts +29 -0
- package/src/tests/helpRoutes.test.ts +291 -0
- package/src/tests/index.test.ts +57 -0
- package/src/tests/overview.test.ts +351 -0
- package/src/tests/pending.test.ts +262 -0
- package/src/types.ts +157 -0
- package/tsconfig.json +33 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
var _a;
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isValidClickAction = exports.AnnouncementClickEvent = void 0;
|
|
8
|
+
var api_1 = require("@terreno/api");
|
|
9
|
+
var mongoose_1 = __importDefault(require("mongoose"));
|
|
10
|
+
var announcementClickEventSchema = new mongoose_1.default.Schema({
|
|
11
|
+
action: {
|
|
12
|
+
description: "Which announcement action the user clicked",
|
|
13
|
+
enum: ["primaryAction"],
|
|
14
|
+
required: true,
|
|
15
|
+
type: String,
|
|
16
|
+
},
|
|
17
|
+
announcementId: {
|
|
18
|
+
description: "Announcement whose primary action was clicked",
|
|
19
|
+
index: true,
|
|
20
|
+
ref: "Announcement",
|
|
21
|
+
required: true,
|
|
22
|
+
type: mongoose_1.default.Schema.Types.ObjectId,
|
|
23
|
+
},
|
|
24
|
+
clickedAt: {
|
|
25
|
+
description: "When the primary action was clicked",
|
|
26
|
+
required: true,
|
|
27
|
+
type: Date,
|
|
28
|
+
},
|
|
29
|
+
platform: {
|
|
30
|
+
description: "Client platform where the click occurred",
|
|
31
|
+
enum: ["ios", "android", "web"],
|
|
32
|
+
type: String,
|
|
33
|
+
},
|
|
34
|
+
userId: {
|
|
35
|
+
description: "User who clicked the announcement action",
|
|
36
|
+
index: true,
|
|
37
|
+
ref: "User",
|
|
38
|
+
required: true,
|
|
39
|
+
type: mongoose_1.default.Schema.Types.ObjectId,
|
|
40
|
+
},
|
|
41
|
+
version: {
|
|
42
|
+
description: "Announcement version at click time",
|
|
43
|
+
required: true,
|
|
44
|
+
type: Number,
|
|
45
|
+
},
|
|
46
|
+
}, { strict: "throw", toJSON: { virtuals: true }, toObject: { virtuals: true } });
|
|
47
|
+
announcementClickEventSchema.plugin(api_1.createdUpdatedPlugin);
|
|
48
|
+
announcementClickEventSchema.plugin(api_1.isDeletedPlugin);
|
|
49
|
+
announcementClickEventSchema.plugin(api_1.findExactlyOne);
|
|
50
|
+
announcementClickEventSchema.plugin(api_1.findOneOrNone);
|
|
51
|
+
announcementClickEventSchema.index({ announcementId: 1, clickedAt: -1 });
|
|
52
|
+
exports.AnnouncementClickEvent = (_a = mongoose_1.default.models.AnnouncementClickEvent) !== null && _a !== void 0 ? _a : mongoose_1.default.model("AnnouncementClickEvent", announcementClickEventSchema);
|
|
53
|
+
var isValidClickAction = function (value) {
|
|
54
|
+
return value === "primaryAction";
|
|
55
|
+
};
|
|
56
|
+
exports.isValidClickAction = isValidClickAction;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
var _a;
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.isValidPlatform = exports.AnnouncementImpression = void 0;
|
|
8
|
+
var api_1 = require("@terreno/api");
|
|
9
|
+
var mongoose_1 = __importDefault(require("mongoose"));
|
|
10
|
+
var announcementImpressionSchema = new mongoose_1.default.Schema({
|
|
11
|
+
announcementId: {
|
|
12
|
+
description: "Announcement that was viewed",
|
|
13
|
+
index: true,
|
|
14
|
+
ref: "Announcement",
|
|
15
|
+
required: true,
|
|
16
|
+
type: mongoose_1.default.Schema.Types.ObjectId,
|
|
17
|
+
},
|
|
18
|
+
platform: {
|
|
19
|
+
description: "Client platform where the impression occurred",
|
|
20
|
+
enum: ["ios", "android", "web"],
|
|
21
|
+
type: String,
|
|
22
|
+
},
|
|
23
|
+
userId: {
|
|
24
|
+
description: "User who viewed the announcement",
|
|
25
|
+
index: true,
|
|
26
|
+
ref: "User",
|
|
27
|
+
required: true,
|
|
28
|
+
type: mongoose_1.default.Schema.Types.ObjectId,
|
|
29
|
+
},
|
|
30
|
+
version: {
|
|
31
|
+
description: "Announcement version viewed by the user",
|
|
32
|
+
required: true,
|
|
33
|
+
type: Number,
|
|
34
|
+
},
|
|
35
|
+
viewedAt: {
|
|
36
|
+
description: "When the announcement was viewed",
|
|
37
|
+
required: true,
|
|
38
|
+
type: Date,
|
|
39
|
+
},
|
|
40
|
+
}, { strict: "throw", toJSON: { virtuals: true }, toObject: { virtuals: true } });
|
|
41
|
+
announcementImpressionSchema.plugin(api_1.createdUpdatedPlugin);
|
|
42
|
+
announcementImpressionSchema.plugin(api_1.isDeletedPlugin);
|
|
43
|
+
announcementImpressionSchema.plugin(api_1.findExactlyOne);
|
|
44
|
+
announcementImpressionSchema.plugin(api_1.findOneOrNone);
|
|
45
|
+
announcementImpressionSchema.index({ announcementId: 1, viewedAt: -1 });
|
|
46
|
+
exports.AnnouncementImpression = (_a = mongoose_1.default.models.AnnouncementImpression) !== null && _a !== void 0 ? _a : mongoose_1.default.model("AnnouncementImpression", announcementImpressionSchema);
|
|
47
|
+
var isValidPlatform = function (value) {
|
|
48
|
+
return value === "ios" || value === "android" || value === "web";
|
|
49
|
+
};
|
|
50
|
+
exports.isValidPlatform = isValidPlatform;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { AcknowledgementPolicy, AnnouncementOverviewResponse } from "./types";
|
|
2
|
+
export interface OverviewPagination {
|
|
3
|
+
limit: number;
|
|
4
|
+
page: number;
|
|
5
|
+
}
|
|
6
|
+
export declare const parseOverviewPagination: (query: {
|
|
7
|
+
limit?: unknown;
|
|
8
|
+
page?: unknown;
|
|
9
|
+
}) => OverviewPagination;
|
|
10
|
+
export declare const fetchAnnouncementOverview: ({ defaultAcknowledgementPolicy, limit, page, }: {
|
|
11
|
+
defaultAcknowledgementPolicy: AcknowledgementPolicy;
|
|
12
|
+
limit: number;
|
|
13
|
+
page: number;
|
|
14
|
+
}) => Promise<AnnouncementOverviewResponse>;
|
package/dist/overview.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
24
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
50
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
51
|
+
if (!m) return o;
|
|
52
|
+
var i = m.call(o), r, ar = [], e;
|
|
53
|
+
try {
|
|
54
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
55
|
+
}
|
|
56
|
+
catch (error) { e = { error: error }; }
|
|
57
|
+
finally {
|
|
58
|
+
try {
|
|
59
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
60
|
+
}
|
|
61
|
+
finally { if (e) throw e.error; }
|
|
62
|
+
}
|
|
63
|
+
return ar;
|
|
64
|
+
};
|
|
65
|
+
var __values = (this && this.__values) || function(o) {
|
|
66
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
67
|
+
if (m) return m.call(o);
|
|
68
|
+
if (o && typeof o.length === "number") return {
|
|
69
|
+
next: function () {
|
|
70
|
+
if (o && i >= o.length) o = void 0;
|
|
71
|
+
return { value: o && o[i++], done: !o };
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
75
|
+
};
|
|
76
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77
|
+
exports.fetchAnnouncementOverview = exports.parseOverviewPagination = void 0;
|
|
78
|
+
var announcement_1 = require("./models/announcement");
|
|
79
|
+
var announcementAcknowledgement_1 = require("./models/announcementAcknowledgement");
|
|
80
|
+
var announcementClickEvent_1 = require("./models/announcementClickEvent");
|
|
81
|
+
var announcementImpression_1 = require("./models/announcementImpression");
|
|
82
|
+
var pending_1 = require("./pending");
|
|
83
|
+
var NOT_DELETED = { deleted: { $ne: true } };
|
|
84
|
+
var parseOverviewPagination = function (query) {
|
|
85
|
+
var _a, _b;
|
|
86
|
+
var parsedLimit = Number((_a = query.limit) !== null && _a !== void 0 ? _a : 20);
|
|
87
|
+
var parsedPage = Number((_b = query.page) !== null && _b !== void 0 ? _b : 1);
|
|
88
|
+
var limit = Number.isFinite(parsedLimit)
|
|
89
|
+
? Math.min(Math.max(Math.trunc(parsedLimit), 1), 100)
|
|
90
|
+
: 20;
|
|
91
|
+
var page = Number.isFinite(parsedPage) ? Math.max(Math.trunc(parsedPage), 1) : 1;
|
|
92
|
+
return { limit: limit, page: page };
|
|
93
|
+
};
|
|
94
|
+
exports.parseOverviewPagination = parseOverviewPagination;
|
|
95
|
+
var countEventTotals = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
96
|
+
var _a, impressionRows, acknowledgementRows, clickRows;
|
|
97
|
+
var _b, _c, _d, _e, _f, _g;
|
|
98
|
+
return __generator(this, function (_h) {
|
|
99
|
+
switch (_h.label) {
|
|
100
|
+
case 0: return [4 /*yield*/, Promise.all([
|
|
101
|
+
announcementImpression_1.AnnouncementImpression.aggregate([{ $match: NOT_DELETED }, { $count: "count" }]),
|
|
102
|
+
announcementAcknowledgement_1.AnnouncementAcknowledgement.aggregate([
|
|
103
|
+
{ $match: NOT_DELETED },
|
|
104
|
+
{ $count: "count" },
|
|
105
|
+
]),
|
|
106
|
+
announcementClickEvent_1.AnnouncementClickEvent.aggregate([{ $match: NOT_DELETED }, { $count: "count" }]),
|
|
107
|
+
])];
|
|
108
|
+
case 1:
|
|
109
|
+
_a = __read.apply(void 0, [_h.sent(), 3]), impressionRows = _a[0], acknowledgementRows = _a[1], clickRows = _a[2];
|
|
110
|
+
return [2 /*return*/, {
|
|
111
|
+
acknowledgements: (_c = (_b = acknowledgementRows[0]) === null || _b === void 0 ? void 0 : _b.count) !== null && _c !== void 0 ? _c : 0,
|
|
112
|
+
clicks: (_e = (_d = clickRows[0]) === null || _d === void 0 ? void 0 : _d.count) !== null && _e !== void 0 ? _e : 0,
|
|
113
|
+
impressions: (_g = (_f = impressionRows[0]) === null || _f === void 0 ? void 0 : _f.count) !== null && _g !== void 0 ? _g : 0,
|
|
114
|
+
}];
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}); };
|
|
118
|
+
var countMetricsByAnnouncement = function (announcementIds) { return __awaiter(void 0, void 0, void 0, function () {
|
|
119
|
+
var metrics, announcementIds_1, announcementIds_1_1, id, matchByAnnouncement, _a, impressionCounts, acknowledgementCounts, clickCounts, impressionCounts_1, impressionCounts_1_1, row, existing, acknowledgementCounts_1, acknowledgementCounts_1_1, row, existing, clickCounts_1, clickCounts_1_1, row, existing;
|
|
120
|
+
var e_1, _b, e_2, _c, e_3, _d, e_4, _e;
|
|
121
|
+
var _f, _g, _h;
|
|
122
|
+
return __generator(this, function (_j) {
|
|
123
|
+
switch (_j.label) {
|
|
124
|
+
case 0:
|
|
125
|
+
metrics = new Map();
|
|
126
|
+
try {
|
|
127
|
+
for (announcementIds_1 = __values(announcementIds), announcementIds_1_1 = announcementIds_1.next(); !announcementIds_1_1.done; announcementIds_1_1 = announcementIds_1.next()) {
|
|
128
|
+
id = announcementIds_1_1.value;
|
|
129
|
+
metrics.set(id.toString(), { acknowledgements: 0, clicks: 0, impressions: 0 });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
133
|
+
finally {
|
|
134
|
+
try {
|
|
135
|
+
if (announcementIds_1_1 && !announcementIds_1_1.done && (_b = announcementIds_1.return)) _b.call(announcementIds_1);
|
|
136
|
+
}
|
|
137
|
+
finally { if (e_1) throw e_1.error; }
|
|
138
|
+
}
|
|
139
|
+
if (announcementIds.length === 0) {
|
|
140
|
+
return [2 /*return*/, metrics];
|
|
141
|
+
}
|
|
142
|
+
matchByAnnouncement = {
|
|
143
|
+
$match: __assign(__assign({}, NOT_DELETED), { announcementId: { $in: announcementIds } }),
|
|
144
|
+
};
|
|
145
|
+
return [4 /*yield*/, Promise.all([
|
|
146
|
+
announcementImpression_1.AnnouncementImpression.aggregate([
|
|
147
|
+
matchByAnnouncement,
|
|
148
|
+
{ $group: { _id: "$announcementId", count: { $sum: 1 } } },
|
|
149
|
+
]),
|
|
150
|
+
announcementAcknowledgement_1.AnnouncementAcknowledgement.aggregate([
|
|
151
|
+
matchByAnnouncement,
|
|
152
|
+
{ $group: { _id: "$announcementId", count: { $sum: 1 } } },
|
|
153
|
+
]),
|
|
154
|
+
announcementClickEvent_1.AnnouncementClickEvent.aggregate([
|
|
155
|
+
matchByAnnouncement,
|
|
156
|
+
{ $group: { _id: "$announcementId", count: { $sum: 1 } } },
|
|
157
|
+
]),
|
|
158
|
+
])];
|
|
159
|
+
case 1:
|
|
160
|
+
_a = __read.apply(void 0, [_j.sent(), 3]), impressionCounts = _a[0], acknowledgementCounts = _a[1], clickCounts = _a[2];
|
|
161
|
+
try {
|
|
162
|
+
for (impressionCounts_1 = __values(impressionCounts), impressionCounts_1_1 = impressionCounts_1.next(); !impressionCounts_1_1.done; impressionCounts_1_1 = impressionCounts_1.next()) {
|
|
163
|
+
row = impressionCounts_1_1.value;
|
|
164
|
+
existing = (_f = metrics.get(row._id.toString())) !== null && _f !== void 0 ? _f : {
|
|
165
|
+
acknowledgements: 0,
|
|
166
|
+
clicks: 0,
|
|
167
|
+
impressions: 0,
|
|
168
|
+
};
|
|
169
|
+
existing.impressions = row.count;
|
|
170
|
+
metrics.set(row._id.toString(), existing);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
174
|
+
finally {
|
|
175
|
+
try {
|
|
176
|
+
if (impressionCounts_1_1 && !impressionCounts_1_1.done && (_c = impressionCounts_1.return)) _c.call(impressionCounts_1);
|
|
177
|
+
}
|
|
178
|
+
finally { if (e_2) throw e_2.error; }
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
for (acknowledgementCounts_1 = __values(acknowledgementCounts), acknowledgementCounts_1_1 = acknowledgementCounts_1.next(); !acknowledgementCounts_1_1.done; acknowledgementCounts_1_1 = acknowledgementCounts_1.next()) {
|
|
182
|
+
row = acknowledgementCounts_1_1.value;
|
|
183
|
+
existing = (_g = metrics.get(row._id.toString())) !== null && _g !== void 0 ? _g : {
|
|
184
|
+
acknowledgements: 0,
|
|
185
|
+
clicks: 0,
|
|
186
|
+
impressions: 0,
|
|
187
|
+
};
|
|
188
|
+
existing.acknowledgements = row.count;
|
|
189
|
+
metrics.set(row._id.toString(), existing);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
193
|
+
finally {
|
|
194
|
+
try {
|
|
195
|
+
if (acknowledgementCounts_1_1 && !acknowledgementCounts_1_1.done && (_d = acknowledgementCounts_1.return)) _d.call(acknowledgementCounts_1);
|
|
196
|
+
}
|
|
197
|
+
finally { if (e_3) throw e_3.error; }
|
|
198
|
+
}
|
|
199
|
+
try {
|
|
200
|
+
for (clickCounts_1 = __values(clickCounts), clickCounts_1_1 = clickCounts_1.next(); !clickCounts_1_1.done; clickCounts_1_1 = clickCounts_1.next()) {
|
|
201
|
+
row = clickCounts_1_1.value;
|
|
202
|
+
existing = (_h = metrics.get(row._id.toString())) !== null && _h !== void 0 ? _h : {
|
|
203
|
+
acknowledgements: 0,
|
|
204
|
+
clicks: 0,
|
|
205
|
+
impressions: 0,
|
|
206
|
+
};
|
|
207
|
+
existing.clicks = row.count;
|
|
208
|
+
metrics.set(row._id.toString(), existing);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
212
|
+
finally {
|
|
213
|
+
try {
|
|
214
|
+
if (clickCounts_1_1 && !clickCounts_1_1.done && (_e = clickCounts_1.return)) _e.call(clickCounts_1);
|
|
215
|
+
}
|
|
216
|
+
finally { if (e_4) throw e_4.error; }
|
|
217
|
+
}
|
|
218
|
+
return [2 /*return*/, metrics];
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}); };
|
|
222
|
+
var toOverviewRow = function (_a) {
|
|
223
|
+
var _b, _c;
|
|
224
|
+
var announcement = _a.announcement, defaultAcknowledgementPolicy = _a.defaultAcknowledgementPolicy, metrics = _a.metrics;
|
|
225
|
+
return ({
|
|
226
|
+
_id: announcement._id.toString(),
|
|
227
|
+
acknowledgementPolicy: (0, pending_1.resolveAcknowledgementPolicy)({
|
|
228
|
+
announcement: announcement,
|
|
229
|
+
defaultAcknowledgementPolicy: defaultAcknowledgementPolicy,
|
|
230
|
+
}),
|
|
231
|
+
audienceType: (0, pending_1.resolveAudienceType)(announcement),
|
|
232
|
+
displayMode: (0, pending_1.resolveDisplayMode)(announcement),
|
|
233
|
+
expiresAt: (_b = announcement.expiresAt) === null || _b === void 0 ? void 0 : _b.toISOString(),
|
|
234
|
+
metrics: metrics,
|
|
235
|
+
priority: announcement.priority,
|
|
236
|
+
publishedAt: (_c = announcement.publishedAt) === null || _c === void 0 ? void 0 : _c.toISOString(),
|
|
237
|
+
status: announcement.status,
|
|
238
|
+
title: announcement.title,
|
|
239
|
+
version: announcement.version,
|
|
240
|
+
});
|
|
241
|
+
};
|
|
242
|
+
var fetchAnnouncementOverview = function (_a) { return __awaiter(void 0, [_a], void 0, function (_b) {
|
|
243
|
+
var skip, _c, facetResult, eventTotals, facet, paginated, total, statusCounts, statusCountMap, totals, metricsByAnnouncement, data;
|
|
244
|
+
var _d, _e, _f, _g, _h, _j, _k;
|
|
245
|
+
var defaultAcknowledgementPolicy = _b.defaultAcknowledgementPolicy, limit = _b.limit, page = _b.page;
|
|
246
|
+
return __generator(this, function (_l) {
|
|
247
|
+
switch (_l.label) {
|
|
248
|
+
case 0:
|
|
249
|
+
skip = (page - 1) * limit;
|
|
250
|
+
return [4 /*yield*/, Promise.all([
|
|
251
|
+
announcement_1.Announcement.aggregate([
|
|
252
|
+
{ $match: NOT_DELETED },
|
|
253
|
+
{
|
|
254
|
+
$facet: {
|
|
255
|
+
paginated: [
|
|
256
|
+
// biome-ignore assist/source/useSortedKeys: MongoDB applies sort keys in insertion order
|
|
257
|
+
{ $sort: { priority: -1, publishedAt: -1, _id: -1 } },
|
|
258
|
+
{ $skip: skip },
|
|
259
|
+
{ $limit: limit },
|
|
260
|
+
],
|
|
261
|
+
statusCounts: [{ $group: { _id: "$status", count: { $sum: 1 } } }],
|
|
262
|
+
totalCount: [{ $count: "count" }],
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
]),
|
|
266
|
+
countEventTotals(),
|
|
267
|
+
])];
|
|
268
|
+
case 1:
|
|
269
|
+
_c = __read.apply(void 0, [_l.sent(), 2]), facetResult = _c[0], eventTotals = _c[1];
|
|
270
|
+
facet = facetResult[0];
|
|
271
|
+
paginated = (_d = facet === null || facet === void 0 ? void 0 : facet.paginated) !== null && _d !== void 0 ? _d : [];
|
|
272
|
+
total = (_f = (_e = facet === null || facet === void 0 ? void 0 : facet.totalCount[0]) === null || _e === void 0 ? void 0 : _e.count) !== null && _f !== void 0 ? _f : 0;
|
|
273
|
+
statusCounts = (_g = facet === null || facet === void 0 ? void 0 : facet.statusCounts) !== null && _g !== void 0 ? _g : [];
|
|
274
|
+
statusCountMap = new Map(statusCounts.map(function (row) { return [row._id, row.count]; }));
|
|
275
|
+
totals = {
|
|
276
|
+
acknowledgements: eventTotals.acknowledgements,
|
|
277
|
+
announcements: total,
|
|
278
|
+
archived: (_h = statusCountMap.get("archived")) !== null && _h !== void 0 ? _h : 0,
|
|
279
|
+
clicks: eventTotals.clicks,
|
|
280
|
+
draft: (_j = statusCountMap.get("draft")) !== null && _j !== void 0 ? _j : 0,
|
|
281
|
+
impressions: eventTotals.impressions,
|
|
282
|
+
published: (_k = statusCountMap.get("published")) !== null && _k !== void 0 ? _k : 0,
|
|
283
|
+
};
|
|
284
|
+
return [4 /*yield*/, countMetricsByAnnouncement(paginated.map(function (announcement) { return announcement._id; }))];
|
|
285
|
+
case 2:
|
|
286
|
+
metricsByAnnouncement = _l.sent();
|
|
287
|
+
data = paginated.map(function (announcement) {
|
|
288
|
+
var _a;
|
|
289
|
+
return toOverviewRow({
|
|
290
|
+
announcement: announcement,
|
|
291
|
+
defaultAcknowledgementPolicy: defaultAcknowledgementPolicy,
|
|
292
|
+
metrics: (_a = metricsByAnnouncement.get(announcement._id.toString())) !== null && _a !== void 0 ? _a : {
|
|
293
|
+
acknowledgements: 0,
|
|
294
|
+
clicks: 0,
|
|
295
|
+
impressions: 0,
|
|
296
|
+
},
|
|
297
|
+
});
|
|
298
|
+
});
|
|
299
|
+
return [2 /*return*/, {
|
|
300
|
+
data: data,
|
|
301
|
+
limit: limit,
|
|
302
|
+
more: skip + data.length < total,
|
|
303
|
+
page: page,
|
|
304
|
+
total: total,
|
|
305
|
+
totals: totals,
|
|
306
|
+
}];
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}); };
|
|
310
|
+
exports.fetchAnnouncementOverview = fetchAnnouncementOverview;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DateTime } from "luxon";
|
|
2
|
+
import type { AcknowledgementPolicy, AnnouncementAudienceType, AnnouncementDisplayMode, AnnouncementDocument, AnnouncementPlatform } from "./types";
|
|
3
|
+
export interface AnnouncementAckState {
|
|
4
|
+
announcementId: string;
|
|
5
|
+
version: number;
|
|
6
|
+
}
|
|
7
|
+
export interface AnnouncementImpressionState {
|
|
8
|
+
announcementId: string;
|
|
9
|
+
version: number;
|
|
10
|
+
}
|
|
11
|
+
export declare const resolveAcknowledgementPolicy: ({ announcement, defaultAcknowledgementPolicy, }: {
|
|
12
|
+
announcement: AnnouncementDocument;
|
|
13
|
+
defaultAcknowledgementPolicy?: AcknowledgementPolicy;
|
|
14
|
+
}) => AcknowledgementPolicy;
|
|
15
|
+
export declare const requiresAcknowledgementForAnnouncement: ({ announcement, defaultAcknowledgementPolicy, }: {
|
|
16
|
+
announcement: AnnouncementDocument;
|
|
17
|
+
defaultAcknowledgementPolicy?: AcknowledgementPolicy;
|
|
18
|
+
}) => boolean;
|
|
19
|
+
export declare const resolveDisplayMode: (announcement: AnnouncementDocument) => AnnouncementDisplayMode;
|
|
20
|
+
export declare const resolveAudienceType: (announcement: AnnouncementDocument) => AnnouncementAudienceType;
|
|
21
|
+
export declare const matchAudienceByType: ({ announcement, isStaff, user, }: {
|
|
22
|
+
announcement: AnnouncementDocument;
|
|
23
|
+
isStaff: (user: unknown) => boolean;
|
|
24
|
+
user: unknown;
|
|
25
|
+
}) => boolean;
|
|
26
|
+
export declare const parseQueryVersion: (raw: unknown) => number | undefined;
|
|
27
|
+
export declare const passesMinBuildNumber: ({ announcement, queryVersion, }: {
|
|
28
|
+
announcement: AnnouncementDocument;
|
|
29
|
+
queryVersion?: number;
|
|
30
|
+
}) => boolean;
|
|
31
|
+
export declare const isInterruptDisplayMode: (announcement: AnnouncementDocument) => boolean;
|
|
32
|
+
export declare const isAnnouncementVisibleNow: ({ announcement, now, }: {
|
|
33
|
+
announcement: AnnouncementDocument;
|
|
34
|
+
now?: DateTime;
|
|
35
|
+
}) => boolean;
|
|
36
|
+
export declare const matchesPlatform: ({ announcement, platform, }: {
|
|
37
|
+
announcement: AnnouncementDocument;
|
|
38
|
+
platform: AnnouncementPlatform;
|
|
39
|
+
}) => boolean;
|
|
40
|
+
export declare const isAnnouncementPendingForUser: ({ acknowledgements, announcement, defaultAcknowledgementPolicy, impressions, }: {
|
|
41
|
+
acknowledgements: AnnouncementAckState[];
|
|
42
|
+
announcement: AnnouncementDocument;
|
|
43
|
+
defaultAcknowledgementPolicy?: AcknowledgementPolicy;
|
|
44
|
+
impressions: AnnouncementImpressionState[];
|
|
45
|
+
}) => boolean;
|
|
46
|
+
export declare const sortAnnouncementsForQueue: (announcements: AnnouncementDocument[]) => AnnouncementDocument[];
|
|
47
|
+
export declare const selectPendingAnnouncements: ({ acknowledgements, announcements, defaultAcknowledgementPolicy, impressions, now, platform, queryVersion, }: {
|
|
48
|
+
acknowledgements: AnnouncementAckState[];
|
|
49
|
+
announcements: AnnouncementDocument[];
|
|
50
|
+
defaultAcknowledgementPolicy?: AcknowledgementPolicy;
|
|
51
|
+
impressions: AnnouncementImpressionState[];
|
|
52
|
+
now?: DateTime;
|
|
53
|
+
platform: AnnouncementPlatform;
|
|
54
|
+
queryVersion?: number;
|
|
55
|
+
}) => AnnouncementDocument[];
|
|
56
|
+
export declare const isAnnouncementVisibleToUser: ({ announcement, isStaff, matchAudience, now, platform, queryVersion, user, }: {
|
|
57
|
+
announcement: AnnouncementDocument;
|
|
58
|
+
isStaff: (user: unknown) => boolean;
|
|
59
|
+
matchAudience: (user: unknown, announcement: AnnouncementDocument) => boolean | Promise<boolean>;
|
|
60
|
+
now?: DateTime;
|
|
61
|
+
platform: AnnouncementPlatform;
|
|
62
|
+
queryVersion?: number;
|
|
63
|
+
user: unknown;
|
|
64
|
+
}) => Promise<boolean>;
|