@yuuvis/client-core 3.1.0 → 3.2.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.
@@ -1,23 +1,16 @@
1
- import * as i1 from '@ngx-translate/core';
1
+ import * as i1$1 from '@ngx-translate/core';
2
2
  import { TranslateService, provideTranslateService, provideMissingTranslationHandler, provideTranslateLoader } from '@ngx-translate/core';
3
- export { TranslateDirective, TranslateLoader, TranslateModule, TranslatePipe, TranslateService } from '@ngx-translate/core';
4
- import * as i1$2 from '@angular/common/http';
3
+ export { TranslateDirective, TranslateLoader, TranslateModule, TranslatePipe, TranslateService, _ as marker } from '@ngx-translate/core';
4
+ 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, 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';
8
+ import { tap, finalize, shareReplay, catchError, filter, map, switchMap, first, scan, delay } from 'rxjs/operators';
9
+ import { EMPTY, Subject, of, forkJoin, tap as tap$1, catchError as catchError$1, Observable, ReplaySubject, BehaviorSubject, map as map$1, fromEvent, throwError, switchMap as switchMap$1, merge, 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';
14
- import { DeviceDetectorService } from 'ngx-device-detector';
15
- import { FormGroup, FormControl } from '@angular/forms';
16
- import { MatTabGroup } from '@angular/material/tabs';
17
- import { DecimalPipe, PercentPipe, CurrencyPipe, registerLocaleData } from '@angular/common';
18
- import * as i1$1 from '@angular/platform-browser';
19
- import { MatDialog } from '@angular/material/dialog';
20
- import { Router, NavigationEnd } from '@angular/router';
13
+ import { registerLocaleData, DecimalPipe, PercentPipe, CurrencyPipe } from '@angular/common';
21
14
  import localeAr from '@angular/common/locales/ar';
22
15
  import localeBn from '@angular/common/locales/bn';
23
16
  import localeDe from '@angular/common/locales/de';
@@ -66,6 +59,13 @@ import localeTr from '@angular/common/locales/tr';
66
59
  import localeUk from '@angular/common/locales/uk';
67
60
  import localeVi from '@angular/common/locales/vi';
68
61
  import localeZh from '@angular/common/locales/zh';
62
+ import { toSignal, takeUntilDestroyed } from '@angular/core/rxjs-interop';
63
+ import { DeviceDetectorService } from 'ngx-device-detector';
64
+ import { FormGroup, FormControl } from '@angular/forms';
65
+ import { MatTabGroup } from '@angular/material/tabs';
66
+ import * as i1$2 from '@angular/platform-browser';
67
+ import { MatDialog } from '@angular/material/dialog';
68
+ import { Router, NavigationEnd } from '@angular/router';
69
69
 
70
70
  const TENANT_HEADER = 'X-ID-TENANT-NAME';
71
71
  var Situation;
@@ -108,6 +108,9 @@ const RelationshipTypeField = {
108
108
  SOURCE_ID: 'system:sourceId',
109
109
  TARGET_ID: 'system:targetId'
110
110
  };
111
+ const LockField = {
112
+ LOCK_TAG: 'system:lock:resistent'
113
+ };
111
114
  const CatalogTypeField = {
112
115
  NATIVE_ID: 'system:nativeId',
113
116
  CATALOG_NATIVE_ID: 'system:catalogNativeId',
@@ -898,10 +901,10 @@ class ConfigService {
898
901
  _getCoreConfig(key) {
899
902
  return this.cfg ? this.cfg.core[key] : undefined;
900
903
  }
901
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
902
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfigService, providedIn: 'root' }); }
904
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
905
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConfigService, providedIn: 'root' }); }
903
906
  }
904
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConfigService, decorators: [{
907
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConfigService, decorators: [{
905
908
  type: Injectable,
906
909
  args: [{
907
910
  providedIn: 'root'
@@ -967,10 +970,10 @@ class Logger {
967
970
  }
968
971
  return should;
969
972
  }
970
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Logger, deps: [{ token: ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
971
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Logger, providedIn: 'root' }); }
973
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: Logger, deps: [{ token: ConfigService }], target: i0.ɵɵFactoryTarget.Injectable }); }
974
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: Logger, providedIn: 'root' }); }
972
975
  }
973
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Logger, decorators: [{
976
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: Logger, decorators: [{
974
977
  type: Injectable,
975
978
  args: [{
976
979
  providedIn: 'root'
@@ -1251,123 +1254,119 @@ class BackendService {
1251
1254
  .pipe(catchError((err) => of({ _error: err }))));
1252
1255
  return forkJoin(httpRequests);
1253
1256
  }
1254
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BackendService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1255
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BackendService, providedIn: 'root' }); }
1257
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BackendService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1258
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BackendService, providedIn: 'root' }); }
1256
1259
  }
1257
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BackendService, decorators: [{
1260
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BackendService, decorators: [{
1258
1261
  type: Injectable,
1259
1262
  args: [{ providedIn: 'root' }]
1260
1263
  }] });
1261
1264
 
1262
- var Operator;
1263
- (function (Operator) {
1264
- Operator["EQUAL"] = "eq";
1265
- Operator["EEQUAL"] = "eeq";
1266
- Operator["IN"] = "in";
1267
- Operator["GREATER_THAN"] = "gt";
1268
- Operator["GREATER_OR_EQUAL"] = "gte";
1269
- Operator["LESS_THAN"] = "lt";
1270
- Operator["LESS_OR_EQUAL"] = "lte";
1271
- Operator["INTERVAL"] = "gtlt";
1272
- Operator["INTERVAL_INCLUDE_BOTH"] = "gtelte";
1273
- Operator["INTERVAL_INCLUDE_TO"] = "gtlte";
1274
- Operator["INTERVAL_INCLUDE_FROM"] = "gtelt";
1275
- Operator["RANGE"] = "rg";
1276
- Operator["LIKE"] = "like";
1277
- Operator["CONTAINS"] = "contains"; // contains
1278
- })(Operator || (Operator = {}));
1279
- const OperatorLabel = {
1280
- /** equal */
1281
- EQUAL: '=',
1282
- /** exact equal */
1283
- EEQUAL: '==',
1284
- /** match at least one of the provided values (value has to be an array) */
1285
- IN: '~',
1286
- /** greater than */
1287
- GREATER_THAN: '>',
1288
- /** greater than or equal */
1289
- GREATER_OR_EQUAL: '≽', //
1290
- LESS_THAN: '<', // less than
1291
- LESS_OR_EQUAL: '≼', // less than or equal
1292
- INTERVAL: '<>', // interval
1293
- INTERVAL_INCLUDE_BOTH: '-', // interval include left and right
1294
- INTERVAL_INCLUDE_TO: '>-', // interval include right
1295
- INTERVAL_INCLUDE_FROM: '-<', // interval include left
1296
- RANGE: '=', // aggegation ranges
1297
- LIKE: '~', // like
1298
- CONTAINS: '~' // contains
1299
- };
1265
+ var Direction;
1266
+ (function (Direction) {
1267
+ Direction["LTR"] = "ltr";
1268
+ Direction["RTL"] = "rtl";
1269
+ })(Direction || (Direction = {}));
1270
+
1271
+ const CUSTOM_EVENTS = new InjectionToken('CUSTOM_EVENTS', { factory: () => [] });
1272
+ const CUSTOM_EVENTS_TRUSTED_ORIGINS = new InjectionToken('CUSTOM_EVENTS_TRUSTED_ORIGINS', { factory: () => [] });
1300
1273
 
1301
1274
  /**
1302
- * Service for saving or caching data on the users device. It uses the most efficient storage
1303
- * available (IndexDB, localstorage, ...) on the device. Depending on the type of storage used,
1304
- * its limitations apply.
1275
+ * Mandatory Custom event prefix for all custom YUV events
1305
1276
  */
1306
- class AppCacheService {
1307
- #storage = inject(StorageMap);
1308
- /**
1309
- * Set item in storage.
1310
- * @param key The key under which the value is stored.
1311
- * @param value The value to store.
1312
- * @returns An Observable that emits true when the operation is successful.
1313
- */
1314
- setItem(key, value) {
1315
- return this.#storage.set(key, value).pipe(map(() => true));
1277
+ const CUSTOM_YUV_EVENT_PREFIX = 'yuv.';
1278
+
1279
+ /**
1280
+ * Service for providing triggered events
1281
+ */
1282
+ class EventService {
1283
+ #customEvents;
1284
+ #customEventsTrustedOrigins;
1285
+ #ngZone;
1286
+ #eventSource;
1287
+ constructor() {
1288
+ this.#customEvents = inject(CUSTOM_EVENTS);
1289
+ this.#customEventsTrustedOrigins = inject(CUSTOM_EVENTS_TRUSTED_ORIGINS);
1290
+ this.#ngZone = inject(NgZone);
1291
+ this.#eventSource = new Subject();
1292
+ this.event$ = this.#eventSource.asObservable();
1293
+ this.#listenToWindowEvents();
1316
1294
  }
1317
- /**
1318
- * Get item from storage.
1319
- * @param key The key of the item to retrieve.
1320
- * @returns An Observable that emits the retrieved value.
1321
- */
1322
- getItem(key) {
1323
- return this.#storage.get(key);
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;
1309
+ }
1310
+ #listenToWindowEvents() {
1311
+ window.addEventListener('message', (event) => {
1312
+ this.#ngZone.run(() => this.#isValidExternalMessage(event) && this.trigger(event.data.type, event.data.data));
1313
+ });
1324
1314
  }
1325
1315
  /**
1326
- * Remove item from storage.
1327
- * @param key The key of the item to remove.
1328
- * @returns An Observable that emits true when the operation is successful.
1316
+ * Triggers a postMessage event that will be sent to the yuuvis global event Trigger
1317
+ * @param type Type/key of the event
1318
+ * @param data Data to be sent along with the event
1329
1319
  */
1330
- removeItem(key) {
1331
- return this.#storage.delete(key).pipe(map(() => true));
1320
+ triggerPostMessageEvent(type, data) {
1321
+ const targetOrigin = window.location.origin;
1322
+ const payload = {
1323
+ type,
1324
+ data,
1325
+ timestamp: Date.now()
1326
+ };
1327
+ window.postMessage(payload, targetOrigin);
1332
1328
  }
1333
1329
  /**
1334
- * Clear storage, optionally filtered by a function.
1335
- * @param filter A function to filter which keys to clear.
1336
- * @returns An Observable that emits true when the operation is successful.
1330
+ * Trigger an global event
1331
+ * @param type Type/key of the event
1332
+ * @param data Data to be send along with the event
1337
1333
  */
1338
- clear(filter) {
1339
- return filter
1340
- ? this.getStorageKeys().pipe(switchMap((keys) => {
1341
- const list = keys.filter((k) => filter(k)).map((k) => this.removeItem(k));
1342
- return list.length ? forkJoin(list).pipe(map(() => true)) : of(true);
1343
- }))
1344
- : this.#storage.clear().pipe(map(() => true));
1334
+ trigger(type, ...args) {
1335
+ this.#eventSource.next({ type: type, data: args[0] });
1345
1336
  }
1346
1337
  /**
1347
- * Get all storage keys.
1348
- * @returns An Observable that emits an array of all storage keys.
1338
+ * Listen on a triggered event
1339
+ * @param types Type/key of the event
1349
1340
  */
1350
- getStorageKeys() {
1351
- return new Observable((observer) => {
1352
- const keys = [];
1353
- this.#storage.keys().subscribe({
1354
- next: (key) => keys.push(key),
1355
- complete: () => observer.next(keys)
1356
- });
1357
- }).pipe(first());
1358
- }
1359
- setStorage(options) {
1360
- return forkJoin(Object.keys(options || {}).map((k) => this.setItem(k, options[k])));
1341
+ on(...types) {
1342
+ return this.event$.pipe(filter((event) => event && !!types.find((t) => t === event.type)));
1361
1343
  }
1362
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AppCacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1363
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AppCacheService, providedIn: 'root' }); }
1344
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1345
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EventService, providedIn: 'root' }); }
1364
1346
  }
1365
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AppCacheService, decorators: [{
1347
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EventService, decorators: [{
1366
1348
  type: Injectable,
1367
1349
  args: [{
1368
1350
  providedIn: 'root'
1369
1351
  }]
1370
- }] });
1352
+ }], ctorParameters: () => [] });
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 = {}));
1371
1370
 
