@yuuvis/client-core 3.2.1 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/yuuvis-client-core.mjs +1362 -1306
- package/fesm2022/yuuvis-client-core.mjs.map +1 -1
- package/package.json +1 -1
- package/types/yuuvis-client-core.d.ts +347 -312
|
@@ -5,11 +5,12 @@ import * as i1 from '@angular/common/http';
|
|
|
5
5
|
import { HttpErrorResponse, HttpClient, HttpHeaders, HttpRequest, HttpParams, HttpResponse, HttpEventType, provideHttpClient, withInterceptors } from '@angular/common/http';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
7
|
import { inject, Injectable, InjectionToken, NgZone, DOCUMENT, Inject, signal, Directive, Pipe, provideEnvironmentInitializer, makeEnvironmentProviders, provideAppInitializer } from '@angular/core';
|
|
8
|
-
import { tap, finalize, shareReplay, catchError,
|
|
9
|
-
import { EMPTY, Subject, of, forkJoin, tap as tap$1, catchError as catchError$1,
|
|
8
|
+
import { tap, finalize, shareReplay, catchError, map, switchMap, first, filter, scan, delay } from 'rxjs/operators';
|
|
9
|
+
import { EMPTY, Subject, of, forkJoin, Observable, tap as tap$1, catchError as catchError$1, ReplaySubject, BehaviorSubject, map as map$1, throwError, switchMap as switchMap$1, merge, fromEvent, filter as filter$1, debounceTime, isObservable } from 'rxjs';
|
|
10
10
|
import { StorageMap } from '@ngx-pwa/local-storage';
|
|
11
11
|
import { __decorate, __param, __metadata } from 'tslib';
|
|
12
12
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
13
|
+
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
13
14
|
import { registerLocaleData, DecimalPipe, PercentPipe, CurrencyPipe } from '@angular/common';
|
|
14
15
|
import localeAr from '@angular/common/locales/ar';
|
|
15
16
|
import localeBn from '@angular/common/locales/bn';
|
|
@@ -59,7 +60,6 @@ import localeTr from '@angular/common/locales/tr';
|
|
|
59
60
|
import localeUk from '@angular/common/locales/uk';
|
|
60
61
|
import localeVi from '@angular/common/locales/vi';
|
|
61
62
|
import localeZh from '@angular/common/locales/zh';
|
|
62
|
-
import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
63
63
|
import { DeviceDetectorService } from 'ngx-device-detector';
|
|
64
64
|
import { FormGroup, FormControl } from '@angular/forms';
|
|
65
65
|
import { MatTabGroup } from '@angular/material/tabs';
|
|
@@ -404,6 +404,28 @@ class YuvUser {
|
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
406
|
|
|
407
|
+
var AuditAction;
|
|
408
|
+
(function (AuditAction) {
|
|
409
|
+
AuditAction["CREATE_METADATA"] = "100";
|
|
410
|
+
AuditAction["CREATE_METADATA_WITH_CONTENT"] = "101";
|
|
411
|
+
AuditAction["CREATE_TAG"] = "110";
|
|
412
|
+
AuditAction["DELETE"] = "200";
|
|
413
|
+
AuditAction["DELETE_CONTENT"] = "201";
|
|
414
|
+
AuditAction["DELETE_MARKED"] = "202";
|
|
415
|
+
AuditAction["DELETE_TAG"] = "210";
|
|
416
|
+
AuditAction["UPDATE_METADATA"] = "300";
|
|
417
|
+
AuditAction["UPDATE_CONTENT"] = "301";
|
|
418
|
+
AuditAction["UPDATE_METADATA_WITH_CONTENT"] = "302";
|
|
419
|
+
AuditAction["UPDATE_MOVE_CONTENT"] = "303";
|
|
420
|
+
AuditAction["UPDATE_TAG"] = "310";
|
|
421
|
+
AuditAction["OBJECT_RESTORED_FROM_VERSION"] = "325";
|
|
422
|
+
AuditAction["GET_CONTENT"] = "400";
|
|
423
|
+
AuditAction["GET_METADATA"] = "401";
|
|
424
|
+
AuditAction["GET_RENDITION_TEXT"] = "402";
|
|
425
|
+
AuditAction["GET_RENDITION_PDF"] = "403";
|
|
426
|
+
AuditAction["GET_RENDITION_THUMBNAIL"] = "404";
|
|
427
|
+
})(AuditAction || (AuditAction = {}));
|
|
428
|
+
|
|
407
429
|
var Sort;
|
|
408
430
|
(function (Sort) {
|
|
409
431
|
Sort["ASC"] = "asc";
|
|
@@ -1262,111 +1284,115 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1262
1284
|
args: [{ providedIn: 'root' }]
|
|
1263
1285
|
}] });
|
|
1264
1286
|
|
|
1265
|
-
var
|
|
1266
|
-
(function (
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1287
|
+
var Operator;
|
|
1288
|
+
(function (Operator) {
|
|
1289
|
+
Operator["EQUAL"] = "eq";
|
|
1290
|
+
Operator["EEQUAL"] = "eeq";
|
|
1291
|
+
Operator["IN"] = "in";
|
|
1292
|
+
Operator["GREATER_THAN"] = "gt";
|
|
1293
|
+
Operator["GREATER_OR_EQUAL"] = "gte";
|
|
1294
|
+
Operator["LESS_THAN"] = "lt";
|
|
1295
|
+
Operator["LESS_OR_EQUAL"] = "lte";
|
|
1296
|
+
Operator["INTERVAL"] = "gtlt";
|
|
1297
|
+
Operator["INTERVAL_INCLUDE_BOTH"] = "gtelte";
|
|
1298
|
+
Operator["INTERVAL_INCLUDE_TO"] = "gtlte";
|
|
1299
|
+
Operator["INTERVAL_INCLUDE_FROM"] = "gtelt";
|
|
1300
|
+
Operator["RANGE"] = "rg";
|
|
1301
|
+
Operator["LIKE"] = "like";
|
|
1302
|
+
Operator["CONTAINS"] = "contains"; // contains
|
|
1303
|
+
})(Operator || (Operator = {}));
|
|
1304
|
+
const OperatorLabel = {
|
|
1305
|
+
/** equal */
|
|
1306
|
+
EQUAL: '=',
|
|
1307
|
+
/** exact equal */
|
|
1308
|
+
EEQUAL: '==',
|
|
1309
|
+
/** match at least one of the provided values (value has to be an array) */
|
|
1310
|
+
IN: '~',
|
|
1311
|
+
/** greater than */
|
|
1312
|
+
GREATER_THAN: '>',
|
|
1313
|
+
/** greater than or equal */
|
|
1314
|
+
GREATER_OR_EQUAL: '≽', //
|
|
1315
|
+
LESS_THAN: '<', // less than
|
|
1316
|
+
LESS_OR_EQUAL: '≼', // less than or equal
|
|
1317
|
+
INTERVAL: '<>', // interval
|
|
1318
|
+
INTERVAL_INCLUDE_BOTH: '-', // interval include left and right
|
|
1319
|
+
INTERVAL_INCLUDE_TO: '>-', // interval include right
|
|
1320
|
+
INTERVAL_INCLUDE_FROM: '-<', // interval include left
|
|
1321
|
+
RANGE: '=', // aggegation ranges
|
|
1322
|
+
LIKE: '~', // like
|
|
1323
|
+
CONTAINS: '~' // contains
|
|
1324
|
+
};
|
|
1278
1325
|
|
|
1279
1326
|
/**
|
|
1280
|
-
* Service for
|
|
1327
|
+
* Service for saving or caching data on the users device. It uses the most efficient storage
|
|
1328
|
+
* available (IndexDB, localstorage, ...) on the device. Depending on the type of storage used,
|
|
1329
|
+
* its limitations apply.
|
|
1281
1330
|
*/
|
|
1282
|
-
class
|
|
1283
|
-
#
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
this.#
|
|
1292
|
-
this.event$ = this.#eventSource.asObservable();
|
|
1293
|
-
this.#listenToWindowEvents();
|
|
1294
|
-
}
|
|
1295
|
-
#startsWithAllowed(value) {
|
|
1296
|
-
return typeof value === 'string' && this.#customEvents.some((prefix) => value.startsWith(prefix));
|
|
1297
|
-
}
|
|
1298
|
-
#isValidExternalMessage(event) {
|
|
1299
|
-
this.#customEvents.push(CUSTOM_YUV_EVENT_PREFIX);
|
|
1300
|
-
if (!event.data || typeof event.data !== 'object')
|
|
1301
|
-
return false;
|
|
1302
|
-
if (!(this.#startsWithAllowed(event.data.source) || this.#startsWithAllowed(event.data.type)))
|
|
1303
|
-
return false;
|
|
1304
|
-
// Accept messages from trusted origins
|
|
1305
|
-
this.#customEventsTrustedOrigins.push(window.location.origin);
|
|
1306
|
-
const isFromTrustedOrigin = this.#customEventsTrustedOrigins.includes(event.origin);
|
|
1307
|
-
const hasValidStructure = event.data && (event.data.type || event.data.eventType) && typeof event.data === 'object';
|
|
1308
|
-
return isFromTrustedOrigin && hasValidStructure;
|
|
1331
|
+
class AppCacheService {
|
|
1332
|
+
#storage = inject(StorageMap);
|
|
1333
|
+
/**
|
|
1334
|
+
* Set item in storage.
|
|
1335
|
+
* @param key The key under which the value is stored.
|
|
1336
|
+
* @param value The value to store.
|
|
1337
|
+
* @returns An Observable that emits true when the operation is successful.
|
|
1338
|
+
*/
|
|
1339
|
+
setItem(key, value) {
|
|
1340
|
+
return this.#storage.set(key, value).pipe(map(() => true));
|
|
1309
1341
|
}
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1342
|
+
/**
|
|
1343
|
+
* Get item from storage.
|
|
1344
|
+
* @param key The key of the item to retrieve.
|
|
1345
|
+
* @returns An Observable that emits the retrieved value.
|
|
1346
|
+
*/
|
|
1347
|
+
getItem(key) {
|
|
1348
|
+
return this.#storage.get(key);
|
|
1314
1349
|
}
|
|
1315
1350
|
/**
|
|
1316
|
-
*
|
|
1317
|
-
* @param
|
|
1318
|
-
* @
|
|
1351
|
+
* Remove item from storage.
|
|
1352
|
+
* @param key The key of the item to remove.
|
|
1353
|
+
* @returns An Observable that emits true when the operation is successful.
|
|
1319
1354
|
*/
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
const payload = {
|
|
1323
|
-
type,
|
|
1324
|
-
data,
|
|
1325
|
-
timestamp: Date.now()
|
|
1326
|
-
};
|
|
1327
|
-
window.postMessage(payload, targetOrigin);
|
|
1355
|
+
removeItem(key) {
|
|
1356
|
+
return this.#storage.delete(key).pipe(map(() => true));
|
|
1328
1357
|
}
|
|
1329
1358
|
/**
|
|
1330
|
-
*
|
|
1331
|
-
* @param
|
|
1332
|
-
* @
|
|
1359
|
+
* Clear storage, optionally filtered by a function.
|
|
1360
|
+
* @param filter A function to filter which keys to clear.
|
|
1361
|
+
* @returns An Observable that emits true when the operation is successful.
|
|
1333
1362
|
*/
|
|
1334
|
-
|
|
1335
|
-
|
|
1363
|
+
clear(filter) {
|
|
1364
|
+
return filter
|
|
1365
|
+
? this.getStorageKeys().pipe(switchMap((keys) => {
|
|
1366
|
+
const list = keys.filter((k) => filter(k)).map((k) => this.removeItem(k));
|
|
1367
|
+
return list.length ? forkJoin(list).pipe(map(() => true)) : of(true);
|
|
1368
|
+
}))
|
|
1369
|
+
: this.#storage.clear().pipe(map(() => true));
|
|
1336
1370
|
}
|
|
1337
1371
|
/**
|
|
1338
|
-
*
|
|
1339
|
-
* @
|
|
1372
|
+
* Get all storage keys.
|
|
1373
|
+
* @returns An Observable that emits an array of all storage keys.
|
|
1340
1374
|
*/
|
|
1341
|
-
|
|
1342
|
-
return
|
|
1375
|
+
getStorageKeys() {
|
|
1376
|
+
return new Observable((observer) => {
|
|
1377
|
+
const keys = [];
|
|
1378
|
+
this.#storage.keys().subscribe({
|
|
1379
|
+
next: (key) => keys.push(key),
|
|
1380
|
+
complete: () => observer.next(keys)
|
|
1381
|
+
});
|
|
1382
|
+
}).pipe(first());
|
|
1343
1383
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1384
|
+
setStorage(options) {
|
|
1385
|
+
return forkJoin(Object.keys(options || {}).map((k) => this.setItem(k, options[k])));
|
|
1386
|
+
}
|
|
1387
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AppCacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1388
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AppCacheService, providedIn: 'root' }); }
|
|
1346
1389
|
}
|
|
1347
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
1390
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AppCacheService, decorators: [{
|
|
1348
1391
|
type: Injectable,
|
|
1349
1392
|
args: [{
|
|
1350
1393
|
providedIn: 'root'
|
|
1351
1394
|
}]
|
|
1352
|
-
}]
|
|
1353
|
-
|
|
1354
|
-
/**
|
|
1355
|
-
* Events emitted by parts of the application
|
|
1356
|
-
*/
|
|
1357
|
-
var YuvEventType;
|
|
1358
|
-
(function (YuvEventType) {
|
|
1359
|
-
YuvEventType["LOGOUT"] = "yuv.user.logout";
|
|
1360
|
-
YuvEventType["CLIENT_LOCALE_CHANGED"] = "yuv.user.locale.client.changed";
|
|
1361
|
-
YuvEventType["DMS_OBJECT_LOADED"] = "yuv.dms.object.loaded";
|
|
1362
|
-
YuvEventType["DMS_OBJECT_CREATED"] = "yuv.dms.object.created";
|
|
1363
|
-
YuvEventType["DMS_OBJECT_DELETED"] = "yuv.dms.object.deleted";
|
|
1364
|
-
YuvEventType["DMS_OBJECT_UPDATED"] = "yuv.dms.object.updated";
|
|
1365
|
-
YuvEventType["DMS_OBJECT_CONTENT_UPDATED"] = "yuv.dms.object.content.updated";
|
|
1366
|
-
YuvEventType["DMS_OBJECTS_MOVED"] = "yuv.dms.objects.moved";
|
|
1367
|
-
YuvEventType["RELATIONSHIP_CREATED"] = "yuv.dms.relationship.created";
|
|
1368
|
-
YuvEventType["RELATIONSHIP_DELETED"] = "yuv.dms.relationship.deleted";
|
|
1369
|
-
})(YuvEventType || (YuvEventType = {}));
|
|
1395
|
+
}] });
|
|
1370
1396
|
|
|
1371
1397
|
/**
|
|
1372
1398
|
* Service managing localizations. The localizations are fetched
|
|
@@ -1397,8 +1423,9 @@ class LocalizationService {
|
|
|
1397
1423
|
}));
|
|
1398
1424
|
}
|
|
1399
1425
|
getLocalizedResource(key) {
|
|
1426
|
+
// TODO: Fix return type to also include undefined
|
|
1400
1427
|
const iso = this.#translate.getCurrentLang();
|
|
1401
|
-
return { ...this.#i18n, ...this.#extension[iso] }[key]
|
|
1428
|
+
return { ...this.#i18n, ...this.#extension[iso] }[key];
|
|
1402
1429
|
}
|
|
1403
1430
|
getLocalizedLabel(id) {
|
|
1404
1431
|
return this.getLocalizedResource(`${id}_label`);
|
|
@@ -1432,77 +1459,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
1432
1459
|
}]
|
|
1433
1460
|
}] });
|
|
1434
1461
|
|
|
1435
|
-
/**
|
|
1436
|
-
* Service for saving or caching data on the users device. It uses the most efficient storage
|
|
1437
|
-
* available (IndexDB, localstorage, ...) on the device. Depending on the type of storage used,
|
|
1438
|
-
* its limitations apply.
|
|
1439
|
-
*/
|
|
1440
|
-
class AppCacheService {
|
|
1441
|
-
#storage = inject(StorageMap);
|
|
1442
|
-
/**
|
|
1443
|
-
* Set item in storage.
|
|
1444
|
-
* @param key The key under which the value is stored.
|
|
1445
|
-
* @param value The value to store.
|
|
1446
|
-
* @returns An Observable that emits true when the operation is successful.
|
|
1447
|
-
*/
|
|
1448
|
-
setItem(key, value) {
|
|
1449
|
-
return this.#storage.set(key, value).pipe(map(() => true));
|
|
1450
|
-
}
|
|
1451
|
-
/**
|
|
1452
|
-
* Get item from storage.
|
|
1453
|
-
* @param key The key of the item to retrieve.
|
|
1454
|
-
* @returns An Observable that emits the retrieved value.
|
|
1455
|
-
*/
|
|
1456
|
-
getItem(key) {
|
|
1457
|
-
return this.#storage.get(key);
|
|
1458
|
-
}
|
|
1459
|
-
/**
|
|
1460
|
-
* Remove item from storage.
|
|
1461
|
-
* @param key The key of the item to remove.
|
|
1462
|
-
* @returns An Observable that emits true when the operation is successful.
|
|
1463
|
-
*/
|
|
1464
|
-
removeItem(key) {
|
|
1465
|
-
return this.#storage.delete(key).pipe(map(() => true));
|
|
1466
|
-
}
|
|
1467
|
-
/**
|
|
1468
|
-
* Clear storage, optionally filtered by a function.
|
|
1469
|
-
* @param filter A function to filter which keys to clear.
|
|
1470
|
-
* @returns An Observable that emits true when the operation is successful.
|
|
1471
|
-
*/
|
|
1472
|
-
clear(filter) {
|
|
1473
|
-
return filter
|
|
1474
|
-
? this.getStorageKeys().pipe(switchMap((keys) => {
|
|
1475
|
-
const list = keys.filter((k) => filter(k)).map((k) => this.removeItem(k));
|
|
1476
|
-
return list.length ? forkJoin(list).pipe(map(() => true)) : of(true);
|
|
1477
|
-
}))
|
|
1478
|
-
: this.#storage.clear().pipe(map(() => true));
|
|
1479
|
-
}
|
|
1480
|
-
/**
|
|
1481
|
-
* Get all storage keys.
|
|
1482
|
-
* @returns An Observable that emits an array of all storage keys.
|
|
1483
|
-
*/
|
|
1484
|
-
getStorageKeys() {
|
|
1485
|
-
return new Observable((observer) => {
|
|
1486
|
-
const keys = [];
|
|
1487
|
-
this.#storage.keys().subscribe({
|
|
1488
|
-
next: (key) => keys.push(key),
|
|
1489
|
-
complete: () => observer.next(keys)
|
|
1490
|
-
});
|
|
1491
|
-
}).pipe(first());
|
|
1492
|
-
}
|
|
1493
|
-
setStorage(options) {
|
|
1494
|
-
return forkJoin(Object.keys(options || {}).map((k) => this.setItem(k, options[k])));
|
|
1495
|
-
}
|
|
1496
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AppCacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1497
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AppCacheService, providedIn: 'root' }); }
|
|
1498
|
-
}
|
|
1499
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AppCacheService, decorators: [{
|
|
1500
|
-
type: Injectable,
|
|
1501
|
-
args: [{
|
|
1502
|
-
providedIn: 'root'
|
|
1503
|
-
}]
|
|
1504
|
-
}] });
|
|
1505
|
-
|
|
1506
1462
|
/**
|
|
1507
1463
|
* Providing system definitions.
|
|
1508
1464
|
*/
|
|
@@ -1714,7 +1670,13 @@ class SystemService {
|
|
|
1714
1670
|
* @deprecated use LocalizationService.getLocalizedResource instead
|
|
1715
1671
|
*/
|
|
1716
1672
|
getLocalizedResource(key) {
|
|
1717
|
-
|
|
1673
|
+
try {
|
|
1674
|
+
// return this.system!.i18n[key];
|
|
1675
|
+
return this.#localization.getLocalizedResource(key);
|
|
1676
|
+
}
|
|
1677
|
+
catch (error) {
|
|
1678
|
+
return key;
|
|
1679
|
+
}
|
|
1718
1680
|
}
|
|
1719
1681
|
/**
|
|
1720
1682
|
* @deprecated use LocalizationService.getLocalizedResource instead
|
|
@@ -2139,1268 +2101,1182 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
2139
2101
|
}]
|
|
2140
2102
|
}] });
|
|
2141
2103
|
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
constructor() {
|
|
2147
|
-
this.#backend = inject(BackendService);
|
|
2148
|
-
this.#translate = inject(TranslateService);
|
|
2149
|
-
this.#logger = inject(Logger);
|
|
2150
|
-
this.#system = inject(SystemService);
|
|
2151
|
-
this.#localization = inject(LocalizationService);
|
|
2152
|
-
this.#eventService = inject(EventService);
|
|
2153
|
-
this.#config = inject(ConfigService);
|
|
2154
|
-
this.#document = inject(DOCUMENT);
|
|
2155
|
-
this.#USERS_SETTINGS = '/users/settings/';
|
|
2156
|
-
this.#DEFAULT_SETTINGS = '/users/settings';
|
|
2157
|
-
this.#SETTINGS_SECTION_OBJECTCONFIG = 'object-config';
|
|
2158
|
-
this.#userSource = new BehaviorSubject(this.#user);
|
|
2159
|
-
this.user$ = this.#userSource.asObservable();
|
|
2160
|
-
this.globalSettings = new Map();
|
|
2161
|
-
this.canCreateObjects = false;
|
|
2162
|
-
}
|
|
2163
|
-
#backend;
|
|
2164
|
-
#translate;
|
|
2165
|
-
#logger;
|
|
2166
|
-
#system;
|
|
2167
|
-
#localization;
|
|
2168
|
-
#eventService;
|
|
2169
|
-
#config;
|
|
2170
|
-
#document;
|
|
2171
|
-
#USERS_SETTINGS;
|
|
2172
|
-
#DEFAULT_SETTINGS;
|
|
2173
|
-
#SETTINGS_SECTION_OBJECTCONFIG;
|
|
2174
|
-
#user;
|
|
2175
|
-
#userSource;
|
|
2104
|
+
class SearchService {
|
|
2105
|
+
#backend = inject(BackendService);
|
|
2106
|
+
#system = inject(SystemService);
|
|
2107
|
+
static { this.DEFAULT_QUERY_SIZE = 50; }
|
|
2176
2108
|
/**
|
|
2177
|
-
*
|
|
2178
|
-
* @param
|
|
2109
|
+
* Execute a search query ans transform the result to a SearchResult object
|
|
2110
|
+
* @param query The search query
|
|
2111
|
+
* @returns Observable of a SearchResult
|
|
2179
2112
|
*/
|
|
2180
|
-
|
|
2181
|
-
this
|
|
2182
|
-
this.changeClientLocale('', false);
|
|
2183
|
-
this.#userSource.next(this.#user);
|
|
2184
|
-
}
|
|
2185
|
-
getCurrentUser() {
|
|
2186
|
-
return this.#user;
|
|
2187
|
-
}
|
|
2188
|
-
get hasAdminRole() {
|
|
2189
|
-
return this.#user?.authorities?.includes(AdministrationRoles.ADMIN) || false;
|
|
2190
|
-
}
|
|
2191
|
-
get hasSystemRole() {
|
|
2192
|
-
return this.#user?.authorities?.includes(AdministrationRoles.SYSTEM) || false;
|
|
2193
|
-
}
|
|
2194
|
-
get hasAdministrationRoles() {
|
|
2195
|
-
return this.hasAdminRole || this.hasSystemRole;
|
|
2196
|
-
}
|
|
2197
|
-
get hasManageSettingsRole() {
|
|
2198
|
-
const customRole = this.#config.get('core.permissions.manageSettingsRole');
|
|
2199
|
-
const manageSettingsRole = customRole || AdministrationRoles.MANAGE_SETTINGS;
|
|
2200
|
-
return this.#user?.authorities?.includes(manageSettingsRole) || false;
|
|
2201
|
-
}
|
|
2202
|
-
get isAdvancedUser() {
|
|
2203
|
-
const customRole = this.#config.get('core.permissions.advancedUserRole');
|
|
2204
|
-
const advancedUserRole = customRole || AdministrationRoles.MANAGE_SETTINGS;
|
|
2205
|
-
return this.#user?.authorities?.includes(advancedUserRole) || false;
|
|
2113
|
+
search(query) {
|
|
2114
|
+
return this.searchRaw(query).pipe(map((res) => this.toSearchResult(res, query.size || SearchService.DEFAULT_QUERY_SIZE, query.from || 0)));
|
|
2206
2115
|
}
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2116
|
+
/**
|
|
2117
|
+
* Execute a raw search query and return the result as is.
|
|
2118
|
+
* @param query The search query
|
|
2119
|
+
* @returns Observable of the raw search result
|
|
2120
|
+
*/
|
|
2121
|
+
searchRaw(query) {
|
|
2122
|
+
if (!query.size)
|
|
2123
|
+
query.size = SearchService.DEFAULT_QUERY_SIZE;
|
|
2124
|
+
return this.#backend.post(`/dms/objects/search`, query);
|
|
2211
2125
|
}
|
|
2212
2126
|
/**
|
|
2213
|
-
*
|
|
2214
|
-
* @param
|
|
2127
|
+
* Search for objects in the dms using CMIS like SQL syntax.
|
|
2128
|
+
* @param statement The query statement
|
|
2129
|
+
* @param size The number of items to return
|
|
2130
|
+
* @returns Observable of a SearchResult
|
|
2215
2131
|
*/
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
const languages = this.#config.getClientLocales().map((lang) => lang.iso);
|
|
2219
|
-
iso = iso || this.#user.getClientLocale(this.#config.getDefaultClientLocale());
|
|
2220
|
-
if (!languages.includes(iso)) {
|
|
2221
|
-
iso = this.#config.getDefaultClientLocale();
|
|
2222
|
-
}
|
|
2223
|
-
this.#logger.debug("Changed client locale to '" + iso + "'");
|
|
2224
|
-
this.#backend.setHeader('Accept-Language', iso);
|
|
2225
|
-
this.#user.uiDirection = this.#getUiDirection(iso);
|
|
2226
|
-
this.#document.body.dir = this.#user.uiDirection;
|
|
2227
|
-
this.#document.documentElement.lang = iso;
|
|
2228
|
-
this.#user.userSettings.locale = iso;
|
|
2229
|
-
if (this.#translate.getCurrentLang() !== iso || this.#system.authData?.language !== iso) {
|
|
2230
|
-
const obs = persist
|
|
2231
|
-
? forkJoin([
|
|
2232
|
-
this.#translate.use(iso),
|
|
2233
|
-
this.#system
|
|
2234
|
-
.updateAuthData({ language: iso })
|
|
2235
|
-
.pipe(switchMap(() => this.#localization.fetchLocalizations())),
|
|
2236
|
-
this.saveUserSettings(this.#user.userSettings).pipe(tap(() => {
|
|
2237
|
-
this.#logger.debug('Loading system definitions i18n resources for new locale.');
|
|
2238
|
-
}))
|
|
2239
|
-
])
|
|
2240
|
-
: this.#translate.use(iso);
|
|
2241
|
-
obs.subscribe(() => this.#eventService.trigger(YuvEventType.CLIENT_LOCALE_CHANGED, iso));
|
|
2242
|
-
}
|
|
2243
|
-
}
|
|
2132
|
+
searchCmis(statement, size = SearchService.DEFAULT_QUERY_SIZE, includePermissions = false) {
|
|
2133
|
+
return this.#executeCmisSearch(statement, size, 0, includePermissions);
|
|
2244
2134
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2135
|
+
#executeCmisSearch(statement, maxItems, skipCount = 0, includePermissions = false) {
|
|
2136
|
+
const payload = {
|
|
2137
|
+
query: {
|
|
2138
|
+
statement,
|
|
2139
|
+
skipCount,
|
|
2140
|
+
maxItems,
|
|
2141
|
+
handleDeletedDocuments: 'DELETED_DOCUMENTS_EXCLUDE'
|
|
2142
|
+
}
|
|
2143
|
+
};
|
|
2144
|
+
if (includePermissions) {
|
|
2145
|
+
payload.query.includePermissions = true;
|
|
2252
2146
|
}
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
this
|
|
2259
|
-
return this.#backend.get(this.#DEFAULT_SETTINGS);
|
|
2260
|
-
}));
|
|
2147
|
+
return this.#backend
|
|
2148
|
+
.post('/dms/objects/cmisSearch', payload
|
|
2149
|
+
// Using API-WEB because it enriches the response with additional information (resolved user names, etc.)
|
|
2150
|
+
// ApiBase.core
|
|
2151
|
+
)
|
|
2152
|
+
.pipe(map((res) => this.toSearchResult(res, maxItems, skipCount)));
|
|
2261
2153
|
}
|
|
2262
2154
|
/**
|
|
2263
|
-
*
|
|
2264
|
-
* @param
|
|
2265
|
-
* @param
|
|
2266
|
-
*
|
|
2155
|
+
* Fetch aggragations for a given query.
|
|
2156
|
+
* @param q The query
|
|
2157
|
+
* @param aggregations List of aggregations to be fetched (e.g. `enaio:objectTypeId`
|
|
2158
|
+
* to get an aggregation of object types)
|
|
2267
2159
|
*/
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
return this.#backend
|
|
2272
|
-
.get(`/idm/users?${params}`)
|
|
2273
|
-
.pipe(map((users) => (!users ? [] : users.map((u) => new YuvUser(u)))));
|
|
2274
|
-
}
|
|
2275
|
-
getUserById(id) {
|
|
2276
|
-
return this.#backend.get(`/idm/users/${id}`).pipe(map((user) => new YuvUser(user, this.#user.userSettings)));
|
|
2277
|
-
}
|
|
2278
|
-
logout(redirRoute) {
|
|
2279
|
-
const redir = redirRoute ? `?redir=${redirRoute}` : '';
|
|
2280
|
-
window.location.href = `${this.#backend.getApiBase('logout')}${redir}`;
|
|
2281
|
-
}
|
|
2282
|
-
getSettings(section) {
|
|
2283
|
-
return this.#user ? this.#backend.get(this.#USERS_SETTINGS + encodeURIComponent(section)) : of(null);
|
|
2284
|
-
}
|
|
2285
|
-
saveObjectConfig(objectConfigs) {
|
|
2286
|
-
return this.#backend.post(this.#USERS_SETTINGS + encodeURIComponent(this.#SETTINGS_SECTION_OBJECTCONFIG), objectConfigs);
|
|
2287
|
-
}
|
|
2288
|
-
loadObjectConfig() {
|
|
2289
|
-
return this.getSettings(this.#SETTINGS_SECTION_OBJECTCONFIG).pipe(catchError(() => of(undefined)));
|
|
2290
|
-
}
|
|
2291
|
-
#getUiDirection(iso) {
|
|
2292
|
-
// languages that are read right to left
|
|
2293
|
-
const rtlLanguages = ['ar', 'arc', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ku', 'ps', 'ur', 'yi'];
|
|
2294
|
-
return !rtlLanguages.includes(iso) ? Direction.LTR : Direction.RTL;
|
|
2295
|
-
}
|
|
2296
|
-
#setUserPermissions(res) {
|
|
2297
|
-
this.userPermissions = {
|
|
2298
|
-
create: this.#mapPermissions('CREATE', res),
|
|
2299
|
-
write: this.#mapPermissions('WRITE', res),
|
|
2300
|
-
read: this.#mapPermissions('READ', res),
|
|
2301
|
-
delete: this.#mapPermissions('DELETE', res)
|
|
2302
|
-
};
|
|
2303
|
-
const permissions = {
|
|
2304
|
-
createableObjectTypes: [
|
|
2305
|
-
...this.userPermissions.create.folderTypes,
|
|
2306
|
-
...this.userPermissions.create.objectTypes,
|
|
2307
|
-
...this.userPermissions.create.secondaryObjectTypes
|
|
2308
|
-
],
|
|
2309
|
-
searchableObjectTypes: [
|
|
2310
|
-
...this.userPermissions.read.folderTypes,
|
|
2311
|
-
...this.userPermissions.read.objectTypes,
|
|
2312
|
-
...this.userPermissions.read.secondaryObjectTypes
|
|
2313
|
-
]
|
|
2314
|
-
};
|
|
2315
|
-
this.#system.setPermissions(permissions);
|
|
2316
|
-
this.canCreateObjects = permissions.createableObjectTypes.length > 0;
|
|
2160
|
+
aggregate(q, aggregations) {
|
|
2161
|
+
q.aggs = aggregations;
|
|
2162
|
+
return this.searchRaw(q).pipe(map((res) => this.#toAggregateResult(res, aggregations)));
|
|
2317
2163
|
}
|
|
2318
|
-
|
|
2319
|
-
|
|
2164
|
+
/**
|
|
2165
|
+
* Map search result from the backend to applications AggregateResult object
|
|
2166
|
+
* @param searchResponse The backend response
|
|
2167
|
+
* @param aggregations The aggregations to be fetched
|
|
2168
|
+
*/
|
|
2169
|
+
#toAggregateResult(searchResponse, aggregations) {
|
|
2170
|
+
const agg = [];
|
|
2171
|
+
if (aggregations) {
|
|
2172
|
+
aggregations.forEach((a) => {
|
|
2173
|
+
const ag = {
|
|
2174
|
+
aggKey: a,
|
|
2175
|
+
entries: searchResponse.objects.map((o) => ({
|
|
2176
|
+
key: o.properties[a].value,
|
|
2177
|
+
count: o.properties['OBJECT_COUNT'].value
|
|
2178
|
+
}))
|
|
2179
|
+
};
|
|
2180
|
+
agg.push(ag);
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2320
2183
|
return {
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
secondaryObjectTypes: res['secondaryObjectTypeIds'] || []
|
|
2184
|
+
totalNumItems: searchResponse.totalNumItems,
|
|
2185
|
+
aggregations: agg
|
|
2324
2186
|
};
|
|
2325
2187
|
}
|
|
2326
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2327
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserService, providedIn: 'root' }); }
|
|
2328
|
-
}
|
|
2329
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserService, decorators: [{
|
|
2330
|
-
type: Injectable,
|
|
2331
|
-
args: [{
|
|
2332
|
-
providedIn: 'root'
|
|
2333
|
-
}]
|
|
2334
|
-
}] });
|
|
2335
|
-
|
|
2336
|
-
/**
|
|
2337
|
-
* @ignore
|
|
2338
|
-
*/
|
|
2339
|
-
const CUSTOM_CONFIG = new InjectionToken('CUSTOM_CONFIG', {
|
|
2340
|
-
factory: () => ({ main: ['assets/_yuuvis/config/main.json'], translations: ['assets/_yuuvis/i18n/'] })
|
|
2341
|
-
});
|
|
2342
|
-
const CORE_CONFIG = new InjectionToken('CORE_CONFIG');
|
|
2343
|
-
|
|
2344
|
-
/**
|
|
2345
|
-
* @ignore
|
|
2346
|
-
*/
|
|
2347
|
-
let CoreConfig = class CoreConfig {
|
|
2348
|
-
constructor(__config) {
|
|
2349
|
-
this.main = ['assets/_yuuvis/config/main.json'];
|
|
2350
|
-
this.translations = ['assets/_yuuvis/i18n/'];
|
|
2351
|
-
this.environment = { production: true };
|
|
2352
|
-
Object.assign(this, __config);
|
|
2353
|
-
}
|
|
2354
|
-
};
|
|
2355
|
-
CoreConfig = __decorate([
|
|
2356
|
-
__param(0, Inject(CUSTOM_CONFIG)),
|
|
2357
|
-
__metadata("design:paramtypes", [CoreConfig])
|
|
2358
|
-
], CoreConfig);
|
|
2359
|
-
|
|
2360
|
-
/**
|
|
2361
|
-
* Service managing the configuarions for object types.
|
|
2362
|
-
* Configuration means that you can pick certain fields
|
|
2363
|
-
* of an object type and assign them to a config object.
|
|
2364
|
-
*/
|
|
2365
|
-
class ObjectConfigService {
|
|
2366
|
-
constructor() {
|
|
2367
|
-
this.#system = inject(SystemService);
|
|
2368
|
-
this.#user = inject(UserService);
|
|
2369
|
-
this.OBJECT_CONFIG_STORAGE_KEY = 'yuv.framework.object-config';
|
|
2370
|
-
this.#objectConfigsSource = new ReplaySubject();
|
|
2371
|
-
this.#objectConfigs$ = this.#objectConfigsSource.asObservable();
|
|
2372
|
-
this.#defaultObjectConfigs = {};
|
|
2373
|
-
this.#registeredDefaultObjectConfigs = {
|
|
2374
|
-
main: {},
|
|
2375
|
-
buckets: []
|
|
2376
|
-
};
|
|
2377
|
-
this.#objectConfigs = {
|
|
2378
|
-
main: {},
|
|
2379
|
-
buckets: []
|
|
2380
|
-
};
|
|
2381
|
-
}
|
|
2382
|
-
#system;
|
|
2383
|
-
#user;
|
|
2384
|
-
#objectConfigsSource;
|
|
2385
|
-
#objectConfigs$;
|
|
2386
|
-
#defaultObjectConfigs;
|
|
2387
|
-
#registeredDefaultObjectConfigs;
|
|
2388
|
-
#objectConfigs;
|
|
2389
|
-
#isValidObjectConfig(soc) {
|
|
2390
|
-
return coerceBooleanProperty(soc && Object.hasOwn(soc, 'main') && Object.hasOwn(soc, 'buckets'));
|
|
2391
|
-
}
|
|
2392
|
-
// called on core init (auth.service -> initApp)
|
|
2393
|
-
init() {
|
|
2394
|
-
return this.#user.loadObjectConfig().pipe(tap$1((res) => {
|
|
2395
|
-
this.#getDefaultObjectConfig();
|
|
2396
|
-
this.#objectConfigs = (this.#isValidObjectConfig(res) && res) || {
|
|
2397
|
-
main: {},
|
|
2398
|
-
buckets: []
|
|
2399
|
-
};
|
|
2400
|
-
this.#objectConfigsSource.next(this.#objectConfigs);
|
|
2401
|
-
}));
|
|
2402
|
-
}
|
|
2403
|
-
getObjectConfigs$(bucket, includeDefaults) {
|
|
2404
|
-
return this.#objectConfigs$.pipe(map$1((soc) => {
|
|
2405
|
-
let ocr = soc.main;
|
|
2406
|
-
const defaults = { ...this.#defaultObjectConfigs, ...this.#getRegisteredDefaults(bucket) };
|
|
2407
|
-
if (bucket) {
|
|
2408
|
-
const tileBucket = soc.buckets.find((b) => b.id === bucket);
|
|
2409
|
-
if (tileBucket) {
|
|
2410
|
-
ocr = tileBucket.configs;
|
|
2411
|
-
if (includeDefaults)
|
|
2412
|
-
Object.keys(ocr).forEach((k) => {
|
|
2413
|
-
ocr[k] = { ...defaults[k], ...ocr[k] };
|
|
2414
|
-
});
|
|
2415
|
-
}
|
|
2416
|
-
}
|
|
2417
|
-
return includeDefaults ? { ...defaults, ...ocr } : { ...ocr };
|
|
2418
|
-
}));
|
|
2419
|
-
}
|
|
2420
2188
|
/**
|
|
2421
|
-
*
|
|
2422
|
-
*
|
|
2423
|
-
* @param
|
|
2424
|
-
* separate the configs from other apps. If not provided configs will be saved for
|
|
2425
|
-
* the global scope
|
|
2189
|
+
* Go to a page of a search result.
|
|
2190
|
+
* @param query SearchQuery or CMIS query statement
|
|
2191
|
+
* @param page The number of the page to go to
|
|
2426
2192
|
*/
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
if (tileBucketIdx !== -1) {
|
|
2432
|
-
this.#registeredDefaultObjectConfigs.buckets[tileBucketIdx].configs = {
|
|
2433
|
-
...this.#registeredDefaultObjectConfigs.buckets[tileBucketIdx].configs,
|
|
2434
|
-
...configs
|
|
2435
|
-
};
|
|
2436
|
-
}
|
|
2437
|
-
else {
|
|
2438
|
-
this.#registeredDefaultObjectConfigs.buckets.push({
|
|
2439
|
-
id: bucket,
|
|
2440
|
-
configs
|
|
2441
|
-
});
|
|
2442
|
-
}
|
|
2443
|
-
}
|
|
2444
|
-
else {
|
|
2445
|
-
this.#registeredDefaultObjectConfigs.main = { ...this.#registeredDefaultObjectConfigs.main, ...configs };
|
|
2446
|
-
}
|
|
2447
|
-
}
|
|
2448
|
-
unregisterDefaults(configs, bucket) {
|
|
2449
|
-
if (bucket) {
|
|
2450
|
-
// does bucket exist?
|
|
2451
|
-
const tileBucketIdx = this.#registeredDefaultObjectConfigs.buckets.findIndex((b) => b.id === bucket);
|
|
2452
|
-
if (tileBucketIdx !== -1) {
|
|
2453
|
-
this.#registeredDefaultObjectConfigs.buckets.splice(tileBucketIdx, 1);
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
2456
|
-
else {
|
|
2457
|
-
Object.keys(configs).forEach((key) => {
|
|
2458
|
-
delete this.#registeredDefaultObjectConfigs.main[key];
|
|
2459
|
-
});
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
getRegisteredDefault(objectTypeId, bucket) {
|
|
2463
|
-
if (bucket) {
|
|
2464
|
-
const b = this.#registeredDefaultObjectConfigs.buckets.find((b) => b.id === bucket);
|
|
2465
|
-
return b ? b.configs[objectTypeId] : undefined;
|
|
2193
|
+
getPage(query, page, pageSize = SearchService.DEFAULT_QUERY_SIZE, includePermissions = false) {
|
|
2194
|
+
const isCmis = typeof query === 'string';
|
|
2195
|
+
if (isCmis) {
|
|
2196
|
+
return this.#executeCmisSearch(query, pageSize, (page - 1) * pageSize, includePermissions);
|
|
2466
2197
|
}
|
|
2467
2198
|
else {
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
}
|
|
2471
|
-
#getRegisteredDefaults(bucket) {
|
|
2472
|
-
if (bucket) {
|
|
2473
|
-
const defaultTileBucket = this.#registeredDefaultObjectConfigs.buckets.find((b) => b.id === bucket);
|
|
2474
|
-
return defaultTileBucket?.configs || {};
|
|
2199
|
+
query.from = (page - 1) * (query.size || pageSize);
|
|
2200
|
+
return this.search(query);
|
|
2475
2201
|
}
|
|
2476
|
-
else
|
|
2477
|
-
return this.#registeredDefaultObjectConfigs.main;
|
|
2478
2202
|
}
|
|
2479
2203
|
/**
|
|
2480
|
-
*
|
|
2481
|
-
* @param
|
|
2482
|
-
* @param bucket Optional bucket ID to fetch the config from. Buckets
|
|
2483
|
-
* define separated areas to store/receive those configs. This way
|
|
2484
|
-
* components/apps can store different object configs than the ones
|
|
2485
|
-
* used accross the whole client application.
|
|
2204
|
+
* Map search result from the backend to applications SearchResult object
|
|
2205
|
+
* @param searchResponse The backend response
|
|
2486
2206
|
*/
|
|
2487
|
-
|
|
2488
|
-
const
|
|
2489
|
-
const
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
main: {},
|
|
2509
|
-
buckets: []
|
|
2510
|
-
};
|
|
2511
|
-
}
|
|
2512
|
-
if (bucket) {
|
|
2513
|
-
// does bucket exist?
|
|
2514
|
-
const tileBucketIdx = this.#objectConfigs.buckets.findIndex((b) => b.id === bucket);
|
|
2515
|
-
if (tileBucketIdx !== -1) {
|
|
2516
|
-
Object.keys(configs).forEach((objectTypeId) => {
|
|
2517
|
-
const config = configs[objectTypeId];
|
|
2518
|
-
if (config) {
|
|
2519
|
-
this.#objectConfigs.buckets[tileBucketIdx].configs[objectTypeId] = config;
|
|
2520
|
-
}
|
|
2521
|
-
else {
|
|
2522
|
-
delete this.#objectConfigs.buckets[tileBucketIdx].configs[objectTypeId];
|
|
2523
|
-
}
|
|
2524
|
-
});
|
|
2525
|
-
}
|
|
2526
|
-
else {
|
|
2527
|
-
const newBucket = { id: bucket, configs: {} };
|
|
2528
|
-
Object.keys(configs).forEach((objectTypeId) => {
|
|
2529
|
-
const config = configs[objectTypeId];
|
|
2530
|
-
if (config) {
|
|
2531
|
-
newBucket.configs[objectTypeId] = config;
|
|
2207
|
+
toSearchResult(searchResponse, pageSize = SearchService.DEFAULT_QUERY_SIZE, skipCount = 0) {
|
|
2208
|
+
const resultListItems = [];
|
|
2209
|
+
const objectTypes = [];
|
|
2210
|
+
searchResponse.objects.forEach((o) => {
|
|
2211
|
+
const fields = new Map();
|
|
2212
|
+
// process properties section of result
|
|
2213
|
+
Object.keys(o.properties).forEach((key) => {
|
|
2214
|
+
let value = o.properties[key].value;
|
|
2215
|
+
if (o.properties[key].clvalue) {
|
|
2216
|
+
// table fields will have a clientValue too ...
|
|
2217
|
+
value = o.properties[key].clvalue;
|
|
2218
|
+
// ... and also may contain values that need to be resolved
|
|
2219
|
+
if (o.properties[key].resolvedValues) {
|
|
2220
|
+
value.forEach((v) => {
|
|
2221
|
+
Object.keys(v).forEach((k) => {
|
|
2222
|
+
const resValue = Array.isArray(v[k]) ? v[k].map((i) => o.properties[key].resolvedValues[i]) : o.properties[key].resolvedValues[v[k]];
|
|
2223
|
+
if (resValue) {
|
|
2224
|
+
v[`${k}_title`] = resValue;
|
|
2225
|
+
}
|
|
2226
|
+
});
|
|
2227
|
+
});
|
|
2532
2228
|
}
|
|
2533
|
-
});
|
|
2534
|
-
this.#objectConfigs.buckets.push(newBucket);
|
|
2535
|
-
}
|
|
2536
|
-
}
|
|
2537
|
-
else {
|
|
2538
|
-
Object.keys(configs).forEach((objectTypeId) => {
|
|
2539
|
-
const config = configs[objectTypeId];
|
|
2540
|
-
if (config) {
|
|
2541
|
-
this.#objectConfigs.main[objectTypeId] = config;
|
|
2542
2229
|
}
|
|
2543
|
-
|
|
2544
|
-
|
|
2230
|
+
fields.set(key, value);
|
|
2231
|
+
if (o.properties[key].title) {
|
|
2232
|
+
fields.set(key + '_title', o.properties[key].title);
|
|
2545
2233
|
}
|
|
2546
2234
|
});
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2235
|
+
// process contentStreams section of result if available.
|
|
2236
|
+
// Objects that don't have files attached won't have this section
|
|
2237
|
+
let content;
|
|
2238
|
+
if (o.contentStreams && o.contentStreams.length > 0) {
|
|
2239
|
+
// we assume that each result object only has ONE file attached, altough
|
|
2240
|
+
// this is an array and there may be more
|
|
2241
|
+
const contentStream = o.contentStreams[0];
|
|
2242
|
+
// also add contentstream related fields to the result fields
|
|
2243
|
+
fields.set(ContentStreamField.LENGTH, contentStream.length);
|
|
2244
|
+
fields.set(ContentStreamField.MIME_TYPE, contentStream.mimeType);
|
|
2245
|
+
fields.set(ContentStreamField.FILENAME, contentStream.fileName);
|
|
2246
|
+
fields.set(ContentStreamField.ID, contentStream.contentStreamId);
|
|
2247
|
+
fields.set(ContentStreamField.RANGE, contentStream.contentStreamRange);
|
|
2248
|
+
fields.set(ContentStreamField.REPOSITORY_ID, contentStream.repositoryId);
|
|
2249
|
+
fields.set(ContentStreamField.DIGEST, contentStream.digest);
|
|
2250
|
+
fields.set(ContentStreamField.ARCHIVE_PATH, contentStream.archivePath);
|
|
2251
|
+
content = {
|
|
2252
|
+
contentStreamId: contentStream.contentStreamId,
|
|
2253
|
+
repositoryId: contentStream.repositoryId,
|
|
2254
|
+
range: contentStream.range,
|
|
2255
|
+
digest: contentStream.digest,
|
|
2256
|
+
archivePath: contentStream.archivePath,
|
|
2257
|
+
fileName: contentStream.fileName,
|
|
2258
|
+
mimeType: contentStream.mimeType,
|
|
2259
|
+
size: contentStream.length
|
|
2260
|
+
};
|
|
2261
|
+
}
|
|
2262
|
+
const objectTypeId = o.properties[BaseObjectTypeField.OBJECT_TYPE_ID] ? o.properties[BaseObjectTypeField.OBJECT_TYPE_ID].value : null;
|
|
2263
|
+
if (objectTypes.indexOf(objectTypeId) === -1) {
|
|
2264
|
+
objectTypes.push(objectTypeId);
|
|
2265
|
+
}
|
|
2266
|
+
resultListItems.push({
|
|
2267
|
+
objectTypeId,
|
|
2268
|
+
content,
|
|
2269
|
+
fields,
|
|
2270
|
+
permissions: o.permissions
|
|
2271
|
+
});
|
|
2272
|
+
});
|
|
2273
|
+
const totalPages = Math.ceil(searchResponse.totalNumItems / pageSize);
|
|
2274
|
+
const page = (!skipCount ? 0 : skipCount / pageSize) + 1;
|
|
2275
|
+
const result = {
|
|
2276
|
+
hasMoreItems: searchResponse.hasMoreItems,
|
|
2277
|
+
totalNumItems: searchResponse.totalNumItems,
|
|
2278
|
+
items: resultListItems,
|
|
2279
|
+
objectTypes: objectTypes,
|
|
2280
|
+
paging: totalPages > 1 ? { page, totalPages } : undefined
|
|
2281
|
+
};
|
|
2282
|
+
return result;
|
|
2591
2283
|
}
|
|
2592
2284
|
/**
|
|
2593
|
-
*
|
|
2594
|
-
*
|
|
2285
|
+
* Maps data extracted from a search form to search filters. Every key of the form data object
|
|
2286
|
+
* will be mapped to a search filter.
|
|
2287
|
+
* @param formData form data
|
|
2288
|
+
* @returns Array of search filters
|
|
2595
2289
|
*/
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2290
|
+
formDataToSearchFilter(formData) {
|
|
2291
|
+
const isRangeValue = (v) => {
|
|
2292
|
+
return typeof v === 'object' && v !== null && 'firstValue' in v && 'operator' in v;
|
|
2293
|
+
};
|
|
2294
|
+
const filters = [];
|
|
2295
|
+
Object.keys(formData).forEach((key) => {
|
|
2296
|
+
const value = formData[key];
|
|
2297
|
+
if (isRangeValue(value)) {
|
|
2298
|
+
const f = this.rangeValueToSearchFilter(value, key);
|
|
2299
|
+
if (f)
|
|
2300
|
+
filters.push(f);
|
|
2301
|
+
}
|
|
2302
|
+
else {
|
|
2303
|
+
filters.push({
|
|
2304
|
+
f: key,
|
|
2305
|
+
o: Array.isArray(value) ? Operator.IN : Operator.EQUAL,
|
|
2306
|
+
v1: value
|
|
2307
|
+
});
|
|
2308
|
+
}
|
|
2605
2309
|
});
|
|
2310
|
+
return filters;
|
|
2606
2311
|
}
|
|
2607
|
-
|
|
2608
|
-
return
|
|
2609
|
-
?
|
|
2610
|
-
|
|
2611
|
-
|
|
2312
|
+
rangeValueToSearchFilter(value, property) {
|
|
2313
|
+
return this.#system.getObjectTypeField(property)?.propertyType === 'datetime'
|
|
2314
|
+
? this.#dateRangeValueToSearchFilter(value, property)
|
|
2315
|
+
: {
|
|
2316
|
+
f: property,
|
|
2317
|
+
o: value.operator,
|
|
2318
|
+
v1: value.firstValue,
|
|
2319
|
+
v2: value.secondValue
|
|
2320
|
+
};
|
|
2321
|
+
}
|
|
2322
|
+
#dateRangeValueToSearchFilter(rv, property) {
|
|
2323
|
+
const v1 = rv.firstValue;
|
|
2324
|
+
const v2 = rv.secondValue;
|
|
2325
|
+
switch (rv.operator) {
|
|
2326
|
+
case Operator.EQUAL: {
|
|
2327
|
+
return {
|
|
2328
|
+
f: property,
|
|
2329
|
+
o: Operator.INTERVAL_INCLUDE_BOTH,
|
|
2330
|
+
v1: this.#dateToISOString(v1, 'start'),
|
|
2331
|
+
v2: this.#dateToISOString(v1, 'end')
|
|
2332
|
+
};
|
|
2612
2333
|
}
|
|
2613
|
-
:
|
|
2334
|
+
case Operator.GREATER_OR_EQUAL: {
|
|
2335
|
+
return {
|
|
2336
|
+
f: property,
|
|
2337
|
+
o: rv.operator,
|
|
2338
|
+
v1: this.#dateToISOString(v1)
|
|
2339
|
+
};
|
|
2340
|
+
}
|
|
2341
|
+
case Operator.LESS_OR_EQUAL: {
|
|
2342
|
+
return {
|
|
2343
|
+
f: property,
|
|
2344
|
+
o: rv.operator,
|
|
2345
|
+
v1: this.#dateToISOString(v1, 'end')
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2348
|
+
case Operator.INTERVAL_INCLUDE_BOTH: {
|
|
2349
|
+
return {
|
|
2350
|
+
f: property,
|
|
2351
|
+
o: rv.operator,
|
|
2352
|
+
v1: this.#dateToISOString(v1, 'start'),
|
|
2353
|
+
v2: v2 ? this.#dateToISOString(v2, 'end') : ''
|
|
2354
|
+
};
|
|
2355
|
+
}
|
|
2356
|
+
default:
|
|
2357
|
+
return undefined;
|
|
2358
|
+
}
|
|
2614
2359
|
}
|
|
2615
|
-
|
|
2616
|
-
|
|
2360
|
+
/**
|
|
2361
|
+
* Checks if value is a date and retrieves an ISOString representation. Optionally you can determine, if it should be the beginning or the end of a day.
|
|
2362
|
+
*
|
|
2363
|
+
* @param value
|
|
2364
|
+
* @param range
|
|
2365
|
+
* @private
|
|
2366
|
+
*/
|
|
2367
|
+
#dateToISOString(value, range = 'start') {
|
|
2368
|
+
const date = typeof value === 'string' ? new Date(value) : value;
|
|
2369
|
+
const offset = Utils.DEFAULT_TIME_OFFSET_V2; // T+23:59:59:999
|
|
2370
|
+
if (!Utils.isValidDate(date))
|
|
2371
|
+
return '';
|
|
2372
|
+
const isoDateString = date.toISOString();
|
|
2373
|
+
// const isoDateStringWithOffset = new Date(date.getTime() + offset).toISOString();
|
|
2374
|
+
switch (range) {
|
|
2375
|
+
case 'start':
|
|
2376
|
+
return isoDateString;
|
|
2377
|
+
case 'end':
|
|
2378
|
+
return isoDateString;
|
|
2379
|
+
default:
|
|
2380
|
+
return isoDateString;
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2384
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchService, providedIn: 'root' }); }
|
|
2617
2385
|
}
|
|
2618
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
2386
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchService, decorators: [{
|
|
2619
2387
|
type: Injectable,
|
|
2620
2388
|
args: [{
|
|
2621
2389
|
providedIn: 'root'
|
|
2622
2390
|
}]
|
|
2623
2391
|
}] });
|
|
2624
2392
|
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2393
|
+
var Direction;
|
|
2394
|
+
(function (Direction) {
|
|
2395
|
+
Direction["LTR"] = "ltr";
|
|
2396
|
+
Direction["RTL"] = "rtl";
|
|
2397
|
+
})(Direction || (Direction = {}));
|
|
2398
|
+
|
|
2399
|
+
const CUSTOM_EVENTS = new InjectionToken('CUSTOM_EVENTS', { factory: () => [] });
|
|
2400
|
+
const CUSTOM_EVENTS_TRUSTED_ORIGINS = new InjectionToken('CUSTOM_EVENTS_TRUSTED_ORIGINS', { factory: () => [] });
|
|
2631
2401
|
|
|
2632
2402
|
/**
|
|
2633
|
-
*
|
|
2403
|
+
* Mandatory Custom event prefix for all custom YUV events
|
|
2634
2404
|
*/
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
#
|
|
2642
|
-
#
|
|
2643
|
-
#
|
|
2644
|
-
#
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
this
|
|
2652
|
-
// user may have been fetched already in bootstrapping process
|
|
2653
|
-
this.#userToken = inject(YUV_USER);
|
|
2654
|
-
this.#eventService = inject(EventService);
|
|
2655
|
-
this.#userService = inject(UserService);
|
|
2656
|
-
this.#objectConfigService = inject(ObjectConfigService);
|
|
2657
|
-
this.#appCache = inject(AppCacheService);
|
|
2658
|
-
this.#systemService = inject(SystemService);
|
|
2659
|
-
this.#localizationService = inject(LocalizationService);
|
|
2660
|
-
this.#backend = inject(BackendService);
|
|
2661
|
-
this.#INITIAL_REQUEST_STORAGE_KEY = 'yuv.core.auth.initialrequest';
|
|
2662
|
-
this.#USER_FETCH_URI = '/idm/whoami';
|
|
2663
|
-
this.#authenticated = false;
|
|
2664
|
-
this.#authSource = new BehaviorSubject(false);
|
|
2665
|
-
this.authenticated$ = this.#authSource.asObservable();
|
|
2666
|
-
}
|
|
2667
|
-
isLoggedIn() {
|
|
2668
|
-
return this.#authenticated;
|
|
2669
|
-
}
|
|
2670
|
-
/**
|
|
2671
|
-
* Called while app/core is initialized (APP_INITIALIZER)
|
|
2672
|
-
* @ignore
|
|
2673
|
-
*/
|
|
2674
|
-
initUser() {
|
|
2675
|
-
return this.fetchUser();
|
|
2676
|
-
}
|
|
2677
|
-
/**
|
|
2678
|
-
* Get the current tenant or the previous one persisted locally
|
|
2679
|
-
*/
|
|
2680
|
-
getTenant() {
|
|
2681
|
-
return this.#authData?.tenant;
|
|
2405
|
+
const CUSTOM_YUV_EVENT_PREFIX = 'yuv.';
|
|
2406
|
+
|
|
2407
|
+
/**
|
|
2408
|
+
* Service for providing triggered events
|
|
2409
|
+
*/
|
|
2410
|
+
class EventService {
|
|
2411
|
+
#customEvents;
|
|
2412
|
+
#customEventsTrustedOrigins;
|
|
2413
|
+
#ngZone;
|
|
2414
|
+
#eventSource;
|
|
2415
|
+
constructor() {
|
|
2416
|
+
this.#customEvents = inject(CUSTOM_EVENTS);
|
|
2417
|
+
this.#customEventsTrustedOrigins = inject(CUSTOM_EVENTS_TRUSTED_ORIGINS);
|
|
2418
|
+
this.#ngZone = inject(NgZone);
|
|
2419
|
+
this.#eventSource = new Subject();
|
|
2420
|
+
this.event$ = this.#eventSource.asObservable();
|
|
2421
|
+
this.#listenToWindowEvents();
|
|
2682
2422
|
}
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
*/
|
|
2686
|
-
fetchUser() {
|
|
2687
|
-
return (this.#userToken ? of(this.#userToken) : this.#backend.get(this.#USER_FETCH_URI)).pipe(tap(() => {
|
|
2688
|
-
this.#authenticated = true;
|
|
2689
|
-
this.#authSource.next(this.#authenticated);
|
|
2690
|
-
}), switchMap((userJson) => this.#initApp(userJson)));
|
|
2423
|
+
#startsWithAllowed(value) {
|
|
2424
|
+
return typeof value === 'string' && this.#customEvents.some((prefix) => value.startsWith(prefix));
|
|
2691
2425
|
}
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
this.#
|
|
2697
|
-
|
|
2698
|
-
|
|
2426
|
+
#isValidExternalMessage(event) {
|
|
2427
|
+
this.#customEvents.push(CUSTOM_YUV_EVENT_PREFIX);
|
|
2428
|
+
if (!event.data || typeof event.data !== 'object')
|
|
2429
|
+
return false;
|
|
2430
|
+
if (!(this.#startsWithAllowed(event.data.source) || this.#startsWithAllowed(event.data.type)))
|
|
2431
|
+
return false;
|
|
2432
|
+
// Accept messages from trusted origins
|
|
2433
|
+
this.#customEventsTrustedOrigins.push(window.location.origin);
|
|
2434
|
+
const isFromTrustedOrigin = this.#customEventsTrustedOrigins.includes(event.origin);
|
|
2435
|
+
const hasValidStructure = event.data && (event.data.type || event.data.eventType) && typeof event.data === 'object';
|
|
2436
|
+
return isFromTrustedOrigin && hasValidStructure;
|
|
2699
2437
|
}
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
*/
|
|
2705
|
-
setInitialRequestUri() {
|
|
2706
|
-
const ignore = ['/', '/index.html'];
|
|
2707
|
-
const baseHref = Utils.getBaseHref();
|
|
2708
|
-
// Check only the pathname against the ignore list so that auth callback
|
|
2709
|
-
// query params (e.g. ?session_state=…) don't bypass the check.
|
|
2710
|
-
let path = location.pathname.replace(baseHref, '');
|
|
2711
|
-
path = !path.startsWith('/') ? `/${path}` : path;
|
|
2712
|
-
if (!ignore.includes(path)) {
|
|
2713
|
-
let uri = `${location.pathname}${location.search}`.replace(baseHref, '');
|
|
2714
|
-
uri = !uri.startsWith('/') ? `/${uri}` : uri;
|
|
2715
|
-
return this.#appCache.setItem(this.#INITIAL_REQUEST_STORAGE_KEY, {
|
|
2716
|
-
uri: uri,
|
|
2717
|
-
timestamp: Date.now()
|
|
2718
|
-
});
|
|
2719
|
-
}
|
|
2720
|
-
return of(false);
|
|
2438
|
+
#listenToWindowEvents() {
|
|
2439
|
+
window.addEventListener('message', (event) => {
|
|
2440
|
+
this.#ngZone.run(() => this.#isValidExternalMessage(event) && this.trigger(event.data.type, event.data.data));
|
|
2441
|
+
});
|
|
2721
2442
|
}
|
|
2722
2443
|
/**
|
|
2723
|
-
*
|
|
2724
|
-
*
|
|
2444
|
+
* Triggers a postMessage event that will be sent to the yuuvis global event Trigger
|
|
2445
|
+
* @param type Type/key of the event
|
|
2446
|
+
* @param data Data to be sent along with the event
|
|
2725
2447
|
*/
|
|
2726
|
-
|
|
2727
|
-
|
|
2448
|
+
triggerPostMessageEvent(type, data) {
|
|
2449
|
+
const targetOrigin = window.location.origin;
|
|
2450
|
+
const payload = {
|
|
2451
|
+
type,
|
|
2452
|
+
data,
|
|
2453
|
+
timestamp: Date.now()
|
|
2454
|
+
};
|
|
2455
|
+
window.postMessage(payload, targetOrigin);
|
|
2728
2456
|
}
|
|
2729
|
-
|
|
2730
|
-
|
|
2457
|
+
/**
|
|
2458
|
+
* Trigger an global event
|
|
2459
|
+
* @param type Type/key of the event
|
|
2460
|
+
* @param data Data to be send along with the event
|
|
2461
|
+
*/
|
|
2462
|
+
trigger(type, ...args) {
|
|
2463
|
+
this.#eventSource.next({ type: type, data: args[0] });
|
|
2731
2464
|
}
|
|
2732
2465
|
/**
|
|
2733
|
-
*
|
|
2734
|
-
*
|
|
2735
|
-
* @param userJson Data retrieved from the backend
|
|
2466
|
+
* Listen on a triggered event
|
|
2467
|
+
* @param types Type/key of the event
|
|
2736
2468
|
*/
|
|
2737
|
-
|
|
2738
|
-
return this
|
|
2739
|
-
const currentUser = new YuvUser(userJson, userSettings);
|
|
2740
|
-
this.#userService.setCurrentUser(currentUser);
|
|
2741
|
-
this.#authData = {
|
|
2742
|
-
tenant: currentUser.tenant,
|
|
2743
|
-
language: currentUser.getClientLocale()
|
|
2744
|
-
};
|
|
2745
|
-
return forkJoin([
|
|
2746
|
-
this.#localizationService.fetchLocalizations(),
|
|
2747
|
-
this.#systemService.getSystemDefinition(this.#authData)
|
|
2748
|
-
]).pipe(switchMap(() => this.#objectConfigService.init()), map(() => currentUser));
|
|
2749
|
-
}));
|
|
2469
|
+
on(...types) {
|
|
2470
|
+
return this.event$.pipe(filter((event) => event && !!types.find((t) => t === event.type)));
|
|
2750
2471
|
}
|
|
2751
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
2752
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
2472
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2473
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EventService, providedIn: 'root' }); }
|
|
2753
2474
|
}
|
|
2754
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
2475
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EventService, decorators: [{
|
|
2755
2476
|
type: Injectable,
|
|
2756
2477
|
args: [{
|
|
2757
2478
|
providedIn: 'root'
|
|
2758
2479
|
}]
|
|
2759
|
-
}], ctorParameters: () => [
|
|
2760
|
-
type: Inject,
|
|
2761
|
-
args: [CORE_CONFIG]
|
|
2762
|
-
}] }] });
|
|
2480
|
+
}], ctorParameters: () => [] });
|
|
2763
2481
|
|
|
2764
2482
|
/**
|
|
2765
|
-
*
|
|
2483
|
+
* Events emitted by parts of the application
|
|
2766
2484
|
*/
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
userService.logout();
|
|
2781
|
-
}
|
|
2782
|
-
}
|
|
2783
|
-
}
|
|
2784
|
-
}));
|
|
2785
|
-
}
|
|
2786
|
-
|
|
2787
|
-
var LoginStateName;
|
|
2788
|
-
(function (LoginStateName) {
|
|
2789
|
-
LoginStateName["STATE_LOGIN_URI"] = "login.uri";
|
|
2790
|
-
LoginStateName["STATE_DONE"] = "login.done";
|
|
2791
|
-
LoginStateName["STATE_CANCELED"] = "login.canceled";
|
|
2792
|
-
})(LoginStateName || (LoginStateName = {}));
|
|
2485
|
+
var YuvEventType;
|
|
2486
|
+
(function (YuvEventType) {
|
|
2487
|
+
YuvEventType["LOGOUT"] = "yuv.user.logout";
|
|
2488
|
+
YuvEventType["CLIENT_LOCALE_CHANGED"] = "yuv.user.locale.client.changed";
|
|
2489
|
+
YuvEventType["DMS_OBJECT_LOADED"] = "yuv.dms.object.loaded";
|
|
2490
|
+
YuvEventType["DMS_OBJECT_CREATED"] = "yuv.dms.object.created";
|
|
2491
|
+
YuvEventType["DMS_OBJECT_DELETED"] = "yuv.dms.object.deleted";
|
|
2492
|
+
YuvEventType["DMS_OBJECT_UPDATED"] = "yuv.dms.object.updated";
|
|
2493
|
+
YuvEventType["DMS_OBJECT_CONTENT_UPDATED"] = "yuv.dms.object.content.updated";
|
|
2494
|
+
YuvEventType["DMS_OBJECTS_MOVED"] = "yuv.dms.objects.moved";
|
|
2495
|
+
YuvEventType["RELATIONSHIP_CREATED"] = "yuv.dms.relationship.created";
|
|
2496
|
+
YuvEventType["RELATIONSHIP_DELETED"] = "yuv.dms.relationship.deleted";
|
|
2497
|
+
})(YuvEventType || (YuvEventType = {}));
|
|
2793
2498
|
|
|
2794
2499
|
/**
|
|
2795
|
-
* Service
|
|
2796
|
-
* It listens to the browser's online and offline events and provides an observable
|
|
2797
|
-
* to track the current connection state.
|
|
2798
|
-
*
|
|
2799
|
-
* An observable `connection$` is provided which emits the current connection state
|
|
2800
|
-
* whenever the online or offline state changes. The initial state is determined by
|
|
2801
|
-
* the `window.navigator.onLine` property.
|
|
2500
|
+
* Service providing user account configurations.
|
|
2802
2501
|
*/
|
|
2803
|
-
class
|
|
2502
|
+
class UserService {
|
|
2503
|
+
constructor() {
|
|
2504
|
+
this.#backend = inject(BackendService);
|
|
2505
|
+
this.#translate = inject(TranslateService);
|
|
2506
|
+
this.#logger = inject(Logger);
|
|
2507
|
+
this.#system = inject(SystemService);
|
|
2508
|
+
this.#localization = inject(LocalizationService);
|
|
2509
|
+
this.#eventService = inject(EventService);
|
|
2510
|
+
this.#config = inject(ConfigService);
|
|
2511
|
+
this.#document = inject(DOCUMENT);
|
|
2512
|
+
this.#USERS_SETTINGS = '/users/settings/';
|
|
2513
|
+
this.#DEFAULT_SETTINGS = '/users/settings';
|
|
2514
|
+
this.#SETTINGS_SECTION_OBJECTCONFIG = 'object-config';
|
|
2515
|
+
this.#userSource = new BehaviorSubject(this.#user);
|
|
2516
|
+
this.user$ = this.#userSource.asObservable();
|
|
2517
|
+
this.globalSettings = new Map();
|
|
2518
|
+
this.canCreateObjects = false;
|
|
2519
|
+
}
|
|
2520
|
+
#backend;
|
|
2521
|
+
#translate;
|
|
2522
|
+
#logger;
|
|
2523
|
+
#system;
|
|
2524
|
+
#localization;
|
|
2525
|
+
#eventService;
|
|
2526
|
+
#config;
|
|
2527
|
+
#document;
|
|
2528
|
+
#USERS_SETTINGS;
|
|
2529
|
+
#DEFAULT_SETTINGS;
|
|
2530
|
+
#SETTINGS_SECTION_OBJECTCONFIG;
|
|
2531
|
+
#user;
|
|
2532
|
+
#userSource;
|
|
2804
2533
|
/**
|
|
2805
|
-
*
|
|
2534
|
+
* Set a new current user
|
|
2535
|
+
* @param user The user to be set as current user
|
|
2806
2536
|
*/
|
|
2807
|
-
|
|
2808
|
-
this
|
|
2809
|
-
|
|
2537
|
+
setCurrentUser(user) {
|
|
2538
|
+
this.#user = user;
|
|
2539
|
+
this.changeClientLocale('', false);
|
|
2540
|
+
this.#userSource.next(this.#user);
|
|
2541
|
+
}
|
|
2542
|
+
getCurrentUser() {
|
|
2543
|
+
return this.#user;
|
|
2544
|
+
}
|
|
2545
|
+
get hasAdminRole() {
|
|
2546
|
+
return this.#user?.authorities?.includes(AdministrationRoles.ADMIN) || false;
|
|
2547
|
+
}
|
|
2548
|
+
get hasSystemRole() {
|
|
2549
|
+
return this.#user?.authorities?.includes(AdministrationRoles.SYSTEM) || false;
|
|
2550
|
+
}
|
|
2551
|
+
get hasAdministrationRoles() {
|
|
2552
|
+
return this.hasAdminRole || this.hasSystemRole;
|
|
2553
|
+
}
|
|
2554
|
+
get hasManageSettingsRole() {
|
|
2555
|
+
const customRole = this.#config.get('core.permissions.manageSettingsRole');
|
|
2556
|
+
const manageSettingsRole = customRole || AdministrationRoles.MANAGE_SETTINGS;
|
|
2557
|
+
return this.#user?.authorities?.includes(manageSettingsRole) || false;
|
|
2558
|
+
}
|
|
2559
|
+
get isAdvancedUser() {
|
|
2560
|
+
const customRole = this.#config.get('core.permissions.advancedUserRole');
|
|
2561
|
+
const advancedUserRole = customRole || AdministrationRoles.MANAGE_SETTINGS;
|
|
2562
|
+
return this.#user?.authorities?.includes(advancedUserRole) || false;
|
|
2563
|
+
}
|
|
2564
|
+
get isRetentionManager() {
|
|
2565
|
+
const customRole = this.#config.get('core.permissions.retentionManagerRole');
|
|
2566
|
+
const retenetionManagerRole = customRole || AdministrationRoles.MANAGE_SETTINGS;
|
|
2567
|
+
return this.#user?.authorities?.includes(retenetionManagerRole) || false;
|
|
2568
|
+
}
|
|
2569
|
+
/**
|
|
2570
|
+
* Change the users client locale
|
|
2571
|
+
* @param iso ISO locale string to be set as new client locale
|
|
2572
|
+
*/
|
|
2573
|
+
changeClientLocale(iso, persist = true) {
|
|
2574
|
+
if (this.#user) {
|
|
2575
|
+
const languages = this.#config.getClientLocales().map((lang) => lang.iso);
|
|
2576
|
+
iso = iso || this.#user.getClientLocale(this.#config.getDefaultClientLocale());
|
|
2577
|
+
if (!languages.includes(iso)) {
|
|
2578
|
+
iso = this.#config.getDefaultClientLocale();
|
|
2579
|
+
}
|
|
2580
|
+
this.#logger.debug("Changed client locale to '" + iso + "'");
|
|
2581
|
+
this.#backend.setHeader('Accept-Language', iso);
|
|
2582
|
+
this.#user.uiDirection = this.#getUiDirection(iso);
|
|
2583
|
+
this.#document.body.dir = this.#user.uiDirection;
|
|
2584
|
+
this.#document.documentElement.lang = iso;
|
|
2585
|
+
this.#user.userSettings.locale = iso;
|
|
2586
|
+
if (this.#translate.getCurrentLang() !== iso || this.#system.authData?.language !== iso) {
|
|
2587
|
+
const obs = persist
|
|
2588
|
+
? forkJoin([
|
|
2589
|
+
this.#translate.use(iso),
|
|
2590
|
+
this.#system
|
|
2591
|
+
.updateAuthData({ language: iso })
|
|
2592
|
+
.pipe(switchMap(() => this.#localization.fetchLocalizations())),
|
|
2593
|
+
this.saveUserSettings(this.#user.userSettings).pipe(tap(() => {
|
|
2594
|
+
this.#logger.debug('Loading system definitions i18n resources for new locale.');
|
|
2595
|
+
}))
|
|
2596
|
+
])
|
|
2597
|
+
: this.#translate.use(iso);
|
|
2598
|
+
obs.subscribe(() => this.#eventService.trigger(YuvEventType.CLIENT_LOCALE_CHANGED, iso));
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
saveUserSettings(settings) {
|
|
2603
|
+
if (this.#user) {
|
|
2604
|
+
//console.log(this.#user.userSettings);
|
|
2605
|
+
this.#user.userSettings = { ...this.#user.userSettings, ...settings };
|
|
2606
|
+
return this.#backend
|
|
2607
|
+
.post(this.#DEFAULT_SETTINGS, this.#user.userSettings)
|
|
2608
|
+
.pipe(tap(() => this.#userSource.next(this.#user)));
|
|
2609
|
+
}
|
|
2610
|
+
else
|
|
2611
|
+
return of(null);
|
|
2612
|
+
}
|
|
2613
|
+
fetchUserSettings() {
|
|
2614
|
+
return this.#backend.get('/dms/permissions').pipe(catchError(() => of(undefined)), switchMap((res) => {
|
|
2615
|
+
this.#setUserPermissions(res);
|
|
2616
|
+
return this.#backend.get(this.#DEFAULT_SETTINGS);
|
|
2617
|
+
}));
|
|
2618
|
+
}
|
|
2619
|
+
/**
|
|
2620
|
+
* Search for a user based on a search term
|
|
2621
|
+
* @param term Search term
|
|
2622
|
+
* @param excludeMe whether or not to exclude myself from the result list
|
|
2623
|
+
* @param roles narrow down the search results by certain roles
|
|
2624
|
+
*/
|
|
2625
|
+
queryUser(term, excludeMe, roles) {
|
|
2626
|
+
let params = new HttpParams().set('search', term).set('excludeMe', `${!!excludeMe}`);
|
|
2627
|
+
roles?.length && roles.map((r) => (params = params.append(`roles`, r)));
|
|
2628
|
+
return this.#backend
|
|
2629
|
+
.get(`/idm/users?${params}`)
|
|
2630
|
+
.pipe(map((users) => (!users ? [] : users.map((u) => new YuvUser(u)))));
|
|
2631
|
+
}
|
|
2632
|
+
getUserById(id) {
|
|
2633
|
+
return this.#backend.get(`/idm/users/${id}`).pipe(map((user) => new YuvUser(user, this.#user.userSettings)));
|
|
2634
|
+
}
|
|
2635
|
+
logout(redirRoute) {
|
|
2636
|
+
const redir = redirRoute ? `?redir=${redirRoute}` : '';
|
|
2637
|
+
window.location.href = `${this.#backend.getApiBase('logout')}${redir}`;
|
|
2638
|
+
}
|
|
2639
|
+
getSettings(section) {
|
|
2640
|
+
return this.#user ? this.#backend.get(this.#USERS_SETTINGS + encodeURIComponent(section)) : of(null);
|
|
2641
|
+
}
|
|
2642
|
+
saveObjectConfig(objectConfigs) {
|
|
2643
|
+
return this.#backend.post(this.#USERS_SETTINGS + encodeURIComponent(this.#SETTINGS_SECTION_OBJECTCONFIG), objectConfigs);
|
|
2644
|
+
}
|
|
2645
|
+
loadObjectConfig() {
|
|
2646
|
+
return this.getSettings(this.#SETTINGS_SECTION_OBJECTCONFIG).pipe(catchError(() => of(undefined)));
|
|
2647
|
+
}
|
|
2648
|
+
#getUiDirection(iso) {
|
|
2649
|
+
// languages that are read right to left
|
|
2650
|
+
const rtlLanguages = ['ar', 'arc', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ku', 'ps', 'ur', 'yi'];
|
|
2651
|
+
return !rtlLanguages.includes(iso) ? Direction.LTR : Direction.RTL;
|
|
2652
|
+
}
|
|
2653
|
+
#setUserPermissions(res) {
|
|
2654
|
+
this.userPermissions = {
|
|
2655
|
+
create: this.#mapPermissions('CREATE', res),
|
|
2656
|
+
write: this.#mapPermissions('WRITE', res),
|
|
2657
|
+
read: this.#mapPermissions('READ', res),
|
|
2658
|
+
delete: this.#mapPermissions('DELETE', res)
|
|
2810
2659
|
};
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2660
|
+
const permissions = {
|
|
2661
|
+
createableObjectTypes: [
|
|
2662
|
+
...this.userPermissions.create.folderTypes,
|
|
2663
|
+
...this.userPermissions.create.objectTypes,
|
|
2664
|
+
...this.userPermissions.create.secondaryObjectTypes
|
|
2665
|
+
],
|
|
2666
|
+
searchableObjectTypes: [
|
|
2667
|
+
...this.userPermissions.read.folderTypes,
|
|
2668
|
+
...this.userPermissions.read.objectTypes,
|
|
2669
|
+
...this.userPermissions.read.secondaryObjectTypes
|
|
2670
|
+
]
|
|
2671
|
+
};
|
|
2672
|
+
this.#system.setPermissions(permissions);
|
|
2673
|
+
this.canCreateObjects = permissions.createableObjectTypes.length > 0;
|
|
2822
2674
|
}
|
|
2823
|
-
|
|
2824
|
-
|
|
2675
|
+
#mapPermissions(section, apiResponse) {
|
|
2676
|
+
const res = apiResponse[section] || {};
|
|
2677
|
+
return {
|
|
2678
|
+
folderTypes: res['folderTypeIds'] || [],
|
|
2679
|
+
objectTypes: res['objectTypeIds'] || [],
|
|
2680
|
+
secondaryObjectTypes: res['secondaryObjectTypeIds'] || []
|
|
2681
|
+
};
|
|
2682
|
+
}
|
|
2683
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2684
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserService, providedIn: 'root' }); }
|
|
2825
2685
|
}
|
|
2826
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
2686
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserService, decorators: [{
|
|
2827
2687
|
type: Injectable,
|
|
2828
2688
|
args: [{
|
|
2829
2689
|
providedIn: 'root'
|
|
2830
2690
|
}]
|
|
2831
|
-
}], ctorParameters: () => [] });
|
|
2832
|
-
|
|
2833
|
-
/**
|
|
2834
|
-
* Http Offline interceptor trys to serving offline content for method/url
|
|
2835
|
-
*/
|
|
2836
|
-
function OfflineInterceptorFnc(req, next) {
|
|
2837
|
-
return next(req);
|
|
2838
|
-
}
|
|
2839
|
-
|
|
2840
|
-
/**
|
|
2841
|
-
* Providing functions,that are are injected at application startup and executed during app initialization.
|
|
2842
|
-
*/
|
|
2843
|
-
const init_moduleFnc = () => {
|
|
2844
|
-
const coreConfig = inject(CORE_CONFIG);
|
|
2845
|
-
const logger = inject(Logger);
|
|
2846
|
-
const http = inject(HttpClient);
|
|
2847
|
-
const configService = inject(ConfigService);
|
|
2848
|
-
const authService = inject(AuthService);
|
|
2849
|
-
return authService.setInitialRequestUri().pipe(switchMap(() => coreConfig.main
|
|
2850
|
-
? !Array.isArray(coreConfig.main)
|
|
2851
|
-
? of([coreConfig.main])
|
|
2852
|
-
: forkJoin([...coreConfig.main].map((uri) => http.get(`${Utils.getBaseHref()}${uri}`).pipe(catchError((e) => {
|
|
2853
|
-
logger.error('failed to catch config file', e);
|
|
2854
|
-
return of({});
|
|
2855
|
-
}), map((res) => res)))).pipe(
|
|
2856
|
-
// switchMap((configs: YuvConfig[]) => configService.extendConfig(configs)),
|
|
2857
|
-
tap((configs) => configService.extendConfig(configs)), switchMap(() => authService.initUser().pipe(catchError((e) => {
|
|
2858
|
-
authService.initError = {
|
|
2859
|
-
status: e.status,
|
|
2860
|
-
key: e.error.error
|
|
2861
|
-
};
|
|
2862
|
-
return of(true);
|
|
2863
|
-
}))))
|
|
2864
|
-
: of(false)));
|
|
2865
|
-
};
|
|
2866
|
-
|
|
2867
|
-
/**
|
|
2868
|
-
* Handles missing translations
|
|
2869
|
-
* @ignore
|
|
2870
|
-
*/
|
|
2871
|
-
class EoxMissingTranslationHandler {
|
|
2872
|
-
handle(params) {
|
|
2873
|
-
return '!missing key: ' + params.key;
|
|
2874
|
-
}
|
|
2875
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxMissingTranslationHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2876
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxMissingTranslationHandler }); }
|
|
2877
|
-
}
|
|
2878
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxMissingTranslationHandler, decorators: [{
|
|
2879
|
-
type: Injectable
|
|
2880
2691
|
}] });
|
|
2881
2692
|
|
|
2882
2693
|
/**
|
|
2883
|
-
*
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
*
|
|
2887
|
-
*
|
|
2694
|
+
* Service providing access to the systems audit entries. Audits can be seen as the history of
|
|
2695
|
+
* an object. Actions perormed on an object (eg. read, write, delete, ...) will be recorded during
|
|
2696
|
+
* the objects lifecycle. Audits are provided based on a users permissions. Beside the audit entries
|
|
2697
|
+
* visible to regular users there are more technical ones that will only be shown to users that
|
|
2698
|
+
* have administrative role.
|
|
2888
2699
|
*/
|
|
2889
|
-
class
|
|
2890
|
-
constructor(
|
|
2891
|
-
this
|
|
2892
|
-
this
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
* @returns Observable<Object>
|
|
2922
|
-
*/
|
|
2923
|
-
getTranslation(lang) {
|
|
2924
|
-
const t = (this.config.translations || []).map((path) => this.loadTranslationFile(path, lang));
|
|
2925
|
-
return forkJoin(t).pipe(map((res) => res.reduce((acc, x) => Object.assign(acc, x), {})));
|
|
2926
|
-
}
|
|
2927
|
-
loadTranslationFile(path, lang) {
|
|
2928
|
-
const version = document.body.dataset['bt'] ?? document.body.dataset['version'];
|
|
2929
|
-
const cacheBuster = version ? `?v=${version}` : '';
|
|
2930
|
-
return this.http.get(`${Utils.getBaseHref()}${path}${lang}.json${cacheBuster}`).pipe(catchError(() => {
|
|
2931
|
-
// ISO codes with more than 2 characters are sub-languages like de-CH.
|
|
2932
|
-
// If there is no translation file for that sub-language we'll try to load
|
|
2933
|
-
// the file for the base language (in this case de).
|
|
2934
|
-
return lang.length > 2 ? this.loadTranslationFile(path, lang.substring(0, 2)) : of({});
|
|
2935
|
-
}));
|
|
2700
|
+
class AuditService {
|
|
2701
|
+
constructor() {
|
|
2702
|
+
this.#searchService = inject(SearchService);
|
|
2703
|
+
this.#userService = inject(UserService);
|
|
2704
|
+
// default number of items to be fetched
|
|
2705
|
+
this.DEFAULT_RES_SIZE = 20;
|
|
2706
|
+
// audit action codes that should be visible to regular users
|
|
2707
|
+
this.userAuditActions = [
|
|
2708
|
+
100, // metadata created
|
|
2709
|
+
101, // metadata created (with content)
|
|
2710
|
+
110, // tag created
|
|
2711
|
+
201, // content deleted
|
|
2712
|
+
210, // tag deleted
|
|
2713
|
+
300, // metadata updated
|
|
2714
|
+
301, // content updated
|
|
2715
|
+
302, // metadata and content updated
|
|
2716
|
+
303, // content moved
|
|
2717
|
+
310, // tag updated
|
|
2718
|
+
325, // object restored form version
|
|
2719
|
+
340, // object moved
|
|
2720
|
+
10000 // custom audit entries
|
|
2721
|
+
];
|
|
2722
|
+
// audit action codes that should be visible to admin users
|
|
2723
|
+
this.adminAuditActions = [
|
|
2724
|
+
202, // marked for delete
|
|
2725
|
+
220, // version deleted
|
|
2726
|
+
400, // content read
|
|
2727
|
+
401, // metadata read
|
|
2728
|
+
402, // rendition read (text)
|
|
2729
|
+
403, // rendition read (pdf)
|
|
2730
|
+
404 // rendition read (thumbnail)
|
|
2731
|
+
];
|
|
2936
2732
|
}
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
}
|
|
2940
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxTranslateJsonLoader, decorators: [{
|
|
2941
|
-
type: Injectable
|
|
2942
|
-
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: CoreConfig, decorators: [{
|
|
2943
|
-
type: Inject,
|
|
2944
|
-
args: [CORE_CONFIG]
|
|
2945
|
-
}] }] });
|
|
2946
|
-
|
|
2947
|
-
var Operator;
|
|
2948
|
-
(function (Operator) {
|
|
2949
|
-
Operator["EQUAL"] = "eq";
|
|
2950
|
-
Operator["EEQUAL"] = "eeq";
|
|
2951
|
-
Operator["IN"] = "in";
|
|
2952
|
-
Operator["GREATER_THAN"] = "gt";
|
|
2953
|
-
Operator["GREATER_OR_EQUAL"] = "gte";
|
|
2954
|
-
Operator["LESS_THAN"] = "lt";
|
|
2955
|
-
Operator["LESS_OR_EQUAL"] = "lte";
|
|
2956
|
-
Operator["INTERVAL"] = "gtlt";
|
|
2957
|
-
Operator["INTERVAL_INCLUDE_BOTH"] = "gtelte";
|
|
2958
|
-
Operator["INTERVAL_INCLUDE_TO"] = "gtlte";
|
|
2959
|
-
Operator["INTERVAL_INCLUDE_FROM"] = "gtelt";
|
|
2960
|
-
Operator["RANGE"] = "rg";
|
|
2961
|
-
Operator["LIKE"] = "like";
|
|
2962
|
-
Operator["CONTAINS"] = "contains"; // contains
|
|
2963
|
-
})(Operator || (Operator = {}));
|
|
2964
|
-
const OperatorLabel = {
|
|
2965
|
-
/** equal */
|
|
2966
|
-
EQUAL: '=',
|
|
2967
|
-
/** exact equal */
|
|
2968
|
-
EEQUAL: '==',
|
|
2969
|
-
/** match at least one of the provided values (value has to be an array) */
|
|
2970
|
-
IN: '~',
|
|
2971
|
-
/** greater than */
|
|
2972
|
-
GREATER_THAN: '>',
|
|
2973
|
-
/** greater than or equal */
|
|
2974
|
-
GREATER_OR_EQUAL: '≽', //
|
|
2975
|
-
LESS_THAN: '<', // less than
|
|
2976
|
-
LESS_OR_EQUAL: '≼', // less than or equal
|
|
2977
|
-
INTERVAL: '<>', // interval
|
|
2978
|
-
INTERVAL_INCLUDE_BOTH: '-', // interval include left and right
|
|
2979
|
-
INTERVAL_INCLUDE_TO: '>-', // interval include right
|
|
2980
|
-
INTERVAL_INCLUDE_FROM: '-<', // interval include left
|
|
2981
|
-
RANGE: '=', // aggegation ranges
|
|
2982
|
-
LIKE: '~', // like
|
|
2983
|
-
CONTAINS: '~' // contains
|
|
2984
|
-
};
|
|
2985
|
-
|
|
2986
|
-
class SearchService {
|
|
2987
|
-
#backend = inject(BackendService);
|
|
2988
|
-
#system = inject(SystemService);
|
|
2989
|
-
static { this.DEFAULT_QUERY_SIZE = 50; }
|
|
2733
|
+
#searchService;
|
|
2734
|
+
#userService;
|
|
2990
2735
|
/**
|
|
2991
|
-
*
|
|
2992
|
-
* @param
|
|
2993
|
-
* @
|
|
2736
|
+
* Get audit entries of a dms object
|
|
2737
|
+
* @param id The id of the object to get the audit entries for
|
|
2738
|
+
* @param options Options
|
|
2994
2739
|
*/
|
|
2995
|
-
|
|
2996
|
-
|
|
2740
|
+
getAuditEntries(id, options = {}) {
|
|
2741
|
+
const auditActions = this.getAuditActions(!!options.allActions, options?.skipActions);
|
|
2742
|
+
const q = {
|
|
2743
|
+
size: this.DEFAULT_RES_SIZE,
|
|
2744
|
+
types: [SystemType.AUDIT],
|
|
2745
|
+
filters: [
|
|
2746
|
+
{
|
|
2747
|
+
f: AuditField.REFERRED_OBJECT_ID,
|
|
2748
|
+
o: Operator.EQUAL,
|
|
2749
|
+
v1: id
|
|
2750
|
+
},
|
|
2751
|
+
{
|
|
2752
|
+
f: AuditField.ACTION,
|
|
2753
|
+
o: Operator.IN,
|
|
2754
|
+
v1: auditActions
|
|
2755
|
+
}
|
|
2756
|
+
],
|
|
2757
|
+
sort: [
|
|
2758
|
+
{
|
|
2759
|
+
field: AuditField.CREATION_DATE,
|
|
2760
|
+
order: 'desc'
|
|
2761
|
+
}
|
|
2762
|
+
]
|
|
2763
|
+
};
|
|
2764
|
+
return this.#fetchAudits(q);
|
|
2997
2765
|
}
|
|
2998
2766
|
/**
|
|
2999
|
-
*
|
|
3000
|
-
*
|
|
3001
|
-
*
|
|
2767
|
+
* Get an array of action codes that are provided by the service. Based on
|
|
2768
|
+
* whether or not the user has admin permissions you'll get a different
|
|
2769
|
+
* set of actions.
|
|
2770
|
+
* @param skipActions codes of actions that should not be fetched
|
|
3002
2771
|
*/
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
return this.#backend.post(`/dms/objects/search`, query);
|
|
2772
|
+
getAuditActions(allActions, skipActions) {
|
|
2773
|
+
const actions = allActions || this.#userService.isAdvancedUser ? [...this.userAuditActions, ...this.adminAuditActions] : this.userAuditActions;
|
|
2774
|
+
return actions.filter((a) => !skipActions || !skipActions.includes(a));
|
|
3007
2775
|
}
|
|
3008
2776
|
/**
|
|
3009
|
-
*
|
|
3010
|
-
* @param
|
|
3011
|
-
* @param
|
|
3012
|
-
* @returns Observable of a SearchResult
|
|
2777
|
+
* Get a certain page for a former audits query.
|
|
2778
|
+
* @param auditsResult The result object of a former audits query
|
|
2779
|
+
* @param page The page to load
|
|
3013
2780
|
*/
|
|
3014
|
-
|
|
3015
|
-
|
|
2781
|
+
getPage(auditsResult, page) {
|
|
2782
|
+
const q = auditsResult.query;
|
|
2783
|
+
q.from = (page - 1) * (q.size || this.DEFAULT_RES_SIZE);
|
|
2784
|
+
return this.#fetchAudits(q);
|
|
3016
2785
|
}
|
|
3017
|
-
#
|
|
3018
|
-
|
|
3019
|
-
query:
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
2786
|
+
#fetchAudits(q) {
|
|
2787
|
+
return this.#searchService.searchRaw(q).pipe(map((res) => ({
|
|
2788
|
+
query: q,
|
|
2789
|
+
items: res.objects.map((o) => ({
|
|
2790
|
+
action: o.properties[AuditField.ACTION].value,
|
|
2791
|
+
actionGroup: this.#getActionGroup(o.properties[AuditField.ACTION].value),
|
|
2792
|
+
detail: o.properties[AuditField.DETAIL].value,
|
|
2793
|
+
subaction: o.properties[AuditField.SUBACTION] ? o.properties[AuditField.SUBACTION].value : null,
|
|
2794
|
+
version: o.properties[AuditField.VERSION].value,
|
|
2795
|
+
creationDate: o.properties[AuditField.CREATION_DATE].value,
|
|
2796
|
+
createdBy: {
|
|
2797
|
+
id: o.properties[AuditField.CREATED_BY].value,
|
|
2798
|
+
title: o.properties[AuditField.CREATED_BY].title
|
|
2799
|
+
}
|
|
2800
|
+
})),
|
|
2801
|
+
hasMoreItems: res.hasMoreItems,
|
|
2802
|
+
page: !q.from ? 1 : q.from / q.size + 1
|
|
2803
|
+
})));
|
|
2804
|
+
}
|
|
2805
|
+
#getActionGroup(action) {
|
|
2806
|
+
try {
|
|
2807
|
+
return parseInt(`${action}`.substr(0, 1));
|
|
2808
|
+
}
|
|
2809
|
+
catch {
|
|
2810
|
+
return -1;
|
|
3028
2811
|
}
|
|
3029
|
-
return this.#backend
|
|
3030
|
-
.post('/dms/objects/cmisSearch', payload
|
|
3031
|
-
// Using API-WEB because it enriches the response with additional information (resolved user names, etc.)
|
|
3032
|
-
// ApiBase.core
|
|
3033
|
-
)
|
|
3034
|
-
.pipe(map((res) => this.toSearchResult(res, maxItems, skipCount)));
|
|
3035
2812
|
}
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
2813
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuditService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2814
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuditService, providedIn: 'root' }); }
|
|
2815
|
+
}
|
|
2816
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuditService, decorators: [{
|
|
2817
|
+
type: Injectable,
|
|
2818
|
+
args: [{
|
|
2819
|
+
providedIn: 'root'
|
|
2820
|
+
}]
|
|
2821
|
+
}] });
|
|
2822
|
+
|
|
2823
|
+
/**
|
|
2824
|
+
* @ignore
|
|
2825
|
+
*/
|
|
2826
|
+
const CUSTOM_CONFIG = new InjectionToken('CUSTOM_CONFIG', {
|
|
2827
|
+
factory: () => ({ main: ['assets/_yuuvis/config/main.json'], translations: ['assets/_yuuvis/i18n/'] })
|
|
2828
|
+
});
|
|
2829
|
+
const CORE_CONFIG = new InjectionToken('CORE_CONFIG');
|
|
2830
|
+
|
|
2831
|
+
/**
|
|
2832
|
+
* @ignore
|
|
2833
|
+
*/
|
|
2834
|
+
let CoreConfig = class CoreConfig {
|
|
2835
|
+
constructor(__config) {
|
|
2836
|
+
this.main = ['assets/_yuuvis/config/main.json'];
|
|
2837
|
+
this.translations = ['assets/_yuuvis/i18n/'];
|
|
2838
|
+
this.environment = { production: true };
|
|
2839
|
+
Object.assign(this, __config);
|
|
2840
|
+
}
|
|
2841
|
+
};
|
|
2842
|
+
CoreConfig = __decorate([
|
|
2843
|
+
__param(0, Inject(CUSTOM_CONFIG)),
|
|
2844
|
+
__metadata("design:paramtypes", [CoreConfig])
|
|
2845
|
+
], CoreConfig);
|
|
2846
|
+
|
|
2847
|
+
/**
|
|
2848
|
+
* Service managing the configuarions for object types.
|
|
2849
|
+
* Configuration means that you can pick certain fields
|
|
2850
|
+
* of an object type and assign them to a config object.
|
|
2851
|
+
*/
|
|
2852
|
+
class ObjectConfigService {
|
|
2853
|
+
constructor() {
|
|
2854
|
+
this.#system = inject(SystemService);
|
|
2855
|
+
this.#user = inject(UserService);
|
|
2856
|
+
this.OBJECT_CONFIG_STORAGE_KEY = 'yuv.framework.object-config';
|
|
2857
|
+
this.#objectConfigsSource = new ReplaySubject();
|
|
2858
|
+
this.#objectConfigs$ = this.#objectConfigsSource.asObservable();
|
|
2859
|
+
this.#defaultObjectConfigs = {};
|
|
2860
|
+
this.#registeredDefaultObjectConfigs = {
|
|
2861
|
+
main: {},
|
|
2862
|
+
buckets: []
|
|
2863
|
+
};
|
|
2864
|
+
this.#objectConfigs = {
|
|
2865
|
+
main: {},
|
|
2866
|
+
buckets: []
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
#system;
|
|
2870
|
+
#user;
|
|
2871
|
+
#objectConfigsSource;
|
|
2872
|
+
#objectConfigs$;
|
|
2873
|
+
#defaultObjectConfigs;
|
|
2874
|
+
#registeredDefaultObjectConfigs;
|
|
2875
|
+
#objectConfigs;
|
|
2876
|
+
#isValidObjectConfig(soc) {
|
|
2877
|
+
return coerceBooleanProperty(soc && Object.hasOwn(soc, 'main') && Object.hasOwn(soc, 'buckets'));
|
|
2878
|
+
}
|
|
2879
|
+
// called on core init (auth.service -> initApp)
|
|
2880
|
+
init() {
|
|
2881
|
+
return this.#user.loadObjectConfig().pipe(tap$1((res) => {
|
|
2882
|
+
this.#getDefaultObjectConfig();
|
|
2883
|
+
this.#objectConfigs = (this.#isValidObjectConfig(res) && res) || {
|
|
2884
|
+
main: {},
|
|
2885
|
+
buckets: []
|
|
2886
|
+
};
|
|
2887
|
+
this.#objectConfigsSource.next(this.#objectConfigs);
|
|
2888
|
+
}));
|
|
2889
|
+
}
|
|
2890
|
+
getObjectConfigs$(bucket, includeDefaults) {
|
|
2891
|
+
return this.#objectConfigs$.pipe(map$1((soc) => {
|
|
2892
|
+
let ocr = soc.main;
|
|
2893
|
+
const defaults = { ...this.#defaultObjectConfigs, ...this.#getRegisteredDefaults(bucket) };
|
|
2894
|
+
if (bucket) {
|
|
2895
|
+
const tileBucket = soc.buckets.find((b) => b.id === bucket);
|
|
2896
|
+
if (tileBucket) {
|
|
2897
|
+
ocr = tileBucket.configs;
|
|
2898
|
+
if (includeDefaults)
|
|
2899
|
+
Object.keys(ocr).forEach((k) => {
|
|
2900
|
+
ocr[k] = { ...defaults[k], ...ocr[k] };
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
return includeDefaults ? { ...defaults, ...ocr } : { ...ocr };
|
|
2905
|
+
}));
|
|
3045
2906
|
}
|
|
3046
2907
|
/**
|
|
3047
|
-
*
|
|
3048
|
-
*
|
|
3049
|
-
* @param
|
|
2908
|
+
* Register default object configs. Apps can pre-define how their
|
|
2909
|
+
* objects should be rendered.
|
|
2910
|
+
* @param bucket Name of a bucket to bind configs to (usually the ID of the app) to
|
|
2911
|
+
* separate the configs from other apps. If not provided configs will be saved for
|
|
2912
|
+
* the global scope
|
|
3050
2913
|
*/
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
count: o.properties['OBJECT_COUNT'].value
|
|
3060
|
-
}))
|
|
2914
|
+
registerDefaults(configs, bucket) {
|
|
2915
|
+
if (bucket) {
|
|
2916
|
+
// does bucket exist?
|
|
2917
|
+
const tileBucketIdx = this.#registeredDefaultObjectConfigs.buckets.findIndex((b) => b.id === bucket);
|
|
2918
|
+
if (tileBucketIdx !== -1) {
|
|
2919
|
+
this.#registeredDefaultObjectConfigs.buckets[tileBucketIdx].configs = {
|
|
2920
|
+
...this.#registeredDefaultObjectConfigs.buckets[tileBucketIdx].configs,
|
|
2921
|
+
...configs
|
|
3061
2922
|
};
|
|
3062
|
-
|
|
2923
|
+
}
|
|
2924
|
+
else {
|
|
2925
|
+
this.#registeredDefaultObjectConfigs.buckets.push({
|
|
2926
|
+
id: bucket,
|
|
2927
|
+
configs
|
|
2928
|
+
});
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
else {
|
|
2932
|
+
this.#registeredDefaultObjectConfigs.main = { ...this.#registeredDefaultObjectConfigs.main, ...configs };
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
unregisterDefaults(configs, bucket) {
|
|
2936
|
+
if (bucket) {
|
|
2937
|
+
// does bucket exist?
|
|
2938
|
+
const tileBucketIdx = this.#registeredDefaultObjectConfigs.buckets.findIndex((b) => b.id === bucket);
|
|
2939
|
+
if (tileBucketIdx !== -1) {
|
|
2940
|
+
this.#registeredDefaultObjectConfigs.buckets.splice(tileBucketIdx, 1);
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
else {
|
|
2944
|
+
Object.keys(configs).forEach((key) => {
|
|
2945
|
+
delete this.#registeredDefaultObjectConfigs.main[key];
|
|
3063
2946
|
});
|
|
3064
2947
|
}
|
|
3065
|
-
return {
|
|
3066
|
-
totalNumItems: searchResponse.totalNumItems,
|
|
3067
|
-
aggregations: agg
|
|
3068
|
-
};
|
|
3069
2948
|
}
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
*/
|
|
3075
|
-
getPage(query, page, pageSize = SearchService.DEFAULT_QUERY_SIZE, includePermissions = false) {
|
|
3076
|
-
const isCmis = typeof query === 'string';
|
|
3077
|
-
if (isCmis) {
|
|
3078
|
-
return this.#executeCmisSearch(query, pageSize, (page - 1) * pageSize, includePermissions);
|
|
2949
|
+
getRegisteredDefault(objectTypeId, bucket) {
|
|
2950
|
+
if (bucket) {
|
|
2951
|
+
const b = this.#registeredDefaultObjectConfigs.buckets.find((b) => b.id === bucket);
|
|
2952
|
+
return b ? b.configs[objectTypeId] : undefined;
|
|
3079
2953
|
}
|
|
3080
2954
|
else {
|
|
3081
|
-
|
|
3082
|
-
|
|
2955
|
+
return this.#registeredDefaultObjectConfigs.main[objectTypeId];
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
#getRegisteredDefaults(bucket) {
|
|
2959
|
+
if (bucket) {
|
|
2960
|
+
const defaultTileBucket = this.#registeredDefaultObjectConfigs.buckets.find((b) => b.id === bucket);
|
|
2961
|
+
return defaultTileBucket?.configs || {};
|
|
3083
2962
|
}
|
|
2963
|
+
else
|
|
2964
|
+
return this.#registeredDefaultObjectConfigs.main;
|
|
3084
2965
|
}
|
|
3085
2966
|
/**
|
|
3086
|
-
*
|
|
3087
|
-
* @param
|
|
2967
|
+
* Get object config for an object type.
|
|
2968
|
+
* @param objectTypeId ID of the object type to get the config for
|
|
2969
|
+
* @param bucket Optional bucket ID to fetch the config from. Buckets
|
|
2970
|
+
* define separated areas to store/receive those configs. This way
|
|
2971
|
+
* components/apps can store different object configs than the ones
|
|
2972
|
+
* used accross the whole client application.
|
|
3088
2973
|
*/
|
|
3089
|
-
|
|
3090
|
-
const
|
|
3091
|
-
const
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
// table fields will have a clientValue too ...
|
|
3099
|
-
value = o.properties[key].clvalue;
|
|
3100
|
-
// ... and also may contain values that need to be resolved
|
|
3101
|
-
if (o.properties[key].resolvedValues) {
|
|
3102
|
-
value.forEach((v) => {
|
|
3103
|
-
Object.keys(v).forEach((k) => {
|
|
3104
|
-
const resValue = Array.isArray(v[k]) ? v[k].map((i) => o.properties[key].resolvedValues[i]) : o.properties[key].resolvedValues[v[k]];
|
|
3105
|
-
if (resValue) {
|
|
3106
|
-
v[`${k}_title`] = resValue;
|
|
3107
|
-
}
|
|
3108
|
-
});
|
|
3109
|
-
});
|
|
3110
|
-
}
|
|
3111
|
-
}
|
|
3112
|
-
fields.set(key, value);
|
|
3113
|
-
if (o.properties[key].title) {
|
|
3114
|
-
fields.set(key + '_title', o.properties[key].title);
|
|
3115
|
-
}
|
|
3116
|
-
});
|
|
3117
|
-
// process contentStreams section of result if available.
|
|
3118
|
-
// Objects that don't have files attached won't have this section
|
|
3119
|
-
let content;
|
|
3120
|
-
if (o.contentStreams && o.contentStreams.length > 0) {
|
|
3121
|
-
// we assume that each result object only has ONE file attached, altough
|
|
3122
|
-
// this is an array and there may be more
|
|
3123
|
-
const contentStream = o.contentStreams[0];
|
|
3124
|
-
// also add contentstream related fields to the result fields
|
|
3125
|
-
fields.set(ContentStreamField.LENGTH, contentStream.length);
|
|
3126
|
-
fields.set(ContentStreamField.MIME_TYPE, contentStream.mimeType);
|
|
3127
|
-
fields.set(ContentStreamField.FILENAME, contentStream.fileName);
|
|
3128
|
-
fields.set(ContentStreamField.ID, contentStream.contentStreamId);
|
|
3129
|
-
fields.set(ContentStreamField.RANGE, contentStream.contentStreamRange);
|
|
3130
|
-
fields.set(ContentStreamField.REPOSITORY_ID, contentStream.repositoryId);
|
|
3131
|
-
fields.set(ContentStreamField.DIGEST, contentStream.digest);
|
|
3132
|
-
fields.set(ContentStreamField.ARCHIVE_PATH, contentStream.archivePath);
|
|
3133
|
-
content = {
|
|
3134
|
-
contentStreamId: contentStream.contentStreamId,
|
|
3135
|
-
repositoryId: contentStream.repositoryId,
|
|
3136
|
-
range: contentStream.range,
|
|
3137
|
-
digest: contentStream.digest,
|
|
3138
|
-
archivePath: contentStream.archivePath,
|
|
3139
|
-
fileName: contentStream.fileName,
|
|
3140
|
-
mimeType: contentStream.mimeType,
|
|
3141
|
-
size: contentStream.length
|
|
3142
|
-
};
|
|
3143
|
-
}
|
|
3144
|
-
const objectTypeId = o.properties[BaseObjectTypeField.OBJECT_TYPE_ID] ? o.properties[BaseObjectTypeField.OBJECT_TYPE_ID].value : null;
|
|
3145
|
-
if (objectTypes.indexOf(objectTypeId) === -1) {
|
|
3146
|
-
objectTypes.push(objectTypeId);
|
|
3147
|
-
}
|
|
3148
|
-
resultListItems.push({
|
|
3149
|
-
objectTypeId,
|
|
3150
|
-
content,
|
|
3151
|
-
fields,
|
|
3152
|
-
permissions: o.permissions
|
|
3153
|
-
});
|
|
3154
|
-
});
|
|
3155
|
-
const totalPages = Math.ceil(searchResponse.totalNumItems / pageSize);
|
|
3156
|
-
const page = (!skipCount ? 0 : skipCount / pageSize) + 1;
|
|
3157
|
-
const result = {
|
|
3158
|
-
hasMoreItems: searchResponse.hasMoreItems,
|
|
3159
|
-
totalNumItems: searchResponse.totalNumItems,
|
|
3160
|
-
items: resultListItems,
|
|
3161
|
-
objectTypes: objectTypes,
|
|
3162
|
-
paging: totalPages > 1 ? { page, totalPages } : undefined
|
|
3163
|
-
};
|
|
2974
|
+
getObjectConfig(type, bucket) {
|
|
2975
|
+
const b = bucket ? this.#objectConfigs.buckets.find((b) => b.id === bucket) : undefined;
|
|
2976
|
+
const otr = b ? b.configs : this.#objectConfigs.main;
|
|
2977
|
+
const oc = otr[type.id];
|
|
2978
|
+
// return oc || this.#getRegisteredDefaults(bucket)[type.id];
|
|
2979
|
+
// override icons by APP_SCHEMA-icons: temporary solution. Todo: remove when handling of custom svg-icons is clear!
|
|
2980
|
+
const result = oc || this.#getRegisteredDefaults(bucket)[type.id] || this.#defaultObjectConfigs[type.id];
|
|
2981
|
+
if (result?.icon)
|
|
2982
|
+
result.icon = type.icon ? { svg: type.icon } : result.icon;
|
|
3164
2983
|
return result;
|
|
3165
2984
|
}
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
2985
|
+
saveObjectConfig(type, config, bucket) {
|
|
2986
|
+
return this.saveObjectConfigs({ [type.id]: config }, bucket);
|
|
2987
|
+
}
|
|
2988
|
+
saveObjectConfigs(configs, bucket) {
|
|
2989
|
+
this.#updateObjectConfig(configs, bucket);
|
|
2990
|
+
return this.#user.saveObjectConfig(this.#objectConfigs);
|
|
2991
|
+
}
|
|
2992
|
+
#updateObjectConfig(configs, bucket) {
|
|
2993
|
+
if (!this.#objectConfigs) {
|
|
2994
|
+
this.#objectConfigs = {
|
|
2995
|
+
main: {},
|
|
2996
|
+
buckets: []
|
|
2997
|
+
};
|
|
2998
|
+
}
|
|
2999
|
+
if (bucket) {
|
|
3000
|
+
// does bucket exist?
|
|
3001
|
+
const tileBucketIdx = this.#objectConfigs.buckets.findIndex((b) => b.id === bucket);
|
|
3002
|
+
if (tileBucketIdx !== -1) {
|
|
3003
|
+
Object.keys(configs).forEach((objectTypeId) => {
|
|
3004
|
+
const config = configs[objectTypeId];
|
|
3005
|
+
if (config) {
|
|
3006
|
+
this.#objectConfigs.buckets[tileBucketIdx].configs[objectTypeId] = config;
|
|
3007
|
+
}
|
|
3008
|
+
else {
|
|
3009
|
+
delete this.#objectConfigs.buckets[tileBucketIdx].configs[objectTypeId];
|
|
3010
|
+
}
|
|
3011
|
+
});
|
|
3183
3012
|
}
|
|
3184
3013
|
else {
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3014
|
+
const newBucket = { id: bucket, configs: {} };
|
|
3015
|
+
Object.keys(configs).forEach((objectTypeId) => {
|
|
3016
|
+
const config = configs[objectTypeId];
|
|
3017
|
+
if (config) {
|
|
3018
|
+
newBucket.configs[objectTypeId] = config;
|
|
3019
|
+
}
|
|
3189
3020
|
});
|
|
3021
|
+
this.#objectConfigs.buckets.push(newBucket);
|
|
3190
3022
|
}
|
|
3191
|
-
}
|
|
3192
|
-
|
|
3023
|
+
}
|
|
3024
|
+
else {
|
|
3025
|
+
Object.keys(configs).forEach((objectTypeId) => {
|
|
3026
|
+
const config = configs[objectTypeId];
|
|
3027
|
+
if (config) {
|
|
3028
|
+
this.#objectConfigs.main[objectTypeId] = config;
|
|
3029
|
+
}
|
|
3030
|
+
else {
|
|
3031
|
+
delete this.#objectConfigs.main[objectTypeId];
|
|
3032
|
+
}
|
|
3033
|
+
});
|
|
3034
|
+
}
|
|
3035
|
+
this.#objectConfigsSource.next(this.#objectConfigs);
|
|
3193
3036
|
}
|
|
3194
|
-
|
|
3195
|
-
return this.#
|
|
3196
|
-
? this.#dateRangeValueToSearchFilter(value, property)
|
|
3197
|
-
: {
|
|
3198
|
-
f: property,
|
|
3199
|
-
o: value.operator,
|
|
3200
|
-
v1: value.firstValue,
|
|
3201
|
-
v2: value.secondValue
|
|
3202
|
-
};
|
|
3037
|
+
getDefaultConfig(objectTypeID) {
|
|
3038
|
+
return this.#defaultObjectConfigs[objectTypeID];
|
|
3203
3039
|
}
|
|
3204
|
-
|
|
3205
|
-
const
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3040
|
+
getResolvedObjectConfig(data, type, bucket, includeDefaults) {
|
|
3041
|
+
const defaultCfg = this.#defaultObjectConfigs[data[BaseObjectTypeField.OBJECT_TYPE_ID]];
|
|
3042
|
+
let oc = this.getObjectConfig(type, bucket) || defaultCfg;
|
|
3043
|
+
if (includeDefaults)
|
|
3044
|
+
oc = { ...defaultCfg, ...oc };
|
|
3045
|
+
const res = {
|
|
3046
|
+
id: data[BaseObjectTypeField.OBJECT_ID],
|
|
3047
|
+
objectTypeId: data[BaseObjectTypeField.OBJECT_TYPE_ID],
|
|
3048
|
+
actions: oc.actions,
|
|
3049
|
+
badges: oc.badges,
|
|
3050
|
+
instanceData: data
|
|
3051
|
+
};
|
|
3052
|
+
if (oc.title)
|
|
3053
|
+
res.title = {
|
|
3054
|
+
propertyName: oc.title.propertyName,
|
|
3055
|
+
value: data[oc.title.propertyName]
|
|
3056
|
+
};
|
|
3057
|
+
if (oc.description)
|
|
3058
|
+
res.description = {
|
|
3059
|
+
propertyName: oc.description.propertyName,
|
|
3060
|
+
value: data[oc.description.propertyName]
|
|
3061
|
+
};
|
|
3062
|
+
if (oc.icon)
|
|
3063
|
+
res.icon = {
|
|
3064
|
+
propertyName: 'custom',
|
|
3065
|
+
value: oc.icon.svg
|
|
3066
|
+
};
|
|
3067
|
+
if (oc.meta)
|
|
3068
|
+
res.meta = {
|
|
3069
|
+
propertyName: oc.meta.propertyName,
|
|
3070
|
+
value: data[oc.meta.propertyName]
|
|
3071
|
+
};
|
|
3072
|
+
if (oc.aside)
|
|
3073
|
+
res.aside = {
|
|
3074
|
+
propertyName: oc.aside.propertyName,
|
|
3075
|
+
value: data[oc.aside.propertyName]
|
|
3076
|
+
};
|
|
3077
|
+
return res;
|
|
3241
3078
|
}
|
|
3242
3079
|
/**
|
|
3243
|
-
*
|
|
3244
|
-
*
|
|
3245
|
-
* @param value
|
|
3246
|
-
* @param range
|
|
3247
|
-
* @private
|
|
3080
|
+
* Load default/fallbac configs based on the object types and
|
|
3081
|
+
* their first properties
|
|
3248
3082
|
*/
|
|
3249
|
-
#
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
case 'end':
|
|
3260
|
-
return isoDateString;
|
|
3261
|
-
default:
|
|
3262
|
-
return isoDateString;
|
|
3263
|
-
}
|
|
3083
|
+
#getDefaultObjectConfig() {
|
|
3084
|
+
this.#system.getObjectTypes(true).forEach((ot) => {
|
|
3085
|
+
this.#defaultObjectConfigs[ot.id] = {
|
|
3086
|
+
objectTypeId: ot.id,
|
|
3087
|
+
title: this.#toObjectProperty(ot.fields[0]),
|
|
3088
|
+
description: this.#toObjectProperty(ot.fields[1]),
|
|
3089
|
+
meta: this.#toObjectProperty(ot.fields[2]),
|
|
3090
|
+
aside: this.#toObjectProperty(ot.fields[3])
|
|
3091
|
+
};
|
|
3092
|
+
});
|
|
3264
3093
|
}
|
|
3265
|
-
|
|
3266
|
-
|
|
3094
|
+
#toObjectProperty(field) {
|
|
3095
|
+
return field
|
|
3096
|
+
? {
|
|
3097
|
+
label: this.#system.getLocalizedLabel(field.id),
|
|
3098
|
+
propertyName: field.id
|
|
3099
|
+
}
|
|
3100
|
+
: undefined;
|
|
3101
|
+
}
|
|
3102
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3103
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectConfigService, providedIn: 'root' }); }
|
|
3267
3104
|
}
|
|
3268
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
3105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectConfigService, decorators: [{
|
|
3269
3106
|
type: Injectable,
|
|
3270
3107
|
args: [{
|
|
3271
3108
|
providedIn: 'root'
|
|
3272
3109
|
}]
|
|
3273
3110
|
}] });
|
|
3274
3111
|
|
|
3112
|
+
const YUV_USER = new InjectionToken('Currently logged in user', {
|
|
3113
|
+
factory: () => undefined
|
|
3114
|
+
});
|
|
3115
|
+
const provideUser = (user) => {
|
|
3116
|
+
return { provide: YUV_USER, useValue: user };
|
|
3117
|
+
};
|
|
3118
|
+
|
|
3275
3119
|
/**
|
|
3276
|
-
* Service
|
|
3277
|
-
* an object. Actions perormed on an object (eg. read, write, delete, ...) will be recorded during
|
|
3278
|
-
* the objects lifecycle. Audits are provided based on a users permissions. Beside the audit entries
|
|
3279
|
-
* visible to regular users there are more technical ones that will only be shown to users that
|
|
3280
|
-
* have administrative role.
|
|
3120
|
+
* Service handling authentication related issues.
|
|
3281
3121
|
*/
|
|
3282
|
-
class
|
|
3283
|
-
|
|
3284
|
-
|
|
3122
|
+
class AuthService {
|
|
3123
|
+
// user may have been fetched already in bootstrapping process
|
|
3124
|
+
#userToken;
|
|
3125
|
+
#eventService;
|
|
3126
|
+
#userService;
|
|
3127
|
+
#objectConfigService;
|
|
3128
|
+
#appCache;
|
|
3129
|
+
#systemService;
|
|
3130
|
+
#localizationService;
|
|
3131
|
+
#backend;
|
|
3132
|
+
#INITIAL_REQUEST_STORAGE_KEY;
|
|
3133
|
+
#USER_FETCH_URI;
|
|
3134
|
+
#authenticated;
|
|
3135
|
+
#authSource;
|
|
3136
|
+
#authData;
|
|
3137
|
+
constructor(coreConfig) {
|
|
3138
|
+
this.coreConfig = coreConfig;
|
|
3139
|
+
// user may have been fetched already in bootstrapping process
|
|
3140
|
+
this.#userToken = inject(YUV_USER);
|
|
3141
|
+
this.#eventService = inject(EventService);
|
|
3285
3142
|
this.#userService = inject(UserService);
|
|
3286
|
-
|
|
3287
|
-
this
|
|
3288
|
-
|
|
3289
|
-
this
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
310, // tag updated
|
|
3300
|
-
325, // object restored form version
|
|
3301
|
-
340, // object moved
|
|
3302
|
-
10000 // custom audit entries
|
|
3303
|
-
];
|
|
3304
|
-
// audit action codes that should be visible to admin users
|
|
3305
|
-
this.adminAuditActions = [
|
|
3306
|
-
202, // marked for delete
|
|
3307
|
-
220, // version deleted
|
|
3308
|
-
400, // content read
|
|
3309
|
-
401, // metadata read
|
|
3310
|
-
402, // rendition read (text)
|
|
3311
|
-
403, // rendition read (pdf)
|
|
3312
|
-
404 // rendition read (thumbnail)
|
|
3313
|
-
];
|
|
3143
|
+
this.#objectConfigService = inject(ObjectConfigService);
|
|
3144
|
+
this.#appCache = inject(AppCacheService);
|
|
3145
|
+
this.#systemService = inject(SystemService);
|
|
3146
|
+
this.#localizationService = inject(LocalizationService);
|
|
3147
|
+
this.#backend = inject(BackendService);
|
|
3148
|
+
this.#INITIAL_REQUEST_STORAGE_KEY = 'yuv.core.auth.initialrequest';
|
|
3149
|
+
this.#USER_FETCH_URI = '/idm/whoami';
|
|
3150
|
+
this.#authenticated = false;
|
|
3151
|
+
this.#authSource = new BehaviorSubject(false);
|
|
3152
|
+
this.authenticated$ = this.#authSource.asObservable();
|
|
3153
|
+
}
|
|
3154
|
+
isLoggedIn() {
|
|
3155
|
+
return this.#authenticated;
|
|
3314
3156
|
}
|
|
3315
|
-
#searchService;
|
|
3316
|
-
#userService;
|
|
3317
3157
|
/**
|
|
3318
|
-
*
|
|
3319
|
-
* @
|
|
3320
|
-
* @param options Options
|
|
3158
|
+
* Called while app/core is initialized (APP_INITIALIZER)
|
|
3159
|
+
* @ignore
|
|
3321
3160
|
*/
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
const q = {
|
|
3325
|
-
size: this.DEFAULT_RES_SIZE,
|
|
3326
|
-
types: [SystemType.AUDIT],
|
|
3327
|
-
filters: [
|
|
3328
|
-
{
|
|
3329
|
-
f: AuditField.REFERRED_OBJECT_ID,
|
|
3330
|
-
o: Operator.EQUAL,
|
|
3331
|
-
v1: id
|
|
3332
|
-
},
|
|
3333
|
-
{
|
|
3334
|
-
f: AuditField.ACTION,
|
|
3335
|
-
o: Operator.IN,
|
|
3336
|
-
v1: auditActions
|
|
3337
|
-
}
|
|
3338
|
-
],
|
|
3339
|
-
sort: [
|
|
3340
|
-
{
|
|
3341
|
-
field: AuditField.CREATION_DATE,
|
|
3342
|
-
order: 'desc'
|
|
3343
|
-
}
|
|
3344
|
-
]
|
|
3345
|
-
};
|
|
3346
|
-
return this.#fetchAudits(q);
|
|
3161
|
+
initUser() {
|
|
3162
|
+
return this.fetchUser();
|
|
3347
3163
|
}
|
|
3348
3164
|
/**
|
|
3349
|
-
* Get
|
|
3350
|
-
* whether or not the user has admin permissions you'll get a different
|
|
3351
|
-
* set of actions.
|
|
3352
|
-
* @param skipActions codes of actions that should not be fetched
|
|
3165
|
+
* Get the current tenant or the previous one persisted locally
|
|
3353
3166
|
*/
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
return actions.filter((a) => !skipActions || !skipActions.includes(a));
|
|
3167
|
+
getTenant() {
|
|
3168
|
+
return this.#authData?.tenant;
|
|
3357
3169
|
}
|
|
3358
3170
|
/**
|
|
3359
|
-
*
|
|
3360
|
-
* @param auditsResult The result object of a former audits query
|
|
3361
|
-
* @param page The page to load
|
|
3171
|
+
* Fetch information about the user currently logged in
|
|
3362
3172
|
*/
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3173
|
+
fetchUser() {
|
|
3174
|
+
return (this.#userToken ? of(this.#userToken) : this.#backend.get(this.#USER_FETCH_URI)).pipe(tap(() => {
|
|
3175
|
+
this.#authenticated = true;
|
|
3176
|
+
this.#authSource.next(this.#authenticated);
|
|
3177
|
+
}), switchMap((userJson) => this.#initApp(userJson)));
|
|
3367
3178
|
}
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
subaction: o.properties[AuditField.SUBACTION] ? o.properties[AuditField.SUBACTION].value : null,
|
|
3376
|
-
version: o.properties[AuditField.VERSION].value,
|
|
3377
|
-
creationDate: o.properties[AuditField.CREATION_DATE].value,
|
|
3378
|
-
createdBy: {
|
|
3379
|
-
id: o.properties[AuditField.CREATED_BY].value,
|
|
3380
|
-
title: o.properties[AuditField.CREATED_BY].title
|
|
3381
|
-
}
|
|
3382
|
-
})),
|
|
3383
|
-
hasMoreItems: res.hasMoreItems,
|
|
3384
|
-
page: !q.from ? 1 : q.from / q.size + 1
|
|
3385
|
-
})));
|
|
3179
|
+
/**
|
|
3180
|
+
* Logs out the current user.
|
|
3181
|
+
*/
|
|
3182
|
+
logout() {
|
|
3183
|
+
this.#authenticated = false;
|
|
3184
|
+
this.#authSource.next(this.#authenticated);
|
|
3185
|
+
this.#eventService.trigger(YuvEventType.LOGOUT);
|
|
3386
3186
|
}
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3187
|
+
/**
|
|
3188
|
+
* Persists the initial request URI. This is nessesary to be able to
|
|
3189
|
+
* redirect the user to the requested page after authentication.
|
|
3190
|
+
* This is done on app initialization (core-init).
|
|
3191
|
+
*/
|
|
3192
|
+
setInitialRequestUri() {
|
|
3193
|
+
const ignore = ['/', '/index.html'];
|
|
3194
|
+
const baseHref = Utils.getBaseHref();
|
|
3195
|
+
// Check only the pathname against the ignore list so that auth callback
|
|
3196
|
+
// query params (e.g. ?session_state=…) don't bypass the check.
|
|
3197
|
+
let path = location.pathname.replace(baseHref, '');
|
|
3198
|
+
path = !path.startsWith('/') ? `/${path}` : path;
|
|
3199
|
+
if (!ignore.includes(path)) {
|
|
3200
|
+
let uri = `${location.pathname}${location.search}`.replace(baseHref, '');
|
|
3201
|
+
uri = !uri.startsWith('/') ? `/${uri}` : uri;
|
|
3202
|
+
return this.#appCache.setItem(this.#INITIAL_REQUEST_STORAGE_KEY, {
|
|
3203
|
+
uri: uri,
|
|
3204
|
+
timestamp: Date.now()
|
|
3205
|
+
});
|
|
3393
3206
|
}
|
|
3207
|
+
return of(false);
|
|
3208
|
+
}
|
|
3209
|
+
/**
|
|
3210
|
+
* Get the URL that entered the app. May be a deep link that could then be
|
|
3211
|
+
* picked up again after user has been authenticated.
|
|
3212
|
+
*/
|
|
3213
|
+
getInitialRequestUri() {
|
|
3214
|
+
return this.#appCache.getItem(this.#INITIAL_REQUEST_STORAGE_KEY);
|
|
3215
|
+
}
|
|
3216
|
+
resetInitialRequestUri() {
|
|
3217
|
+
return this.#appCache.removeItem(this.#INITIAL_REQUEST_STORAGE_KEY);
|
|
3218
|
+
}
|
|
3219
|
+
/**
|
|
3220
|
+
* Initialize/setup the application for a given user. This involves fetching
|
|
3221
|
+
* settings and schema information.
|
|
3222
|
+
* @param userJson Data retrieved from the backend
|
|
3223
|
+
*/
|
|
3224
|
+
#initApp(userJson) {
|
|
3225
|
+
return this.#userService.fetchUserSettings().pipe(switchMap((userSettings) => {
|
|
3226
|
+
const currentUser = new YuvUser(userJson, userSettings);
|
|
3227
|
+
this.#userService.setCurrentUser(currentUser);
|
|
3228
|
+
this.#authData = {
|
|
3229
|
+
tenant: currentUser.tenant,
|
|
3230
|
+
language: currentUser.getClientLocale()
|
|
3231
|
+
};
|
|
3232
|
+
return forkJoin([
|
|
3233
|
+
this.#localizationService.fetchLocalizations(),
|
|
3234
|
+
this.#systemService.getSystemDefinition(this.#authData)
|
|
3235
|
+
]).pipe(switchMap(() => this.#objectConfigService.init()), map(() => currentUser));
|
|
3236
|
+
}));
|
|
3394
3237
|
}
|
|
3395
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
3396
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
3238
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuthService, deps: [{ token: CORE_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3239
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuthService, providedIn: 'root' }); }
|
|
3397
3240
|
}
|
|
3398
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type:
|
|
3241
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuthService, decorators: [{
|
|
3399
3242
|
type: Injectable,
|
|
3400
3243
|
args: [{
|
|
3401
3244
|
providedIn: 'root'
|
|
3402
3245
|
}]
|
|
3403
|
-
}]
|
|
3246
|
+
}], ctorParameters: () => [{ type: CoreConfig, decorators: [{
|
|
3247
|
+
type: Inject,
|
|
3248
|
+
args: [CORE_CONFIG]
|
|
3249
|
+
}] }] });
|
|
3250
|
+
|
|
3251
|
+
/**
|
|
3252
|
+
* Prevent app from running into 401 issues related to gateway timeouts.
|
|
3253
|
+
*/
|
|
3254
|
+
function AuthInterceptorFnc(req, next) {
|
|
3255
|
+
const userService = inject(UserService);
|
|
3256
|
+
const auth = inject(AuthService);
|
|
3257
|
+
return next(req).pipe(tap({
|
|
3258
|
+
next: (event) => {
|
|
3259
|
+
if (event instanceof HttpResponse) {
|
|
3260
|
+
// do stuff with response if you want
|
|
3261
|
+
}
|
|
3262
|
+
},
|
|
3263
|
+
error: (error) => {
|
|
3264
|
+
if (error instanceof HttpErrorResponse || error.isHttpErrorResponse) {
|
|
3265
|
+
if (error.status === 401) {
|
|
3266
|
+
auth.logout();
|
|
3267
|
+
userService.logout();
|
|
3268
|
+
}
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
}));
|
|
3272
|
+
}
|
|
3273
|
+
|
|
3274
|
+
var LoginStateName;
|
|
3275
|
+
(function (LoginStateName) {
|
|
3276
|
+
LoginStateName["STATE_LOGIN_URI"] = "login.uri";
|
|
3277
|
+
LoginStateName["STATE_DONE"] = "login.done";
|
|
3278
|
+
LoginStateName["STATE_CANCELED"] = "login.canceled";
|
|
3279
|
+
})(LoginStateName || (LoginStateName = {}));
|
|
3404
3280
|
|
|
3405
3281
|
const ProcessAction = {
|
|
3406
3282
|
complete: 'complete',
|
|
@@ -3453,6 +3329,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
3453
3329
|
}]
|
|
3454
3330
|
}] });
|
|
3455
3331
|
|
|
3332
|
+
const LOCALIZATION_COLUMNS = ['locale', 'label', 'description'];
|
|
3333
|
+
|
|
3456
3334
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
3457
3335
|
const transformResponse = () => map((res) => (res.body ? res.body.objects.map((val) => val) : null));
|
|
3458
3336
|
/**
|
|
@@ -4352,8 +4230,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
4352
4230
|
}]
|
|
4353
4231
|
}] });
|
|
4354
4232
|
|
|
4355
|
-
const LOCALIZATION_COLUMNS = ['locale', 'label', 'description'];
|
|
4356
|
-
|
|
4357
4233
|
class CatalogService {
|
|
4358
4234
|
constructor() {
|
|
4359
4235
|
this.#backend = inject(BackendService);
|
|
@@ -4476,7 +4352,11 @@ class CatalogService {
|
|
|
4476
4352
|
#getCatalogs() {
|
|
4477
4353
|
return this.#search.searchCmis(`SELECT * FROM ${SystemType.CATALOG}`, 1000).pipe(map$1((res) => res.items.map((item) => ({
|
|
4478
4354
|
objectId: item.fields.get(BaseObjectTypeField.OBJECT_ID),
|
|
4479
|
-
name: item.fields.get(CatalogTypeField.NATIVE_ID)
|
|
4355
|
+
name: item.fields.get(CatalogTypeField.NATIVE_ID),
|
|
4356
|
+
raw: Array.from(item.fields).reduce((acc, [key, wrapper]) => {
|
|
4357
|
+
acc[key] = wrapper;
|
|
4358
|
+
return acc;
|
|
4359
|
+
}, {})
|
|
4480
4360
|
}))));
|
|
4481
4361
|
}
|
|
4482
4362
|
/** Loads the catalog list, sorts by name and publishes to the `catalogs` signal. */
|
|
@@ -4530,16 +4410,35 @@ class CatalogService {
|
|
|
4530
4410
|
totalNumItems: response.totalNumItems
|
|
4531
4411
|
};
|
|
4532
4412
|
}
|
|
4413
|
+
#getEntryState(properties) {
|
|
4414
|
+
const validFrom = this.#prop(properties, CatalogTypeField.DATE_VALID_FROM);
|
|
4415
|
+
const validUntil = this.#prop(properties, CatalogTypeField.DATE_VALID_UNTIL);
|
|
4416
|
+
const now = new Date().toISOString();
|
|
4417
|
+
if (validFrom && now < validFrom) {
|
|
4418
|
+
return 'upcoming';
|
|
4419
|
+
}
|
|
4420
|
+
if (validUntil && now > validUntil) {
|
|
4421
|
+
return 'expired';
|
|
4422
|
+
}
|
|
4423
|
+
return 'active';
|
|
4424
|
+
}
|
|
4533
4425
|
#mapEntry(apiObject) {
|
|
4534
4426
|
const props = apiObject.properties;
|
|
4535
4427
|
return {
|
|
4428
|
+
_state: this.#getEntryState(props),
|
|
4536
4429
|
objectId: this.#prop(props, BaseObjectTypeField.OBJECT_ID),
|
|
4537
4430
|
name: this.#prop(props, CatalogTypeField.NATIVE_ID),
|
|
4538
4431
|
catalogName: this.#prop(props, CatalogTypeField.CATALOG_NATIVE_ID),
|
|
4539
4432
|
localizations: this.#parseLocalization(props[CatalogTypeField.LOCALIZATION]),
|
|
4540
4433
|
validFrom: this.#prop(props, CatalogTypeField.DATE_VALID_FROM),
|
|
4541
4434
|
validUntil: this.#prop(props, CatalogTypeField.DATE_VALID_UNTIL),
|
|
4542
|
-
properties: this.#extractCustomProperties(props)
|
|
4435
|
+
properties: this.#extractCustomProperties(props),
|
|
4436
|
+
raw: Object.entries(props).reduce((acc, [key, wrapper]) => {
|
|
4437
|
+
if (wrapper && typeof wrapper === 'object' && 'value' in wrapper) {
|
|
4438
|
+
acc[key] = wrapper.value;
|
|
4439
|
+
}
|
|
4440
|
+
return acc;
|
|
4441
|
+
}, {})
|
|
4543
4442
|
};
|
|
4544
4443
|
}
|
|
4545
4444
|
#prop(properties, key) {
|
|
@@ -4743,6 +4642,159 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
4743
4642
|
}]
|
|
4744
4643
|
}] });
|
|
4745
4644
|
|
|
4645
|
+
/**
|
|
4646
|
+
* Service to monitor the online/offline state of the application.
|
|
4647
|
+
* It listens to the browser's online and offline events and provides an observable
|
|
4648
|
+
* to track the current connection state.
|
|
4649
|
+
*
|
|
4650
|
+
* An observable `connection$` is provided which emits the current connection state
|
|
4651
|
+
* whenever the online or offline state changes. The initial state is determined by
|
|
4652
|
+
* the `window.navigator.onLine` property.
|
|
4653
|
+
*/
|
|
4654
|
+
class ConnectionService {
|
|
4655
|
+
/**
|
|
4656
|
+
* @ignore
|
|
4657
|
+
*/
|
|
4658
|
+
constructor() {
|
|
4659
|
+
this.currentState = {
|
|
4660
|
+
isOnline: window.navigator.onLine
|
|
4661
|
+
};
|
|
4662
|
+
this.connectionStateSource = new ReplaySubject();
|
|
4663
|
+
this.connection$ = this.connectionStateSource.asObservable();
|
|
4664
|
+
this.connectionStateSource.next(this.currentState);
|
|
4665
|
+
fromEvent(window, 'online').subscribe(() => {
|
|
4666
|
+
this.currentState.isOnline = true;
|
|
4667
|
+
this.connectionStateSource.next(this.currentState);
|
|
4668
|
+
});
|
|
4669
|
+
fromEvent(window, 'offline').subscribe(() => {
|
|
4670
|
+
this.currentState.isOnline = false;
|
|
4671
|
+
this.connectionStateSource.next(this.currentState);
|
|
4672
|
+
});
|
|
4673
|
+
}
|
|
4674
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConnectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4675
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConnectionService, providedIn: 'root' }); }
|
|
4676
|
+
}
|
|
4677
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConnectionService, decorators: [{
|
|
4678
|
+
type: Injectable,
|
|
4679
|
+
args: [{
|
|
4680
|
+
providedIn: 'root'
|
|
4681
|
+
}]
|
|
4682
|
+
}], ctorParameters: () => [] });
|
|
4683
|
+
|
|
4684
|
+
/**
|
|
4685
|
+
* Http Offline interceptor trys to serving offline content for method/url
|
|
4686
|
+
*/
|
|
4687
|
+
function OfflineInterceptorFnc(req, next) {
|
|
4688
|
+
return next(req);
|
|
4689
|
+
}
|
|
4690
|
+
|
|
4691
|
+
/**
|
|
4692
|
+
* Providing functions,that are are injected at application startup and executed during app initialization.
|
|
4693
|
+
*/
|
|
4694
|
+
const init_moduleFnc = () => {
|
|
4695
|
+
const coreConfig = inject(CORE_CONFIG);
|
|
4696
|
+
const logger = inject(Logger);
|
|
4697
|
+
const http = inject(HttpClient);
|
|
4698
|
+
const configService = inject(ConfigService);
|
|
4699
|
+
const authService = inject(AuthService);
|
|
4700
|
+
return authService.setInitialRequestUri().pipe(switchMap(() => coreConfig.main
|
|
4701
|
+
? !Array.isArray(coreConfig.main)
|
|
4702
|
+
? of([coreConfig.main])
|
|
4703
|
+
: forkJoin([...coreConfig.main].map((uri) => http.get(`${Utils.getBaseHref()}${uri}`).pipe(catchError((e) => {
|
|
4704
|
+
logger.error('failed to catch config file', e);
|
|
4705
|
+
return of({});
|
|
4706
|
+
}), map((res) => res)))).pipe(
|
|
4707
|
+
// switchMap((configs: YuvConfig[]) => configService.extendConfig(configs)),
|
|
4708
|
+
tap((configs) => configService.extendConfig(configs)), switchMap(() => authService.initUser().pipe(catchError((e) => {
|
|
4709
|
+
authService.initError = {
|
|
4710
|
+
status: e.status,
|
|
4711
|
+
key: e.error.error
|
|
4712
|
+
};
|
|
4713
|
+
return of(true);
|
|
4714
|
+
}))))
|
|
4715
|
+
: of(false)));
|
|
4716
|
+
};
|
|
4717
|
+
|
|
4718
|
+
/**
|
|
4719
|
+
* Handles missing translations
|
|
4720
|
+
* @ignore
|
|
4721
|
+
*/
|
|
4722
|
+
class EoxMissingTranslationHandler {
|
|
4723
|
+
handle(params) {
|
|
4724
|
+
return '!missing key: ' + params.key;
|
|
4725
|
+
}
|
|
4726
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxMissingTranslationHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4727
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxMissingTranslationHandler }); }
|
|
4728
|
+
}
|
|
4729
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxMissingTranslationHandler, decorators: [{
|
|
4730
|
+
type: Injectable
|
|
4731
|
+
}] });
|
|
4732
|
+
|
|
4733
|
+
/**
|
|
4734
|
+
* i18n packages
|
|
4735
|
+
*/
|
|
4736
|
+
/**
|
|
4737
|
+
* Loader that fetches translations based on the configured locations
|
|
4738
|
+
* @ignore
|
|
4739
|
+
*/
|
|
4740
|
+
class EoxTranslateJsonLoader {
|
|
4741
|
+
constructor(http, config) {
|
|
4742
|
+
this.http = http;
|
|
4743
|
+
this.config = config;
|
|
4744
|
+
registerLocaleData(localeDe, 'de', localeExtraDe); // German
|
|
4745
|
+
registerLocaleData(localeAr, 'ar', localeExtraAr); // Arabic
|
|
4746
|
+
registerLocaleData(localeEs, 'es', localeExtraEs); // Spanish
|
|
4747
|
+
registerLocaleData(localePt, 'pt', localeExtraPt); // Portuguese
|
|
4748
|
+
registerLocaleData(localeFr, 'fr', localeExtraFr); // French
|
|
4749
|
+
registerLocaleData(localeZh, 'zh', localeExtraZh); // Chinese
|
|
4750
|
+
registerLocaleData(localeLv, 'lv', localeExtraLv); // Latvian
|
|
4751
|
+
registerLocaleData(localeRu, 'ru', localeExtraRu); // Russian
|
|
4752
|
+
registerLocaleData(localeIt, 'it', localeExtraIt); // Italian
|
|
4753
|
+
registerLocaleData(localeSk, 'sk', localeExtraSk); // Slovak
|
|
4754
|
+
registerLocaleData(localePl, 'pl', localeExtraPl); // Polish
|
|
4755
|
+
registerLocaleData(localeUk, 'uk', localeExtraUk); // Ukrainian
|
|
4756
|
+
registerLocaleData(localeJa, 'ja', localeExtraJa); // Japanese
|
|
4757
|
+
registerLocaleData(localeKo, 'ko', localeExtraKo); // Korean
|
|
4758
|
+
registerLocaleData(localeHi, 'hi', localeExtraHi); // Hindi
|
|
4759
|
+
registerLocaleData(localeBn, 'bn', localeExtraBn); // Bengalese
|
|
4760
|
+
registerLocaleData(localeVi, 'vi', localeExtraVi); // Vietnamese
|
|
4761
|
+
registerLocaleData(localeTr, 'tr', localeExtraTr); // Turkish
|
|
4762
|
+
registerLocaleData(localeNl, 'nl', localeExtraNl); // Dutch
|
|
4763
|
+
registerLocaleData(localeNb, 'nb', localeExtraNb); // Norwegian
|
|
4764
|
+
registerLocaleData(localeTh, 'th', localeExtraTh); // Thai
|
|
4765
|
+
registerLocaleData(localeFi, 'fi', localeExtraFi); // Finnish
|
|
4766
|
+
registerLocaleData(localeSv, 'sv', localeExtraSv); // Swedish
|
|
4767
|
+
registerLocaleData(localeDeCh, 'de-CH', localeExtraDeCh); // German Swiss
|
|
4768
|
+
}
|
|
4769
|
+
/**
|
|
4770
|
+
*
|
|
4771
|
+
* @param string lang
|
|
4772
|
+
* @returns Observable<Object>
|
|
4773
|
+
*/
|
|
4774
|
+
getTranslation(lang) {
|
|
4775
|
+
const t = (this.config.translations || []).map((path) => this.loadTranslationFile(path, lang));
|
|
4776
|
+
return forkJoin(t).pipe(map((res) => res.reduce((acc, x) => Object.assign(acc, x), {})));
|
|
4777
|
+
}
|
|
4778
|
+
loadTranslationFile(path, lang) {
|
|
4779
|
+
const version = document.body.dataset['bt'] ?? document.body.dataset['version'];
|
|
4780
|
+
const cacheBuster = version ? `?v=${version}` : '';
|
|
4781
|
+
return this.http.get(`${Utils.getBaseHref()}${path}${lang}.json${cacheBuster}`).pipe(catchError(() => {
|
|
4782
|
+
// ISO codes with more than 2 characters are sub-languages like de-CH.
|
|
4783
|
+
// If there is no translation file for that sub-language we'll try to load
|
|
4784
|
+
// the file for the base language (in this case de).
|
|
4785
|
+
return lang.length > 2 ? this.loadTranslationFile(path, lang.substring(0, 2)) : of({});
|
|
4786
|
+
}));
|
|
4787
|
+
}
|
|
4788
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxTranslateJsonLoader, deps: [{ token: i1.HttpClient }, { token: CORE_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4789
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxTranslateJsonLoader }); }
|
|
4790
|
+
}
|
|
4791
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxTranslateJsonLoader, decorators: [{
|
|
4792
|
+
type: Injectable
|
|
4793
|
+
}], ctorParameters: () => [{ type: i1.HttpClient }, { type: CoreConfig, decorators: [{
|
|
4794
|
+
type: Inject,
|
|
4795
|
+
args: [CORE_CONFIG]
|
|
4796
|
+
}] }] });
|
|
4797
|
+
|
|
4746
4798
|
var DeviceScreenOrientation;
|
|
4747
4799
|
(function (DeviceScreenOrientation) {
|
|
4748
4800
|
DeviceScreenOrientation["PORTRAIT"] = "portrait";
|
|
@@ -5508,6 +5560,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5508
5560
|
}]
|
|
5509
5561
|
}] });
|
|
5510
5562
|
|
|
5563
|
+
/**
|
|
5564
|
+
* Interface to be implemented by all components (state components) that are aware of pending changes
|
|
5565
|
+
*/
|
|
5566
|
+
|
|
5511
5567
|
/**
|
|
5512
5568
|
* EditingObserver service is used to track changes made inside the application, that should prevent
|
|
5513
5569
|
* doing something or going somewhere before the changes are persisted or ignored. For example when
|
|
@@ -5627,27 +5683,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5627
5683
|
}]
|
|
5628
5684
|
}] });
|
|
5629
5685
|
|
|
5630
|
-
/**
|
|
5631
|
-
* Providing a `PendingChangesComponent`.
|
|
5632
|
-
*/
|
|
5633
|
-
class PendingChangesGuard {
|
|
5634
|
-
constructor(pendingChanges) {
|
|
5635
|
-
this.pendingChanges = pendingChanges;
|
|
5636
|
-
}
|
|
5637
|
-
canDeactivate(component) {
|
|
5638
|
-
// if there are no pending changes, just allow deactivation; else confirm first
|
|
5639
|
-
return !this.pendingChanges.check(component);
|
|
5640
|
-
}
|
|
5641
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesGuard, deps: [{ token: PendingChangesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5642
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesGuard, providedIn: 'root' }); }
|
|
5643
|
-
}
|
|
5644
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesGuard, decorators: [{
|
|
5645
|
-
type: Injectable,
|
|
5646
|
-
args: [{
|
|
5647
|
-
providedIn: 'root'
|
|
5648
|
-
}]
|
|
5649
|
-
}], ctorParameters: () => [{ type: PendingChangesService }] });
|
|
5650
|
-
|
|
5651
5686
|
/**
|
|
5652
5687
|
* Service that provides guards for Material Dialog close operations.
|
|
5653
5688
|
*
|
|
@@ -5803,6 +5838,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImpo
|
|
|
5803
5838
|
type: Injectable
|
|
5804
5839
|
}] });
|
|
5805
5840
|
|
|
5841
|
+
/**
|
|
5842
|
+
* Providing a `PendingChangesComponent`.
|
|
5843
|
+
*/
|
|
5844
|
+
class PendingChangesGuard {
|
|
5845
|
+
constructor(pendingChanges) {
|
|
5846
|
+
this.pendingChanges = pendingChanges;
|
|
5847
|
+
}
|
|
5848
|
+
canDeactivate(component) {
|
|
5849
|
+
// if there are no pending changes, just allow deactivation; else confirm first
|
|
5850
|
+
return !this.pendingChanges.check(component);
|
|
5851
|
+
}
|
|
5852
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesGuard, deps: [{ token: PendingChangesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5853
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesGuard, providedIn: 'root' }); }
|
|
5854
|
+
}
|
|
5855
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesGuard, decorators: [{
|
|
5856
|
+
type: Injectable,
|
|
5857
|
+
args: [{
|
|
5858
|
+
providedIn: 'root'
|
|
5859
|
+
}]
|
|
5860
|
+
}], ctorParameters: () => [{ type: PendingChangesService }] });
|
|
5861
|
+
|
|
5806
5862
|
class TabGuardDirective {
|
|
5807
5863
|
#tabGroup = inject(MatTabGroup);
|
|
5808
5864
|
#pending = inject(PendingChangesService);
|
|
@@ -6556,5 +6612,5 @@ const provideYuvClientCore = (options = { translations: [] }, customEvents, cust
|
|
|
6556
6612
|
* Generated bundle index. Do not edit.
|
|
6557
6613
|
*/
|
|
6558
6614
|
|
|
6559
|
-
export { AFO_STATE, AVAILABLE_BACKEND_APPS, AdministrationRoles, ApiBase, AppCacheService, AuditField, AuditService, AuthInterceptorFnc, AuthService, BackendService, BaseObjectTypeField, BpmService, CLIENT_APP_REQUIREMENTS, CORE_CONFIG, CUSTOM_CONFIG, CUSTOM_YUV_EVENT_PREFIX, CatalogService, CatalogTypeField, Classification, ClassificationPrefix, ClientCacheService, ClientDefaultsObjectTypeField, ClipboardService, ColumnConfigSkipFields, ConfigService, ConnectionService, ContentStreamAllowed, ContentStreamField, CoreConfig, DEFAULT_LOCK_OPTIONS, DeviceScreenOrientation, DeviceService, DialogCloseGuard, Direction, DmsObject, DmsService, EoxMissingTranslationHandler, EoxTranslateJsonLoader, EventService, FileSizePipe, IdmService, InternalFieldType, KeysPipe, LOCALIZATION_COLUMNS, LOCK_TAG_OWNER_INDEX, LocaleCurrencyPipe, LocaleDatePipe, LocaleDecimalPipe, LocaleNumberPipe, LocalePercentPipe, LocalizationService, LockField, Logger, LoginStateName, NativeNotificationService, NotificationService, ObjectConfigService, ObjectFormControl, ObjectFormControlWrapper, ObjectFormGroup, ObjectLockingService, ObjectTag, ObjectTypeClassification, ObjectTypePropertyClassification, OfflineInterceptorFnc, Operator, OperatorLabel, ParentField, PendingChangesGuard, PendingChangesService, PredictionService, ProcessAction, RelationshipTypeField, RetentionField, RetentionService, SafeHtmlPipe, SafeUrlPipe, SearchService, SearchUtils, SecondaryObjectTypeClassification, SessionStorageService, Situation, Sort, SystemResult, SystemSOT, SystemService, SystemType, TENANT_HEADER, TabGuardDirective, ToastService, UploadService, UserRoles, UserService, UserStorageService, Utils, YUV_USER, YuvError, YuvEventType, YuvUser, findLockTag, init_moduleFnc, provideAvailabilityManagement, provideBeforeUnloadProtection, provideNavigationProtection, providePopstateDialogProtection, provideRequirements, provideUser, provideYuvClientCore };
|
|
6615
|
+
export { AFO_STATE, AVAILABLE_BACKEND_APPS, AdministrationRoles, ApiBase, AppCacheService, AuditAction, AuditField, AuditService, AuthInterceptorFnc, AuthService, BackendService, BaseObjectTypeField, BpmService, CLIENT_APP_REQUIREMENTS, CORE_CONFIG, CUSTOM_CONFIG, CUSTOM_EVENTS, CUSTOM_EVENTS_TRUSTED_ORIGINS, CUSTOM_YUV_EVENT_PREFIX, CatalogService, CatalogTypeField, Classification, ClassificationPrefix, ClientCacheService, ClientDefaultsObjectTypeField, ClipboardService, ColumnConfigSkipFields, ConfigService, ConnectionService, ContentStreamAllowed, ContentStreamField, CoreConfig, DEFAULT_LOCK_OPTIONS, DeviceScreenOrientation, DeviceService, DialogCloseGuard, Direction, DmsObject, DmsService, EoxMissingTranslationHandler, EoxTranslateJsonLoader, EventService, FileSizePipe, IdmService, InternalFieldType, KeysPipe, LOCALIZATION_COLUMNS, LOCK_TAG_OWNER_INDEX, LocaleCurrencyPipe, LocaleDatePipe, LocaleDecimalPipe, LocaleNumberPipe, LocalePercentPipe, LocalizationService, LockField, Logger, LoginStateName, NativeNotificationService, NotificationService, ObjectConfigService, ObjectFormControl, ObjectFormControlWrapper, ObjectFormGroup, ObjectLockingService, ObjectTag, ObjectTypeClassification, ObjectTypePropertyClassification, OfflineInterceptorFnc, Operator, OperatorLabel, ParentField, PendingChangesGuard, PendingChangesService, PredictionService, ProcessAction, RelationshipTypeField, RetentionField, RetentionService, SafeHtmlPipe, SafeUrlPipe, SearchService, SearchUtils, SecondaryObjectTypeClassification, SessionStorageService, Situation, Sort, SystemResult, SystemSOT, SystemService, SystemType, TENANT_HEADER, TabGuardDirective, ToastService, UploadService, UserRoles, UserService, UserStorageService, Utils, YUV_USER, YuvError, YuvEventType, YuvToastStyles, YuvUser, findLockTag, init_moduleFnc, provideAvailabilityManagement, provideBeforeUnloadProtection, provideNavigationProtection, providePopstateDialogProtection, provideRequirements, provideUser, provideYuvClientCore };
|
|
6560
6616
|
//# sourceMappingURL=yuuvis-client-core.mjs.map
|