clarion-shared-types 1.0.113 → 1.0.115

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.
Files changed (26) hide show
  1. package/dist/cjs/modules/chat/index.js +1 -0
  2. package/dist/cjs/modules/chat/index.js.map +1 -1
  3. package/dist/cjs/modules/chat/interfaces/chat-analytics.js +35 -0
  4. package/dist/cjs/modules/chat/interfaces/chat-analytics.js.map +1 -0
  5. package/dist/cjs/modules/notification/index.js +2 -0
  6. package/dist/cjs/modules/notification/index.js.map +1 -1
  7. package/dist/cjs/modules/notification/interfaces/notification-analytics.js +27 -0
  8. package/dist/cjs/modules/notification/interfaces/notification-analytics.js.map +1 -0
  9. package/dist/cjs/modules/permission/enums/permission-actions.enum.js +6 -0
  10. package/dist/cjs/modules/permission/enums/permission-actions.enum.js.map +1 -1
  11. package/dist/esm/modules/chat/index.js +1 -0
  12. package/dist/esm/modules/chat/index.js.map +1 -1
  13. package/dist/esm/modules/chat/interfaces/chat-analytics.js +34 -0
  14. package/dist/esm/modules/chat/interfaces/chat-analytics.js.map +1 -0
  15. package/dist/esm/modules/notification/index.js +2 -0
  16. package/dist/esm/modules/notification/index.js.map +1 -1
  17. package/dist/esm/modules/notification/interfaces/notification-analytics.js +26 -0
  18. package/dist/esm/modules/notification/interfaces/notification-analytics.js.map +1 -0
  19. package/dist/esm/modules/permission/enums/permission-actions.enum.js +6 -0
  20. package/dist/esm/modules/permission/enums/permission-actions.enum.js.map +1 -1
  21. package/dist/types/modules/chat/index.d.ts +1 -0
  22. package/dist/types/modules/chat/interfaces/chat-analytics.d.ts +275 -0
  23. package/dist/types/modules/notification/index.d.ts +1 -0
  24. package/dist/types/modules/notification/interfaces/notification-analytics.d.ts +273 -0
  25. package/dist/types/modules/permission/enums/permission-actions.enum.d.ts +2 -0
  26. package/package.json +45 -45