1372
1371
  /**
1373
1372
  * Service managing localizations. The localizations are fetched
@@ -1423,10 +1422,81 @@ class LocalizationService {
1423
1422
  extendLocalizations(localizations) {
1424
1423
  this.#extension = { ...this.#extension, ...localizations };
1425
1424
  }
1426
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocalizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1427
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocalizationService, providedIn: 'root' }); }
1425
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocalizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1426
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocalizationService, providedIn: 'root' }); }
1427
+ }
1428
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocalizationService, decorators: [{
1429
+ type: Injectable,
1430
+ args: [{
1431
+ providedIn: 'root'
1432
+ }]
1433
+ }] });
1434
+
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' }); }
1428
1498
  }
1429
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocalizationService, decorators: [{
1499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AppCacheService, decorators: [{
1430
1500
  type: Injectable,
1431
1501
  args: [{
1432
1502
  providedIn: 'root'
@@ -2059,411 +2129,16 @@ class SystemService {
2059
2129
  }
2060
2130
  return classifications;
2061
2131
  }
2062
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SystemService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2063
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SystemService, providedIn: 'root' }); }
2132
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SystemService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2133
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SystemService, providedIn: 'root' }); }
2064
2134
  }
2065
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SystemService, decorators: [{
2135
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SystemService, decorators: [{
2066
2136
  type: Injectable,
2067
2137
  args: [{
2068
2138
  providedIn: 'root'
2069
2139
  }]
2070
2140
  }] });
2071
2141
 
2072
- class SearchService {
2073
- #backend = inject(BackendService);
2074
- #system = inject(SystemService);
2075
- static { this.DEFAULT_QUERY_SIZE = 50; }
2076
- /**
2077
- * Execute a search query ans transform the result to a SearchResult object
2078
- * @param query The search query
2079
- * @returns Observable of a SearchResult
2080
- */
2081
- search(query) {
2082
- return this.searchRaw(query).pipe(map((res) => this.toSearchResult(res, query.size || SearchService.DEFAULT_QUERY_SIZE, query.from || 0)));
2083
- }
2084
- /**
2085
- * Execute a raw search query and return the result as is.
2086
- * @param query The search query
2087
- * @returns Observable of the raw search result
2088
- */
2089
- searchRaw(query) {
2090
- if (!query.size)
2091
- query.size = SearchService.DEFAULT_QUERY_SIZE;
2092
- return this.#backend.post(`/dms/objects/search`, query);
2093
- }
2094
- /**
2095
- * Search for objects in the dms using CMIS like SQL syntax.
2096
- * @param statement The query statement
2097
- * @param size The number of items to return
2098
- * @returns Observable of a SearchResult
2099
- */
2100
- searchCmis(statement, size = SearchService.DEFAULT_QUERY_SIZE, includePermissions = false) {
2101
- return this.#executeCmisSearch(statement, size, 0, includePermissions);
2102
- }
2103
- #executeCmisSearch(statement, maxItems, skipCount = 0, includePermissions = false) {
2104
- const payload = {
2105
- query: {
2106
- statement,
2107
- skipCount,
2108
- maxItems,
2109
- handleDeletedDocuments: 'DELETED_DOCUMENTS_EXCLUDE'
2110
- }
2111
- };
2112
- if (includePermissions) {
2113
- payload.query.includePermissions = true;
2114
- }
2115
- return this.#backend
2116
- .post('/dms/objects/cmisSearch', payload
2117
- // Using API-WEB because it enriches the response with additional information (resolved user names, etc.)
2118
- // ApiBase.core
2119
- )
2120
- .pipe(map((res) => this.toSearchResult(res, maxItems, skipCount)));
2121
- }
2122
- /**
2123
- * Fetch aggragations for a given query.
2124
- * @param q The query
2125
- * @param aggregations List of aggregations to be fetched (e.g. `enaio:objectTypeId`
2126
- * to get an aggregation of object types)
2127
- */
2128
- aggregate(q, aggregations) {
2129
- q.aggs = aggregations;
2130
- return this.searchRaw(q).pipe(map((res) => this.#toAggregateResult(res, aggregations)));
2131
- }
2132
- /**
2133
- * Map search result from the backend to applications AggregateResult object
2134
- * @param searchResponse The backend response
2135
- * @param aggregations The aggregations to be fetched
2136
- */
2137
- #toAggregateResult(searchResponse, aggregations) {
2138
- const agg = [];
2139
- if (aggregations) {
2140
- aggregations.forEach((a) => {
2141
- const ag = {
2142
- aggKey: a,
2143
- entries: searchResponse.objects.map((o) => ({
2144
- key: o.properties[a].value,
2145
- count: o.properties['OBJECT_COUNT'].value
2146
- }))
2147
- };
2148
- agg.push(ag);
2149
- });
2150
- }
2151
- return {
2152
- totalNumItems: searchResponse.totalNumItems,
2153
- aggregations: agg
2154
- };
2155
- }
2156
- /**
2157
- * Go to a page of a search result.
2158
- * @param query SearchQuery or CMIS query statement
2159
- * @param page The number of the page to go to
2160
- */
2161
- getPage(query, page, pageSize = SearchService.DEFAULT_QUERY_SIZE, includePermissions = false) {
2162
- const isCmis = typeof query === 'string';
2163
- if (isCmis) {
2164
- return this.#executeCmisSearch(query, pageSize, (page - 1) * pageSize, includePermissions);
2165
- }
2166
- else {
2167
- query.from = (page - 1) * (query.size || pageSize);
2168
- return this.search(query);
2169
- }
2170
- }
2171
- /**
2172
- * Map search result from the backend to applications SearchResult object
2173
- * @param searchResponse The backend response
2174
- */
2175
- toSearchResult(searchResponse, pageSize = SearchService.DEFAULT_QUERY_SIZE, skipCount = 0) {
2176
- const resultListItems = [];
2177
- const objectTypes = [];
2178
- searchResponse.objects.forEach((o) => {
2179
- const fields = new Map();
2180
- // process properties section of result
2181
- Object.keys(o.properties).forEach((key) => {
2182
- let value = o.properties[key].value;
2183
- if (o.properties[key].clvalue) {
2184
- // table fields will have a clientValue too ...
2185
- value = o.properties[key].clvalue;
2186
- // ... and also may contain values that need to be resolved
2187
- if (o.properties[key].resolvedValues) {
2188
- value.forEach((v) => {
2189
- Object.keys(v).forEach((k) => {
2190
- const resValue = Array.isArray(v[k]) ? v[k].map((i) => o.properties[key].resolvedValues[i]) : o.properties[key].resolvedValues[v[k]];
2191
- if (resValue) {
2192
- v[`${k}_title`] = resValue;
2193
- }
2194
- });
2195
- });
2196
- }
2197
- }
2198
- fields.set(key, value);
2199
- if (o.properties[key].title) {
2200
- fields.set(key + '_title', o.properties[key].title);
2201
- }
2202
- });
2203
- // process contentStreams section of result if available.
2204
- // Objects that don't have files attached won't have this section
2205
- let content;
2206
- if (o.contentStreams && o.contentStreams.length > 0) {
2207
- // we assume that each result object only has ONE file attached, altough
2208
- // this is an array and there may be more
2209
- const contentStream = o.contentStreams[0];
2210
- // also add contentstream related fields to the result fields
2211
- fields.set(ContentStreamField.LENGTH, contentStream.length);
2212
- fields.set(ContentStreamField.MIME_TYPE, contentStream.mimeType);
2213
- fields.set(ContentStreamField.FILENAME, contentStream.fileName);
2214
- fields.set(ContentStreamField.ID, contentStream.contentStreamId);
2215
- fields.set(ContentStreamField.RANGE, contentStream.contentStreamRange);
2216
- fields.set(ContentStreamField.REPOSITORY_ID, contentStream.repositoryId);
2217
- fields.set(ContentStreamField.DIGEST, contentStream.digest);
2218
- fields.set(ContentStreamField.ARCHIVE_PATH, contentStream.archivePath);
2219
- content = {
2220
- contentStreamId: contentStream.contentStreamId,
2221
- repositoryId: contentStream.repositoryId,
2222
- range: contentStream.range,
2223
- digest: contentStream.digest,
2224
- archivePath: contentStream.archivePath,
2225
- fileName: contentStream.fileName,
2226
- mimeType: contentStream.mimeType,
2227
- size: contentStream.length
2228
- };
2229
- }
2230
- const objectTypeId = o.properties[BaseObjectTypeField.OBJECT_TYPE_ID] ? o.properties[BaseObjectTypeField.OBJECT_TYPE_ID].value : null;
2231
- if (objectTypes.indexOf(objectTypeId) === -1) {
2232
- objectTypes.push(objectTypeId);
2233
- }
2234
- resultListItems.push({
2235
- objectTypeId,
2236
- content,
2237
- fields,
2238
- permissions: o.permissions
2239
- });
2240
- });
2241
- const totalPages = Math.ceil(searchResponse.totalNumItems / pageSize);
2242
- const page = (!skipCount ? 0 : skipCount / pageSize) + 1;
2243
- const result = {
2244
- hasMoreItems: searchResponse.hasMoreItems,
2245
- totalNumItems: searchResponse.totalNumItems,
2246
- items: resultListItems,
2247
- objectTypes: objectTypes,
2248
- paging: totalPages > 1 ? { page, totalPages } : undefined
2249
- };
2250
- return result;
2251
- }
2252
- /**
2253
- * Maps data extracted from a search form to search filters. Every key of the form data object
2254
- * will be mapped to a search filter.
2255
- * @param formData form data
2256
- * @returns Array of search filters
2257
- */
2258
- formDataToSearchFilter(formData) {
2259
- const isRangeValue = (v) => {
2260
- return typeof v === 'object' && v !== null && 'firstValue' in v && 'operator' in v;
2261
- };
2262
- const filters = [];
2263
- Object.keys(formData).forEach((key) => {
2264
- const value = formData[key];
2265
- if (isRangeValue(value)) {
2266
- const f = this.rangeValueToSearchFilter(value, key);
2267
- if (f)
2268
- filters.push(f);
2269
- }
2270
- else {
2271
- filters.push({
2272
- f: key,
2273
- o: Array.isArray(value) ? Operator.IN : Operator.EQUAL,
2274
- v1: value
2275
- });
2276
- }
2277
- });
2278
- return filters;
2279
- }
2280
- rangeValueToSearchFilter(value, property) {
2281
- return this.#system.getObjectTypeField(property)?.propertyType === 'datetime'
2282
- ? this.#dateRangeValueToSearchFilter(value, property)
2283
- : {
2284
- f: property,
2285
- o: value.operator,
2286
- v1: value.firstValue,
2287
- v2: value.secondValue
2288
- };
2289
- }
2290
- #dateRangeValueToSearchFilter(rv, property) {
2291
- const v1 = rv.firstValue;
2292
- const v2 = rv.secondValue;
2293
- switch (rv.operator) {
2294
- case Operator.EQUAL: {
2295
- return {
2296
- f: property,
2297
- o: Operator.INTERVAL_INCLUDE_BOTH,
2298
- v1: this.#dateToISOString(v1, 'start'),
2299
- v2: this.#dateToISOString(v1, 'end')
2300
- };
2301
- }
2302
- case Operator.GREATER_OR_EQUAL: {
2303
- return {
2304
- f: property,
2305
- o: rv.operator,
2306
- v1: this.#dateToISOString(v1)
2307
- };
2308
- }
2309
- case Operator.LESS_OR_EQUAL: {
2310
- return {
2311
- f: property,
2312
- o: rv.operator,
2313
- v1: this.#dateToISOString(v1, 'end')
2314
- };
2315
- }
2316
- case Operator.INTERVAL_INCLUDE_BOTH: {
2317
- return {
2318
- f: property,
2319
- o: rv.operator,
2320
- v1: this.#dateToISOString(v1, 'start'),
2321
- v2: v2 ? this.#dateToISOString(v2, 'end') : ''
2322
- };
2323
- }
2324
- default:
2325
- return undefined;
2326
- }
2327
- }
2328
- /**
2329
- * 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.
2330
- *
2331
- * @param value
2332
- * @param range
2333
- * @private
2334
- */
2335
- #dateToISOString(value, range = 'start') {
2336
- const date = typeof value === 'string' ? new Date(value) : value;
2337
- const offset = Utils.DEFAULT_TIME_OFFSET_V2; // T+23:59:59:999
2338
- if (!Utils.isValidDate(date))
2339
- return '';
2340
- const isoDateString = date.toISOString();
2341
- // const isoDateStringWithOffset = new Date(date.getTime() + offset).toISOString();
2342
- switch (range) {
2343
- case 'start':
2344
- return isoDateString;
2345
- case 'end':
2346
- return isoDateString;
2347
- default:
2348
- return isoDateString;
2349
- }
2350
- }
2351
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SearchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2352
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SearchService, providedIn: 'root' }); }
2353
- }
2354
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SearchService, decorators: [{
2355
- type: Injectable,
2356
- args: [{
2357
- providedIn: 'root'
2358
- }]
2359
- }] });
2360
-
2361
- var Direction;
2362
- (function (Direction) {
2363
- Direction["LTR"] = "ltr";
2364
- Direction["RTL"] = "rtl";
2365
- })(Direction || (Direction = {}));
2366
-
2367
- const CUSTOM_EVENTS = new InjectionToken('CUSTOM_EVENTS', { factory: () => [] });
2368
- const CUSTOM_EVENTS_TRUSTED_ORIGINS = new InjectionToken('CUSTOM_EVENTS_TRUSTED_ORIGINS', { factory: () => [] });
2369
-
2370
- /**
2371
- * Mandatory Custom event prefix for all custom YUV events
2372
- */
2373
- const CUSTOM_YUV_EVENT_PREFIX = 'yuv.';
2374
-
2375
- /**
2376
- * Service for providing triggered events
2377
- */
2378
- class EventService {
2379
- #customEvents;
2380
- #customEventsTrustedOrigins;
2381
- #ngZone;
2382
- #eventSource;
2383
- constructor() {
2384
- this.#customEvents = inject(CUSTOM_EVENTS);
2385
- this.#customEventsTrustedOrigins = inject(CUSTOM_EVENTS_TRUSTED_ORIGINS);
2386
- this.#ngZone = inject(NgZone);
2387
- this.#eventSource = new Subject();
2388
- this.event$ = this.#eventSource.asObservable();
2389
- this.#listenToWindowEvents();
2390
- }
2391
- #startsWithAllowed(value) {
2392
- return typeof value === 'string' && this.#customEvents.some((prefix) => value.startsWith(prefix));
2393
- }
2394
- #isValidExternalMessage(event) {
2395
- this.#customEvents.push(CUSTOM_YUV_EVENT_PREFIX);
2396
- if (!event.data || typeof event.data !== 'object')
2397
- return false;
2398
- if (!(this.#startsWithAllowed(event.data.source) || this.#startsWithAllowed(event.data.type)))
2399
- return false;
2400
- // Accept messages from trusted origins
2401
- this.#customEventsTrustedOrigins.push(window.location.origin);
2402
- const isFromTrustedOrigin = this.#customEventsTrustedOrigins.includes(event.origin);
2403
- const hasValidStructure = event.data && (event.data.type || event.data.eventType) && typeof event.data === 'object';
2404
- return isFromTrustedOrigin && hasValidStructure;
2405
- }
2406
- #listenToWindowEvents() {
2407
- window.addEventListener('message', (event) => {
2408
- this.#ngZone.run(() => this.#isValidExternalMessage(event) && this.trigger(event.data.type, event.data.data));
2409
- });
2410
- }
2411
- /**
2412
- * Triggers a postMessage event that will be sent to the yuuvis global event Trigger
2413
- * @param type Type/key of the event
2414
- * @param data Data to be sent along with the event
2415
- */
2416
- triggerPostMessageEvent(type, data) {
2417
- const targetOrigin = window.location.origin;
2418
- const payload = {
2419
- type,
2420
- data,
2421
- timestamp: Date.now()
2422
- };
2423
- window.postMessage(payload, targetOrigin);
2424
- }
2425
- /**
2426
- * Trigger an global event
2427
- * @param type Type/key of the event
2428
- * @param data Data to be send along with the event
2429
- */
2430
- trigger(type, ...args) {
2431
- this.#eventSource.next({ type: type, data: args[0] });
2432
- }
2433
- /**
2434
- * Listen on a triggered event
2435
- * @param types Type/key of the event
2436
- */
2437
- on(...types) {
2438
- return this.event$.pipe(filter((event) => event && !!types.find((t) => t === event.type)));
2439
- }
2440
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EventService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2441
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EventService, providedIn: 'root' }); }
2442
- }
2443
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EventService, decorators: [{
2444
- type: Injectable,
2445
- args: [{
2446
- providedIn: 'root'
2447
- }]
2448
- }], ctorParameters: () => [] });
2449
-
2450
- /**
2451
- * Events emitted by parts of the application
2452
- */
2453
- var YuvEventType;
2454
- (function (YuvEventType) {
2455
- YuvEventType["LOGOUT"] = "yuv.user.logout";
2456
- YuvEventType["CLIENT_LOCALE_CHANGED"] = "yuv.user.locale.client.changed";
2457
- YuvEventType["DMS_OBJECT_LOADED"] = "yuv.dms.object.loaded";
2458
- YuvEventType["DMS_OBJECT_CREATED"] = "yuv.dms.object.created";
2459
- YuvEventType["DMS_OBJECT_DELETED"] = "yuv.dms.object.deleted";
2460
- YuvEventType["DMS_OBJECT_UPDATED"] = "yuv.dms.object.updated";
2461
- YuvEventType["DMS_OBJECT_CONTENT_UPDATED"] = "yuv.dms.object.content.updated";
2462
- YuvEventType["DMS_OBJECTS_MOVED"] = "yuv.dms.objects.moved";
2463
- YuvEventType["RELATIONSHIP_CREATED"] = "yuv.dms.relationship.created";
2464
- YuvEventType["RELATIONSHIP_DELETED"] = "yuv.dms.relationship.deleted";
2465
- })(YuvEventType || (YuvEventType = {}));
2466
-
2467
2142
  /**
2468
2143
  * Service providing user account configurations.
2469
2144
  */
