@hmcts/opal-frontend-common 0.0.83 → 0.0.85
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/fesm2022/hmcts-opal-frontend-common-guards-business-unit-route-permissions.mjs +98 -0
- package/fesm2022/hmcts-opal-frontend-common-services-history-transformation-service.mjs +329 -0
- package/package.json +11 -1
- package/types/hmcts-opal-frontend-common-guards-business-unit-route-permissions.d.ts +38 -0
- package/types/hmcts-opal-frontend-common-services-history-transformation-service.d.ts +250 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { InjectionToken, inject } from '@angular/core';
|
|
2
|
+
import { createUrlTreeFromSnapshot, Router } from '@angular/router';
|
|
3
|
+
import { isObservable, firstValueFrom } from 'rxjs';
|
|
4
|
+
import { PermissionsService } from '@hmcts/opal-frontend-common/services/permissions-service';
|
|
5
|
+
import { PAGES_ROUTING_PATHS } from '@hmcts/opal-frontend-common/pages/routing/constants';
|
|
6
|
+
import { OpalUserService } from '@hmcts/opal-frontend-common/services/opal-user-service';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Injection token used by consuming applications to provide a resolver that can
|
|
10
|
+
* determine the business unit for the current route context.
|
|
11
|
+
*/
|
|
12
|
+
const BUSINESS_UNIT_ID_RESOLVER = new InjectionToken('BUSINESS_UNIT_ID_RESOLVER');
|
|
13
|
+
/**
|
|
14
|
+
* Resolves values that may be synchronous, promise-based, or observable-based into a promise.
|
|
15
|
+
*
|
|
16
|
+
* @param value - The value to resolve.
|
|
17
|
+
* @returns A promise containing the resolved value.
|
|
18
|
+
*/
|
|
19
|
+
const resolveMaybeAsync = async (value) => isObservable(value) ? firstValueFrom(value) : Promise.resolve(value);
|
|
20
|
+
/**
|
|
21
|
+
* Reads and normalizes the permission ids declared on route data.
|
|
22
|
+
*
|
|
23
|
+
* @param route - The route whose permission metadata should be inspected.
|
|
24
|
+
* @returns A filtered array of numeric permission ids.
|
|
25
|
+
*/
|
|
26
|
+
const getRoutePermissionIds = (route) => {
|
|
27
|
+
const routePermissionIds = route.data?.['routePermissionId'];
|
|
28
|
+
if (Array.isArray(routePermissionIds)) {
|
|
29
|
+
return routePermissionIds.filter((permissionId) => typeof permissionId === 'number');
|
|
30
|
+
}
|
|
31
|
+
if (typeof routePermissionIds === 'number') {
|
|
32
|
+
return [routePermissionIds];
|
|
33
|
+
}
|
|
34
|
+
return [];
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Creates the access denied redirect for permission failures.
|
|
38
|
+
*
|
|
39
|
+
* Absolute paths are resolved from the app root. Relative paths are resolved
|
|
40
|
+
* from the guarded route's parent so account-flow denied pages stay under the
|
|
41
|
+
* current account route.
|
|
42
|
+
*
|
|
43
|
+
* @param route - The route being protected by the guard.
|
|
44
|
+
* @param router - The router used to create the redirect URL tree.
|
|
45
|
+
* @param accessDeniedPath - The configured access denied path.
|
|
46
|
+
* @returns A URL tree pointing to the denied route.
|
|
47
|
+
*/
|
|
48
|
+
const toAccessDeniedUrlTree = (route, router, accessDeniedPath) => {
|
|
49
|
+
if (accessDeniedPath.startsWith('/')) {
|
|
50
|
+
return router.createUrlTree([accessDeniedPath]);
|
|
51
|
+
}
|
|
52
|
+
return createUrlTreeFromSnapshot(route.parent ?? route, [accessDeniedPath]);
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Guard that checks route permissions against the business unit resolved for the
|
|
56
|
+
* current route instead of against the user's global permission set.
|
|
57
|
+
*
|
|
58
|
+
* If the route does not declare any permission ids, the guard allows access.
|
|
59
|
+
* Otherwise it loads the logged-in user state, resolves the route business unit,
|
|
60
|
+
* and confirms that at least one declared permission exists within that business unit.
|
|
61
|
+
*
|
|
62
|
+
* @param route - The route being activated.
|
|
63
|
+
* @returns `true` when access is allowed, otherwise a redirect to access denied.
|
|
64
|
+
*/
|
|
65
|
+
const businessUnitRoutePermissionsGuard = async (route) => {
|
|
66
|
+
const routePermissionIds = getRoutePermissionIds(route);
|
|
67
|
+
if (!routePermissionIds.length) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const permissionService = inject(PermissionsService);
|
|
71
|
+
const opalUserService = inject(OpalUserService);
|
|
72
|
+
const businessUnitResolver = inject(BUSINESS_UNIT_ID_RESOLVER);
|
|
73
|
+
const router = inject(Router);
|
|
74
|
+
const accessDeniedPath = route.data?.['accessDeniedPath'] ?? `/${PAGES_ROUTING_PATHS.children.accessDenied}`;
|
|
75
|
+
try {
|
|
76
|
+
const userState = await firstValueFrom(opalUserService.getLoggedInUserState());
|
|
77
|
+
const businessUnitUsers = userState?.business_unit_users ?? [];
|
|
78
|
+
if (!businessUnitUsers.length) {
|
|
79
|
+
return toAccessDeniedUrlTree(route, router, `${accessDeniedPath}`);
|
|
80
|
+
}
|
|
81
|
+
const businessUnitId = await resolveMaybeAsync(businessUnitResolver.resolveBusinessUnitId(route));
|
|
82
|
+
if (typeof businessUnitId !== 'number' || !Number.isFinite(businessUnitId) || businessUnitId <= 0) {
|
|
83
|
+
return toAccessDeniedUrlTree(route, router, `${accessDeniedPath}`);
|
|
84
|
+
}
|
|
85
|
+
const hasAccess = routePermissionIds.some((permissionId) => permissionService.hasBusinessUnitPermissionAccess(permissionId, businessUnitId, businessUnitUsers));
|
|
86
|
+
return hasAccess ? true : toAccessDeniedUrlTree(route, router, `${accessDeniedPath}`);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return toAccessDeniedUrlTree(route, router, `${accessDeniedPath}`);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Generated bundle index. Do not edit.
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
export { BUSINESS_UNIT_ID_RESOLVER, businessUnitRoutePermissionsGuard };
|
|
98
|
+
//# sourceMappingURL=hmcts-opal-frontend-common-guards-business-unit-route-permissions.mjs.map
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable } from '@angular/core';
|
|
3
|
+
import { DateService } from '@hmcts/opal-frontend-common/services/date-service';
|
|
4
|
+
|
|
5
|
+
const HISTORY_DETAILS_PATTERNS = {
|
|
6
|
+
keyNormalise: /[\s_-]/g,
|
|
7
|
+
snakeCaseBoundary: /([a-z])([A-Z])/g,
|
|
8
|
+
snakeCaseSeparator: /[\s-]/g,
|
|
9
|
+
transactionTypeSpace: /\s+/g,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const HISTORY_DETAILS_DATE_SERVICE = new DateService();
|
|
13
|
+
/**
|
|
14
|
+
* Transforms a raw history item into the configured structured details model.
|
|
15
|
+
*
|
|
16
|
+
* @param item - The raw history item.
|
|
17
|
+
* @param config - The domain-specific transformation configuration.
|
|
18
|
+
* @returns The transformed details model.
|
|
19
|
+
*/
|
|
20
|
+
function transformHistoryDetails(item, config) {
|
|
21
|
+
const itemType = normaliseHistoryKey(getHistoryString(item, config.historyItemTypeAliases, config.aliasPathPrefixes, config.emptyValues));
|
|
22
|
+
const transformer = itemType ? config.transformers[itemType] : null;
|
|
23
|
+
return transformer ? transformer(item) : transformHistoryFallbackDetails(item, config);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Transforms raw history items while preserving the rest of each item.
|
|
27
|
+
*
|
|
28
|
+
* @param items - The raw history items.
|
|
29
|
+
* @param config - The domain-specific transformation configuration.
|
|
30
|
+
* @returns The items with transformed structured details.
|
|
31
|
+
*/
|
|
32
|
+
function transformHistoryItems(items, config) {
|
|
33
|
+
return items.map((item) => ({
|
|
34
|
+
...item,
|
|
35
|
+
details: transformHistoryDetails(item, config),
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Builds fallback details from configured fallback fields when no transformer matches.
|
|
40
|
+
*
|
|
41
|
+
* @param item - The raw history item.
|
|
42
|
+
* @param config - The domain-specific transformation configuration.
|
|
43
|
+
* @returns The fallback structured details model.
|
|
44
|
+
*/
|
|
45
|
+
function transformHistoryFallbackDetails(item, config) {
|
|
46
|
+
return createHistoryDetails([
|
|
47
|
+
createHistoryTextPart(getHistoryString(item, config.fallbackAliases, config.aliasPathPrefixes, config.emptyValues) ??
|
|
48
|
+
getHistoryString(item, config.historyItemTypeAliases, config.aliasPathPrefixes, config.emptyValues)),
|
|
49
|
+
]);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Creates a details object and normalises an empty secondary line to null.
|
|
53
|
+
*
|
|
54
|
+
* @param line1Parts - The primary line parts.
|
|
55
|
+
* @param line2Parts - The secondary line parts.
|
|
56
|
+
* @returns The structured details object.
|
|
57
|
+
*/
|
|
58
|
+
function createHistoryDetails(line1Parts, line2Parts = []) {
|
|
59
|
+
const line1 = line1Parts.filter(isPresentPart);
|
|
60
|
+
const line2 = line2Parts.filter(isPresentPart);
|
|
61
|
+
return {
|
|
62
|
+
line1,
|
|
63
|
+
line2: line2.length ? line2 : null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Creates a details part after removing empty fragments.
|
|
68
|
+
*
|
|
69
|
+
* @param fragments - The fragments for the part.
|
|
70
|
+
* @returns The details part or null when no fragments are visible.
|
|
71
|
+
*/
|
|
72
|
+
function createHistoryDetailsPart(fragments) {
|
|
73
|
+
const visibleFragments = fragments.filter(({ text }) => text.length > 0);
|
|
74
|
+
return visibleFragments.length ? { fragments: visibleFragments } : null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Creates a text-only details part.
|
|
78
|
+
*
|
|
79
|
+
* @param text - The part text.
|
|
80
|
+
* @returns The details part or null when text is empty.
|
|
81
|
+
*/
|
|
82
|
+
function createHistoryTextPart(text) {
|
|
83
|
+
return text ? createHistoryDetailsPart([createHistoryFragment(text)]) : null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Creates a details part containing a bold label and plain value.
|
|
87
|
+
*
|
|
88
|
+
* @param label - The label text.
|
|
89
|
+
* @param value - The value text.
|
|
90
|
+
* @returns The labelled details part or null when value is empty.
|
|
91
|
+
*/
|
|
92
|
+
function createHistoryLabelValuePart(label, value) {
|
|
93
|
+
return value
|
|
94
|
+
? createHistoryDetailsPart([createHistoryFragment(label, { bold: true }), createHistoryFragment(value)])
|
|
95
|
+
: null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Creates a text fragment with default styling flags.
|
|
99
|
+
*
|
|
100
|
+
* @param text - The fragment text.
|
|
101
|
+
* @param options - Optional fragment styling and link metadata.
|
|
102
|
+
* @returns The details fragment.
|
|
103
|
+
*/
|
|
104
|
+
function createHistoryFragment(text, options = {}) {
|
|
105
|
+
return {
|
|
106
|
+
text,
|
|
107
|
+
bold: options.bold ?? false,
|
|
108
|
+
hyphen: options.hyphen ?? false,
|
|
109
|
+
...(options.link ? { link: options.link } : {}),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Creates link metadata for a details fragment.
|
|
114
|
+
*
|
|
115
|
+
* @param type - The link type emitted by the UI.
|
|
116
|
+
* @param emit - The emitted linked entity identifier.
|
|
117
|
+
* @returns The fragment link metadata.
|
|
118
|
+
*/
|
|
119
|
+
function createHistoryLink(type, emit) {
|
|
120
|
+
return { type, emit };
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Reads the first non-empty scalar value from candidate aliases as a string.
|
|
124
|
+
*
|
|
125
|
+
* @param item - The raw history item.
|
|
126
|
+
* @param aliases - The candidate field aliases.
|
|
127
|
+
* @param aliasPathPrefixes - The prefixes used for unqualified aliases.
|
|
128
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
129
|
+
* @returns The string value or null.
|
|
130
|
+
*/
|
|
131
|
+
function getHistoryString(item, aliases, aliasPathPrefixes, emptyValues) {
|
|
132
|
+
const value = getHistoryValue(item, aliases, aliasPathPrefixes, emptyValues);
|
|
133
|
+
if (isHistoryEmptyValue(value, emptyValues) || isHistoryRecord(value)) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
return String(value);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Reads the first non-empty value from candidate aliases.
|
|
140
|
+
*
|
|
141
|
+
* @param item - The raw history item.
|
|
142
|
+
* @param aliases - The candidate field aliases.
|
|
143
|
+
* @param aliasPathPrefixes - The prefixes used for unqualified aliases.
|
|
144
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
145
|
+
* @returns The matched value or null.
|
|
146
|
+
*/
|
|
147
|
+
function getHistoryValue(item, aliases, aliasPathPrefixes, emptyValues) {
|
|
148
|
+
for (const alias of aliases) {
|
|
149
|
+
for (const path of getHistoryAliasPaths(alias, aliasPathPrefixes)) {
|
|
150
|
+
const value = getHistoryValueByPath(item, path);
|
|
151
|
+
if (!isHistoryEmptyValue(value, emptyValues)) {
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Expands an alias into candidate dot-notated paths.
|
|
160
|
+
*
|
|
161
|
+
* @param alias - The field alias.
|
|
162
|
+
* @param aliasPathPrefixes - The prefixes used for unqualified aliases.
|
|
163
|
+
* @returns The candidate paths.
|
|
164
|
+
*/
|
|
165
|
+
function getHistoryAliasPaths(alias, aliasPathPrefixes) {
|
|
166
|
+
return alias.includes('.') ? [alias] : aliasPathPrefixes.map((prefix) => `${prefix}${alias}`);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Reads a value from an history item using a dot-notated path.
|
|
170
|
+
*
|
|
171
|
+
* @param item - The raw history item.
|
|
172
|
+
* @param path - The dot-notated path.
|
|
173
|
+
* @returns The matched value or undefined.
|
|
174
|
+
*/
|
|
175
|
+
function getHistoryValueByPath(item, path) {
|
|
176
|
+
return path.split('.').reduce((value, key) => {
|
|
177
|
+
if (!isHistoryRecord(value)) {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
return value[key];
|
|
181
|
+
}, item);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Checks whether a value is a non-null record.
|
|
185
|
+
*
|
|
186
|
+
* @param value - The value to check.
|
|
187
|
+
* @returns True when the value is a record.
|
|
188
|
+
*/
|
|
189
|
+
function isHistoryRecord(value) {
|
|
190
|
+
return typeof value === 'object' && value !== null;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Checks whether a value should be treated as empty.
|
|
194
|
+
*
|
|
195
|
+
* @param value - The value to check.
|
|
196
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
197
|
+
* @returns True when the value is empty.
|
|
198
|
+
*/
|
|
199
|
+
function isHistoryEmptyValue(value, emptyValues) {
|
|
200
|
+
return emptyValues.includes(value);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Checks whether a string value is present.
|
|
204
|
+
*
|
|
205
|
+
* @param value - The value to check.
|
|
206
|
+
* @returns True when the value is a non-empty string.
|
|
207
|
+
*/
|
|
208
|
+
function isHistoryPresentString(value) {
|
|
209
|
+
return !!value;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Normalises a history item type key for transformer lookup.
|
|
213
|
+
*
|
|
214
|
+
* @param value - The raw key.
|
|
215
|
+
* @returns The normalised key or null.
|
|
216
|
+
*/
|
|
217
|
+
function normaliseHistoryKey(value) {
|
|
218
|
+
return value ? value.replace(HISTORY_DETAILS_PATTERNS.keyNormalise, '').toLowerCase() : null;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Normalises a transaction type code for switch matching.
|
|
222
|
+
*
|
|
223
|
+
* @param value - The raw transaction type.
|
|
224
|
+
* @returns The normalised transaction type or null.
|
|
225
|
+
*/
|
|
226
|
+
function normaliseHistoryTransactionType(value) {
|
|
227
|
+
return value ? value.trim().toUpperCase().replace(HISTORY_DETAILS_PATTERNS.transactionTypeSpace, ' ') : null;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Converts a camel, space, or hyphen value to snake case.
|
|
231
|
+
*
|
|
232
|
+
* @param value - The raw value.
|
|
233
|
+
* @returns The snake case value.
|
|
234
|
+
*/
|
|
235
|
+
function toHistorySnakeCase(value) {
|
|
236
|
+
return value
|
|
237
|
+
.replace(HISTORY_DETAILS_PATTERNS.snakeCaseBoundary, '$1_$2')
|
|
238
|
+
.replace(HISTORY_DETAILS_PATTERNS.snakeCaseSeparator, '_')
|
|
239
|
+
.toLowerCase();
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Formats configured date strings to the configured output format.
|
|
243
|
+
*
|
|
244
|
+
* @param value - The raw date value.
|
|
245
|
+
* @param dateFormat - The input and output date formats.
|
|
246
|
+
* @returns The formatted date or original value when parsing fails.
|
|
247
|
+
*/
|
|
248
|
+
function formatHistoryDate(value, dateFormat) {
|
|
249
|
+
if (!value) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
const parsedFormattedDate = HISTORY_DETAILS_DATE_SERVICE.getFromFormat(value, dateFormat.input);
|
|
253
|
+
if (HISTORY_DETAILS_DATE_SERVICE.isValidDate(parsedFormattedDate)) {
|
|
254
|
+
return HISTORY_DETAILS_DATE_SERVICE.getFromFormatToFormat(value, dateFormat.input, dateFormat.output);
|
|
255
|
+
}
|
|
256
|
+
const isoDate = HISTORY_DETAILS_DATE_SERVICE.getFromIso(value);
|
|
257
|
+
return HISTORY_DETAILS_DATE_SERVICE.isValidDate(isoDate)
|
|
258
|
+
? HISTORY_DETAILS_DATE_SERVICE.toFormat(isoDate, dateFormat.output)
|
|
259
|
+
: value;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Formats numeric values as currency while preserving preformatted text.
|
|
263
|
+
*
|
|
264
|
+
* @param value - The raw money value.
|
|
265
|
+
* @param currencyPrefix - The currency prefix to prepend to numeric values.
|
|
266
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
267
|
+
* @returns The formatted money text or null.
|
|
268
|
+
*/
|
|
269
|
+
function formatHistoryMoney(value, currencyPrefix, emptyValues) {
|
|
270
|
+
if (isHistoryEmptyValue(value, emptyValues)) {
|
|
271
|
+
return null;
|
|
272
|
+
}
|
|
273
|
+
if (typeof value === 'number') {
|
|
274
|
+
return `${currencyPrefix}${value.toFixed(2)}`;
|
|
275
|
+
}
|
|
276
|
+
const text = String(value);
|
|
277
|
+
if (text.startsWith(currencyPrefix)) {
|
|
278
|
+
return text;
|
|
279
|
+
}
|
|
280
|
+
const numericValue = Number(text);
|
|
281
|
+
return Number.isFinite(numericValue) ? `${currencyPrefix}${numericValue.toFixed(2)}` : text;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Checks whether a details part should be kept in the rendered output.
|
|
285
|
+
*
|
|
286
|
+
* @param value - The details part to check.
|
|
287
|
+
* @returns True when the part is present.
|
|
288
|
+
*/
|
|
289
|
+
function isPresentPart(value) {
|
|
290
|
+
return !!value;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
class HistoryTransformationService {
|
|
294
|
+
/**
|
|
295
|
+
* Transforms a raw history item into the structured details model.
|
|
296
|
+
*
|
|
297
|
+
* @param item - The raw history item.
|
|
298
|
+
* @param config - The domain-specific transformation configuration.
|
|
299
|
+
* @returns The transformed history details.
|
|
300
|
+
*/
|
|
301
|
+
transformDetails(item, config) {
|
|
302
|
+
return transformHistoryDetails(item, config);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Transforms raw history items while preserving the rest of each item.
|
|
306
|
+
*
|
|
307
|
+
* @param items - The raw history items.
|
|
308
|
+
* @param config - The domain-specific transformation configuration.
|
|
309
|
+
* @returns The items with transformed structured details.
|
|
310
|
+
*/
|
|
311
|
+
transformItems(items, config) {
|
|
312
|
+
return transformHistoryItems(items, config);
|
|
313
|
+
}
|
|
314
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HistoryTransformationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
315
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HistoryTransformationService, providedIn: 'root' });
|
|
316
|
+
}
|
|
317
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: HistoryTransformationService, decorators: [{
|
|
318
|
+
type: Injectable,
|
|
319
|
+
args: [{
|
|
320
|
+
providedIn: 'root',
|
|
321
|
+
}]
|
|
322
|
+
}] });
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Generated bundle index. Do not edit.
|
|
326
|
+
*/
|
|
327
|
+
|
|
328
|
+
export { HISTORY_DETAILS_PATTERNS, HistoryTransformationService, createHistoryDetails, createHistoryDetailsPart, createHistoryFragment, createHistoryLabelValuePart, createHistoryLink, createHistoryTextPart, formatHistoryDate, formatHistoryMoney, getHistoryAliasPaths, getHistoryString, getHistoryValue, getHistoryValueByPath, isHistoryEmptyValue, isHistoryPresentString, isHistoryRecord, normaliseHistoryKey, normaliseHistoryTransactionType, toHistorySnakeCase, transformHistoryDetails, transformHistoryFallbackDetails, transformHistoryItems };
|
|
329
|
+
//# sourceMappingURL=hmcts-opal-frontend-common-services-history-transformation-service.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hmcts/opal-frontend-common",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.85",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -596,6 +596,11 @@
|
|
|
596
596
|
"types": "./types/hmcts-opal-frontend-common-guards-account.d.ts",
|
|
597
597
|
"default": "./fesm2022/hmcts-opal-frontend-common-guards-account.mjs"
|
|
598
598
|
},
|
|
599
|
+
"./guards/business-unit-route-permissions": {
|
|
600
|
+
"import": "./fesm2022/hmcts-opal-frontend-common-guards-business-unit-route-permissions.mjs",
|
|
601
|
+
"types": "./types/hmcts-opal-frontend-common-guards-business-unit-route-permissions.d.ts",
|
|
602
|
+
"default": "./fesm2022/hmcts-opal-frontend-common-guards-business-unit-route-permissions.mjs"
|
|
603
|
+
},
|
|
599
604
|
"./guards/can-deactivate": {
|
|
600
605
|
"import": "./fesm2022/hmcts-opal-frontend-common-guards-can-deactivate.mjs",
|
|
601
606
|
"types": "./types/hmcts-opal-frontend-common-guards-can-deactivate.d.ts",
|
|
@@ -729,6 +734,11 @@
|
|
|
729
734
|
"types": "./types/hmcts-opal-frontend-common-services-app-initializer-service.d.ts",
|
|
730
735
|
"default": "./fesm2022/hmcts-opal-frontend-common-services-app-initializer-service.mjs"
|
|
731
736
|
},
|
|
737
|
+
"./services/history-transformation-service": {
|
|
738
|
+
"import": "./fesm2022/hmcts-opal-frontend-common-services-history-transformation-service.mjs",
|
|
739
|
+
"types": "./types/hmcts-opal-frontend-common-services-history-transformation-service.d.ts",
|
|
740
|
+
"default": "./fesm2022/hmcts-opal-frontend-common-services-history-transformation-service.mjs"
|
|
741
|
+
},
|
|
732
742
|
"./services/transfer-state-service": {
|
|
733
743
|
"import": "./fesm2022/hmcts-opal-frontend-common-services-transfer-state-service.mjs",
|
|
734
744
|
"types": "./types/hmcts-opal-frontend-common-services-transfer-state-service.d.ts",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
import { ActivatedRouteSnapshot, MaybeAsync, CanActivateFn } from '@angular/router';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Contract implemented by consuming apps to resolve the business unit for the active route.
|
|
6
|
+
*/
|
|
7
|
+
interface BusinessUnitIdResolver {
|
|
8
|
+
/**
|
|
9
|
+
* Resolves the business unit id that should be used for route-level permission checks.
|
|
10
|
+
*
|
|
11
|
+
* Return `null` when the business unit cannot be determined for the route.
|
|
12
|
+
*
|
|
13
|
+
* @param route - The route being protected by the business-unit permission guard.
|
|
14
|
+
* @returns The business unit id, or `null` when no valid business unit is available.
|
|
15
|
+
*/
|
|
16
|
+
resolveBusinessUnitId(route: ActivatedRouteSnapshot): MaybeAsync<number | null>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Injection token used by consuming applications to provide a resolver that can
|
|
21
|
+
* determine the business unit for the current route context.
|
|
22
|
+
*/
|
|
23
|
+
declare const BUSINESS_UNIT_ID_RESOLVER: InjectionToken<BusinessUnitIdResolver>;
|
|
24
|
+
/**
|
|
25
|
+
* Guard that checks route permissions against the business unit resolved for the
|
|
26
|
+
* current route instead of against the user's global permission set.
|
|
27
|
+
*
|
|
28
|
+
* If the route does not declare any permission ids, the guard allows access.
|
|
29
|
+
* Otherwise it loads the logged-in user state, resolves the route business unit,
|
|
30
|
+
* and confirms that at least one declared permission exists within that business unit.
|
|
31
|
+
*
|
|
32
|
+
* @param route - The route being activated.
|
|
33
|
+
* @returns `true` when access is allowed, otherwise a redirect to access denied.
|
|
34
|
+
*/
|
|
35
|
+
declare const businessUnitRoutePermissionsGuard: CanActivateFn;
|
|
36
|
+
|
|
37
|
+
export { BUSINESS_UNIT_ID_RESOLVER, businessUnitRoutePermissionsGuard };
|
|
38
|
+
export type { BusinessUnitIdResolver };
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
|
|
3
|
+
interface IHistoryDetailsLink {
|
|
4
|
+
type: string;
|
|
5
|
+
emit: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface IHistoryDetailsFragment {
|
|
9
|
+
text: string;
|
|
10
|
+
bold: boolean;
|
|
11
|
+
hyphen: boolean;
|
|
12
|
+
link?: IHistoryDetailsLink | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface IHistoryDetailsPart {
|
|
16
|
+
fragments: IHistoryDetailsFragment[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface IHistoryDetails {
|
|
20
|
+
line1: IHistoryDetailsPart[];
|
|
21
|
+
line2: IHistoryDetailsPart[] | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface IHistoryDetailsDateFormat {
|
|
25
|
+
input: string;
|
|
26
|
+
output: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type THistoryDetailsRawItem = Record<string, unknown>;
|
|
30
|
+
|
|
31
|
+
type THistoryDetailsTransformer = (item: THistoryDetailsRawItem) => IHistoryDetails;
|
|
32
|
+
|
|
33
|
+
type THistoryDetailsTransformerConfig = Record<string, THistoryDetailsTransformer>;
|
|
34
|
+
|
|
35
|
+
interface IHistoryTransformationConfig {
|
|
36
|
+
aliasPathPrefixes: string[];
|
|
37
|
+
dateFormat: IHistoryDetailsDateFormat;
|
|
38
|
+
emptyValues: readonly unknown[];
|
|
39
|
+
fallbackAliases: string[];
|
|
40
|
+
historyItemTypeAliases: string[];
|
|
41
|
+
transformers: THistoryDetailsTransformerConfig;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
declare class HistoryTransformationService {
|
|
45
|
+
/**
|
|
46
|
+
* Transforms a raw history item into the structured details model.
|
|
47
|
+
*
|
|
48
|
+
* @param item - The raw history item.
|
|
49
|
+
* @param config - The domain-specific transformation configuration.
|
|
50
|
+
* @returns The transformed history details.
|
|
51
|
+
*/
|
|
52
|
+
transformDetails(item: THistoryDetailsRawItem, config: IHistoryTransformationConfig): IHistoryDetails;
|
|
53
|
+
/**
|
|
54
|
+
* Transforms raw history items while preserving the rest of each item.
|
|
55
|
+
*
|
|
56
|
+
* @param items - The raw history items.
|
|
57
|
+
* @param config - The domain-specific transformation configuration.
|
|
58
|
+
* @returns The items with transformed structured details.
|
|
59
|
+
*/
|
|
60
|
+
transformItems<T extends THistoryDetailsRawItem>(items: T[], config: IHistoryTransformationConfig): Array<Omit<T, 'details'> & {
|
|
61
|
+
details: IHistoryDetails;
|
|
62
|
+
}>;
|
|
63
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<HistoryTransformationService, never>;
|
|
64
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<HistoryTransformationService>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
declare const HISTORY_DETAILS_PATTERNS: {
|
|
68
|
+
keyNormalise: RegExp;
|
|
69
|
+
snakeCaseBoundary: RegExp;
|
|
70
|
+
snakeCaseSeparator: RegExp;
|
|
71
|
+
transactionTypeSpace: RegExp;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
interface IHistoryFragmentOptions {
|
|
75
|
+
bold?: boolean;
|
|
76
|
+
hyphen?: boolean;
|
|
77
|
+
link?: IHistoryDetailsLink | null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Transforms a raw history item into the configured structured details model.
|
|
82
|
+
*
|
|
83
|
+
* @param item - The raw history item.
|
|
84
|
+
* @param config - The domain-specific transformation configuration.
|
|
85
|
+
* @returns The transformed details model.
|
|
86
|
+
*/
|
|
87
|
+
declare function transformHistoryDetails(item: THistoryDetailsRawItem, config: IHistoryTransformationConfig): IHistoryDetails;
|
|
88
|
+
/**
|
|
89
|
+
* Transforms raw history items while preserving the rest of each item.
|
|
90
|
+
*
|
|
91
|
+
* @param items - The raw history items.
|
|
92
|
+
* @param config - The domain-specific transformation configuration.
|
|
93
|
+
* @returns The items with transformed structured details.
|
|
94
|
+
*/
|
|
95
|
+
declare function transformHistoryItems<T extends THistoryDetailsRawItem>(items: T[], config: IHistoryTransformationConfig): Array<Omit<T, 'details'> & {
|
|
96
|
+
details: IHistoryDetails;
|
|
97
|
+
}>;
|
|
98
|
+
/**
|
|
99
|
+
* Builds fallback details from configured fallback fields when no transformer matches.
|
|
100
|
+
*
|
|
101
|
+
* @param item - The raw history item.
|
|
102
|
+
* @param config - The domain-specific transformation configuration.
|
|
103
|
+
* @returns The fallback structured details model.
|
|
104
|
+
*/
|
|
105
|
+
declare function transformHistoryFallbackDetails(item: THistoryDetailsRawItem, config: IHistoryTransformationConfig): IHistoryDetails;
|
|
106
|
+
/**
|
|
107
|
+
* Creates a details object and normalises an empty secondary line to null.
|
|
108
|
+
*
|
|
109
|
+
* @param line1Parts - The primary line parts.
|
|
110
|
+
* @param line2Parts - The secondary line parts.
|
|
111
|
+
* @returns The structured details object.
|
|
112
|
+
*/
|
|
113
|
+
declare function createHistoryDetails(line1Parts: Array<IHistoryDetailsPart | null>, line2Parts?: Array<IHistoryDetailsPart | null>): IHistoryDetails;
|
|
114
|
+
/**
|
|
115
|
+
* Creates a details part after removing empty fragments.
|
|
116
|
+
*
|
|
117
|
+
* @param fragments - The fragments for the part.
|
|
118
|
+
* @returns The details part or null when no fragments are visible.
|
|
119
|
+
*/
|
|
120
|
+
declare function createHistoryDetailsPart(fragments: IHistoryDetailsFragment[]): IHistoryDetailsPart | null;
|
|
121
|
+
/**
|
|
122
|
+
* Creates a text-only details part.
|
|
123
|
+
*
|
|
124
|
+
* @param text - The part text.
|
|
125
|
+
* @returns The details part or null when text is empty.
|
|
126
|
+
*/
|
|
127
|
+
declare function createHistoryTextPart(text: string | null): IHistoryDetailsPart | null;
|
|
128
|
+
/**
|
|
129
|
+
* Creates a details part containing a bold label and plain value.
|
|
130
|
+
*
|
|
131
|
+
* @param label - The label text.
|
|
132
|
+
* @param value - The value text.
|
|
133
|
+
* @returns The labelled details part or null when value is empty.
|
|
134
|
+
*/
|
|
135
|
+
declare function createHistoryLabelValuePart(label: string, value: string | null): IHistoryDetailsPart | null;
|
|
136
|
+
/**
|
|
137
|
+
* Creates a text fragment with default styling flags.
|
|
138
|
+
*
|
|
139
|
+
* @param text - The fragment text.
|
|
140
|
+
* @param options - Optional fragment styling and link metadata.
|
|
141
|
+
* @returns The details fragment.
|
|
142
|
+
*/
|
|
143
|
+
declare function createHistoryFragment(text: string, options?: IHistoryFragmentOptions): IHistoryDetailsFragment;
|
|
144
|
+
/**
|
|
145
|
+
* Creates link metadata for a details fragment.
|
|
146
|
+
*
|
|
147
|
+
* @param type - The link type emitted by the UI.
|
|
148
|
+
* @param emit - The emitted linked entity identifier.
|
|
149
|
+
* @returns The fragment link metadata.
|
|
150
|
+
*/
|
|
151
|
+
declare function createHistoryLink(type: string, emit: string): IHistoryDetailsLink;
|
|
152
|
+
/**
|
|
153
|
+
* Reads the first non-empty scalar value from candidate aliases as a string.
|
|
154
|
+
*
|
|
155
|
+
* @param item - The raw history item.
|
|
156
|
+
* @param aliases - The candidate field aliases.
|
|
157
|
+
* @param aliasPathPrefixes - The prefixes used for unqualified aliases.
|
|
158
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
159
|
+
* @returns The string value or null.
|
|
160
|
+
*/
|
|
161
|
+
declare function getHistoryString(item: THistoryDetailsRawItem, aliases: string[], aliasPathPrefixes: string[], emptyValues: readonly unknown[]): string | null;
|
|
162
|
+
/**
|
|
163
|
+
* Reads the first non-empty value from candidate aliases.
|
|
164
|
+
*
|
|
165
|
+
* @param item - The raw history item.
|
|
166
|
+
* @param aliases - The candidate field aliases.
|
|
167
|
+
* @param aliasPathPrefixes - The prefixes used for unqualified aliases.
|
|
168
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
169
|
+
* @returns The matched value or null.
|
|
170
|
+
*/
|
|
171
|
+
declare function getHistoryValue(item: THistoryDetailsRawItem, aliases: string[], aliasPathPrefixes: string[], emptyValues: readonly unknown[]): unknown;
|
|
172
|
+
/**
|
|
173
|
+
* Expands an alias into candidate dot-notated paths.
|
|
174
|
+
*
|
|
175
|
+
* @param alias - The field alias.
|
|
176
|
+
* @param aliasPathPrefixes - The prefixes used for unqualified aliases.
|
|
177
|
+
* @returns The candidate paths.
|
|
178
|
+
*/
|
|
179
|
+
declare function getHistoryAliasPaths(alias: string, aliasPathPrefixes: string[]): string[];
|
|
180
|
+
/**
|
|
181
|
+
* Reads a value from an history item using a dot-notated path.
|
|
182
|
+
*
|
|
183
|
+
* @param item - The raw history item.
|
|
184
|
+
* @param path - The dot-notated path.
|
|
185
|
+
* @returns The matched value or undefined.
|
|
186
|
+
*/
|
|
187
|
+
declare function getHistoryValueByPath(item: THistoryDetailsRawItem, path: string): unknown;
|
|
188
|
+
/**
|
|
189
|
+
* Checks whether a value is a non-null record.
|
|
190
|
+
*
|
|
191
|
+
* @param value - The value to check.
|
|
192
|
+
* @returns True when the value is a record.
|
|
193
|
+
*/
|
|
194
|
+
declare function isHistoryRecord(value: unknown): value is Record<string, unknown>;
|
|
195
|
+
/**
|
|
196
|
+
* Checks whether a value should be treated as empty.
|
|
197
|
+
*
|
|
198
|
+
* @param value - The value to check.
|
|
199
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
200
|
+
* @returns True when the value is empty.
|
|
201
|
+
*/
|
|
202
|
+
declare function isHistoryEmptyValue(value: unknown, emptyValues: readonly unknown[]): boolean;
|
|
203
|
+
/**
|
|
204
|
+
* Checks whether a string value is present.
|
|
205
|
+
*
|
|
206
|
+
* @param value - The value to check.
|
|
207
|
+
* @returns True when the value is a non-empty string.
|
|
208
|
+
*/
|
|
209
|
+
declare function isHistoryPresentString(value: string | null): value is string;
|
|
210
|
+
/**
|
|
211
|
+
* Normalises a history item type key for transformer lookup.
|
|
212
|
+
*
|
|
213
|
+
* @param value - The raw key.
|
|
214
|
+
* @returns The normalised key or null.
|
|
215
|
+
*/
|
|
216
|
+
declare function normaliseHistoryKey(value: string | null): string | null;
|
|
217
|
+
/**
|
|
218
|
+
* Normalises a transaction type code for switch matching.
|
|
219
|
+
*
|
|
220
|
+
* @param value - The raw transaction type.
|
|
221
|
+
* @returns The normalised transaction type or null.
|
|
222
|
+
*/
|
|
223
|
+
declare function normaliseHistoryTransactionType(value: string | null): string | null;
|
|
224
|
+
/**
|
|
225
|
+
* Converts a camel, space, or hyphen value to snake case.
|
|
226
|
+
*
|
|
227
|
+
* @param value - The raw value.
|
|
228
|
+
* @returns The snake case value.
|
|
229
|
+
*/
|
|
230
|
+
declare function toHistorySnakeCase(value: string): string;
|
|
231
|
+
/**
|
|
232
|
+
* Formats configured date strings to the configured output format.
|
|
233
|
+
*
|
|
234
|
+
* @param value - The raw date value.
|
|
235
|
+
* @param dateFormat - The input and output date formats.
|
|
236
|
+
* @returns The formatted date or original value when parsing fails.
|
|
237
|
+
*/
|
|
238
|
+
declare function formatHistoryDate(value: string | null, dateFormat: IHistoryDetailsDateFormat): string | null;
|
|
239
|
+
/**
|
|
240
|
+
* Formats numeric values as currency while preserving preformatted text.
|
|
241
|
+
*
|
|
242
|
+
* @param value - The raw money value.
|
|
243
|
+
* @param currencyPrefix - The currency prefix to prepend to numeric values.
|
|
244
|
+
* @param emptyValues - Values that should be treated as empty.
|
|
245
|
+
* @returns The formatted money text or null.
|
|
246
|
+
*/
|
|
247
|
+
declare function formatHistoryMoney(value: unknown, currencyPrefix: string, emptyValues: readonly unknown[]): string | null;
|
|
248
|
+
|
|
249
|
+
export { HISTORY_DETAILS_PATTERNS, HistoryTransformationService, createHistoryDetails, createHistoryDetailsPart, createHistoryFragment, createHistoryLabelValuePart, createHistoryLink, createHistoryTextPart, formatHistoryDate, formatHistoryMoney, getHistoryAliasPaths, getHistoryString, getHistoryValue, getHistoryValueByPath, isHistoryEmptyValue, isHistoryPresentString, isHistoryRecord, normaliseHistoryKey, normaliseHistoryTransactionType, toHistorySnakeCase, transformHistoryDetails, transformHistoryFallbackDetails, transformHistoryItems };
|
|
250
|
+
export type { IHistoryDetails, IHistoryDetailsDateFormat, IHistoryDetailsFragment, IHistoryDetailsLink, IHistoryDetailsPart, IHistoryFragmentOptions, IHistoryTransformationConfig, THistoryDetailsRawItem, THistoryDetailsTransformer, THistoryDetailsTransformerConfig };
|