@@ -25,6 +25,7 @@ __exportStar(require("./interfaces/chat-conversation-with-participants"), export
25
25
  __exportStar(require("./interfaces/chat-message"), exports);
26
26
  __exportStar(require("./interfaces/chat-participant"), exports);
27
27
  __exportStar(require("./interfaces/chat-presence-info"), exports);
28
+ __exportStar(require("./interfaces/chat-analytics"), exports);
28
29
  // constants
29
30
  __exportStar(require("./constants/chat-ws-events"), exports);
30
31
  __exportStar(require("./constants/chat-room-names"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/chat/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,QAAQ;AACR,wEAAsD;AACtD,sEAAoD;AACpD,iEAA+C;AAC/C,qEAAmD;AAEnD,aAAa;AACb,iEAA+C;AAC/C,mFAAiE;AACjE,4DAA0C;AAC1C,gEAA8C;AAC9C,kEAAgD;AAEhD,YAAY;AACZ,6DAA2C;AAC3C,8DAA4C"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/chat/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,QAAQ;AACR,wEAAsD;AACtD,sEAAoD;AACpD,iEAA+C;AAC/C,qEAAmD;AAEnD,aAAa;AACb,iEAA+C;AAC/C,mFAAiE;AACjE,4DAA0C;AAC1C,gEAA8C;AAC9C,kEAAgD;AAChD,8DAA4C;AAE5C,YAAY;AACZ,6DAA2C;AAC3C,8DAA4C"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * Chat analytics (the admin's Chat Analytics): how the conversations on Clarion went over
4
+ * a period - incident chats, Follow Me chats and direct chats - how much was written and
5
+ * by whom, and above all how quickly a member who wrote was answered.
6
+ *
7
+ * One read, computed by clarion-chat from one consistent snapshot, with who each person
8
+ * is from clarion-authentication. Counts, rates and durations only: never a message, a
9
+ * member's name or a trip's label. The only people named are STAFF - the control room,
10
+ * responders and administrators - as agents are on the support analytics.
11
+ *
12
+ * DURATIONS ARE IN SECONDS, like every analytics contract.
13
+ *
14
+ * How it is counted:
15
+ * - A conversation belongs to the organization, control centre and country of the
16
+ * person who STARTED it: the member who raised the SOS, the traveller on a Follow Me
17
+ * trip, the administrator who opened a direct chat. clarion-chat keeps no organization
18
+ * of its own. Everything written in a conversation is its organization's, whoever
19
+ * wrote it - a guardian, or a responder from another organization.
20
+ * - What a conversation is for (`ChatAnalyticsContext`): INCIDENT is an incident's chat,
21
+ * including a Follow Me chat that an SOS adopted; FOLLOW_ME a trip's; DIRECT one person
22
+ * to another; GROUP any other group.
23
+ * - Who writes (`ChatAnalyticsSenderKind`), from the roles a person holds NOW: anybody
24
+ * with a control-centre role is the CONTROL_ROOM, then RESPONDER, then ADMINISTRATOR
25
+ * (organization roles, Super-Admin) - together, STAFF. Everybody else is a MEMBER: the
26
+ * people the service is for, their guardians included. UNKNOWN is an account that no
27
+ * longer exists. Whoever started an incident's or a Follow Me chat from the app is its
28
+ * MEMBER there, whatever else they hold - staff raise SOSes too.
29
+ * - A member's TURN starts with a member's message that opens a conversation or follows
30
+ * a staff message. It is ANSWERED by the first staff message after it, and the wait is
31
+ * the time between. Turns started in the period, answered whenever.
32
+ * - System messages are counted on their own and never take part in a turn.
33
+ */
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ //# sourceMappingURL=chat-analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-analytics.js","sourceRoot":"","sources":["../../../../../src/modules/chat/interfaces/chat-analytics.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG"}
@@ -31,4 +31,6 @@ __exportStar(require("./interfaces/notification-dispatch-result"), exports);
31
31
  __exportStar(require("./interfaces/organization-notification-settings.dto"), exports);
32
32
  // Utilities
33
33
  __exportStar(require("./utils/notification-sender.util"), exports);
34
+ // Notification Analytics (GET /notifications/admin/analytics)
35
+ __exportStar(require("./interfaces/notification-analytics"), exports);
34
36
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,QAAQ;AACR,oEAAkD;AAClD,iEAA+C;AAC/C,mEAAiD;AACjD,2EAAyD;AACzD,uEAAqD;AACrD,sEAAoD;AAEpD,4CAA4C;AAC5C,gEAA8C;AAC9C,kEAAgD;AAChD,+DAA6C;AAC7C,iEAA+C;AAC/C,4EAA0D;AAE1D,kEAAkE;AAClE,sFAAoE;AAEpE,YAAY;AACZ,mEAAiD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,QAAQ;AACR,oEAAkD;AAClD,iEAA+C;AAC/C,mEAAiD;AACjD,2EAAyD;AACzD,uEAAqD;AACrD,sEAAoD;AAEpD,4CAA4C;AAC5C,gEAA8C;AAC9C,kEAAgD;AAChD,+DAA6C;AAC7C,iEAA+C;AAC/C,4EAA0D;AAE1D,kEAAkE;AAClE,sFAAoE;AAEpE,YAAY;AACZ,mEAAiD;AAEjD,8DAA8D;AAC9D,sEAAoD"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /**
3
+ * Notification analytics (the admin's Notification Analytics): what Clarion sent people
4
+ * over a period, on every channel - push to the app, the console's in-app notifications,
5
+ * SMS and email - whether it got through, whether it was opened, and how many people a
6
+ * push can reach at all.
7
+ *
8
+ * One read, computed by clarion-notification from one consistent snapshot, with who each
9
+ * recipient is from clarion-authentication. Counts, rates and durations only: never a
10
+ * title, a message, a phone number or an address.
11
+ *
12
+ * DURATIONS ARE IN SECONDS, like every analytics contract.
13
+ *
14
+ * How it is counted:
15
+ * - Everything by when it was CREATED - the moment Clarion decided to tell somebody.
16
+ * - Whose it is: the organization recorded on it; for a push, the organization of the
17
+ * post it announces, then the recipient's; for an SMS, the recipient's. Older SMS and
18
+ * email (before 21 September 2026) recorded no organization and often no recipient:
19
+ * those are counted only in the platform view (`unattributed`).
20
+ * - Got through: accepted by the provider - Firebase for a push, the SMS gateway, the
21
+ * mail service - or, in the console, delivered. Nothing reports whether an SMS or an
22
+ * email was read, so only push (tapped) and in-app (read) have an open rate.
23
+ * - A country narrows push, in-app and devices by the recipient's country and SMS by
24
+ * the number's; email has no country and is never narrowed.
25
+ */
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ //# sourceMappingURL=notification-analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-analytics.js","sourceRoot":"","sources":["../../../../../src/modules/notification/interfaces/notification-analytics.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
@@ -54,6 +54,9 @@ var PermissionActions;
54
54
  PermissionActions["READ_INCIDENT"] = "read:incident";
55
55
  PermissionActions["UPDATE_INCIDENT"] = "update:incident";
56
56
  PermissionActions["DELETE_INCIDENT"] = "delete:incident";
57
+ // Chat Analytics: how the chats went and how quickly members were answered - totals
58
+ // only. Held by exactly the roles that read the user analytics.
59
+ PermissionActions["READ_CHAT_ANALYTICS"] = "read:chat-analytics";
57
60
  PermissionActions["CREATE_INCIDENT_CATEGORY_TYPE"] = "create:incident-category-type";
58
61
  PermissionActions["READ_INCIDENT_CATEGORY_TYPE"] = "read:incident-category-type";
59
62
  PermissionActions["UPDATE_INCIDENT_CATEGORY_TYPE"] = "update:incident-category-type";
@@ -125,6 +128,9 @@ var PermissionActions;
125
128
  // emails are branded, the address they are sent from, and the sender ID its
126
129
  // SMS arrive under - one family per thing configured. Mirrors grm-shared-library.
127
130
  PermissionActions["READ_NOTIFICATION_BRANDING"] = "read:notification-branding";
131
+ // Notification Analytics: what went out on every channel and whether it got
132
+ // through - totals only. Held by exactly the roles that read the notification settings.
133
+ PermissionActions["READ_NOTIFICATION_ANALYTICS"] = "read:notification-analytics";
128
134
  PermissionActions["UPDATE_NOTIFICATION_BRANDING"] = "update:notification-branding";
129
135
  PermissionActions["CREATE_NOTIFICATION_EMAIL_SENDER"] = "create:notification-email-sender";
130
136
  PermissionActions["READ_NOTIFICATION_EMAIL_SENDER"] = "read:notification-email-sender";
@@ -1 +1 @@
1
- {"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,7 @@ export * from './interfaces/chat-conversation-with-participants';
9
9
  export * from './interfaces/chat-message';
10
10
  export * from './interfaces/chat-participant';
11
11
  export * from './interfaces/chat-presence-info';
12
+ export * from './interfaces/chat-analytics';
12
13
  // constants
13
14
  export * from './constants/chat-ws-events';
14
15
  export * from './constants/chat-room-names';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/chat/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AAEnD,aAAa;AACb,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kDAAkD,CAAC;AACjE,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAEhD,YAAY;AACZ,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/chat/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,uCAAuC,CAAC;AACtD,cAAc,qCAAqC,CAAC;AACpD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AAEnD,aAAa;AACb,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kDAAkD,CAAC;AACjE,cAAc,2BAA2B,CAAC;AAC1C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAE5C,YAAY;AACZ,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Chat analytics (the admin's Chat Analytics): how the conversations on Clarion went over
3
+ * a period - incident chats, Follow Me chats and direct chats - how much was written and
4
+ * by whom, and above all how quickly a member who wrote was answered.
5
+ *
6
+ * One read, computed by clarion-chat from one consistent snapshot, with who each person
7
+ * is from clarion-authentication. Counts, rates and durations only: never a message, a
8
+ * member's name or a trip's label. The only people named are STAFF - the control room,
9
+ * responders and administrators - as agents are on the support analytics.
10
+ *
11
+ * DURATIONS ARE IN SECONDS, like every analytics contract.
12
+ *
13
+ * How it is counted:
14
+ * - A conversation belongs to the organization, control centre and country of the
15
+ * person who STARTED it: the member who raised the SOS, the traveller on a Follow Me
16
+ * trip, the administrator who opened a direct chat. clarion-chat keeps no organization
17
+ * of its own. Everything written in a conversation is its organization's, whoever
18
+ * wrote it - a guardian, or a responder from another organization.
19
+ * - What a conversation is for (`ChatAnalyticsContext`): INCIDENT is an incident's chat,
20
+ * including a Follow Me chat that an SOS adopted; FOLLOW_ME a trip's; DIRECT one person
21
+ * to another; GROUP any other group.
22
+ * - Who writes (`ChatAnalyticsSenderKind`), from the roles a person holds NOW: anybody
23
+ * with a control-centre role is the CONTROL_ROOM, then RESPONDER, then ADMINISTRATOR
24
+ * (organization roles, Super-Admin) - together, STAFF. Everybody else is a MEMBER: the
25
+ * people the service is for, their guardians included. UNKNOWN is an account that no
26
+ * longer exists. Whoever started an incident's or a Follow Me chat from the app is its
27
+ * MEMBER there, whatever else they hold - staff raise SOSes too.
28
+ * - A member's TURN starts with a member's message that opens a conversation or follows
29
+ * a staff message. It is ANSWERED by the first staff message after it, and the wait is
30
+ * the time between. Turns started in the period, answered whenever.
31
+ * - System messages are counted on their own and never take part in a turn.
32
+ */
33
+ export {};
34
+ //# sourceMappingURL=chat-analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat-analytics.js","sourceRoot":"","sources":["../../../../../src/modules/chat/interfaces/chat-analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG"}
@@ -15,4 +15,6 @@ export * from './interfaces/notification-dispatch-result';
15
15
  export * from './interfaces/organization-notification-settings.dto';
16
16
  // Utilities
17
17
  export * from './utils/notification-sender.util';
18
+ // Notification Analytics (GET /notifications/admin/analytics)
19
+ export * from './interfaces/notification-analytics';
18
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AAEpD,4CAA4C;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2CAA2C,CAAC;AAE1D,kEAAkE;AAClE,cAAc,qDAAqD,CAAC;AAEpE,YAAY;AACZ,cAAc,kCAAkC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/notification/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,mCAAmC,CAAC;AAClD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kCAAkC,CAAC;AACjD,cAAc,0CAA0C,CAAC;AACzD,cAAc,sCAAsC,CAAC;AACrD,cAAc,qCAAqC,CAAC;AAEpD,4CAA4C;AAC5C,cAAc,+BAA+B,CAAC;AAC9C,cAAc,iCAAiC,CAAC;AAChD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2CAA2C,CAAC;AAE1D,kEAAkE;AAClE,cAAc,qDAAqD,CAAC;AAEpE,YAAY;AACZ,cAAc,kCAAkC,CAAC;AAEjD,8DAA8D;AAC9D,cAAc,qCAAqC,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Notification analytics (the admin's Notification Analytics): what Clarion sent people
3
+ * over a period, on every channel - push to the app, the console's in-app notifications,
4
+ * SMS and email - whether it got through, whether it was opened, and how many people a
5
+ * push can reach at all.
6
+ *
7
+ * One read, computed by clarion-notification from one consistent snapshot, with who each
8
+ * recipient is from clarion-authentication. Counts, rates and durations only: never a
9
+ * title, a message, a phone number or an address.
10
+ *
11
+ * DURATIONS ARE IN SECONDS, like every analytics contract.
12
+ *
13
+ * How it is counted:
14
+ * - Everything by when it was CREATED - the moment Clarion decided to tell somebody.
15
+ * - Whose it is: the organization recorded on it; for a push, the organization of the
16
+ * post it announces, then the recipient's; for an SMS, the recipient's. Older SMS and
17
+ * email (before 21 September 2026) recorded no organization and often no recipient:
18
+ * those are counted only in the platform view (`unattributed`).
19
+ * - Got through: accepted by the provider - Firebase for a push, the SMS gateway, the
20
+ * mail service - or, in the console, delivered. Nothing reports whether an SMS or an
21
+ * email was read, so only push (tapped) and in-app (read) have an open rate.
22
+ * - A country narrows push, in-app and devices by the recipient's country and SMS by
23
+ * the number's; email has no country and is never narrowed.
24
+ */
25
+ export {};
26
+ //# sourceMappingURL=notification-analytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notification-analytics.js","sourceRoot":"","sources":["../../../../../src/modules/notification/interfaces/notification-analytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG"}
@@ -51,6 +51,9 @@ export var PermissionActions;
51
51
  PermissionActions["READ_INCIDENT"] = "read:incident";
52
52
  PermissionActions["UPDATE_INCIDENT"] = "update:incident";
53
53
  PermissionActions["DELETE_INCIDENT"] = "delete:incident";
54
+ // Chat Analytics: how the chats went and how quickly members were answered - totals
55
+ // only. Held by exactly the roles that read the user analytics.
56
+ PermissionActions["READ_CHAT_ANALYTICS"] = "read:chat-analytics";
54
57
  PermissionActions["CREATE_INCIDENT_CATEGORY_TYPE"] = "create:incident-category-type";
55
58
  PermissionActions["READ_INCIDENT_CATEGORY_TYPE"] = "read:incident-category-type";
56
59
  PermissionActions["UPDATE_INCIDENT_CATEGORY_TYPE"] = "update:incident-category-type";
@@ -122,6 +125,9 @@ export var PermissionActions;
122
125
  // emails are branded, the address they are sent from, and the sender ID its
123
126
  // SMS arrive under - one family per thing configured. Mirrors grm-shared-library.
124
127
  PermissionActions["READ_NOTIFICATION_BRANDING"] = "read:notification-branding";
128
+ // Notification Analytics: what went out on every channel and whether it got
129
+ // through - totals only. Held by exactly the roles that read the notification settings.
130
+ PermissionActions["READ_NOTIFICATION_ANALYTICS"] = "read:notification-analytics";
125
131
  PermissionActions["UPDATE_NOTIFICATION_BRANDING"] = "update:notification-branding";
126
132
  PermissionActions["CREATE_NOTIFICATION_EMAIL_SENDER"] = "create:notification-email-sender";
127
133
  PermissionActions["READ_NOTIFICATION_EMAIL_SENDER"] = "read:notification-email-sender";
@@ -1 +1 @@
1
- {"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"permission-actions.enum.js","sourceRoot":"","sources":["../../../../../src/modules/permission/enums/permission-actions.enum.ts"],"names":[],"mappings":"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"}
@@ -7,5 +7,6 @@ export * from './interfaces/chat-conversation-with-participants';
7
7
  export * from './interfaces/chat-message';
8
8
  export * from './interfaces/chat-participant';
9
9
  export * from './interfaces/chat-presence-info';
10
+ export * from './interfaces/chat-analytics';
10
11
  export * from './constants/chat-ws-events';
11
12
  export * from './constants/chat-room-names';
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Chat analytics (the admin's Chat Analytics): how the conversations on Clarion went over
3
+ * a period - incident chats, Follow Me chats and direct chats - how much was written and
4
+ * by whom, and above all how quickly a member who wrote was answered.
5
+ *
6
+ * One read, computed by clarion-chat from one consistent snapshot, with who each person
7
+ * is from clarion-authentication. Counts, rates and durations only: never a message, a
8
+ * member's name or a trip's label. The only people named are STAFF - the control room,
9
+ * responders and administrators - as agents are on the support analytics.
10
+ *
11
+ * DURATIONS ARE IN SECONDS, like every analytics contract.
12
+ *
13
+ * How it is counted:
14
+ * - A conversation belongs to the organization, control centre and country of the
15
+ * person who STARTED it: the member who raised the SOS, the traveller on a Follow Me
16
+ * trip, the administrator who opened a direct chat. clarion-chat keeps no organization
17
+ * of its own. Everything written in a conversation is its organization's, whoever
18
+ * wrote it - a guardian, or a responder from another organization.
19
+ * - What a conversation is for (`ChatAnalyticsContext`): INCIDENT is an incident's chat,
20
+ * including a Follow Me chat that an SOS adopted; FOLLOW_ME a trip's; DIRECT one person
21
+ * to another; GROUP any other group.
22
+ * - Who writes (`ChatAnalyticsSenderKind`), from the roles a person holds NOW: anybody
23
+ * with a control-centre role is the CONTROL_ROOM, then RESPONDER, then ADMINISTRATOR
24
+ * (organization roles, Super-Admin) - together, STAFF. Everybody else is a MEMBER: the
25
+ * people the service is for, their guardians included. UNKNOWN is an account that no
26
+ * longer exists. Whoever started an incident's or a Follow Me chat from the app is its
27
+ * MEMBER there, whatever else they hold - staff raise SOSes too.
28
+ * - A member's TURN starts with a member's message that opens a conversation or follows
29
+ * a staff message. It is ANSWERED by the first staff message after it, and the wait is
30
+ * the time between. Turns started in the period, answered whenever.
31
+ * - System messages are counted on their own and never take part in a turn.
32
+ */
33
+ /** How the period is cut into points for the charts. Chosen by the service from the length of the period. */
34
+ export type ChatAnalyticsBucket = 'hour' | 'day' | 'week' | 'month';
35
+ /** What a conversation is for. */
36
+ export type ChatAnalyticsContext = 'INCIDENT' | 'FOLLOW_ME' | 'DIRECT' | 'GROUP';
37
+ /** Who wrote a message: the three kinds of staff, a member, or an account that no longer exists. */
38
+ export type ChatAnalyticsSenderKind = 'CONTROL_ROOM' | 'RESPONDER' | 'ADMINISTRATOR' | 'MEMBER' | 'UNKNOWN';
39
+ export interface ChatAnalyticsRange {
40
+ /** Inclusive, ISO 8601. The first conversation when the period asked for was "forever". */
41
+ from: string;
42
+ /** Exclusive, ISO 8601. */
43
+ to: string;
44
+ bucket: ChatAnalyticsBucket;
45
+ /** IANA time zone the buckets and the hour-of-week grid are cut in. */
46
+ timeZone: string;
47
+ }
48
+ /** A count by a key (a context, a kind, a band), largest first unless the section says otherwise. */
49
+ export interface ChatAnalyticsCount<K extends string = string> {
50
+ key: K;
51
+ count: number;
52
+ }
53
+ /** Median and 90th percentile of one duration, in seconds; null when nothing was measured. */
54
+ export interface ChatAnalyticsDuration {
55
+ median: number | null;
56
+ p90: number | null;
57
+ /** How many were measured. */
58
+ count: number;
59
+ }
60
+ /** One kind of conversation and how it went in the period. */
61
+ export interface ChatAnalyticsContextRow {
62
+ context: ChatAnalyticsContext;
63
+ /** Started in the period. */
64
+ started: number;
65
+ /** Of those, written in at least once (whenever). */
66
+ used: number;
67
+ /** Written in during the period, whenever started. */
68
+ active: number;
69
+ /** Messages written in the period, not counting system messages. */
70
+ messages: number;
71
+ memberMessages: number;
72
+ staffMessages: number;
73
+ /** Members' turns started in the period, and of those answered. */
74
+ turns: number;
75
+ answered: number;
76
+ /** answered / turns, as a percentage. */
77
+ replyRate: number | null;
78
+ medianSecondsToReply: number | null;
79
+ }
80
+ /** The conversations: what was started, what was used, and who was in them. */
81
+ export interface ChatAnalyticsConversations {
82
+ /** Started in the period. */
83
+ started: number;
84
+ /** Of those, written in at least once (whenever) - and as a percentage. */
85
+ used: number;
86
+ usedRate: number | null;
87
+ /** Of those, a member AND staff both wrote in - a conversation rather than a notice. */
88
+ twoWay: number;
89
+ /** Written in during the period, whenever started. */
90
+ active: number;
91
+ /** People seated in the conversations started in the period, each counted once. */
92
+ people: number;
93
+ /** People per conversation started in the period. */
94
+ averageParticipants: number | null;
95
+ /**
96
+ * In the period, in any conversation in scope: people added AFTER it started (a
97
+ * responder assigned, a guardian added - not the people it started with), and seats
98
+ * given up (removed, or left).
99
+ */
100
+ joined: number;
101
+ left: number;
102
+ /** Start to the first message - conversations started in the period that were used. */
103
+ toFirstMessage: ChatAnalyticsDuration;
104
+ /** Start to the first staff message - conversations started in the period that staff wrote in. */
105
+ toFirstStaffMessage: ChatAnalyticsDuration;
106
+ /** INCIDENT, FOLLOW_ME, DIRECT, GROUP - in that order, zeros included. */
107
+ byContext: ChatAnalyticsContextRow[];
108
+ /** Conversations started in the period by how many people are in them now: 1, 2, 3, 4, 5, 6+ - in that order. */
109
+ bySize: ChatAnalyticsCount[];
110
+ /** Conversations started in the period, by the country of whoever started them. */
111
+ byCountry: ChatAnalyticsCount[];
112
+ }
113
+ /** The messages written in the period. */
114
+ export interface ChatAnalyticsMessages {
115
+ /** Written by people (system messages are `system`). */
116
+ sent: number;
117
+ fromMembers: number;
118
+ fromStaff: number;
119
+ /** By accounts that no longer exist. */
120
+ fromUnknown: number;
121
+ system: number;
122
+ /** Removed in the period, whenever written. */
123
+ removed: number;
124
+ /** Different people who wrote. */
125
+ senders: number;
126
+ memberSenders: number;
127
+ staffSenders: number;
128
+ /** sent / active conversations. */
129
+ perActiveConversation: number | null;
130
+ /** CONTROL_ROOM, RESPONDER, ADMINISTRATOR, MEMBER, UNKNOWN - in that order, zeros included. */
131
+ bySenderKind: ChatAnalyticsCount<ChatAnalyticsSenderKind>[];
132
+ /** Characters, never the words. */
133
+ medianLength: number | null;
134
+ /** SHORT (under 20 characters), MEDIUM (20-79), LONG (80-279), VERY_LONG (280+) - in that order. */
135
+ byLength: ChatAnalyticsCount[];
136
+ }
137
+ /** How quickly members were answered. */
138
+ export interface ChatAnalyticsReplies {
139
+ /** Members' turns started in the period. */
140
+ turns: number;
141
+ answered: number;
142
+ /** Never answered - the last word in that conversation is still the member's. */
143
+ unanswered: number;
144
+ /** answered / turns, as a percentage. */
145
+ replyRate: number | null;
146
+ /** The member's message to the first staff message after it - turns answered. */
147
+ toReply: ChatAnalyticsDuration;
148
+ /** Answered within a minute, 5 minutes, 15 minutes, an hour, later: UNDER_1M, 1-5M, 5-15M, 15-60M, OVER_1H - in that order. */
149
+ byWait: ChatAnalyticsCount[];
150
+ /** Answered within 5 minutes, as a percentage of turns. */
151
+ withinFiveMinutes: number | null;
152
+ }
153
+ /** One member of staff who wrote in the period. Staff are named; members never are. */
154
+ export interface ChatAnalyticsStaffRow {
155
+ userId: number;
156
+ name: string | null;
157
+ kind: ChatAnalyticsSenderKind;
158
+ /** Messages they wrote in the period. */
159
+ messages: number;
160
+ /** Conversations they wrote in, in the period. */
161
+ conversations: number;
162
+ /** Members' turns started in the period that they were first to answer. */
163
+ replies: number;
164
+ medianSecondsToReply: number | null;
165
+ }
166
+ /** One conversation, for a table - never its messages, its members or its label. */
167
+ export interface ChatAnalyticsConversationRow {
168
+ id: string;
169
+ context: ChatAnalyticsContext;
170
+ /** The incident it belongs to, for an incident's chat. */
171
+ incidentId: number | null;
172
+ organizationId: number | null;
173
+ startedAt: string;
174
+ /** People in it now. */
175
+ participants: number;
176
+ /** Written in the period. */
177
+ messages: number;
178
+ memberMessages: number;
179
+ staffMessages: number;
180
+ /** Its latest message, whenever. */
181
+ lastMessageAt: string | null;
182
+ /** Its members' turns started in the period, answered. */
183
+ medianSecondsToReply: number | null;
184
+ /** The last word is a member's, and nobody from staff has answered it. */
185
+ awaitingReply: boolean;
186
+ /** When that unanswered member's turn began; null when nothing is waiting. */
187
+ waitingSince: string | null;
188
+ }
189
+ /** One point on the charts: a bucket of the period. */
190
+ export interface ChatAnalyticsPoint {
191
+ /** Local wall-clock start of the bucket, in `range.timeZone` (no offset). */
192
+ bucket: string;
193
+ /** Conversations started in the bucket, and of those incident chats. */
194
+ started: number;
195
+ incidentChats: number;
196
+ memberMessages: number;
197
+ staffMessages: number;
198
+ /** Conversations written in during the bucket. */
199
+ active: number;
200
+ /** Members' turns started in the bucket, and of those answered. */
201
+ turns: number;
202
+ answered: number;
203
+ medianSecondsToReply: number | null;
204
+ }
205
+ /** One hour of the week. Weekday 1 is Monday. */
206
+ export interface ChatAnalyticsHeatCell {
207
+ weekday: number;
208
+ hour: number;
209
+ /** When members write. */
210
+ memberMessages: number;
211
+ /** When staff write. */
212
+ staffMessages: number;
213
+ }
214
+ /** The previous period of the same length, for the change on each headline figure. */
215
+ export interface ChatAnalyticsPrevious {
216
+ from: string;
217
+ to: string;
218
+ started: number;
219
+ used: number;
220
+ active: number;
221
+ sent: number;
222
+ memberMessages: number;
223
+ staffMessages: number;
224
+ senders: number;
225
+ turns: number;
226
+ answered: number;
227
+ replyRate: number | null;
228
+ medianSecondsToReply: number | null;
229
+ }
230
+ /** A Super-Admin's view of every organization: one row each, busiest first. */
231
+ export interface ChatAnalyticsOrganizationRow {
232
+ organizationId: number;
233
+ started: number;
234
+ active: number;
235
+ sent: number;
236
+ memberMessages: number;
237
+ staffMessages: number;
238
+ turns: number;
239
+ replyRate: number | null;
240
+ medianSecondsToReply: number | null;
241
+ }
242
+ export interface ChatAnalytics {
243
+ /** Whose figures: one organization (and one control centre in it), or null for every organization. */
244
+ organizationId: number | null;
245
+ controlCentreId: number | null;
246
+ /** The one country the figures are narrowed to, or null for every country. */
247
+ countryCode: string | null;
248
+ range: ChatAnalyticsRange;
249
+ generatedAt: string;
250
+ previous: ChatAnalyticsPrevious | null;
251
+ /** Countries with conversations in scope, whatever country is chosen - for narrowing to one. */
252
+ countryOptions: ChatAnalyticsCount[];
253
+ conversations: ChatAnalyticsConversations;
254
+ messages: ChatAnalyticsMessages;
255
+ replies: ChatAnalyticsReplies;
256
+ /** Staff who wrote in the period, busiest first - at most 25. */
257
+ staff: ChatAnalyticsStaffRow[];
258
+ /** The 15 conversations most written in during the period. */
259
+ busiest: ChatAnalyticsConversationRow[];
260
+ /** Conversations written in during the period whose member is still waiting for an answer, latest first - at most 25. */
261
+ waiting: ChatAnalyticsConversationRow[];
262
+ timeline: ChatAnalyticsPoint[];
263
+ /** All 168 hours of the week, Monday first, zeros included. */
264
+ heatmap: ChatAnalyticsHeatCell[];
265
+ /** A Super-Admin looking at every organization only. */
266
+ byOrganization?: ChatAnalyticsOrganizationRow[];
267
+ }
268
+ /** What a dashboard asks: the period, one country - and, for a Super-Admin, whose figures. */
269
+ export interface ChatAnalyticsQuery {
270
+ from?: string;
271
+ to?: string;
272
+ timeZone?: string;
273
+ organizationId?: number;
274
+ countryCode?: string;
275
+ }
@@ -11,3 +11,4 @@ export * from './interfaces/email-send-result';
11
11
  export * from './interfaces/notification-dispatch-result';
12
12
  export * from './interfaces/organization-notification-settings.dto';
13
13
  export * from './utils/notification-sender.util';
14
+ export * from './interfaces/notification-analytics';
@@ -0,0 +1,273 @@
1
+ /**
2
+ * Notification analytics (the admin's Notification Analytics): what Clarion sent people
3
+ * over a period, on every channel - push to the app, the console's in-app notifications,
4
+ * SMS and email - whether it got through, whether it was opened, and how many people a
5
+ * push can reach at all.
6
+ *
7
+ * One read, computed by clarion-notification from one consistent snapshot, with who each
8
+ * recipient is from clarion-authentication. Counts, rates and durations only: never a
9
+ * title, a message, a phone number or an address.
10
+ *
11
+ * DURATIONS ARE IN SECONDS, like every analytics contract.
12
+ *
13
+ * How it is counted:
14
+ * - Everything by when it was CREATED - the moment Clarion decided to tell somebody.
15
+ * - Whose it is: the organization recorded on it; for a push, the organization of the
16
+ * post it announces, then the recipient's; for an SMS, the recipient's. Older SMS and
17
+ * email (before 21 September 2026) recorded no organization and often no recipient:
18
+ * those are counted only in the platform view (`unattributed`).
19
+ * - Got through: accepted by the provider - Firebase for a push, the SMS gateway, the
20
+ * mail service - or, in the console, delivered. Nothing reports whether an SMS or an
21
+ * email was read, so only push (tapped) and in-app (read) have an open rate.
22
+ * - A country narrows push, in-app and devices by the recipient's country and SMS by
23
+ * the number's; email has no country and is never narrowed.
24
+ */
25
+ /** How the period is cut into points for the charts. Chosen by the service from the length of the period. */
26
+ export type NotificationAnalyticsBucket = 'hour' | 'day' | 'week' | 'month';
27
+ /** The four ways Clarion tells somebody something. */
28
+ export type NotificationAnalyticsChannel = 'PUSH' | 'IN_APP' | 'SMS' | 'EMAIL';
29
+ export interface NotificationAnalyticsRange {
30
+ /** Inclusive, ISO 8601. The first notification when the period asked for was "forever". */
31
+ from: string;
32
+ /** Exclusive, ISO 8601. */
33
+ to: string;
34
+ bucket: NotificationAnalyticsBucket;
35
+ /** IANA time zone the buckets and the hour-of-week grid are cut in. */
36
+ timeZone: string;
37
+ }
38
+ /** A count by a key (a kind, a provider, a reason), largest first unless the section says otherwise. */
39
+ export interface NotificationAnalyticsCount<K extends string = string> {
40
+ key: K;
41
+ count: number;
42
+ }
43
+ /** Median and 90th percentile of one duration, in seconds; null when nothing was measured. */
44
+ export interface NotificationAnalyticsDuration {
45
+ median: number | null;
46
+ p90: number | null;
47
+ /** How many were measured. */
48
+ count: number;
49
+ }
50
+ /** One channel over the period. */
51
+ export interface NotificationAnalyticsChannelRow {
52
+ channel: NotificationAnalyticsChannel;
53
+ /** Created in the period. */
54
+ total: number;
55
+ /** Got through: accepted by the provider, or delivered to the console. */
56
+ succeeded: number;
57
+ failed: number;
58
+ /** No outcome yet: waiting, or cancelled before it was sent. */
59
+ pending: number;
60
+ /** succeeded / (succeeded + failed), as a percentage. */
61
+ successRate: number | null;
62
+ /** Push tapped, in-app read; null for SMS and email - nothing reports it. */
63
+ opened: number | null;
64
+ /** opened / succeeded, as a percentage. */
65
+ openRate: number | null;
66
+ }
67
+ /** One kind of push - what it announced - and how it went. */
68
+ export interface NotificationAnalyticsPushKindRow {
69
+ /** The event it announced (NEWSFEED_POST_PUBLISHED, GUARDIAN_INCIDENT_ALERT...), else its category (INCIDENT, ALERT...). */
70
+ kind: string;
71
+ total: number;
72
+ failed: number;
73
+ opened: number;
74
+ /** opened / those that got through, as a percentage. */
75
+ openRate: number | null;
76
+ medianSecondsToOpen: number | null;
77
+ }
78
+ /** Push notifications to the app. */
79
+ export interface NotificationAnalyticsPush {
80
+ /** One per device: a notification to somebody with two phones is two. */
81
+ total: number;
82
+ succeeded: number;
83
+ failed: number;
84
+ pending: number;
85
+ opened: number;
86
+ successRate: number | null;
87
+ openRate: number | null;
88
+ /** Different people pushed to. */
89
+ recipients: number;
90
+ /** Notifications as Clarion decided them, each fanned out to its recipients' devices. */
91
+ sends: number;
92
+ /** Created to accepted by Firebase - seconds, with decimals. */
93
+ toSend: NotificationAnalyticsDuration;
94
+ /** Created to tapped. */
95
+ toOpen: NotificationAnalyticsDuration;
96
+ byKind: NotificationAnalyticsPushKindRow[];
97
+ /** Critical, High, Normal, Low - in that order, zeros included. */
98
+ byPriority: NotificationAnalyticsCount[];
99
+ /** The Android channel it rang on (urgent, incidents...); DEFAULT when none. */
100
+ byChannel: NotificationAnalyticsCount[];
101
+ /** Why pushes failed, as the provider said it - ids, numbers and addresses masked. The eight commonest. */
102
+ failureReasons: NotificationAnalyticsCount[];
103
+ }
104
+ /** The phones and browsers a push can reach - NOW, whatever the period, apart from `registered`. */
105
+ export interface NotificationAnalyticsDevices {
106
+ activeNow: number;
107
+ /** Switched off: signed out, replaced by a newer registration, or refused by the provider. */
108
+ inactiveNow: number;
109
+ /** People with at least one active device: who a push can reach. */
110
+ reachableNow: number;
111
+ /** Registered in the period. */
112
+ registered: number;
113
+ /** Active devices by kind (android, ios, web). */
114
+ byType: NotificationAnalyticsCount[];
115
+ /** Active devices by app version; NONE when not recorded. */
116
+ byAppVersion: NotificationAnalyticsCount[];
117
+ byLanguage: NotificationAnalyticsCount[];
118
+ }
119
+ /** The console's own notifications, to the staff using it. */
120
+ export interface NotificationAnalyticsInApp {
121
+ total: number;
122
+ succeeded: number;
123
+ failed: number;
124
+ pending: number;
125
+ read: number;
126
+ /** read / total, as a percentage. */
127
+ readRate: number | null;
128
+ /** Different people notified. */
129
+ recipients: number;
130
+ /** INCIDENT, ALERT, MESSAGE... */
131
+ byType: NotificationAnalyticsCount[];
132
+ /** What happened (Created, Auto-Stopped, CHAT_MESSAGE...). */
133
+ byAction: NotificationAnalyticsCount[];
134
+ /** NOW: notifications nobody has read yet, whenever created. */
135
+ unreadNow: number;
136
+ }
137
+ /** Cost recorded on SMS, per currency. */
138
+ export interface NotificationAnalyticsSmsCost {
139
+ currency: string;
140
+ amount: number;
141
+ /** Messages with a cost recorded. */
142
+ messages: number;
143
+ }
144
+ /** SMS. */
145
+ export interface NotificationAnalyticsSms {
146
+ total: number;
147
+ succeeded: number;
148
+ failed: number;
149
+ pending: number;
150
+ successRate: number | null;
151
+ /** Created to accepted by the gateway. */
152
+ toSend: NotificationAnalyticsDuration;
153
+ /** What it was for: otp:verify_phone, otp:reset_password, guardian_incident_notification...; NOT_RECORDED for the oldest. */
154
+ byPurpose: NotificationAnalyticsCount[];
155
+ /** The gateway that took it (uwazii, twilio, africastalking); NOT_RECORDED for the oldest. */
156
+ byProvider: NotificationAnalyticsCount[];
157
+ /** Whose sender ID it went out under (PLATFORM_DEFAULT, ORGANIZATION); NOT_RECORDED for the oldest. */
158
+ bySenderSource: NotificationAnalyticsCount[];
159
+ /** The number's country; UNKNOWN when not recorded. */
160
+ byCountry: NotificationAnalyticsCount[];
161
+ /** Why messages failed - ids, numbers and addresses masked. The eight commonest. */
162
+ failureReasons: NotificationAnalyticsCount[];
163
+ cost: NotificationAnalyticsSmsCost[];
164
+ }
165
+ /** Email. */
166
+ export interface NotificationAnalyticsEmail {
167
+ total: number;
168
+ succeeded: number;
169
+ failed: number;
170
+ successRate: number | null;
171
+ /** Verification, Password Reset, Notification, Acknowledgement... */
172
+ byType: NotificationAnalyticsCount[];
173
+ /** The mail service that took it; NOT_RECORDED for the oldest. */
174
+ byProvider: NotificationAnalyticsCount[];
175
+ bySenderSource: NotificationAnalyticsCount[];
176
+ }
177
+ /** One point on the charts: a bucket of the period. */
178
+ export interface NotificationAnalyticsPoint {
179
+ /** Local wall-clock start of the bucket, in `range.timeZone` (no offset). */
180
+ bucket: string;
181
+ push: number;
182
+ pushFailed: number;
183
+ /** Of the pushes created in the bucket, those tapped (whenever). */
184
+ pushOpened: number;
185
+ inApp: number;
186
+ inAppRead: number;
187
+ sms: number;
188
+ smsFailed: number;
189
+ email: number;
190
+ emailFailed: number;
191
+ }
192
+ /** One hour of the week. Weekday 1 is Monday. */
193
+ export interface NotificationAnalyticsHeatCell {
194
+ weekday: number;
195
+ hour: number;
196
+ /** Notifications created in it, every channel. */
197
+ sent: number;
198
+ /** Pushes tapped in it - when people look. */
199
+ opened: number;
200
+ }
201
+ /** The previous period of the same length, for the change on each headline figure. */
202
+ export interface NotificationAnalyticsPrevious {
203
+ from: string;
204
+ to: string;
205
+ total: number;
206
+ push: number;
207
+ pushFailed: number;
208
+ pushOpened: number;
209
+ pushOpenRate: number | null;
210
+ pushSuccessRate: number | null;
211
+ inApp: number;
212
+ inAppRead: number;
213
+ sms: number;
214
+ smsFailed: number;
215
+ smsSuccessRate: number | null;
216
+ email: number;
217
+ emailFailed: number;
218
+ devicesRegistered: number;
219
+ }
220
+ /** A Super-Admin's view of every organization: one row each, busiest first. */
221
+ export interface NotificationAnalyticsOrganizationRow {
222
+ organizationId: number;
223
+ total: number;
224
+ push: number;
225
+ pushFailed: number;
226
+ pushOpenRate: number | null;
227
+ inApp: number;
228
+ inAppReadRate: number | null;
229
+ sms: number;
230
+ smsFailed: number;
231
+ email: number;
232
+ /** NOW. */
233
+ activeDevices: number;
234
+ }
235
+ /** Notifications of the period no organization could be found for - the platform view only. */
236
+ export interface NotificationAnalyticsUnattributed {
237
+ push: number;
238
+ sms: number;
239
+ email: number;
240
+ }
241
+ export interface NotificationAnalytics {
242
+ /** Whose figures: one organization, or null for every organization. */
243
+ organizationId: number | null;
244
+ /** The one country the figures are narrowed to, or null for every country. */
245
+ countryCode: string | null;
246
+ range: NotificationAnalyticsRange;
247
+ generatedAt: string;
248
+ previous: NotificationAnalyticsPrevious | null;
249
+ /** Countries with notifications or devices in scope, whatever country is chosen - for narrowing to one. */
250
+ countryOptions: NotificationAnalyticsCount[];
251
+ /** PUSH, IN_APP, SMS, EMAIL - in that order. */
252
+ channels: NotificationAnalyticsChannelRow[];
253
+ push: NotificationAnalyticsPush;
254
+ devices: NotificationAnalyticsDevices;
255
+ inApp: NotificationAnalyticsInApp;
256
+ sms: NotificationAnalyticsSms;
257
+ email: NotificationAnalyticsEmail;
258
+ timeline: NotificationAnalyticsPoint[];
259
+ /** All 168 hours of the week, Monday first, zeros included. */
260
+ heatmap: NotificationAnalyticsHeatCell[];
261
+ /** A Super-Admin looking at every organization only. */
262
+ byOrganization?: NotificationAnalyticsOrganizationRow[];
263
+ /** A Super-Admin looking at every organization only. */
264
+ unattributed?: NotificationAnalyticsUnattributed;
265
+ }
266
+ /** What a dashboard asks: the period, one country - and, for a Super-Admin, whose figures. */
267
+ export interface NotificationAnalyticsQuery {
268
+ from?: string;
269
+ to?: string;
270
+ timeZone?: string;
271
+ organizationId?: number;
272
+ countryCode?: string;
273
+ }
@@ -32,6 +32,7 @@ export declare enum PermissionActions {
32
32
  READ_INCIDENT = "read:incident",
33
33
  UPDATE_INCIDENT = "update:incident",
34
34
  DELETE_INCIDENT = "delete:incident",
35
+ READ_CHAT_ANALYTICS = "read:chat-analytics",
35
36
  CREATE_INCIDENT_CATEGORY_TYPE = "create:incident-category-type",
36
37
  READ_INCIDENT_CATEGORY_TYPE = "read:incident-category-type",
37
38
  UPDATE_INCIDENT_CATEGORY_TYPE = "update:incident-category-type",
@@ -86,6 +87,7 @@ export declare enum PermissionActions {
86
87
  READ_SUPPORT_SYNC = "read:support-sync",
87
88
  MANAGE_SUPPORT_SYNC = "manage:support-sync",
88
89
  READ_NOTIFICATION_BRANDING = "read:notification-branding",
90
+ READ_NOTIFICATION_ANALYTICS = "read:notification-analytics",
89
91
  UPDATE_NOTIFICATION_BRANDING = "update:notification-branding",
90
92
  CREATE_NOTIFICATION_EMAIL_SENDER = "create:notification-email-sender",
91
93
  READ_NOTIFICATION_EMAIL_SENDER = "read:notification-email-sender",
package/package.json CHANGED
@@ -1,45 +1,45 @@
1
- {
2
- "name": "clarion-shared-types",
3
- "version": "1.0.113",
4
- "main": "dist/cjs/index.js",
5
- "module": "dist/esm/index.js",
6
- "types": "dist/types/index.d.ts",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/types/index.d.ts",
10
- "import": "./dist/esm/index.js",
11
- "require": "./dist/cjs/index.js"
12
- },
13
- "./dist/modules/*": {
14
- "types": "./dist/types/modules/*.d.ts",
15
- "import": "./dist/esm/modules/*.js",
16
- "require": "./dist/cjs/modules/*.js"
17
- }
18
- },
19
- "files": [
20
- "dist/**/*"
21
- ],
22
- "scripts": {
23
- "clean": "rimraf dist dist-test",
24
- "build:cjs": "tsc -p tsconfig.cjs.json",
25
- "build:esm": "tsc -p tsconfig.esm.json",
26
- "build:types": "tsc -p tsconfig.types.json",
27
- "build": "npm run clean && npm run build:types && npm run build:cjs && npm run build:esm",
28
- "prepublishOnly": "npm run build",
29
- "pretest": "rimraf dist-test",
30
- "test": "tsc -p tsconfig.spec.json && node --test \"dist-test/**/*.spec.js\""
31
- },
32
- "keywords": [],
33
- "author": "vince_lawino",
34
- "license": "ISC",
35
- "description": "",
36
- "publishConfig": {
37
- "access": "public"
38
- },
39
- "devDependencies": {
40
- "@types/geojson": "^7946.0.16",
41
- "@types/node": "^20.11.2",
42
- "rimraf": "^5.0.5",
43
- "typescript": "^5.7.3"
44
- }
45
- }
1
+ {
2
+ "name": "clarion-shared-types",
3
+ "version": "1.0.115",
4
+ "main": "dist/cjs/index.js",
5
+ "module": "dist/esm/index.js",
6
+ "types": "dist/types/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/types/index.d.ts",
10
+ "import": "./dist/esm/index.js",
11
+ "require": "./dist/cjs/index.js"
12
+ },
13
+ "./dist/modules/*": {
14
+ "types": "./dist/types/modules/*.d.ts",
15
+ "import": "./dist/esm/modules/*.js",
16
+ "require": "./dist/cjs/modules/*.js"
17
+ }
18
+ },
19
+ "files": [
20
+ "dist/**/*"
21
+ ],
22
+ "scripts": {
23
+ "clean": "rimraf dist dist-test",
24
+ "build:cjs": "tsc -p tsconfig.cjs.json",
25
+ "build:esm": "tsc -p tsconfig.esm.json",
26
+ "build:types": "tsc -p tsconfig.types.json",
27
+ "build": "npm run clean && npm run build:types && npm run build:cjs && npm run build:esm",
28
+ "prepublishOnly": "npm run build",
29
+ "pretest": "rimraf dist-test",
30
+ "test": "tsc -p tsconfig.spec.json && node --test \"dist-test/**/*.spec.js\""
31
+ },
32
+ "keywords": [],
33
+ "author": "vince_lawino",
34
+ "license": "ISC",
35
+ "description": "",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "devDependencies": {
40
+ "@types/geojson": "^7946.0.16",
41
+ "@types/node": "^20.11.2",
42
+ "rimraf": "^5.0.5",
43
+ "typescript": "^5.7.3"
44
+ }
45
+ }