@@ -2567,226 +2242,547 @@ class UserService {
2567
2242
  }
2568
2243
  }
2569
2244
  }
2570
- saveUserSettings(settings) {
2571
- if (this.#user) {
2572
- //console.log(this.#user.userSettings);
2573
- this.#user.userSettings = { ...this.#user.userSettings, ...settings };
2574
- return this.#backend
2575
- .post(this.#DEFAULT_SETTINGS, this.#user.userSettings)
2576
- .pipe(tap(() => this.#userSource.next(this.#user)));
2245
+ saveUserSettings(settings) {
2246
+ if (this.#user) {
2247
+ //console.log(this.#user.userSettings);
2248
+ this.#user.userSettings = { ...this.#user.userSettings, ...settings };
2249
+ return this.#backend
2250
+ .post(this.#DEFAULT_SETTINGS, this.#user.userSettings)
2251
+ .pipe(tap(() => this.#userSource.next(this.#user)));
2252
+ }
2253
+ else
2254
+ return of(null);
2255
+ }
2256
+ fetchUserSettings() {
2257
+ return this.#backend.get('/dms/permissions').pipe(catchError(() => of(undefined)), switchMap((res) => {
2258
+ this.#setUserPermissions(res);
2259
+ return this.#backend.get(this.#DEFAULT_SETTINGS);
2260
+ }));
2261
+ }
2262
+ /**
2263
+ * Search for a user based on a search term
2264
+ * @param term Search term
2265
+ * @param excludeMe whether or not to exclude myself from the result list
2266
+ * @param roles narrow down the search results by certain roles
2267
+ */
2268
+ queryUser(term, excludeMe, roles) {
2269
+ let params = new HttpParams().set('search', term).set('excludeMe', `${!!excludeMe}`);
2270
+ roles?.length && roles.map((r) => (params = params.append(`roles`, r)));
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;
2317
+ }
2318
+ #mapPermissions(section, apiResponse) {
2319
+ const res = apiResponse[section] || {};
2320
+ return {
2321
+ folderTypes: res['folderTypeIds'] || [],
2322
+ objectTypes: res['objectTypeIds'] || [],
2323
+ secondaryObjectTypes: res['secondaryObjectTypeIds'] || []
2324
+ };
2325
+ }
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
+ /**
2421
+ * Register default object configs. Apps can pre-define how their
2422
+ * objects should be rendered.
2423
+ * @param bucket Name of a bucket to bind configs to (usually the ID of the app) to
2424
+ * separate the configs from other apps. If not provided configs will be saved for
2425
+ * the global scope
2426
+ */
2427
+ registerDefaults(configs, bucket) {
2428
+ if (bucket) {
2429
+ // does bucket exist?
2430
+ const tileBucketIdx = this.#registeredDefaultObjectConfigs.buckets.findIndex((b) => b.id === bucket);
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;
2466
+ }
2467
+ else {
2468
+ return this.#registeredDefaultObjectConfigs.main[objectTypeId];
2577
2469
  }
2578
- else
2579
- return of(null);
2580
2470
  }
2581
- fetchUserSettings() {
2582
- return this.#backend.get('/dms/permissions').pipe(catchError(() => of(undefined)), switchMap((res) => {
2583
- this.#setUserPermissions(res);
2584
- return this.#backend.get(this.#DEFAULT_SETTINGS);
2585
- }));
2471
+ #getRegisteredDefaults(bucket) {
2472
+ if (bucket) {
2473
+ const defaultTileBucket = this.#registeredDefaultObjectConfigs.buckets.find((b) => b.id === bucket);
2474
+ return defaultTileBucket?.configs || {};
2475
+ }
2476
+ else
2477
+ return this.#registeredDefaultObjectConfigs.main;
2586
2478
  }
2587
2479
  /**
2588
- * Search for a user based on a search term
2589
- * @param term Search term
2590
- * @param excludeMe whether or not to exclude myself from the result list
2591
- * @param roles narrow down the search results by certain roles
2480
+ * Get object config for an object type.
2481
+ * @param objectTypeId ID of the object type to get the config for
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.
2592
2486
  */
2593
- queryUser(term, excludeMe, roles) {
2594
- let params = new HttpParams().set('search', term).set('excludeMe', `${!!excludeMe}`);
2595
- roles?.length && roles.map((r) => (params = params.append(`roles`, r)));
2596
- return this.#backend
2597
- .get(`/idm/users?${params}`)
2598
- .pipe(map((users) => (!users ? [] : users.map((u) => new YuvUser(u)))));
2599
- }
2600
- getUserById(id) {
2601
- return this.#backend.get(`/idm/users/${id}`).pipe(map((user) => new YuvUser(user, this.#user.userSettings)));
2602
- }
2603
- logout(redirRoute) {
2604
- const redir = redirRoute ? `?redir=${redirRoute}` : '';
2605
- window.location.href = `${this.#backend.getApiBase('logout')}${redir}`;
2487
+ getObjectConfig(type, bucket) {
2488
+ const b = bucket ? this.#objectConfigs.buckets.find((b) => b.id === bucket) : undefined;
2489
+ const otr = b ? b.configs : this.#objectConfigs.main;
2490
+ const oc = otr[type.id];
2491
+ // return oc || this.#getRegisteredDefaults(bucket)[type.id];
2492
+ // override icons by APP_SCHEMA-icons: temporary solution. Todo: remove when handling of custom svg-icons is clear!
2493
+ const result = oc || this.#getRegisteredDefaults(bucket)[type.id] || this.#defaultObjectConfigs[type.id];
2494
+ if (result?.icon)
2495
+ result.icon = type.icon ? { svg: type.icon } : result.icon;
2496
+ return result;
2606
2497
  }
2607
- getSettings(section) {
2608
- return this.#user ? this.#backend.get(this.#USERS_SETTINGS + encodeURIComponent(section)) : of(null);
2498
+ saveObjectConfig(type, config, bucket) {
2499
+ return this.saveObjectConfigs({ [type.id]: config }, bucket);
2609
2500
  }
2610
- saveObjectConfig(objectConfigs) {
2611
- return this.#backend.post(this.#USERS_SETTINGS + encodeURIComponent(this.#SETTINGS_SECTION_OBJECTCONFIG), objectConfigs);
2501
+ saveObjectConfigs(configs, bucket) {
2502
+ this.#updateObjectConfig(configs, bucket);
2503
+ return this.#user.saveObjectConfig(this.#objectConfigs);
2612
2504
  }
2613
- loadObjectConfig() {
2614
- return this.getSettings(this.#SETTINGS_SECTION_OBJECTCONFIG).pipe(catchError(() => of(undefined)));
2505
+ #updateObjectConfig(configs, bucket) {
2506
+ if (!this.#objectConfigs) {
2507
+ this.#objectConfigs = {
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;
2532
+ }
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
+ }
2543
+ else {
2544
+ delete this.#objectConfigs.main[objectTypeId];
2545
+ }
2546
+ });
2547
+ }
2548
+ this.#objectConfigsSource.next(this.#objectConfigs);
2615
2549
  }
2616
- #getUiDirection(iso) {
2617
- // languages that are read right to left
2618
- const rtlLanguages = ['ar', 'arc', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ku', 'ps', 'ur', 'yi'];
2619
- return !rtlLanguages.includes(iso) ? Direction.LTR : Direction.RTL;
2550
+ getDefaultConfig(objectTypeID) {
2551
+ return this.#defaultObjectConfigs[objectTypeID];
2620
2552
  }
2621
- #setUserPermissions(res) {
2622
- this.userPermissions = {
2623
- create: this.#mapPermissions('CREATE', res),
2624
- write: this.#mapPermissions('WRITE', res),
2625
- read: this.#mapPermissions('READ', res),
2626
- delete: this.#mapPermissions('DELETE', res)
2627
- };
2628
- const permissions = {
2629
- createableObjectTypes: [
2630
- ...this.userPermissions.create.folderTypes,
2631
- ...this.userPermissions.create.objectTypes,
2632
- ...this.userPermissions.create.secondaryObjectTypes
2633
- ],
2634
- searchableObjectTypes: [
2635
- ...this.userPermissions.read.folderTypes,
2636
- ...this.userPermissions.read.objectTypes,
2637
- ...this.userPermissions.read.secondaryObjectTypes
2638
- ]
2553
+ getResolvedObjectConfig(data, type, bucket, includeDefaults) {
2554
+ const defaultCfg = this.#defaultObjectConfigs[data[BaseObjectTypeField.OBJECT_TYPE_ID]];
2555
+ let oc = this.getObjectConfig(type, bucket) || defaultCfg;
2556
+ if (includeDefaults)
2557
+ oc = { ...defaultCfg, ...oc };
2558
+ const res = {
2559
+ id: data[BaseObjectTypeField.OBJECT_ID],
2560
+ objectTypeId: data[BaseObjectTypeField.OBJECT_TYPE_ID],
2561
+ actions: oc.actions,
2562
+ badges: oc.badges,
2563
+ instanceData: data
2639
2564
  };
2640
- this.#system.setPermissions(permissions);
2641
- this.canCreateObjects = permissions.createableObjectTypes.length > 0;
2565
+ if (oc.title)
2566
+ res.title = {
2567
+ propertyName: oc.title.propertyName,
2568
+ value: data[oc.title.propertyName]
2569
+ };
2570
+ if (oc.description)
2571
+ res.description = {
2572
+ propertyName: oc.description.propertyName,
2573
+ value: data[oc.description.propertyName]
2574
+ };
2575
+ if (oc.icon)
2576
+ res.icon = {
2577
+ propertyName: 'custom',
2578
+ value: oc.icon.svg
2579
+ };
2580
+ if (oc.meta)
2581
+ res.meta = {
2582
+ propertyName: oc.meta.propertyName,
2583
+ value: data[oc.meta.propertyName]
2584
+ };
2585
+ if (oc.aside)
2586
+ res.aside = {
2587
+ propertyName: oc.aside.propertyName,
2588
+ value: data[oc.aside.propertyName]
2589
+ };
2590
+ return res;
2642
2591
  }
2643
- #mapPermissions(section, apiResponse) {
2644
- const res = apiResponse[section] || {};
2645
- return {
2646
- folderTypes: res['folderTypeIds'] || [],
2647
- objectTypes: res['objectTypeIds'] || [],
2648
- secondaryObjectTypes: res['secondaryObjectTypeIds'] || []
2649
- };
2592
+ /**
2593
+ * Load default/fallbac configs based on the object types and
2594
+ * their first properties
2595
+ */
2596
+ #getDefaultObjectConfig() {
2597
+ this.#system.getObjectTypes(true).forEach((ot) => {
2598
+ this.#defaultObjectConfigs[ot.id] = {
2599
+ objectTypeId: ot.id,
2600
+ title: this.#toObjectProperty(ot.fields[0]),
2601
+ description: this.#toObjectProperty(ot.fields[1]),
2602
+ meta: this.#toObjectProperty(ot.fields[2]),
2603
+ aside: this.#toObjectProperty(ot.fields[3])
2604
+ };
2605
+ });
2606
+ }
2607
+ #toObjectProperty(field) {
2608
+ return field
2609
+ ? {
2610
+ label: this.#system.getLocalizedLabel(field.id),
2611
+ propertyName: field.id
2612
+ }
2613
+ : undefined;
2650
2614
  }
2651
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2652
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserService, providedIn: 'root' }); }
2615
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2616
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectConfigService, providedIn: 'root' }); }
2653
2617
  }
2654
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserService, decorators: [{
2618
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectConfigService, decorators: [{
2655
2619
  type: Injectable,
2656
2620
  args: [{
2657
2621
  providedIn: 'root'
2658
2622
  }]
2659
2623
  }] });
2660
2624
 
