clarion-shared-types 1.0.114 → 1.0.116
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/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/modules/dispatch/enums/response-unit-dispatch-enums.js +133 -0
- package/dist/cjs/modules/dispatch/enums/response-unit-dispatch-enums.js.map +1 -0
- package/dist/cjs/modules/dispatch/index.js +23 -0
- package/dist/cjs/modules/dispatch/index.js.map +1 -0
- package/dist/cjs/modules/dispatch/interfaces/response-unit-dispatch.dto.js +3 -0
- package/dist/cjs/modules/dispatch/interfaces/response-unit-dispatch.dto.js.map +1 -0
- package/dist/cjs/modules/dispatch/utils/response-unit-dispatch-display.util.js +198 -0
- package/dist/cjs/modules/dispatch/utils/response-unit-dispatch-display.util.js.map +1 -0
- package/dist/cjs/modules/incident/enums/incident-actions.enum.js +2 -0
- package/dist/cjs/modules/incident/enums/incident-actions.enum.js.map +1 -1
- package/dist/cjs/modules/notification/index.js +2 -0
- package/dist/cjs/modules/notification/index.js.map +1 -1
- package/dist/cjs/modules/notification/interfaces/notification-analytics.js +27 -0
- package/dist/cjs/modules/notification/interfaces/notification-analytics.js.map +1 -0
- package/dist/cjs/modules/permission/enums/permission-actions.enum.js +9 -0
- package/dist/cjs/modules/permission/enums/permission-actions.enum.js.map +1 -1
- package/dist/cjs/modules/permission/enums/permissions-moudule.enum.js +1 -0
- package/dist/cjs/modules/permission/enums/permissions-moudule.enum.js.map +1 -1
- package/dist/cjs/modules/response-unit/enums/response-unit/response-capability.enum.js +28 -0
- package/dist/cjs/modules/response-unit/enums/response-unit/response-capability.enum.js.map +1 -0
- package/dist/cjs/modules/response-unit/index.js +1 -0
- package/dist/cjs/modules/response-unit/index.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/modules/dispatch/enums/response-unit-dispatch-enums.js +130 -0
- package/dist/esm/modules/dispatch/enums/response-unit-dispatch-enums.js.map +1 -0
- package/dist/esm/modules/dispatch/index.js +7 -0
- package/dist/esm/modules/dispatch/index.js.map +1 -0
- package/dist/esm/modules/dispatch/interfaces/response-unit-dispatch.dto.js +2 -0
- package/dist/esm/modules/dispatch/interfaces/response-unit-dispatch.dto.js.map +1 -0
- package/dist/esm/modules/dispatch/utils/response-unit-dispatch-display.util.js +188 -0
- package/dist/esm/modules/dispatch/utils/response-unit-dispatch-display.util.js.map +1 -0
- package/dist/esm/modules/incident/enums/incident-actions.enum.js +2 -0
- package/dist/esm/modules/incident/enums/incident-actions.enum.js.map +1 -1
- package/dist/esm/modules/notification/index.js +2 -0
- package/dist/esm/modules/notification/index.js.map +1 -1
- package/dist/esm/modules/notification/interfaces/notification-analytics.js +26 -0
- package/dist/esm/modules/notification/interfaces/notification-analytics.js.map +1 -0
- package/dist/esm/modules/permission/enums/permission-actions.enum.js +9 -0
- package/dist/esm/modules/permission/enums/permission-actions.enum.js.map +1 -1
- package/dist/esm/modules/permission/enums/permissions-moudule.enum.js +1 -0
- package/dist/esm/modules/permission/enums/permissions-moudule.enum.js.map +1 -1
- package/dist/esm/modules/response-unit/enums/response-unit/response-capability.enum.js +25 -0
- package/dist/esm/modules/response-unit/enums/response-unit/response-capability.enum.js.map +1 -0
- package/dist/esm/modules/response-unit/index.js +1 -0
- package/dist/esm/modules/response-unit/index.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/modules/dispatch/enums/response-unit-dispatch-enums.d.ts +109 -0
- package/dist/types/modules/dispatch/index.d.ts +3 -0
- package/dist/types/modules/dispatch/interfaces/response-unit-dispatch.dto.d.ts +166 -0
- package/dist/types/modules/dispatch/utils/response-unit-dispatch-display.util.d.ts +30 -0
- package/dist/types/modules/incident/enums/incident-actions.enum.d.ts +2 -0
- package/dist/types/modules/incident/intefaces/incident-category.d.ts +6 -0
- package/dist/types/modules/incident/intefaces/incident-type.d.ts +6 -0
- package/dist/types/modules/notification/index.d.ts +1 -0
- package/dist/types/modules/notification/interfaces/notification-analytics.d.ts +273 -0
- package/dist/types/modules/permission/enums/permission-actions.enum.d.ts +4 -0
- package/dist/types/modules/permission/enums/permissions-moudule.enum.d.ts +1 -0
- package/dist/types/modules/response-unit/enums/response-unit/response-capability.enum.d.ts +22 -0
- package/dist/types/modules/response-unit/index.d.ts +1 -0
- package/dist/types/modules/response-unit/interfaces/response-unit/response-unit.d.ts +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/** Where one unit is in answering one incident. ACTIVE = DISPATCHED..ON_SCENE. */
|
|
2
|
+
export declare enum ResponseUnitDispatchStatus {
|
|
3
|
+
DISPATCHED = "DISPATCHED",
|
|
4
|
+
ACKNOWLEDGED = "ACKNOWLEDGED",
|
|
5
|
+
EN_ROUTE = "EN_ROUTE",
|
|
6
|
+
ON_SCENE = "ON_SCENE",
|
|
7
|
+
COMPLETED = "COMPLETED",
|
|
8
|
+
CANCELLED = "CANCELLED"
|
|
9
|
+
}
|
|
10
|
+
export declare enum ResponseUnitDispatchTransitionSource {
|
|
11
|
+
DISPATCHER = "DISPATCHER",
|
|
12
|
+
INCIDENT_LIFECYCLE = "INCIDENT_LIFECYCLE",
|
|
13
|
+
RESPONDER = "RESPONDER",
|
|
14
|
+
WORKFLOW = "WORKFLOW"
|
|
15
|
+
}
|
|
16
|
+
export declare enum ResponseUnitCapabilityMatch {
|
|
17
|
+
MATCH = "MATCH",
|
|
18
|
+
NOT_REQUIRED = "NOT_REQUIRED",
|
|
19
|
+
UNKNOWN = "UNKNOWN",
|
|
20
|
+
NOT_SUITED = "NOT_SUITED"
|
|
21
|
+
}
|
|
22
|
+
export declare enum ResponseCapabilityRequirementSource {
|
|
23
|
+
INCIDENT_TYPE = "INCIDENT_TYPE",
|
|
24
|
+
INCIDENT_CATEGORY = "INCIDENT_CATEGORY",
|
|
25
|
+
NONE = "NONE"
|
|
26
|
+
}
|
|
27
|
+
export declare enum ResponseUnitLocationSource {
|
|
28
|
+
LIVE = "LIVE",
|
|
29
|
+
BASE = "BASE",
|
|
30
|
+
NONE = "NONE"
|
|
31
|
+
}
|
|
32
|
+
export declare enum ResponseUnitLocationFreshness {
|
|
33
|
+
CURRENT = "CURRENT",
|
|
34
|
+
STALE = "STALE",
|
|
35
|
+
UNKNOWN = "UNKNOWN"
|
|
36
|
+
}
|
|
37
|
+
export declare enum ResponseUnitDistanceBasis {
|
|
38
|
+
STRAIGHT_LINE = "STRAIGHT_LINE",
|
|
39
|
+
ROAD_ROUTE = "ROAD_ROUTE"
|
|
40
|
+
}
|
|
41
|
+
/** Why a unit cannot be dispatched (blockers) or is not recommended (cautions). */
|
|
42
|
+
export declare enum ResponseUnitDispatchConstraint {
|
|
43
|
+
INACTIVE = "INACTIVE",
|
|
44
|
+
OPERATIONALLY_UNAVAILABLE = "OPERATIONALLY_UNAVAILABLE",
|
|
45
|
+
ENGAGED = "ENGAGED",
|
|
46
|
+
ALREADY_DISPATCHED = "ALREADY_DISPATCHED",
|
|
47
|
+
OTHER_CONTROL_CENTRE = "OTHER_CONTROL_CENTRE",
|
|
48
|
+
CAPABILITY_REQUIRED = "CAPABILITY_REQUIRED",
|
|
49
|
+
NOT_SUITED = "NOT_SUITED",
|
|
50
|
+
NO_LOCATION = "NO_LOCATION",
|
|
51
|
+
LOCATION_STALE = "LOCATION_STALE",
|
|
52
|
+
OUTSIDE_SEARCH_AREA = "OUTSIDE_SEARCH_AREA"
|
|
53
|
+
}
|
|
54
|
+
export declare enum ResponseUnitRecommendationReason {
|
|
55
|
+
AVAILABLE = "AVAILABLE",
|
|
56
|
+
CAPABILITY_MATCH = "CAPABILITY_MATCH",
|
|
57
|
+
NO_CAPABILITY_REQUIREMENT = "NO_CAPABILITY_REQUIREMENT",
|
|
58
|
+
CAPABILITY_UNKNOWN = "CAPABILITY_UNKNOWN",
|
|
59
|
+
SAME_CONTROL_CENTRE = "SAME_CONTROL_CENTRE",
|
|
60
|
+
OTHER_CONTROL_CENTRE = "OTHER_CONTROL_CENTRE",
|
|
61
|
+
LIVE_LOCATION_CURRENT = "LIVE_LOCATION_CURRENT",
|
|
62
|
+
LIVE_LOCATION_STALE = "LIVE_LOCATION_STALE",
|
|
63
|
+
BASE_LOCATION = "BASE_LOCATION",
|
|
64
|
+
NEAREST = "NEAREST",
|
|
65
|
+
QUICKEST = "QUICKEST"
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* NO_UNITS_CONFIGURED hides the dispatch panel (this control room has no units);
|
|
69
|
+
* NO_ELIGIBLE_UNITS is an alarm (it has units and none can go).
|
|
70
|
+
*/
|
|
71
|
+
export declare enum ResponseUnitRecommendationStatus {
|
|
72
|
+
RECOMMENDED = "RECOMMENDED",
|
|
73
|
+
NO_RECOMMENDATION = "NO_RECOMMENDATION",
|
|
74
|
+
NO_ELIGIBLE_UNITS = "NO_ELIGIBLE_UNITS",
|
|
75
|
+
NO_UNITS_CONFIGURED = "NO_UNITS_CONFIGURED",
|
|
76
|
+
NOT_DISPATCHABLE = "NOT_DISPATCHABLE"
|
|
77
|
+
}
|
|
78
|
+
export declare enum IncidentDispatchBlocker {
|
|
79
|
+
INCIDENT_ENDED = "INCIDENT_ENDED",
|
|
80
|
+
NOT_AN_EMERGENCY_INCIDENT = "NOT_AN_EMERGENCY_INCIDENT",
|
|
81
|
+
PROVIDER_RESPONSE_NOT_REQUESTED = "PROVIDER_RESPONSE_NOT_REQUESTED",
|
|
82
|
+
DISPATCH_DISABLED = "DISPATCH_DISABLED"
|
|
83
|
+
}
|
|
84
|
+
export declare enum ResponseUnitDispatchNotificationStatus {
|
|
85
|
+
PENDING = "PENDING",
|
|
86
|
+
SENT = "SENT",
|
|
87
|
+
FAILED = "FAILED",
|
|
88
|
+
NOT_POSSIBLE = "NOT_POSSIBLE"
|
|
89
|
+
}
|
|
90
|
+
export declare enum ResponseUnitDispatchNotificationFailure {
|
|
91
|
+
NO_PHONE_NUMBER = "NO_PHONE_NUMBER",
|
|
92
|
+
INVALID_PHONE_NUMBER = "INVALID_PHONE_NUMBER",
|
|
93
|
+
PROVIDER_FAILURE = "PROVIDER_FAILURE",
|
|
94
|
+
NOT_CONFIGURED = "NOT_CONFIGURED",
|
|
95
|
+
NO_RESPONSE = "NO_RESPONSE"
|
|
96
|
+
}
|
|
97
|
+
/** The `code` on a refused request (the gateway returns it under `details`). */
|
|
98
|
+
export declare enum ResponseUnitDispatchErrorCode {
|
|
99
|
+
INCIDENT_NOT_DISPATCHABLE = "INCIDENT_NOT_DISPATCHABLE",
|
|
100
|
+
RESPONSE_UNIT_NOT_FOUND = "RESPONSE_UNIT_NOT_FOUND",
|
|
101
|
+
RESPONSE_UNIT_NOT_DISPATCHABLE = "RESPONSE_UNIT_NOT_DISPATCHABLE",
|
|
102
|
+
RESPONSE_UNIT_ENGAGED = "RESPONSE_UNIT_ENGAGED",
|
|
103
|
+
RESPONSE_UNIT_ALREADY_DISPATCHED = "RESPONSE_UNIT_ALREADY_DISPATCHED",
|
|
104
|
+
IDEMPOTENCY_KEY_REUSED = "IDEMPOTENCY_KEY_REUSED",
|
|
105
|
+
DISPATCH_NOT_FOUND = "DISPATCH_NOT_FOUND",
|
|
106
|
+
INVALID_STATUS_TRANSITION = "INVALID_STATUS_TRANSITION",
|
|
107
|
+
NOTIFICATION_NOT_RESENDABLE = "NOTIFICATION_NOT_RESENDABLE",
|
|
108
|
+
ORGANIZATION_UNAVAILABLE = "ORGANIZATION_UNAVAILABLE"
|
|
109
|
+
}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { ResponseCapability, ResponseUnitAvailability } from '../../response-unit/enums/response-unit/response-capability.enum';
|
|
2
|
+
import { IncidentDispatchBlocker, ResponseCapabilityRequirementSource, ResponseUnitCapabilityMatch, ResponseUnitDispatchConstraint, ResponseUnitDispatchNotificationFailure, ResponseUnitDispatchNotificationStatus, ResponseUnitDispatchStatus, ResponseUnitDispatchTransitionSource, ResponseUnitDistanceBasis, ResponseUnitLocationFreshness, ResponseUnitLocationSource, ResponseUnitRecommendationReason, ResponseUnitRecommendationStatus } from '../enums/response-unit-dispatch-enums';
|
|
3
|
+
export interface ResponseCapabilityRequirementDto {
|
|
4
|
+
capabilities: ResponseCapability[];
|
|
5
|
+
source: ResponseCapabilityRequirementSource;
|
|
6
|
+
}
|
|
7
|
+
export interface ResponseUnitCandidateLocationDto {
|
|
8
|
+
source: ResponseUnitLocationSource;
|
|
9
|
+
freshness: ResponseUnitLocationFreshness;
|
|
10
|
+
latitude: number | null;
|
|
11
|
+
longitude: number | null;
|
|
12
|
+
recordedAt: string | null;
|
|
13
|
+
ageSeconds: number | null;
|
|
14
|
+
accuracyMetres: number | null;
|
|
15
|
+
}
|
|
16
|
+
export interface ResponseUnitTravelEstimateDto {
|
|
17
|
+
distanceMetres: number;
|
|
18
|
+
durationSeconds: number | null;
|
|
19
|
+
basis: ResponseUnitDistanceBasis;
|
|
20
|
+
trafficAware: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface ResponseUnitCandidateDto {
|
|
23
|
+
responseUnitId: number;
|
|
24
|
+
name: string;
|
|
25
|
+
responseUnitType: string;
|
|
26
|
+
vehicleType: string | null;
|
|
27
|
+
registrationNumber: string | null;
|
|
28
|
+
controlCentreId: number | null;
|
|
29
|
+
sameControlCentre: boolean;
|
|
30
|
+
operationalStatus: string | null;
|
|
31
|
+
availability: ResponseUnitAvailability;
|
|
32
|
+
engagedIncidentId: number | null;
|
|
33
|
+
capabilities: ResponseCapability[];
|
|
34
|
+
capabilityMatch: ResponseUnitCapabilityMatch;
|
|
35
|
+
matchedCapabilities: ResponseCapability[];
|
|
36
|
+
location: ResponseUnitCandidateLocationDto;
|
|
37
|
+
distanceMetres: number | null;
|
|
38
|
+
travel: ResponseUnitTravelEstimateDto | null;
|
|
39
|
+
hasPhoneNumber: boolean;
|
|
40
|
+
dispatchable: boolean;
|
|
41
|
+
recommendable: boolean;
|
|
42
|
+
constraints: ResponseUnitDispatchConstraint[];
|
|
43
|
+
reasons: ResponseUnitRecommendationReason[];
|
|
44
|
+
rank: number | null;
|
|
45
|
+
}
|
|
46
|
+
export interface ResponseUnitRecommendationSummaryDto {
|
|
47
|
+
configuredUnits: number;
|
|
48
|
+
dispatchableUnits: number;
|
|
49
|
+
recommendableUnits: number;
|
|
50
|
+
engagedUnits: number;
|
|
51
|
+
unavailableUnits: number;
|
|
52
|
+
unitsWithoutLocation: number;
|
|
53
|
+
truncated: boolean;
|
|
54
|
+
}
|
|
55
|
+
export interface ResponseUnitDispatchUnitSnapshotDto {
|
|
56
|
+
availability: ResponseUnitAvailability;
|
|
57
|
+
operationalStatus: string | null;
|
|
58
|
+
capabilities: ResponseCapability[];
|
|
59
|
+
capabilityMatch: ResponseUnitCapabilityMatch;
|
|
60
|
+
sameControlCentre: boolean;
|
|
61
|
+
locationSource: ResponseUnitLocationSource;
|
|
62
|
+
locationFreshness: ResponseUnitLocationFreshness;
|
|
63
|
+
locationRecordedAt: string | null;
|
|
64
|
+
locationAgeSeconds: number | null;
|
|
65
|
+
distanceMetres: number | null;
|
|
66
|
+
hasPhoneNumber: boolean;
|
|
67
|
+
}
|
|
68
|
+
export interface ResponseUnitDispatchRecommendationSnapshotDto {
|
|
69
|
+
generatedAt: string;
|
|
70
|
+
status: ResponseUnitRecommendationStatus;
|
|
71
|
+
recommendedResponseUnitId: number | null;
|
|
72
|
+
ranked: Array<{
|
|
73
|
+
responseUnitId: number;
|
|
74
|
+
rank: number;
|
|
75
|
+
distanceMetres: number | null;
|
|
76
|
+
capabilityMatch: ResponseUnitCapabilityMatch;
|
|
77
|
+
locationFreshness: ResponseUnitLocationFreshness;
|
|
78
|
+
}>;
|
|
79
|
+
requiredCapabilities: ResponseCapability[];
|
|
80
|
+
requirementSource: ResponseCapabilityRequirementSource;
|
|
81
|
+
liveTrackingAvailable: boolean;
|
|
82
|
+
}
|
|
83
|
+
export interface ResponseUnitDispatchNotificationStateDto {
|
|
84
|
+
channel: 'SMS';
|
|
85
|
+
status: ResponseUnitDispatchNotificationStatus;
|
|
86
|
+
failureReason: ResponseUnitDispatchNotificationFailure | null;
|
|
87
|
+
/** Masked (+2547******78). */
|
|
88
|
+
recipient: string | null;
|
|
89
|
+
attempts: number;
|
|
90
|
+
requestedAt: string | null;
|
|
91
|
+
resultAt: string | null;
|
|
92
|
+
providerCode: string | null;
|
|
93
|
+
}
|
|
94
|
+
/** One response unit sent to one incident. */
|
|
95
|
+
export interface IncidentResponseUnitDispatchDto {
|
|
96
|
+
id: number;
|
|
97
|
+
reference: string;
|
|
98
|
+
incidentId: number;
|
|
99
|
+
organizationId: number;
|
|
100
|
+
controlCentreId: number | null;
|
|
101
|
+
responseUnitId: number;
|
|
102
|
+
responseUnitName: string;
|
|
103
|
+
responseUnitType: string | null;
|
|
104
|
+
responseUnitControlCentreId: number | null;
|
|
105
|
+
status: ResponseUnitDispatchStatus;
|
|
106
|
+
dispatchedByUserId: number;
|
|
107
|
+
dispatchedAt: string;
|
|
108
|
+
wasRecommended: boolean;
|
|
109
|
+
recommendedResponseUnitId: number | null;
|
|
110
|
+
shownRecommendedResponseUnitId: number | null;
|
|
111
|
+
overrideReason: string | null;
|
|
112
|
+
notes: string | null;
|
|
113
|
+
distanceMetres: number | null;
|
|
114
|
+
unitSnapshot: ResponseUnitDispatchUnitSnapshotDto;
|
|
115
|
+
recommendationSnapshot: ResponseUnitDispatchRecommendationSnapshotDto | null;
|
|
116
|
+
statusChangedAt: string;
|
|
117
|
+
statusChangedByUserId: number | null;
|
|
118
|
+
statusSource: ResponseUnitDispatchTransitionSource;
|
|
119
|
+
statusReason: string | null;
|
|
120
|
+
acknowledgedAt: string | null;
|
|
121
|
+
enRouteAt: string | null;
|
|
122
|
+
onSceneAt: string | null;
|
|
123
|
+
completedAt: string | null;
|
|
124
|
+
cancelledAt: string | null;
|
|
125
|
+
notification: ResponseUnitDispatchNotificationStateDto;
|
|
126
|
+
createdAt: string;
|
|
127
|
+
updatedAt: string;
|
|
128
|
+
}
|
|
129
|
+
/** `GET /api/incidents/:id/response-unit-recommendation`. */
|
|
130
|
+
export interface ResponseUnitRecommendationDto {
|
|
131
|
+
incidentId: number;
|
|
132
|
+
organizationId: number;
|
|
133
|
+
controlCentreId: number | null;
|
|
134
|
+
generatedAt: string;
|
|
135
|
+
status: ResponseUnitRecommendationStatus;
|
|
136
|
+
incidentBlockers: IncidentDispatchBlocker[];
|
|
137
|
+
requirement: ResponseCapabilityRequirementDto;
|
|
138
|
+
recommended: ResponseUnitCandidateDto | null;
|
|
139
|
+
alternatives: ResponseUnitCandidateDto[];
|
|
140
|
+
otherUnits: ResponseUnitCandidateDto[];
|
|
141
|
+
activeDispatches: IncidentResponseUnitDispatchDto[];
|
|
142
|
+
summary: ResponseUnitRecommendationSummaryDto;
|
|
143
|
+
incidentLocationAvailable: boolean;
|
|
144
|
+
liveTrackingAvailable: boolean;
|
|
145
|
+
travelTimeEnabled: boolean;
|
|
146
|
+
}
|
|
147
|
+
/** `POST /api/incidents/:id/response-unit-dispatches` body. Send an Idempotency-Key header with it. */
|
|
148
|
+
export interface DispatchResponseUnitRequest {
|
|
149
|
+
responseUnitId: number;
|
|
150
|
+
/** The unit the screen showed as recommended. */
|
|
151
|
+
recommendedResponseUnitId?: number | null;
|
|
152
|
+
/** Optional: why another unit than the recommended one. */
|
|
153
|
+
overrideReason?: string;
|
|
154
|
+
notes?: string;
|
|
155
|
+
}
|
|
156
|
+
/** `POST /api/incidents/:id/response-unit-dispatches` response. */
|
|
157
|
+
export interface DispatchResponseUnitResultDto {
|
|
158
|
+
dispatch: IncidentResponseUnitDispatchDto;
|
|
159
|
+
/** A repeat of an earlier request (same Idempotency-Key): nothing was sent again. */
|
|
160
|
+
replayed: boolean;
|
|
161
|
+
}
|
|
162
|
+
/** `POST /api/incidents/:id/response-unit-dispatches/:dispatchId/status` body. */
|
|
163
|
+
export interface UpdateResponseUnitDispatchStatusRequest {
|
|
164
|
+
status: ResponseUnitDispatchStatus;
|
|
165
|
+
reason?: string;
|
|
166
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ResponseCapability, ResponseUnitAvailability } from '../../response-unit/enums/response-unit/response-capability.enum';
|
|
2
|
+
import { IncidentDispatchBlocker, ResponseUnitDispatchConstraint, ResponseUnitDispatchNotificationFailure, ResponseUnitDispatchNotificationStatus, ResponseUnitDispatchStatus } from '../enums/response-unit-dispatch-enums';
|
|
3
|
+
import { ResponseUnitCandidateDto } from '../interfaces/response-unit-dispatch.dto';
|
|
4
|
+
export declare const RESPONSE_CAPABILITY_LABELS: Readonly<Record<ResponseCapability, string>>;
|
|
5
|
+
export declare const RESPONSE_UNIT_AVAILABILITY_LABELS: Readonly<Record<ResponseUnitAvailability, string>>;
|
|
6
|
+
export declare const RESPONSE_UNIT_DISPATCH_STATUS_LABELS: Readonly<Record<ResponseUnitDispatchStatus, string>>;
|
|
7
|
+
/** Why a unit cannot go, or is not suggested - as the dispatcher reads it. */
|
|
8
|
+
export declare const RESPONSE_UNIT_DISPATCH_CONSTRAINT_LABELS: Readonly<Record<ResponseUnitDispatchConstraint, string>>;
|
|
9
|
+
export declare const INCIDENT_DISPATCH_BLOCKER_LABELS: Readonly<Record<IncidentDispatchBlocker, string>>;
|
|
10
|
+
export declare const RESPONSE_UNIT_DISPATCH_NOTIFICATION_STATUS_LABELS: Readonly<Record<ResponseUnitDispatchNotificationStatus, string>>;
|
|
11
|
+
export declare const RESPONSE_UNIT_DISPATCH_NOTIFICATION_FAILURE_LABELS: Readonly<Record<ResponseUnitDispatchNotificationFailure, string>>;
|
|
12
|
+
/** Where each dispatch may be moved next (forward only; steps may be skipped). */
|
|
13
|
+
export declare const RESPONSE_UNIT_DISPATCH_NEXT_STATUSES: Readonly<Record<ResponseUnitDispatchStatus, readonly ResponseUnitDispatchStatus[]>>;
|
|
14
|
+
export declare const ACTIVE_RESPONSE_UNIT_DISPATCH_STATUSES: readonly ResponseUnitDispatchStatus[];
|
|
15
|
+
export declare function isActiveResponseUnitDispatch(status: ResponseUnitDispatchStatus | string | null | undefined): boolean;
|
|
16
|
+
/** "850 m", "2.4 km", "38 km". */
|
|
17
|
+
export declare function formatDispatchDistance(metres: number | null | undefined): string;
|
|
18
|
+
/** "18 sec ago", "4 min ago", "2 h ago". */
|
|
19
|
+
export declare function formatDispatchAge(seconds: number | null | undefined): string;
|
|
20
|
+
/** "7 min", "1 h 05 min". */
|
|
21
|
+
export declare function formatDispatchDuration(seconds: number | null | undefined): string;
|
|
22
|
+
/** A candidate's position, as one short phrase: "Live 18 sec ago", "Live, out of date (6 min ago)", "Base location". */
|
|
23
|
+
export declare function describeCandidateLocation(candidate: ResponseUnitCandidateDto, ageSeconds?: number | null): string;
|
|
24
|
+
/**
|
|
25
|
+
* The "Recommended because" lines, from the reasons and the numbers behind
|
|
26
|
+
* them. Never the scoring - the facts it rests on, in the order it weighs them.
|
|
27
|
+
*/
|
|
28
|
+
export declare function explainRecommendation(candidate: ResponseUnitCandidateDto, ageSeconds?: number | null): string[];
|
|
29
|
+
/** The reasons a unit cannot go or is not suggested, as labels. */
|
|
30
|
+
export declare function describeCandidateConstraints(candidate: ResponseUnitCandidateDto): string[];
|
|
@@ -7,6 +7,8 @@ export declare enum IncidentActions {
|
|
|
7
7
|
ON_HOLD = "On Hold",
|
|
8
8
|
ASSIGNED = "Assigned",
|
|
9
9
|
RESPONSE_UNIT_ASSIGNED = "Response Unit Assigned",
|
|
10
|
+
RESPONSE_UNIT_DISPATCHED = "Response Unit Dispatched",
|
|
11
|
+
RESPONSE_UNIT_DISPATCH_UPDATED = "Response Unit Dispatch Updated",
|
|
10
12
|
REOPENED = "Reopened",
|
|
11
13
|
REPORT_CREATED = "Report Created",
|
|
12
14
|
COMMENTED = "Commented",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ResponseCapability } from "../../response-unit/enums/response-unit/response-capability.enum";
|
|
1
2
|
import { IncidentType } from "./incident-type";
|
|
2
3
|
export interface IncidentCategory {
|
|
3
4
|
id?: number;
|
|
@@ -13,5 +14,10 @@ export interface IncidentCategory {
|
|
|
13
14
|
* `includeSystem=true`.
|
|
14
15
|
*/
|
|
15
16
|
isSystem?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Response capabilities this kind of incident needs; a unit with ANY of them
|
|
19
|
+
* is suitable. A type's list overrides its category's; empty = no requirement.
|
|
20
|
+
*/
|
|
21
|
+
responseCapabilities?: ResponseCapability[];
|
|
16
22
|
types?: IncidentType[];
|
|
17
23
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ResponseCapability } from "../../response-unit/enums/response-unit/response-capability.enum";
|
|
1
2
|
import { IncidentCategory } from "./incident-category";
|
|
2
3
|
export interface IncidentType {
|
|
3
4
|
id?: number;
|
|
@@ -14,5 +15,10 @@ export interface IncidentType {
|
|
|
14
15
|
* `includeSystem=true`.
|
|
15
16
|
*/
|
|
16
17
|
isSystem?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Response capabilities this kind of incident needs; a unit with ANY of them
|
|
20
|
+
* is suitable. A type's list overrides its category's; empty = no requirement.
|
|
21
|
+
*/
|
|
22
|
+
responseCapabilities?: ResponseCapability[];
|
|
17
23
|
category?: IncidentCategory;
|
|
18
24
|
}
|
|
@@ -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
|
+
}
|
|
@@ -53,6 +53,9 @@ export declare enum PermissionActions {
|
|
|
53
53
|
READ_TRACKING_HISTORY = "read:tracking-history",
|
|
54
54
|
READ_TRACKING_OPERATIONS = "read:tracking-operations",
|
|
55
55
|
MANAGE_TRACKING_OPERATIONS = "manage:tracking-operations",
|
|
56
|
+
READ_RESPONSE_UNIT_DISPATCH = "read:response-unit-dispatch",
|
|
57
|
+
CREATE_RESPONSE_UNIT_DISPATCH = "create:response-unit-dispatch",
|
|
58
|
+
UPDATE_RESPONSE_UNIT_DISPATCH = "update:response-unit-dispatch",
|
|
56
59
|
CREATE_SUPPORT_TICKET = "create:support-ticket",
|
|
57
60
|
READ_SUPPORT_TICKET = "read:support-ticket",
|
|
58
61
|
UPDATE_SUPPORT_TICKET = "update:support-ticket",
|
|
@@ -87,6 +90,7 @@ export declare enum PermissionActions {
|
|
|
87
90
|
READ_SUPPORT_SYNC = "read:support-sync",
|
|
88
91
|
MANAGE_SUPPORT_SYNC = "manage:support-sync",
|
|
89
92
|
READ_NOTIFICATION_BRANDING = "read:notification-branding",
|
|
93
|
+
READ_NOTIFICATION_ANALYTICS = "read:notification-analytics",
|
|
90
94
|
UPDATE_NOTIFICATION_BRANDING = "update:notification-branding",
|
|
91
95
|
CREATE_NOTIFICATION_EMAIL_SENDER = "create:notification-email-sender",
|
|
92
96
|
READ_NOTIFICATION_EMAIL_SENDER = "read:notification-email-sender",
|