2661
- /**
2662
- * Service providing access to the systems audit entries. Audits can be seen as the history of
2663
- * an object. Actions perormed on an object (eg. read, write, delete, ...) will be recorded during
2664
- * the objects lifecycle. Audits are provided based on a users permissions. Beside the audit entries
2665
- * visible to regular users there are more technical ones that will only be shown to users that
2666
- * have administrative role.
2667
- */
2668
- class AuditService {
2669
- constructor() {
2670
- this.#searchService = inject(SearchService);
2671
- this.#userService = inject(UserService);
2672
- // default number of items to be fetched
2673
- this.DEFAULT_RES_SIZE = 20;
2674
- // audit action codes that should be visible to regular users
2675
- this.userAuditActions = [
2676
- 100, // metadata created
2677
- 101, // metadata created (with content)
2678
- 110, // tag created
2679
- 201, // content deleted
2680
- 210, // tag deleted
2681
- 300, // metadata updated
2682
- 301, // content updated
2683
- 302, // metadata and content updated
2684
- 303, // content moved
2685
- 310, // tag updated
2686
- 325, // object restored form version
2687
- 340, // object moved
2688
- 10000 // custom audit entries
2689
- ];
2690
- // audit action codes that should be visible to admin users
2691
- this.adminAuditActions = [
2692
- 202, // marked for delete
2693
- 220, // version deleted
2694
- 400, // content read
2695
- 401, // metadata read
2696
- 402, // rendition read (text)
2697
- 403, // rendition read (pdf)
2698
- 404 // rendition read (thumbnail)
2699
- ];
2700
- }
2701
- #searchService;
2625
+ const YUV_USER = new InjectionToken('Currently logged in user', {
2626
+ factory: () => undefined
2627
+ });
2628
+ const provideUser = (user) => {
2629
+ return { provide: YUV_USER, useValue: user };
2630
+ };
2631
+
2632
+ /**
2633
+ * Service handling authentication related issues.
2634
+ */
2635
+ class AuthService {
2636
+ // user may have been fetched already in bootstrapping process
2637
+ #userToken;
2638
+ #eventService;
2702
2639
  #userService;
2640
+ #objectConfigService;
2641
+ #appCache;
2642
+ #systemService;
2643
+ #localizationService;
2644
+ #backend;
2645
+ #INITIAL_REQUEST_STORAGE_KEY;
2646
+ #USER_FETCH_URI;
2647
+ #authenticated;
2648
+ #authSource;
2649
+ #authData;
2650
+ constructor(coreConfig) {
2651
+ this.coreConfig = coreConfig;
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
+ }
2703
2670
  /**
2704
- * Get audit entries of a dms object
2705
- * @param id The id of the object to get the audit entries for
2706
- * @param options Options
2671
+ * Called while app/core is initialized (APP_INITIALIZER)
2672
+ * @ignore
2707
2673
  */
2708
- getAuditEntries(id, options = {}) {
2709
- const auditActions = this.getAuditActions(!!options.allActions, options?.skipActions);
2710
- const q = {
2711
- size: this.DEFAULT_RES_SIZE,
2712
- types: [SystemType.AUDIT],
2713
- filters: [
2714
- {
2715
- f: AuditField.REFERRED_OBJECT_ID,
2716
- o: Operator.EQUAL,
2717
- v1: id
2718
- },
2719
- {
2720
- f: AuditField.ACTION,
2721
- o: Operator.IN,
2722
- v1: auditActions
2723
- }
2724
- ],
2725
- sort: [
2726
- {
2727
- field: AuditField.CREATION_DATE,
2728
- order: 'desc'
2729
- }
2730
- ]
2731
- };
2732
- return this.#fetchAudits(q);
2674
+ initUser() {
2675
+ return this.fetchUser();
2733
2676
  }
2734
2677
  /**
2735
- * Get an array of action codes that are provided by the service. Based on
2736
- * whether or not the user has admin permissions you'll get a different
2737
- * set of actions.
2738
- * @param skipActions codes of actions that should not be fetched
2678
+ * Get the current tenant or the previous one persisted locally
2739
2679
  */
2740
- getAuditActions(allActions, skipActions) {
2741
- const actions = allActions || this.#userService.isAdvancedUser ? [...this.userAuditActions, ...this.adminAuditActions] : this.userAuditActions;
2742
- return actions.filter((a) => !skipActions || !skipActions.includes(a));
2680
+ getTenant() {
2681
+ return this.#authData?.tenant;
2743
2682
  }
2744
2683
  /**
2745
- * Get a certain page for a former audits query.
2746
- * @param auditsResult The result object of a former audits query
2747
- * @param page The page to load
2684
+ * Fetch information about the user currently logged in
2748
2685
  */
2749
- getPage(auditsResult, page) {
2750
- const q = auditsResult.query;
2751
- q.from = (page - 1) * (q.size || this.DEFAULT_RES_SIZE);
2752
- return this.#fetchAudits(q);
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)));
2753
2691
  }
2754
- #fetchAudits(q) {
2755
- return this.#searchService.searchRaw(q).pipe(map((res) => ({
2756
- query: q,
2757
- items: res.objects.map((o) => ({
2758
- action: o.properties[AuditField.ACTION].value,
2759
- actionGroup: this.#getActionGroup(o.properties[AuditField.ACTION].value),
2760
- detail: o.properties[AuditField.DETAIL].value,
2761
- subaction: o.properties[AuditField.SUBACTION] ? o.properties[AuditField.SUBACTION].value : null,
2762
- version: o.properties[AuditField.VERSION].value,
2763
- creationDate: o.properties[AuditField.CREATION_DATE].value,
2764
- createdBy: {
2765
- id: o.properties[AuditField.CREATED_BY].value,
2766
- title: o.properties[AuditField.CREATED_BY].title
2767
- }
2768
- })),
2769
- hasMoreItems: res.hasMoreItems,
2770
- page: !q.from ? 1 : q.from / q.size + 1
2771
- })));
2692
+ /**
2693
+ * Logs out the current user.
2694
+ */
2695
+ logout() {
2696
+ this.#authenticated = false;
2697
+ this.#authSource.next(this.#authenticated);
2698
+ this.#eventService.trigger(YuvEventType.LOGOUT);
2772
2699
  }
2773
- #getActionGroup(action) {
2774
- try {
2775
- return parseInt(`${action}`.substr(0, 1));
2776
- }
2777
- catch {
2778
- return -1;
2700
+ /**
2701
+ * Persists the initial request URI. This is nessesary to be able to
2702
+ * redirect the user to the requested page after authentication.
2703
+ * This is done on app initialization (core-init).
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
+ });
2779
2719
  }
2720
+ return of(false);
2721
+ }
2722
+ /**
2723
+ * Get the URL that entered the app. May be a deep link that could then be
2724
+ * picked up again after user has been authenticated.
2725
+ */
2726
+ getInitialRequestUri() {
2727
+ return this.#appCache.getItem(this.#INITIAL_REQUEST_STORAGE_KEY);
2728
+ }
2729
+ resetInitialRequestUri() {
2730
+ return this.#appCache.removeItem(this.#INITIAL_REQUEST_STORAGE_KEY);
2731
+ }
2732
+ /**
2733
+ * Initialize/setup the application for a given user. This involves fetching
2734
+ * settings and schema information.
2735
+ * @param userJson Data retrieved from the backend
2736
+ */
2737
+ #initApp(userJson) {
2738
+ return this.#userService.fetchUserSettings().pipe(switchMap((userSettings) => {
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
+ }));
2780
2750
  }
2781
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuditService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2782
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuditService, providedIn: 'root' }); }
2751
+ 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 }); }
2752
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuthService, providedIn: 'root' }); }
2783
2753
  }
2784
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuditService, decorators: [{
2754
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuthService, decorators: [{
2785
2755
  type: Injectable,
2786
2756
  args: [{
2787
2757
  providedIn: 'root'
2788
2758
  }]
2789
- }] });
2759
+ }], ctorParameters: () => [{ type: CoreConfig, decorators: [{
2760
+ type: Inject,
2761
+ args: [CORE_CONFIG]
2762
+ }] }] });
2763
+
2764
+ /**
2765
+ * Prevent app from running into 401 issues related to gateway timeouts.
2766
+ */
2767
+ function AuthInterceptorFnc(req, next) {
2768
+ const userService = inject(UserService);
2769
+ const auth = inject(AuthService);
2770
+ return next(req).pipe(tap({
2771
+ next: (event) => {
2772
+ if (event instanceof HttpResponse) {
2773
+ // do stuff with response if you want
2774
+ }
2775
+ },
2776
+ error: (error) => {
2777
+ if (error instanceof HttpErrorResponse || error.isHttpErrorResponse) {
2778
+ if (error.status === 401) {
2779
+ auth.logout();
2780
+ userService.logout();
2781
+ }
2782
+ }
2783
+ }
2784
+ }));
2785
+ }
2790
2786
 
2791
2787
  var LoginStateName;
2792
2788
  (function (LoginStateName) {
@@ -2796,432 +2792,615 @@ var LoginStateName;
2796
2792
  })(LoginStateName || (LoginStateName = {}));
2797
2793
 
2798
2794
  /**
2795
+ * Service to monitor the online/offline state of the application.
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.
2802
+ */
2803
+ class ConnectionService {
2804
+ /**
2805
+ * @ignore
2806
+ */
2807
+ constructor() {
2808
+ this.currentState = {
2809
+ isOnline: window.navigator.onLine
2810
+ };
2811
+ this.connectionStateSource = new ReplaySubject();
2812
+ this.connection$ = this.connectionStateSource.asObservable();
2813
+ this.connectionStateSource.next(this.currentState);
2814
+ fromEvent(window, 'online').subscribe(() => {
2815
+ this.currentState.isOnline = true;
2816
+ this.connectionStateSource.next(this.currentState);
2817
+ });
2818
+ fromEvent(window, 'offline').subscribe(() => {
2819
+ this.currentState.isOnline = false;
2820
+ this.connectionStateSource.next(this.currentState);
2821
+ });
2822
+ }
2823
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConnectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2824
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConnectionService, providedIn: 'root' }); }
2825
+ }
2826
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ConnectionService, decorators: [{
2827
+ type: Injectable,
2828
+ args: [{
2829
+ providedIn: 'root'
2830
+ }]
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
2799
2869
  * @ignore
2800
2870
  */
2801
- const CUSTOM_CONFIG = new InjectionToken('CUSTOM_CONFIG', {
2802
- factory: () => ({ main: ['assets/_yuuvis/config/main.json'], translations: ['assets/_yuuvis/i18n/'] })
2803
- });
2804
- const CORE_CONFIG = new InjectionToken('CORE_CONFIG');
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
+ }] });
2805
2881
 
2806
2882
  /**
2807
- * @ignore
2883
+ * i18n packages
2808
2884
  */
2809
- let CoreConfig = class CoreConfig {
2810
- constructor(__config) {
2811
- this.main = ['assets/_yuuvis/config/main.json'];
2812
- this.translations = ['assets/_yuuvis/i18n/'];
2813
- this.environment = { production: true };
2814
- Object.assign(this, __config);
2815
- }
2816
- };
2817
- CoreConfig = __decorate([
2818
- __param(0, Inject(CUSTOM_CONFIG)),
2819
- __metadata("design:paramtypes", [CoreConfig])
2820
- ], CoreConfig);
2821
-
2822
2885
  /**
2823
- * Service managing the configuarions for object types.
2824
- * Configuration means that you can pick certain fields
2825
- * of an object type and assign them to a config object.
2886
+ * Loader that fetches translations based on the configured locations
2887
+ * @ignore
2826
2888
  */
2827
- class ObjectConfigService {
2828
- constructor() {
2829
- this.#system = inject(SystemService);
2830
- this.#user = inject(UserService);
2831
- this.OBJECT_CONFIG_STORAGE_KEY = 'yuv.framework.object-config';
2832
- this.#objectConfigsSource = new ReplaySubject();
2833
- this.#objectConfigs$ = this.#objectConfigsSource.asObservable();
2834
- this.#defaultObjectConfigs = {};
2835
- this.#registeredDefaultObjectConfigs = {
2836
- main: {},
2837
- buckets: []
2838
- };
2839
- this.#objectConfigs = {
2840
- main: {},
2841
- buckets: []
2842
- };
2889
+ class EoxTranslateJsonLoader {
2890
+ constructor(http, config) {
2891
+ this.http = http;
2892
+ this.config = config;
2893
+ registerLocaleData(localeDe, 'de', localeExtraDe); // German
2894
+ registerLocaleData(localeAr, 'ar', localeExtraAr); // Arabic
2895
+ registerLocaleData(localeEs, 'es', localeExtraEs); // Spanish
2896
+ registerLocaleData(localePt, 'pt', localeExtraPt); // Portuguese
2897
+ registerLocaleData(localeFr, 'fr', localeExtraFr); // French
2898
+ registerLocaleData(localeZh, 'zh', localeExtraZh); // Chinese
2899
+ registerLocaleData(localeLv, 'lv', localeExtraLv); // Latvian
2900
+ registerLocaleData(localeRu, 'ru', localeExtraRu); // Russian
2901
+ registerLocaleData(localeIt, 'it', localeExtraIt); // Italian
2902
+ registerLocaleData(localeSk, 'sk', localeExtraSk); // Slovak
2903
+ registerLocaleData(localePl, 'pl', localeExtraPl); // Polish
2904
+ registerLocaleData(localeUk, 'uk', localeExtraUk); // Ukrainian
2905
+ registerLocaleData(localeJa, 'ja', localeExtraJa); // Japanese
2906
+ registerLocaleData(localeKo, 'ko', localeExtraKo); // Korean
2907
+ registerLocaleData(localeHi, 'hi', localeExtraHi); // Hindi
2908
+ registerLocaleData(localeBn, 'bn', localeExtraBn); // Bengalese
2909
+ registerLocaleData(localeVi, 'vi', localeExtraVi); // Vietnamese
2910
+ registerLocaleData(localeTr, 'tr', localeExtraTr); // Turkish
2911
+ registerLocaleData(localeNl, 'nl', localeExtraNl); // Dutch
2912
+ registerLocaleData(localeNb, 'nb', localeExtraNb); // Norwegian
2913
+ registerLocaleData(localeTh, 'th', localeExtraTh); // Thai
2914
+ registerLocaleData(localeFi, 'fi', localeExtraFi); // Finnish
2915
+ registerLocaleData(localeSv, 'sv', localeExtraSv); // Swedish
2916
+ registerLocaleData(localeDeCh, 'de-CH', localeExtraDeCh); // German Swiss
2843
2917
  }
2844
- #system;
2845
- #user;
2846
- #objectConfigsSource;
2847
- #objectConfigs$;
2848
- #defaultObjectConfigs;
2849
- #registeredDefaultObjectConfigs;
2850
- #objectConfigs;
2851
- #isValidObjectConfig(soc) {
2852
- return coerceBooleanProperty(soc && Object.hasOwn(soc, 'main') && Object.hasOwn(soc, 'buckets'));
2918
+ /**
2919
+ *
2920
+ * @param string lang
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), {})));
2853
2926
  }
2854
- // called on core init (auth.service -> initApp)
2855
- init() {
2856
- return this.#user.loadObjectConfig().pipe(tap$1((res) => {
2857
- this.#getDefaultObjectConfig();
2858
- this.#objectConfigs = (this.#isValidObjectConfig(res) && res) || {
2859
- main: {},
2860
- buckets: []
2861
- };
2862
- this.#objectConfigsSource.next(this.#objectConfigs);
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({});
2863
2935
  }));
2864
2936
  }
2865
- getObjectConfigs$(bucket, includeDefaults) {
2866
- return this.#objectConfigs$.pipe(map$1((soc) => {
2867
- let ocr = soc.main;
2868
- const defaults = { ...this.#defaultObjectConfigs, ...this.#getRegisteredDefaults(bucket) };
2869
- if (bucket) {
2870
- const tileBucket = soc.buckets.find((b) => b.id === bucket);
2871
- if (tileBucket) {
2872
- ocr = tileBucket.configs;
2873
- if (includeDefaults)
2874
- Object.keys(ocr).forEach((k) => {
2875
- ocr[k] = { ...defaults[k], ...ocr[k] };
2876
- });
2877
- }
2878
- }
2879
- return includeDefaults ? { ...defaults, ...ocr } : { ...ocr };
2880
- }));
2937
+ 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 }); }
2938
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EoxTranslateJsonLoader }); }
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; }
2990
+ /**
2991
+ * Execute a search query ans transform the result to a SearchResult object
2992
+ * @param query The search query
2993
+ * @returns Observable of a SearchResult
2994
+ */
2995
+ search(query) {
2996
+ return this.searchRaw(query).pipe(map((res) => this.toSearchResult(res, query.size || SearchService.DEFAULT_QUERY_SIZE, query.from || 0)));
2881
2997
  }
2882
2998
  /**
2883
- * Register default object configs. Apps can pre-define how their
2884
- * objects should be rendered.
2885
- * @param bucket Name of a bucket to bind configs to (usually the ID of the app) to
2886
- * separate the configs from other apps. If not provided configs will be saved for
2887
- * the global scope
2999
+ * Execute a raw search query and return the result as is.
3000
+ * @param query The search query
3001
+ * @returns Observable of the raw search result
2888
3002
  */
2889
- registerDefaults(configs, bucket) {
2890
- if (bucket) {
2891
- // does bucket exist?
2892
- const tileBucketIdx = this.#registeredDefaultObjectConfigs.buckets.findIndex((b) => b.id === bucket);
2893
- if (tileBucketIdx !== -1) {
2894
- this.#registeredDefaultObjectConfigs.buckets[tileBucketIdx].configs = {
2895
- ...this.#registeredDefaultObjectConfigs.buckets[tileBucketIdx].configs,
2896
- ...configs
2897
- };
2898
- }
2899
- else {
2900
- this.#registeredDefaultObjectConfigs.buckets.push({
2901
- id: bucket,
2902
- configs
2903
- });
3003
+ searchRaw(query) {
3004
+ if (!query.size)
3005
+ query.size = SearchService.DEFAULT_QUERY_SIZE;
3006
+ return this.#backend.post(`/dms/objects/search`, query);
3007
+ }
3008
+ /**
3009
+ * Search for objects in the dms using CMIS like SQL syntax.
3010
+ * @param statement The query statement
3011
+ * @param size The number of items to return
3012
+ * @returns Observable of a SearchResult
3013
+ */
3014
+ searchCmis(statement, size = SearchService.DEFAULT_QUERY_SIZE, includePermissions = false) {
3015
+ return this.#executeCmisSearch(statement, size, 0, includePermissions);
3016
+ }
3017
+ #executeCmisSearch(statement, maxItems, skipCount = 0, includePermissions = false) {
3018
+ const payload = {
3019
+ query: {
3020
+ statement,
3021
+ skipCount,
3022
+ maxItems,
3023
+ handleDeletedDocuments: 'DELETED_DOCUMENTS_EXCLUDE'
2904
3024
  }
3025
+ };
3026
+ if (includePermissions) {
3027
+ payload.query.includePermissions = true;
2905
3028
  }
2906
- else {
2907
- this.#registeredDefaultObjectConfigs.main = { ...this.#registeredDefaultObjectConfigs.main, ...configs };
2908
- }
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
+ }
3036
+ /**
3037
+ * Fetch aggragations for a given query.
3038
+ * @param q The query
3039
+ * @param aggregations List of aggregations to be fetched (e.g. `enaio:objectTypeId`
3040
+ * to get an aggregation of object types)
3041
+ */
3042
+ aggregate(q, aggregations) {
3043
+ q.aggs = aggregations;
3044
+ return this.searchRaw(q).pipe(map((res) => this.#toAggregateResult(res, aggregations)));
2909
3045
  }
2910
- unregisterDefaults(configs, bucket) {
2911
- if (bucket) {
2912
- // does bucket exist?
2913
- const tileBucketIdx = this.#registeredDefaultObjectConfigs.buckets.findIndex((b) => b.id === bucket);
2914
- if (tileBucketIdx !== -1) {
2915
- this.#registeredDefaultObjectConfigs.buckets.splice(tileBucketIdx, 1);
2916
- }
2917
- }
2918
- else {
2919
- Object.keys(configs).forEach((key) => {
2920
- delete this.#registeredDefaultObjectConfigs.main[key];
3046
+ /**
3047
+ * Map search result from the backend to applications AggregateResult object
3048
+ * @param searchResponse The backend response
3049
+ * @param aggregations The aggregations to be fetched
3050
+ */
3051
+ #toAggregateResult(searchResponse, aggregations) {
3052
+ const agg = [];
3053
+ if (aggregations) {
3054
+ aggregations.forEach((a) => {
3055
+ const ag = {
3056
+ aggKey: a,
3057
+ entries: searchResponse.objects.map((o) => ({
3058
+ key: o.properties[a].value,
3059
+ count: o.properties['OBJECT_COUNT'].value
3060
+ }))
3061
+ };
3062
+ agg.push(ag);
2921
3063
  });
2922
3064
  }
3065
+ return {
3066
+ totalNumItems: searchResponse.totalNumItems,
3067
+ aggregations: agg
3068
+ };
2923
3069
  }
2924
- getRegisteredDefault(objectTypeId, bucket) {
2925
- if (bucket) {
2926
- const b = this.#registeredDefaultObjectConfigs.buckets.find((b) => b.id === bucket);
2927
- return b ? b.configs[objectTypeId] : undefined;
3070
+ /**
3071
+ * Go to a page of a search result.
3072
+ * @param query SearchQuery or CMIS query statement
3073
+ * @param page The number of the page to go to
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);
2928
3079
  }
2929
3080
  else {
2930
- return this.#registeredDefaultObjectConfigs.main[objectTypeId];
2931
- }
2932
- }
2933
- #getRegisteredDefaults(bucket) {
2934
- if (bucket) {
2935
- const defaultTileBucket = this.#registeredDefaultObjectConfigs.buckets.find((b) => b.id === bucket);
2936
- return defaultTileBucket?.configs || {};
3081
+ query.from = (page - 1) * (query.size || pageSize);
3082
+ return this.search(query);
2937
3083
  }
2938
- else
2939
- return this.#registeredDefaultObjectConfigs.main;
2940
3084
  }
2941
3085
  /**
2942
- * Get object config for an object type.
2943
- * @param objectTypeId ID of the object type to get the config for
2944
- * @param bucket Optional bucket ID to fetch the config from. Buckets
2945
- * define separated areas to store/receive those configs. This way
2946
- * components/apps can store different object configs than the ones
2947
- * used accross the whole client application.
3086
+ * Map search result from the backend to applications SearchResult object
3087
+ * @param searchResponse The backend response
2948
3088
  */
2949
- getObjectConfig(type, bucket) {
2950
- const b = bucket ? this.#objectConfigs.buckets.find((b) => b.id === bucket) : undefined;
2951
- const otr = b ? b.configs : this.#objectConfigs.main;
2952
- const oc = otr[type.id];
2953
- // return oc || this.#getRegisteredDefaults(bucket)[type.id];
2954
- // override icons by APP_SCHEMA-icons: temporary solution. Todo: remove when handling of custom svg-icons is clear!
2955
- const result = oc || this.#getRegisteredDefaults(bucket)[type.id] || this.#defaultObjectConfigs[type.id];
2956
- if (result?.icon)
2957
- result.icon = type.icon ? { svg: type.icon } : result.icon;
3089
+ toSearchResult(searchResponse, pageSize = SearchService.DEFAULT_QUERY_SIZE, skipCount = 0) {
3090
+ const resultListItems = [];
3091
+ const objectTypes = [];
3092
+ searchResponse.objects.forEach((o) => {
3093
+ const fields = new Map();
3094
+ // process properties section of result
3095
+ Object.keys(o.properties).forEach((key) => {
3096
+ let value = o.properties[key].value;
3097
+ if (o.properties[key].clvalue) {
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
+ };
2958
3164
  return result;
2959
3165
  }
2960
- saveObjectConfig(type, config, bucket) {
2961
- return this.saveObjectConfigs({ [type.id]: config }, bucket);
2962
- }
2963
- saveObjectConfigs(configs, bucket) {
2964
- this.#updateObjectConfig(configs, bucket);
2965
- return this.#user.saveObjectConfig(this.#objectConfigs);
2966
- }
2967
- #updateObjectConfig(configs, bucket) {
2968
- if (!this.#objectConfigs) {
2969
- this.#objectConfigs = {
2970
- main: {},
2971
- buckets: []
2972
- };
2973
- }
2974
- if (bucket) {
2975
- // does bucket exist?
2976
- const tileBucketIdx = this.#objectConfigs.buckets.findIndex((b) => b.id === bucket);
2977
- if (tileBucketIdx !== -1) {
2978
- Object.keys(configs).forEach((objectTypeId) => {
2979
- const config = configs[objectTypeId];
2980
- if (config) {
2981
- this.#objectConfigs.buckets[tileBucketIdx].configs[objectTypeId] = config;
2982
- }
2983
- else {
2984
- delete this.#objectConfigs.buckets[tileBucketIdx].configs[objectTypeId];
2985
- }
2986
- });
3166
+ /**
3167
+ * Maps data extracted from a search form to search filters. Every key of the form data object
3168
+ * will be mapped to a search filter.
3169
+ * @param formData form data
3170
+ * @returns Array of search filters
3171
+ */
3172
+ formDataToSearchFilter(formData) {
3173
+ const isRangeValue = (v) => {
3174
+ return typeof v === 'object' && v !== null && 'firstValue' in v && 'operator' in v;
3175
+ };
3176
+ const filters = [];
3177
+ Object.keys(formData).forEach((key) => {
3178
+ const value = formData[key];
3179
+ if (isRangeValue(value)) {
3180
+ const f = this.rangeValueToSearchFilter(value, key);
3181
+ if (f)
3182
+ filters.push(f);
2987
3183
  }
2988
3184
  else {
2989
- const newBucket = { id: bucket, configs: {} };
2990
- Object.keys(configs).forEach((objectTypeId) => {
2991
- const config = configs[objectTypeId];
2992
- if (config) {
2993
- newBucket.configs[objectTypeId] = config;
2994
- }
3185
+ filters.push({
3186
+ f: key,
3187
+ o: Array.isArray(value) ? Operator.IN : Operator.EQUAL,
3188
+ v1: value
2995
3189
  });
2996
- this.#objectConfigs.buckets.push(newBucket);
2997
3190
  }
3191
+ });
3192
+ return filters;
3193
+ }
3194
+ rangeValueToSearchFilter(value, property) {
3195
+ return this.#system.getObjectTypeField(property)?.propertyType === 'datetime'
3196
+ ? this.#dateRangeValueToSearchFilter(value, property)
3197
+ : {
3198
+ f: property,
3199
+ o: value.operator,
3200
+ v1: value.firstValue,
3201
+ v2: value.secondValue
3202
+ };
3203
+ }
3204
+ #dateRangeValueToSearchFilter(rv, property) {
3205
+ const v1 = rv.firstValue;
3206
+ const v2 = rv.secondValue;
3207
+ switch (rv.operator) {
3208
+ case Operator.EQUAL: {
3209
+ return {
3210
+ f: property,
3211
+ o: Operator.INTERVAL_INCLUDE_BOTH,
3212
+ v1: this.#dateToISOString(v1, 'start'),
3213
+ v2: this.#dateToISOString(v1, 'end')
3214
+ };
3215
+ }
3216
+ case Operator.GREATER_OR_EQUAL: {
3217
+ return {
3218
+ f: property,
3219
+ o: rv.operator,
3220
+ v1: this.#dateToISOString(v1)
3221
+ };
3222
+ }
3223
+ case Operator.LESS_OR_EQUAL: {
3224
+ return {
3225
+ f: property,
3226
+ o: rv.operator,
3227
+ v1: this.#dateToISOString(v1, 'end')
3228
+ };
3229
+ }
3230
+ case Operator.INTERVAL_INCLUDE_BOTH: {
3231
+ return {
3232
+ f: property,
3233
+ o: rv.operator,
3234
+ v1: this.#dateToISOString(v1, 'start'),
3235
+ v2: v2 ? this.#dateToISOString(v2, 'end') : ''
3236
+ };
3237
+ }
3238
+ default:
3239
+ return undefined;
2998
3240
  }
2999
- else {
3000
- Object.keys(configs).forEach((objectTypeId) => {
3001
- const config = configs[objectTypeId];
3002
- if (config) {
3003
- this.#objectConfigs.main[objectTypeId] = config;
3004
- }
3005
- else {
3006
- delete this.#objectConfigs.main[objectTypeId];
3007
- }
3008
- });
3009
- }
3010
- this.#objectConfigsSource.next(this.#objectConfigs);
3011
- }
3012
- getDefaultConfig(objectTypeID) {
3013
- return this.#defaultObjectConfigs[objectTypeID];
3014
- }
3015
- getResolvedObjectConfig(data, type, bucket, includeDefaults) {
3016
- const defaultCfg = this.#defaultObjectConfigs[data[BaseObjectTypeField.OBJECT_TYPE_ID]];
3017
- let oc = this.getObjectConfig(type, bucket) || defaultCfg;
3018
- if (includeDefaults)
3019
- oc = { ...defaultCfg, ...oc };
3020
- const res = {
3021
- id: data[BaseObjectTypeField.OBJECT_ID],
3022
- objectTypeId: data[BaseObjectTypeField.OBJECT_TYPE_ID],
3023
- actions: oc.actions,
3024
- badges: oc.badges,
3025
- instanceData: data
3026
- };
3027
- if (oc.title)
3028
- res.title = {
3029
- propertyName: oc.title.propertyName,
3030
- value: data[oc.title.propertyName]
3031
- };
3032
- if (oc.description)
3033
- res.description = {
3034
- propertyName: oc.description.propertyName,
3035
- value: data[oc.description.propertyName]
3036
- };
3037
- if (oc.icon)
3038
- res.icon = {
3039
- propertyName: 'custom',
3040
- value: oc.icon.svg
3041
- };
3042
- if (oc.meta)
3043
- res.meta = {
3044
- propertyName: oc.meta.propertyName,
3045
- value: data[oc.meta.propertyName]
3046
- };
3047
- if (oc.aside)
3048
- res.aside = {
3049
- propertyName: oc.aside.propertyName,
3050
- value: data[oc.aside.propertyName]
3051
- };
3052
- return res;
3053
3241
  }
3054
3242
  /**
3055
- * Load default/fallbac configs based on the object types and
3056
- * their first properties
3243
+ * 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.
3244
+ *
3245
+ * @param value
3246
+ * @param range
3247
+ * @private
3057
3248
  */
3058
- #getDefaultObjectConfig() {
3059
- this.#system.getObjectTypes(true).forEach((ot) => {
3060
- this.#defaultObjectConfigs[ot.id] = {
3061
- objectTypeId: ot.id,
3062
- title: this.#toObjectProperty(ot.fields[0]),
3063
- description: this.#toObjectProperty(ot.fields[1]),
3064
- meta: this.#toObjectProperty(ot.fields[2]),
3065
- aside: this.#toObjectProperty(ot.fields[3])
3066
- };
3067
- });
3068
- }
3069
- #toObjectProperty(field) {
3070
- return field
3071
- ? {
3072
- label: this.#system.getLocalizedLabel(field.id),
3073
- propertyName: field.id
3074
- }
3075
- : undefined;
3249
+ #dateToISOString(value, range = 'start') {
3250
+ const date = typeof value === 'string' ? new Date(value) : value;
3251
+ const offset = Utils.DEFAULT_TIME_OFFSET_V2; // T+23:59:59:999
3252
+ if (!Utils.isValidDate(date))
3253
+ return '';
3254
+ const isoDateString = date.toISOString();
3255
+ // const isoDateStringWithOffset = new Date(date.getTime() + offset).toISOString();
3256
+ switch (range) {
3257
+ case 'start':
3258
+ return isoDateString;
3259
+ case 'end':
3260
+ return isoDateString;
3261
+ default:
3262
+ return isoDateString;
3263
+ }
3076
3264
  }
3077
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ObjectConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3078
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ObjectConfigService, providedIn: 'root' }); }
3265
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3266
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchService, providedIn: 'root' }); }
3079
3267
  }
3080
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ObjectConfigService, decorators: [{
3268
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchService, decorators: [{
3081
3269
  type: Injectable,
3082
3270
  args: [{
3083
3271
  providedIn: 'root'
3084
3272
  }]
3085
3273
  }] });
3086
3274
 
3087
- const YUV_USER = new InjectionToken('Currently logged in user', {
3088
- factory: () => undefined
3089
- });
3090
- const provideUser = (user) => {
3091
- return { provide: YUV_USER, useValue: user };
3092
- };
3093
-
3094
3275
  /**
3095
- * Service handling authentication related issues.
3276
+ * Service providing access to the systems audit entries. Audits can be seen as the history of
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.
3096
3281
  */
3097
- class AuthService {
3098
- // user may have been fetched already in bootstrapping process
3099
- #userToken;
3100
- #eventService;
3101
- #userService;
3102
- #objectConfigService;
3103
- #appCache;
3104
- #systemService;
3105
- #localizationService;
3106
- #backend;
3107
- #INITIAL_REQUEST_STORAGE_KEY;
3108
- #USER_FETCH_URI;
3109
- #authenticated;
3110
- #authSource;
3111
- #authData;
3112
- constructor(coreConfig) {
3113
- this.coreConfig = coreConfig;
3114
- // user may have been fetched already in bootstrapping process
3115
- this.#userToken = inject(YUV_USER);
3116
- this.#eventService = inject(EventService);
3282
+ class AuditService {
3283
+ constructor() {
3284
+ this.#searchService = inject(SearchService);
3117
3285
  this.#userService = inject(UserService);
3118
- this.#objectConfigService = inject(ObjectConfigService);
3119
- this.#appCache = inject(AppCacheService);
3120
- this.#systemService = inject(SystemService);
3121
- this.#localizationService = inject(LocalizationService);
3122
- this.#backend = inject(BackendService);
3123
- this.#INITIAL_REQUEST_STORAGE_KEY = 'yuv.core.auth.initialrequest';
3124
- this.#USER_FETCH_URI = '/idm/whoami';
3125
- this.#authenticated = false;
3126
- this.#authSource = new BehaviorSubject(false);
3127
- this.authenticated$ = this.#authSource.asObservable();
3128
- }
3129
- isLoggedIn() {
3130
- return this.#authenticated;
3131
- }
3132
- /**
3133
- * Called while app/core is initialized (APP_INITIALIZER)
3134
- * @ignore
3135
- */
3136
- initUser() {
3137
- return this.fetchUser();
3138
- }
3139
- /**
3140
- * Get the current tenant or the previous one persisted locally
3141
- */
3142
- getTenant() {
3143
- return this.#authData?.tenant;
3144
- }
3145
- /**
3146
- * Fetch information about the user currently logged in
3147
- */
3148
- fetchUser() {
3149
- return (this.#userToken ? of(this.#userToken) : this.#backend.get(this.#USER_FETCH_URI)).pipe(tap(() => {
3150
- this.#authenticated = true;
3151
- this.#authSource.next(this.#authenticated);
3152
- }), switchMap((userJson) => this.#initApp(userJson)));
3286
+ // default number of items to be fetched
3287
+ this.DEFAULT_RES_SIZE = 20;
3288
+ // audit action codes that should be visible to regular users
3289
+ this.userAuditActions = [
3290
+ 100, // metadata created
3291
+ 101, // metadata created (with content)
3292
+ 110, // tag created
3293
+ 201, // content deleted
3294
+ 210, // tag deleted
3295
+ 300, // metadata updated
3296
+ 301, // content updated
3297
+ 302, // metadata and content updated
3298
+ 303, // content moved
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
+ ];
3153
3314
  }
3315
+ #searchService;
3316
+ #userService;
3154
3317
  /**
3155
- * Logs out the current user.
3318
+ * Get audit entries of a dms object
3319
+ * @param id The id of the object to get the audit entries for
3320
+ * @param options Options
3156
3321
  */
3157
- logout() {
3158
- this.#authenticated = false;
3159
- this.#authSource.next(this.#authenticated);
3160
- this.#eventService.trigger(YuvEventType.LOGOUT);
3322
+ getAuditEntries(id, options = {}) {
3323
+ const auditActions = this.getAuditActions(!!options.allActions, options?.skipActions);
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
3347
  }
3162
3348
  /**
3163
- * Persists the initial request URI. This is nessesary to be able to
3164
- * redirect the user to the requested page after authentication.
3165
- * This is done on app initialization (core-init).
3349
+ * Get an array of action codes that are provided by the service. Based on
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
3166
3353
  */
3167
- setInitialRequestUri() {
3168
- const ignore = ['/', '/index.html'];
3169
- const baseHref = Utils.getBaseHref();
3170
- // Check only the pathname against the ignore list so that auth callback
3171
- // query params (e.g. ?session_state=…) don't bypass the check.
3172
- let path = location.pathname.replace(baseHref, '');
3173
- path = !path.startsWith('/') ? `/${path}` : path;
3174
- if (!ignore.includes(path)) {
3175
- let uri = `${location.pathname}${location.search}`.replace(baseHref, '');
3176
- uri = !uri.startsWith('/') ? `/${uri}` : uri;
3177
- return this.#appCache.setItem(this.#INITIAL_REQUEST_STORAGE_KEY, {
3178
- uri: uri,
3179
- timestamp: Date.now()
3180
- });
3181
- }
3182
- return of(false);
3354
+ getAuditActions(allActions, skipActions) {
3355
+ const actions = allActions || this.#userService.isAdvancedUser ? [...this.userAuditActions, ...this.adminAuditActions] : this.userAuditActions;
3356
+ return actions.filter((a) => !skipActions || !skipActions.includes(a));
3183
3357
  }
3184
3358
  /**
3185
- * Get the URL that entered the app. May be a deep link that could then be
3186
- * picked up again after user has been authenticated.
3359
+ * Get a certain page for a former audits query.
3360
+ * @param auditsResult The result object of a former audits query
3361
+ * @param page The page to load
3187
3362
  */
3188
- getInitialRequestUri() {
3189
- return this.#appCache.getItem(this.#INITIAL_REQUEST_STORAGE_KEY);
3363
+ getPage(auditsResult, page) {
3364
+ const q = auditsResult.query;
3365
+ q.from = (page - 1) * (q.size || this.DEFAULT_RES_SIZE);
3366
+ return this.#fetchAudits(q);
3190
3367
  }
3191
- resetInitialRequestUri() {
3192
- return this.#appCache.removeItem(this.#INITIAL_REQUEST_STORAGE_KEY);
3368
+ #fetchAudits(q) {
3369
+ return this.#searchService.searchRaw(q).pipe(map((res) => ({
3370
+ query: q,
3371
+ items: res.objects.map((o) => ({
3372
+ action: o.properties[AuditField.ACTION].value,
3373
+ actionGroup: this.#getActionGroup(o.properties[AuditField.ACTION].value),
3374
+ detail: o.properties[AuditField.DETAIL].value,
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
+ })));
3193
3386
  }
3194
- /**
3195
- * Initialize/setup the application for a given user. This involves fetching
3196
- * settings and schema information.
3197
- * @param userJson Data retrieved from the backend
3198
- */
3199
- #initApp(userJson) {
3200
- return this.#userService.fetchUserSettings().pipe(switchMap((userSettings) => {
3201
- const currentUser = new YuvUser(userJson, userSettings);
3202
- this.#userService.setCurrentUser(currentUser);
3203
- this.#authData = {
3204
- tenant: currentUser.tenant,
3205
- language: currentUser.getClientLocale()
3206
- };
3207
- return forkJoin([
3208
- this.#localizationService.fetchLocalizations(),
3209
- this.#systemService.getSystemDefinition(this.#authData)
3210
- ]).pipe(switchMap(() => this.#objectConfigService.init()), map(() => currentUser));
3211
- }));
3387
+ #getActionGroup(action) {
3388
+ try {
3389
+ return parseInt(`${action}`.substr(0, 1));
3390
+ }
3391
+ catch {
3392
+ return -1;
3393
+ }
3212
3394
  }
3213
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuthService, deps: [{ token: CORE_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
3214
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuthService, providedIn: 'root' }); }
3395
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuditService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3396
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuditService, providedIn: 'root' }); }
3215
3397
  }
3216
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AuthService, decorators: [{
3398
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: AuditService, decorators: [{
3217
3399
  type: Injectable,
3218
3400
  args: [{
3219
3401
  providedIn: 'root'
3220
3402
  }]
3221
- }], ctorParameters: () => [{ type: CoreConfig, decorators: [{
3222
- type: Inject,
3223
- args: [CORE_CONFIG]
3224
- }] }] });
3403
+ }] });
3225
3404
 
3226
3405
  const ProcessAction = {
3227
3406
  complete: 'complete',
@@ -3264,18 +3443,16 @@ class BpmService {
3264
3443
  const pl = { ...payload, action: action };
3265
3444
  return this.#backend.put(`/bpm/tasks/${taskId}`, pl, ApiBase.apiWeb);
3266
3445
  }
3267
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BpmService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3268
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BpmService, providedIn: 'root' }); }
3446
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BpmService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3447
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BpmService, providedIn: 'root' }); }
3269
3448
  }
3270
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: BpmService, decorators: [{
3449
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: BpmService, decorators: [{
3271
3450
  type: Injectable,
3272
3451
  args: [{
3273
3452
  providedIn: 'root'
3274
3453
  }]
3275
3454
  }] });
3276
3455
 
3277
- const LOCALIZATION_COLUMNS = ['locale', 'label', 'description'];
3278
-
3279
3456
  // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
3280
3457
  const transformResponse = () => map((res) => (res.body ? res.body.objects.map((val) => val) : null));
3281
3458
  /**
@@ -3636,10 +3813,10 @@ class UploadService {
3636
3813
  this.#statusSource.next(this.#status);
3637
3814
  });
3638
3815
  }
3639
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3640
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UploadService, providedIn: 'root' }); }
3816
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UploadService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3817
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UploadService, providedIn: 'root' }); }
3641
3818
  }
3642
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UploadService, decorators: [{
3819
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UploadService, decorators: [{
3643
3820
  type: Injectable,
3644
3821
  args: [{
3645
3822
  providedIn: 'root'
@@ -4165,16 +4342,18 @@ class DmsService {
4165
4342
  #searchResultToDmsObject(resItem) {
4166
4343
  return new DmsObject(resItem);
4167
4344
  }
4168
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DmsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4169
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DmsService, providedIn: 'root' }); }
4345
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DmsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4346
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DmsService, providedIn: 'root' }); }
4170
4347
  }
4171
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DmsService, decorators: [{
4348
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DmsService, decorators: [{
4172
4349
  type: Injectable,
4173
4350
  args: [{
4174
4351
  providedIn: 'root'
4175
4352
  }]
4176
4353
  }] });
4177
4354
 
4355
+ const LOCALIZATION_COLUMNS = ['locale', 'label', 'description'];
4356
+
4178
4357
  class CatalogService {
4179
4358
  constructor() {
4180
4359
  this.#backend = inject(BackendService);
@@ -4398,10 +4577,10 @@ class CatalogService {
4398
4577
  }
4399
4578
  return result;
4400
4579
  }
4401
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CatalogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4402
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CatalogService, providedIn: 'root' }); }
4580
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CatalogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4581
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CatalogService, providedIn: 'root' }); }
4403
4582
  }
4404
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: CatalogService, decorators: [{
4583
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CatalogService, decorators: [{
4405
4584
  type: Injectable,
4406
4585
  args: [{
4407
4586
  providedIn: 'root'
@@ -4459,10 +4638,10 @@ class ClientCacheService {
4459
4638
  clear() {
4460
4639
  return this.#appCacheService.clear((k) => k.startsWith(this.#CLIENT_CACHE_PREFIX));
4461
4640
  }
4462
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ClientCacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4463
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ClientCacheService, providedIn: 'root' }); }
4641
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ClientCacheService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4642
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ClientCacheService, providedIn: 'root' }); }
4464
4643
  }
4465
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ClientCacheService, decorators: [{
4644
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ClientCacheService, decorators: [{
4466
4645
  type: Injectable,
4467
4646
  args: [{
4468
4647
  providedIn: 'root'
@@ -4554,82 +4733,16 @@ class ClipboardService {
4554
4733
  console.error('Failed to copy text: ', error);
4555
4734
  }
4556
4735
  }
4557
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4558
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ClipboardService, providedIn: 'root' }); }
4736
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ClipboardService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4737
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ClipboardService, providedIn: 'root' }); }
4559
4738
  }
4560
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ClipboardService, decorators: [{
4739
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ClipboardService, decorators: [{
4561
4740
  type: Injectable,
4562
4741
  args: [{
4563
4742
  providedIn: 'root'
4564
4743
  }]
4565
4744
  }] });
4566
4745
 
4567
- /**
4568
- * Service to monitor the online/offline state of the application.
4569
- * It listens to the browser's online and offline events and provides an observable
4570
- * to track the current connection state.
4571
- *
4572
- * An observable `connection$` is provided which emits the current connection state
4573
- * whenever the online or offline state changes. The initial state is determined by
4574
- * the `window.navigator.onLine` property.
4575
- */
4576
- class ConnectionService {
4577
- /**
4578
- * @ignore
4579
- */
4580
- constructor() {
4581
- this.currentState = {
4582
- isOnline: window.navigator.onLine
4583
- };
4584
- this.connectionStateSource = new ReplaySubject();
4585
- this.connection$ = this.connectionStateSource.asObservable();
4586
- this.connectionStateSource.next(this.currentState);
4587
- fromEvent(window, 'online').subscribe(() => {
4588
- this.currentState.isOnline = true;
4589
- this.connectionStateSource.next(this.currentState);
4590
- });
4591
- fromEvent(window, 'offline').subscribe(() => {
4592
- this.currentState.isOnline = false;
4593
- this.connectionStateSource.next(this.currentState);
4594
- });
4595
- }
4596
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConnectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4597
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConnectionService, providedIn: 'root' }); }
4598
- }
4599
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ConnectionService, decorators: [{
4600
- type: Injectable,
4601
- args: [{
4602
- providedIn: 'root'
4603
- }]
4604
- }], ctorParameters: () => [] });
4605
-
4606
- /**
4607
- * Providing functions,that are are injected at application startup and executed during app initialization.
4608
- */
4609
- const init_moduleFnc = () => {
4610
- const coreConfig = inject(CORE_CONFIG);
4611
- const logger = inject(Logger);
4612
- const http = inject(HttpClient);
4613
- const configService = inject(ConfigService);
4614
- const authService = inject(AuthService);
4615
- return authService.setInitialRequestUri().pipe(switchMap(() => coreConfig.main
4616
- ? !Array.isArray(coreConfig.main)
4617
- ? of([coreConfig.main])
4618
- : forkJoin([...coreConfig.main].map((uri) => http.get(`${Utils.getBaseHref()}${uri}`).pipe(catchError((e) => {
4619
- logger.error('failed to catch config file', e);
4620
- return of({});
4621
- }), map((res) => res)))).pipe(
4622
- // switchMap((configs: YuvConfig[]) => configService.extendConfig(configs)),
4623
- tap((configs) => configService.extendConfig(configs)), switchMap(() => authService.initUser().pipe(catchError((e) => {
4624
- authService.initError = {
4625
- status: e.status,
4626
- key: e.error.error
4627
- };
4628
- return of(true);
4629
- }))))
4630
- : of(false)));
4631
- };
4632
-
4633
4746
  var DeviceScreenOrientation;
4634
4747
  (function (DeviceScreenOrientation) {
4635
4748
  DeviceScreenOrientation["PORTRAIT"] = "portrait";
@@ -4777,10 +4890,10 @@ class DeviceService {
4777
4890
  // keyboard appears, so we dont't need to debounce
4778
4891
  return this.isMobile ? 0 : 500;
4779
4892
  }
4780
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4781
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DeviceService, providedIn: 'root' }); }
4893
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4894
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DeviceService, providedIn: 'root' }); }
4782
4895
  }
4783
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DeviceService, decorators: [{
4896
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DeviceService, decorators: [{
4784
4897
  type: Injectable,
4785
4898
  args: [{
4786
4899
  providedIn: 'root'
@@ -4980,10 +5093,10 @@ class IdmService {
4980
5093
  next: (cache) => (this.#userCache = cache || {})
4981
5094
  });
4982
5095
  }
4983
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: IdmService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4984
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: IdmService, providedIn: 'root' }); }
5096
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: IdmService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5097
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: IdmService, providedIn: 'root' }); }
4985
5098
  }
4986
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: IdmService, decorators: [{
5099
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: IdmService, decorators: [{
4987
5100
  type: Injectable,
4988
5101
  args: [{
4989
5102
  providedIn: 'root'
@@ -5170,10 +5283,10 @@ class ToastService {
5170
5283
  style.innerHTML = YuvToastStyles;
5171
5284
  this.document.head.appendChild(style);
5172
5285
  }
5173
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ToastService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
5174
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ToastService, providedIn: 'root' }); }
5286
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ToastService, deps: [{ token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Injectable }); }
5287
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ToastService, providedIn: 'root' }); }
5175
5288
  }
5176
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: ToastService, decorators: [{
5289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ToastService, decorators: [{
5177
5290
  type: Injectable,
5178
5291
  args: [{
5179
5292
  providedIn: 'root'
@@ -5298,10 +5411,10 @@ class NotificationService {
5298
5411
  }
5299
5412
  }
5300
5413
  }
5301
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5302
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationService, providedIn: 'root' }); }
5414
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: NotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5415
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: NotificationService, providedIn: 'root' }); }
5303
5416
  }
5304
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NotificationService, decorators: [{
5417
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: NotificationService, decorators: [{
5305
5418
  type: Injectable,
5306
5419
  args: [{
5307
5420
  providedIn: 'root'
@@ -5329,6 +5442,72 @@ class ObjectFormControl extends FormControl {
5329
5442
  }
5330
5443
  }
5331
5444
 
5445
+ const LOCK_TAG = LockField.LOCK_TAG;
5446
+ const LOCK_TAG_OWNER_INDEX = 4;
5447
+ function findLockTag(dmsObject) {
5448
+ const tags = dmsObject.data[BaseObjectTypeField.TAGS];
5449
+ return tags?.find((tag) => Array.isArray(tag) && tag[0] === LOCK_TAG);
5450
+ }
5451
+
5452
+ const DEFAULT_LOCK_OPTIONS = {
5453
+ lockTag: LockField.LOCK_TAG,
5454
+ state: 1,
5455
+ override: false,
5456
+ includeObjects: true
5457
+ };
5458
+
5459
+ /**
5460
+ * Service to lock and unlock DMS objects via the backend tag API.
5461
+ */
5462
+ class ObjectLockingService {
5463
+ #backend = inject(BackendService);
5464
+ #userService = inject(UserService);
5465
+ /**
5466
+ * Lock a DMS object by setting a lock tag with a given state.
5467
+ * @param id ID of the object to lock
5468
+ * @returns Observable emitting the updated tag data of the locked object
5469
+ * @see {@link ObjectLockingResponse}
5470
+ */
5471
+ lock(id) {
5472
+ const { lockTag, state, override, includeObjects } = DEFAULT_LOCK_OPTIONS;
5473
+ return this.#backend.post(`/api/dms/objects/${id}/tags/${lockTag}/state/${state}?overwrite=${override}&includeObjects=${includeObjects}`, undefined, ApiBase.none);
5474
+ }
5475
+ /**
5476
+ * Remove the lock tag from a DMS object.
5477
+ * @param id ID of the object to unlock
5478
+ * @param lockTag Tag identifier to remove; defaults to `LockField.LOCK_TAG`
5479
+ * @returns Observable that completes once the tag has been deleted
5480
+ */
5481
+ unlock(id, lockTag = LockField.LOCK_TAG) {
5482
+ return this.#backend.delete(`/api/dms/objects/${id}/tags/${lockTag}`, ApiBase.none);
5483
+ }
5484
+ /**
5485
+ * Inspect the lock state of a DMS object relative to the current user.
5486
+ * @param dmsObject Object to inspect
5487
+ * @returns `locked` flag, whether the current user is the lock owner, and the owner id when present.
5488
+ */
5489
+ getLockState(dmsObject) {
5490
+ const tag = findLockTag(dmsObject);
5491
+ if (!tag)
5492
+ return { locked: false, lockedByCurrentUser: false };
5493
+ const ownerId = tag[LOCK_TAG_OWNER_INDEX];
5494
+ const currentUser = this.#userService.getCurrentUser();
5495
+ return {
5496
+ locked: true,
5497
+ lockedByCurrentUser: !!ownerId && ownerId === currentUser?.id,
5498
+ ownerId
5499
+ };
5500
+ }
5501
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectLockingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5502
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectLockingService, providedIn: 'root' }); }
5503
+ }
5504
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ObjectLockingService, decorators: [{
5505
+ type: Injectable,
5506
+ args: [{
5507
+ providedIn: 'root'
5508
+ }]
5509
+ }] });
5510
+
5332
5511
  /**
5333
5512
  * EditingObserver service is used to track changes made inside the application, that should prevent
5334
5513
  * doing something or going somewhere before the changes are persisted or ignored. For example when
@@ -5438,10 +5617,10 @@ class PendingChangesService {
5438
5617
  this.#tasks = [];
5439
5618
  this.#tasksSource.next(this.#tasks);
5440
5619
  }
5441
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PendingChangesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5442
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PendingChangesService, providedIn: 'root' }); }
5620
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5621
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesService, providedIn: 'root' }); }
5443
5622
  }
5444
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PendingChangesService, decorators: [{
5623
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesService, decorators: [{
5445
5624
  type: Injectable,
5446
5625
  args: [{
5447
5626
  providedIn: 'root'
@@ -5459,10 +5638,10 @@ class PendingChangesGuard {
5459
5638
  // if there are no pending changes, just allow deactivation; else confirm first
5460
5639
  return !this.pendingChanges.check(component);
5461
5640
  }
5462
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PendingChangesGuard, deps: [{ token: PendingChangesService }], target: i0.ɵɵFactoryTarget.Injectable }); }
5463
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PendingChangesGuard, providedIn: 'root' }); }
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' }); }
5464
5643
  }
5465
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PendingChangesGuard, decorators: [{
5644
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PendingChangesGuard, decorators: [{
5466
5645
  type: Injectable,
5467
5646
  args: [{
5468
5647
  providedIn: 'root'
@@ -5617,10 +5796,10 @@ class DialogCloseGuard {
5617
5796
  dialogRef.disableClose = true;
5618
5797
  return merge(dialogRef.backdropClick(), dialogRef.keydownEvents().pipe(filter$1((event) => event.key === 'Escape'))).pipe(switchMap$1(() => of(this.#pendingChangesService.check())), map$1((canClose) => !canClose && dialogRef.close()));
5619
5798
  }
5620
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DialogCloseGuard, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5621
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DialogCloseGuard }); }
5799
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DialogCloseGuard, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5800
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DialogCloseGuard }); }
5622
5801
  }
5623
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DialogCloseGuard, decorators: [{
5802
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DialogCloseGuard, decorators: [{
5624
5803
  type: Injectable
5625
5804
  }] });
5626
5805
 
@@ -5638,10 +5817,10 @@ class TabGuardDirective {
5638
5817
  const hasPending = this.#pending.hasPendingTask();
5639
5818
  this.#tabGroup._tabs.forEach((tab, i) => (tab.disabled = hasPending && i !== activeIndex));
5640
5819
  }
5641
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TabGuardDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5642
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: TabGuardDirective, isStandalone: true, selector: "mat-tab-group[yuvTabGuardDisable]", ngImport: i0 }); }
5820
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TabGuardDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5821
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.12", type: TabGuardDirective, isStandalone: true, selector: "mat-tab-group[yuvTabGuardDisable]", ngImport: i0 }); }
5643
5822
  }
5644
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: TabGuardDirective, decorators: [{
5823
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: TabGuardDirective, decorators: [{
5645
5824
  type: Directive,
5646
5825
  args: [{
5647
5826
  selector: 'mat-tab-group[yuvTabGuardDisable]'
@@ -5692,10 +5871,10 @@ class PredictionService {
5692
5871
  }
5693
5872
  }), {})));
5694
5873
  }
5695
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PredictionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5696
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PredictionService, providedIn: 'root' }); }
5874
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PredictionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5875
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PredictionService, providedIn: 'root' }); }
5697
5876
  }
5698
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: PredictionService, decorators: [{
5877
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PredictionService, decorators: [{
5699
5878
  type: Injectable,
5700
5879
  args: [{
5701
5880
  providedIn: 'root'
@@ -5754,10 +5933,10 @@ class RetentionService {
5754
5933
  else
5755
5934
  return { underRetention: false };
5756
5935
  }
5757
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RetentionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5758
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RetentionService, providedIn: 'root' }); }
5936
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: RetentionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5937
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: RetentionService, providedIn: 'root' }); }
5759
5938
  }
5760
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RetentionService, decorators: [{
5939
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: RetentionService, decorators: [{
5761
5940
  type: Injectable,
5762
5941
  args: [{
5763
5942
  providedIn: 'root'
@@ -5946,10 +6125,10 @@ class SessionStorageService {
5946
6125
  }
5947
6126
  return res;
5948
6127
  }
5949
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SessionStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5950
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SessionStorageService, providedIn: 'root' }); }
6128
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SessionStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6129
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SessionStorageService, providedIn: 'root' }); }
5951
6130
  }
5952
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SessionStorageService, decorators: [{
6131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SessionStorageService, decorators: [{
5953
6132
  type: Injectable,
5954
6133
  args: [{
5955
6134
  providedIn: 'root'
@@ -5980,10 +6159,10 @@ class UserStorageService {
5980
6159
  #sanitizeSection(section) {
5981
6160
  return encodeURIComponent(section);
5982
6161
  }
5983
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5984
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserStorageService, providedIn: 'root' }); }
6162
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserStorageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6163
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserStorageService, providedIn: 'root' }); }
5985
6164
  }
5986
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: UserStorageService, decorators: [{
6165
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UserStorageService, decorators: [{
5987
6166
  type: Injectable,
5988
6167
  args: [{
5989
6168
  providedIn: 'root'
@@ -6001,16 +6180,16 @@ class LocaleDecimalPipe extends DecimalPipe {
6001
6180
  transform(value, digits, locale) {
6002
6181
  return super.transform(value, digits, locale || this.translate.getCurrentLang() || 'en');
6003
6182
  }
6004
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleDecimalPipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6005
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: LocaleDecimalPipe, isStandalone: true, name: "localeDecimal" }); }
6183
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleDecimalPipe, deps: [{ token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6184
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: LocaleDecimalPipe, isStandalone: true, name: "localeDecimal" }); }
6006
6185
  }
6007
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleDecimalPipe, decorators: [{
6186
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleDecimalPipe, decorators: [{
6008
6187
  type: Pipe,
6009
6188
  args: [{
6010
6189
  name: 'localeDecimal',
6011
6190
  standalone: true
6012
6191
  }]
6013
- }], ctorParameters: () => [{ type: i1.TranslateService }] });
6192
+ }], ctorParameters: () => [{ type: i1$1.TranslateService }] });
6014
6193
  /**
6015
6194
  * @ignore
6016
6195
  */
@@ -6022,17 +6201,17 @@ class LocalePercentPipe extends PercentPipe {
6022
6201
  transform(value, digits, locale) {
6023
6202
  return super.transform(value, digits, locale || this.translate.getCurrentLang() || 'en');
6024
6203
  }
6025
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocalePercentPipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6026
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: LocalePercentPipe, isStandalone: true, name: "localePercent", pure: false }); }
6204
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocalePercentPipe, deps: [{ token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6205
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: LocalePercentPipe, isStandalone: true, name: "localePercent", pure: false }); }
6027
6206
  }
6028
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocalePercentPipe, decorators: [{
6207
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocalePercentPipe, decorators: [{
6029
6208
  type: Pipe,
6030
6209
  args: [{
6031
6210
  name: 'localePercent',
6032
6211
  pure: false,
6033
6212
  standalone: true
6034
6213
  }]
6035
- }], ctorParameters: () => [{ type: i1.TranslateService }] });
6214
+ }], ctorParameters: () => [{ type: i1$1.TranslateService }] });
6036
6215
  /**
6037
6216
  * @ignore
6038
6217
  */
@@ -6044,16 +6223,16 @@ class LocaleCurrencyPipe extends CurrencyPipe {
6044
6223
  transform(value, currencyCode, display, digits, locale) {
6045
6224
  return super.transform(value, currencyCode, display, digits, locale || this.translate.getCurrentLang() || 'en');
6046
6225
  }
6047
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleCurrencyPipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6048
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: LocaleCurrencyPipe, isStandalone: true, name: "localeCurrency" }); }
6226
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleCurrencyPipe, deps: [{ token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6227
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: LocaleCurrencyPipe, isStandalone: true, name: "localeCurrency" }); }
6049
6228
  }
6050
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleCurrencyPipe, decorators: [{
6229
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleCurrencyPipe, decorators: [{
6051
6230
  type: Pipe,
6052
6231
  args: [{
6053
6232
  name: 'localeCurrency',
6054
6233
  standalone: true
6055
6234
  }]
6056
- }], ctorParameters: () => [{ type: i1.TranslateService }] });
6235
+ }], ctorParameters: () => [{ type: i1$1.TranslateService }] });
6057
6236
  class LocaleNumberPipe {
6058
6237
  constructor(translate) {
6059
6238
  this.translate = translate;
@@ -6089,16 +6268,16 @@ class LocaleNumberPipe {
6089
6268
  scale = typeof scale === 'number' ? scale : 2;
6090
6269
  return this.transform(value, grouping, pattern, scale, `1.${scale}-${scale}`);
6091
6270
  }
6092
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleNumberPipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6093
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: LocaleNumberPipe, isStandalone: true, name: "localeNumber" }); }
6271
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleNumberPipe, deps: [{ token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6272
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: LocaleNumberPipe, isStandalone: true, name: "localeNumber" }); }
6094
6273
  }
6095
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleNumberPipe, decorators: [{
6274
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleNumberPipe, decorators: [{
6096
6275
  type: Pipe,
6097
6276
  args: [{
6098
6277
  name: 'localeNumber',
6099
6278
  standalone: true
6100
6279
  }]
6101
- }], ctorParameters: () => [{ type: i1.TranslateService }] });
6280
+ }], ctorParameters: () => [{ type: i1$1.TranslateService }] });
6102
6281
 
6103
6282
  /**
6104
6283
  * This pipe transforms its input (supposed to be a file size in bytes) into a more
@@ -6126,10 +6305,10 @@ class FileSizePipe extends LocaleNumberPipe {
6126
6305
  const number = super.stringToNumber((match ? match[1] : value).trim());
6127
6306
  return isNaN(number) ? number : Math.round(number * Math.pow(1024, match ? sizes.indexOf(match[2]) : 0));
6128
6307
  }
6129
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FileSizePipe, deps: null, target: i0.ɵɵFactoryTarget.Pipe }); }
6130
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: FileSizePipe, isStandalone: true, name: "fileSize" }); }
6308
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: FileSizePipe, deps: null, target: i0.ɵɵFactoryTarget.Pipe }); }
6309
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: FileSizePipe, isStandalone: true, name: "fileSize" }); }
6131
6310
  }
6132
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FileSizePipe, decorators: [{
6311
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: FileSizePipe, decorators: [{
6133
6312
  type: Pipe,
6134
6313
  args: [{ name: 'fileSize', standalone: true }]
6135
6314
  }] });
@@ -6164,16 +6343,16 @@ class LocaleDatePipe {
6164
6343
  }
6165
6344
  }
6166
6345
  }
6167
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleDatePipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6168
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: LocaleDatePipe, isStandalone: true, name: "localeDate" }); }
6346
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleDatePipe, deps: [{ token: i1$1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); }
6347
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: LocaleDatePipe, isStandalone: true, name: "localeDate" }); }
6169
6348
  }
6170
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: LocaleDatePipe, decorators: [{
6349
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: LocaleDatePipe, decorators: [{
6171
6350
  type: Pipe,
6172
6351
  args: [{
6173
6352
  name: 'localeDate',
6174
6353
  standalone: true
6175
6354
  }]
6176
- }], ctorParameters: () => [{ type: i1.TranslateService }] });
6355
+ }], ctorParameters: () => [{ type: i1$1.TranslateService }] });
6177
6356
 
6178
6357
  /**
6179
6358
  * This pipe bypass security and trust the given value to be safe HTML.
@@ -6188,13 +6367,13 @@ class SafeHtmlPipe {
6188
6367
  transform(style) {
6189
6368
  return this.sanitizer.bypassSecurityTrustHtml(style);
6190
6369
  }
6191
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
6192
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: SafeHtmlPipe, isStandalone: true, name: "safeHtml" }); }
6370
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SafeHtmlPipe, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
6371
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: SafeHtmlPipe, isStandalone: true, name: "safeHtml" }); }
6193
6372
  }
6194
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SafeHtmlPipe, decorators: [{
6373
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SafeHtmlPipe, decorators: [{
6195
6374
  type: Pipe,
6196
6375
  args: [{ name: 'safeHtml', standalone: true }]
6197
- }], ctorParameters: () => [{ type: i1$1.DomSanitizer }] });
6376
+ }], ctorParameters: () => [{ type: i1$2.DomSanitizer }] });
6198
6377
  /**
6199
6378
  * This pipe bypass security and trust the given value to be a safe style URL, i.e. a value that can be used in hyperlinks or img src.
6200
6379
  * @example
@@ -6207,13 +6386,13 @@ class SafeUrlPipe {
6207
6386
  transform(url) {
6208
6387
  return this.sanitizer.bypassSecurityTrustResourceUrl(url);
6209
6388
  }
6210
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SafeUrlPipe, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
6211
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: SafeUrlPipe, isStandalone: true, name: "safeUrl" }); }
6389
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SafeUrlPipe, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe }); }
6390
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: SafeUrlPipe, isStandalone: true, name: "safeUrl" }); }
6212
6391
  }
6213
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SafeUrlPipe, decorators: [{
6392
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SafeUrlPipe, decorators: [{
6214
6393
  type: Pipe,
6215
6394
  args: [{ name: 'safeUrl', standalone: true }]
6216
- }], ctorParameters: () => [{ type: i1$1.DomSanitizer }] });
6395
+ }], ctorParameters: () => [{ type: i1$2.DomSanitizer }] });
6217
6396
 
6218
6397
  /**
6219
6398
  * @ignore
@@ -6222,10 +6401,10 @@ class KeysPipe {
6222
6401
  transform(value) {
6223
6402
  return Object.keys(value);
6224
6403
  }
6225
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: KeysPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
6226
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: KeysPipe, isStandalone: true, name: "keys", pure: false }); }
6404
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: KeysPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
6405
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.2.12", ngImport: i0, type: KeysPipe, isStandalone: true, name: "keys", pure: false }); }
6227
6406
  }
6228
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: KeysPipe, decorators: [{
6407
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: KeysPipe, decorators: [{
6229
6408
  type: Pipe,
6230
6409
  args: [{ name: 'keys', pure: false, standalone: true }]
6231
6410
  }] });
@@ -6258,10 +6437,10 @@ class NativeNotificationService {
6258
6437
  };
6259
6438
  }
6260
6439
  }
6261
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NativeNotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6262
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NativeNotificationService, providedIn: 'root' }); }
6440
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: NativeNotificationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6441
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: NativeNotificationService, providedIn: 'root' }); }
6263
6442
  }
6264
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: NativeNotificationService, decorators: [{
6443
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: NativeNotificationService, decorators: [{
6265
6444
  type: Injectable,
6266
6445
  args: [{
6267
6446
  providedIn: 'root'
@@ -6352,116 +6531,6 @@ function provideNavigationProtection() {
6352
6531
  return [provideBeforeUnloadProtection(), providePopstateDialogProtection()];
6353
6532
  }
6354
6533
 
6355
- /**
6356
- * Prevent app from running into 401 issues related to gateway timeouts.
6357
- */
6358
- function AuthInterceptorFnc(req, next) {
6359
- const userService = inject(UserService);
6360
- const auth = inject(AuthService);
6361
- return next(req).pipe(tap({
6362
- next: (event) => {
6363
- if (event instanceof HttpResponse) {
6364
- // do stuff with response if you want
6365
- }
6366
- },
6367
- error: (error) => {
6368
- if (error instanceof HttpErrorResponse || error.isHttpErrorResponse) {
6369
- if (error.status === 401) {
6370
- auth.logout();
6371
- userService.logout();
6372
- }
6373
- }
6374
- }
6375
- }));
6376
- }
6377
-
6378
- /**
6379
- * Http Offline interceptor trys to serving offline content for method/url
6380
- */
6381
- function OfflineInterceptorFnc(req, next) {
6382
- return next(req);
6383
- }
6384
-
6385
- /**
6386
- * Handles missing translations
6387
- * @ignore
6388
- */
6389
- class EoxMissingTranslationHandler {
6390
- handle(params) {
6391
- return '!missing key: ' + params.key;
6392
- }
6393
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EoxMissingTranslationHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
6394
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EoxMissingTranslationHandler }); }
6395
- }
6396
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EoxMissingTranslationHandler, decorators: [{
6397
- type: Injectable
6398
- }] });
6399
-
6400
- /**
6401
- * i18n packages
6402
- */
6403
- /**
6404
- * Loader that fetches translations based on the configured locations
6405
- * @ignore
6406
- */
6407
- class EoxTranslateJsonLoader {
6408
- constructor(http, config) {
6409
- this.http = http;
6410
- this.config = config;
6411
- registerLocaleData(localeDe, 'de', localeExtraDe); // German
6412
- registerLocaleData(localeAr, 'ar', localeExtraAr); // Arabic
6413
- registerLocaleData(localeEs, 'es', localeExtraEs); // Spanish
6414
- registerLocaleData(localePt, 'pt', localeExtraPt); // Portuguese
6415
- registerLocaleData(localeFr, 'fr', localeExtraFr); // French
6416
- registerLocaleData(localeZh, 'zh', localeExtraZh); // Chinese
6417
- registerLocaleData(localeLv, 'lv', localeExtraLv); // Latvian
6418
- registerLocaleData(localeRu, 'ru', localeExtraRu); // Russian
6419
- registerLocaleData(localeIt, 'it', localeExtraIt); // Italian
6420
- registerLocaleData(localeSk, 'sk', localeExtraSk); // Slovak
6421
- registerLocaleData(localePl, 'pl', localeExtraPl); // Polish
6422
- registerLocaleData(localeUk, 'uk', localeExtraUk); // Ukrainian
6423
- registerLocaleData(localeJa, 'ja', localeExtraJa); // Japanese
6424
- registerLocaleData(localeKo, 'ko', localeExtraKo); // Korean
6425
- registerLocaleData(localeHi, 'hi', localeExtraHi); // Hindi
6426
- registerLocaleData(localeBn, 'bn', localeExtraBn); // Bengalese
6427
- registerLocaleData(localeVi, 'vi', localeExtraVi); // Vietnamese
6428
- registerLocaleData(localeTr, 'tr', localeExtraTr); // Turkish
6429
- registerLocaleData(localeNl, 'nl', localeExtraNl); // Dutch
6430
- registerLocaleData(localeNb, 'nb', localeExtraNb); // Norwegian
6431
- registerLocaleData(localeTh, 'th', localeExtraTh); // Thai
6432
- registerLocaleData(localeFi, 'fi', localeExtraFi); // Finnish
6433
- registerLocaleData(localeSv, 'sv', localeExtraSv); // Swedish
6434
- registerLocaleData(localeDeCh, 'de-CH', localeExtraDeCh); // German Swiss
6435
- }
6436
- /**
6437
- *
6438
- * @param string lang
6439
- * @returns Observable<Object>
6440
- */
6441
- getTranslation(lang) {
6442
- const t = (this.config.translations || []).map((path) => this.loadTranslationFile(path, lang));
6443
- return forkJoin(t).pipe(map((res) => res.reduce((acc, x) => Object.assign(acc, x), {})));
6444
- }
6445
- loadTranslationFile(path, lang) {
6446
- const version = document.body.dataset['bt'] ?? document.body.dataset['version'];
6447
- const cacheBuster = version ? `?v=${version}` : '';
6448
- return this.http.get(`${Utils.getBaseHref()}${path}${lang}.json${cacheBuster}`).pipe(catchError(() => {
6449
- // ISO codes with more than 2 characters are sub-languages like de-CH.
6450
- // If there is no translation file for that sub-language we'll try to load
6451
- // the file for the base language (in this case de).
6452
- return lang.length > 2 ? this.loadTranslationFile(path, lang.substring(0, 2)) : of({});
6453
- }));
6454
- }
6455
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EoxTranslateJsonLoader, deps: [{ token: i1$2.HttpClient }, { token: CORE_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
6456
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EoxTranslateJsonLoader }); }
6457
- }
6458
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: EoxTranslateJsonLoader, decorators: [{
6459
- type: Injectable
6460
- }], ctorParameters: () => [{ type: i1$2.HttpClient }, { type: CoreConfig, decorators: [{
6461
- type: Inject,
6462
- args: [CORE_CONFIG]
6463
- }] }] });
6464
-
6465
6534
  const provideYuvClientCore = (options = { translations: [] }, customEvents, customEventsTrustedOrigin, disableBeforeUnloadProtection = false, disablePopstateDialogProtection = false) => {
6466
6535
  return makeEnvironmentProviders([
6467
6536
  provideTranslateService({
@@ -6487,5 +6556,5 @@ const provideYuvClientCore = (options = { translations: [] }, customEvents, cust
6487
6556
  * Generated bundle index. Do not edit.
6488
6557
  */
6489
6558
 
6490
- export { AFO_STATE, AVAILABLE_BACKEND_APPS, AdministrationRoles, ApiBase, AppCacheService, AuditField, AuditService, 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, DeviceScreenOrientation, DeviceService, DialogCloseGuard, Direction, DmsObject, DmsService, EventService, FileSizePipe, IdmService, InternalFieldType, KeysPipe, LOCALIZATION_COLUMNS, LocaleCurrencyPipe, LocaleDatePipe, LocaleDecimalPipe, LocaleNumberPipe, LocalePercentPipe, LocalizationService, Logger, LoginStateName, NativeNotificationService, NotificationService, ObjectConfigService, ObjectFormControl, ObjectFormControlWrapper, ObjectFormGroup, ObjectTag, ObjectTypeClassification, ObjectTypePropertyClassification, 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, init_moduleFnc, provideAvailabilityManagement, provideBeforeUnloadProtection, provideNavigationProtection, providePopstateDialogProtection, provideRequirements, provideUser, provideYuvClientCore };
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 };
6491
6560
  //# sourceMappingURL=yuuvis-client-core.mjs.map