vc-error-handlers 0.1.7 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/esm2020/lib/shared/components/chunk-unavailable/chunk-unavailable.component.mjs +26 -6
  2. package/esm2020/lib/shared/components/error-modal/error-modal.component.mjs +61 -0
  3. package/esm2020/lib/shared/components/page-not-found/page-not-found.component.mjs +27 -25
  4. package/esm2020/lib/shared/components/server-error/server-error.component.mjs +63 -6
  5. package/esm2020/lib/shared/components/session-expired/session-expired.component.mjs +11 -11
  6. package/esm2020/lib/shared/components/unauthorized/unauthorized.component.mjs +21 -22
  7. package/esm2020/lib/shared/constants/api-config.constants.mjs +43 -0
  8. package/esm2020/lib/shared/constants/error-handling.constants.mjs +19 -2
  9. package/esm2020/lib/shared/errorhandler/sentry-error.handler.mjs +15 -10
  10. package/esm2020/lib/shared/interceptors/http.interceptor.mjs +8 -3
  11. package/esm2020/lib/shared/services/global-error.service.mjs +115 -5
  12. package/esm2020/lib/shared/services/util.service.mjs +21 -0
  13. package/esm2020/lib/shared/types/global-error.types.mjs +1 -1
  14. package/esm2020/lib/ui-kit/snack-bar/snack-bar/snack-bar.component.mjs +1 -2
  15. package/esm2020/lib/vc-error-handlers.component.mjs +65 -10
  16. package/esm2020/lib/vc-error-handlers.module.mjs +6 -6
  17. package/esm2020/public-api.mjs +2 -2
  18. package/fesm2015/vc-error-handlers.mjs +552 -223
  19. package/fesm2015/vc-error-handlers.mjs.map +1 -1
  20. package/fesm2020/vc-error-handlers.mjs +550 -223
  21. package/fesm2020/vc-error-handlers.mjs.map +1 -1
  22. package/lib/shared/components/chunk-unavailable/chunk-unavailable.component.d.ts +10 -2
  23. package/lib/shared/components/error-modal/error-modal.component.d.ts +17 -0
  24. package/lib/shared/components/page-not-found/page-not-found.component.d.ts +5 -1
  25. package/lib/shared/components/server-error/server-error.component.d.ts +12 -5
  26. package/lib/shared/components/session-expired/session-expired.component.d.ts +1 -3
  27. package/lib/shared/components/unauthorized/unauthorized.component.d.ts +3 -1
  28. package/lib/shared/constants/api-config.constants.d.ts +19 -0
  29. package/lib/shared/constants/error-handling.constants.d.ts +18 -1
  30. package/lib/shared/errorhandler/sentry-error.handler.d.ts +5 -3
  31. package/lib/shared/services/global-error.service.d.ts +20 -1
  32. package/lib/shared/services/util.service.d.ts +6 -0
  33. package/lib/shared/types/global-error.types.d.ts +1 -1
  34. package/lib/vc-error-handlers.component.d.ts +15 -2
  35. package/lib/vc-error-handlers.module.d.ts +2 -2
  36. package/package.json +1 -1
  37. package/public-api.d.ts +1 -1
  38. package/esm2020/lib/shared/components/session-expired-modal/session-expired-modal.component.mjs +0 -48
  39. package/lib/shared/components/session-expired-modal/session-expired-modal.component.d.ts +0 -18
@@ -1,14 +1,14 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, Component, Directive, ViewChild, NgModule, Optional, InjectionToken, ErrorHandler } from '@angular/core';
2
+ import { Injectable, Component, Input, Directive, ViewChild, NgModule, Optional, InjectionToken, ErrorHandler } from '@angular/core';
3
3
  import { Subject, throwError } from 'rxjs';
4
- import * as i1 from '@vcomply/authorizer';
5
- import * as i4 from '@angular/common';
6
- import { CommonModule } from '@angular/common';
7
4
  import * as i3 from '@angular/router';
8
5
  import { NavigationStart, NavigationEnd, NavigationError } from '@angular/router';
9
- import { HTTP_INTERCEPTORS } from '@angular/common/http';
6
+ import * as i1 from '@vcomply/authorizer';
7
+ import * as i2 from '@angular/common';
8
+ import { CommonModule } from '@angular/common';
9
+ import { HttpResponse, HTTP_INTERCEPTORS } from '@angular/common/http';
10
10
  import * as Sentry from '@sentry/angular-ivy';
11
- import { timeout, catchError } from 'rxjs/operators';
11
+ import { timeout, tap, catchError } from 'rxjs/operators';
12
12
 
13
13
  class VcErrorHandlersService {
14
14
  constructor() { }
@@ -38,17 +38,182 @@ var ErrorStatusCode;
38
38
  ErrorStatusCode[ErrorStatusCode["JSChunkUnavailable"] = 600] = "JSChunkUnavailable";
39
39
  })(ErrorStatusCode || (ErrorStatusCode = {}));
40
40
 
41
- class GlobalErrorService {
41
+ const VCOMPLY_LOGO_URL = 'https://cdn.v-comply.com/logo/prod/v-logo.svg';
42
+ const API_TIMEOUT_TIME = 1000 * 15;
43
+ const ERROR_CONFIG = {
44
+ PAGE_NOT_FOUND: {
45
+ imageUrl: 'https://cdn.v-comply.com/application/images/Error-page-illustration.svg',
46
+ title: 'Oops!',
47
+ description: "The page you're looking for doesn't exist.",
48
+ details: 'Please check the URL or return to the homepage.',
49
+ buttonText: 'GO TO DASHBOARD',
50
+ },
51
+ UNAUTHORIZED: {
52
+ imageUrl: 'https://cdn.v-comply.com/application/images/Error-page-illustration.svg',
53
+ title: 'Oops!',
54
+ description: "You don't have permission to access this page.",
55
+ details: 'If you believe this is an error, please contact',
56
+ email: 'help@v-comply.com',
57
+ support: 'for support',
58
+ buttonText: 'CONTACT SUPPORT',
59
+ mail: 'mailto:help@v-comply.com',
60
+ },
61
+ SESSION_EXPIRED: {
62
+ heading: 'Session Expired!',
63
+ description: 'Your session has expired. Please log in again to continue using the app.',
64
+ buttonText: 'LOGIN',
65
+ },
66
+ CHUNK_UNAVAILABLE: {
67
+ heading: 'Oops!',
68
+ description: 'We are unable to load the data.',
69
+ buttonText: 'REFRESH',
70
+ },
71
+ SERVER_ERROR: {
72
+ imageUrl: 'https://cdn.v-comply.com/application/images/Error-page-illustration.svg',
73
+ title: 'Oops!',
74
+ description: 'We are unable to load the data.',
75
+ details: 'Please refresh this page or try again later.',
76
+ buttonText: 'REFRESH',
77
+ snackBarMessage: `Oops! Something went wrong. Please try again later.`,
78
+ },
79
+ NETWORK_UNAVAILABLE: {
80
+ offlineMessage: "You're currently offline.Please check your internet connection and try again.",
81
+ },
82
+ };
83
+
84
+ const PAGE_LEVEL_API_CONFIG = [
85
+ {
86
+ method: 'POST',
87
+ path: '/compliance_post',
88
+ query: { mode: 'xyz' },
89
+ body: { mode: 'abc' },
90
+ pageCodes: ['compliance:mr', 'risk:mr'],
91
+ },
92
+ {
93
+ method: 'GET',
94
+ path: '/compliance_post',
95
+ query: { mode: 'xyz' },
96
+ body: { mode: 'abc' },
97
+ pageCodes: ['compliance:mr', 'risk:mr'],
98
+ },
99
+ ];
100
+ const COMPONENT_LEVEL_API_CONFIG = [
101
+ {
102
+ method: 'GET',
103
+ path: '/organization/?mode=organisationUsersList',
104
+ query: { type: 'active' },
105
+ body: null,
106
+ },
107
+ {
108
+ method: 'GET',
109
+ path: '/organization/?mode=organisationUsersList',
110
+ query: { type: 'power_users' },
111
+ body: null,
112
+ },
113
+ {
114
+ method: 'GET',
115
+ path: '/organization/?mode=organisationUsersList',
116
+ query: { type: 'light_users' },
117
+ body: null,
118
+ },
119
+ {
120
+ method: 'GET',
121
+ path: '/organization/?mode=organisationUsersList',
122
+ query: { type: 'inactive' },
123
+ body: null,
124
+ },
125
+ ];
126
+
127
+ class SnackBarService {
42
128
  constructor() {
129
+ this.snackbarSubject = new Subject();
130
+ this.snackbarState = this.snackbarSubject.asObservable();
131
+ }
132
+ show(message, type) {
133
+ this.snackbarSubject.next({
134
+ show: true,
135
+ message,
136
+ icon: type,
137
+ });
138
+ }
139
+ hide() {
140
+ this.snackbarSubject.next({
141
+ show: false,
142
+ message: '',
143
+ icon: '',
144
+ });
145
+ }
146
+ }
147
+ SnackBarService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
148
+ SnackBarService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarService, providedIn: 'root' });
149
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarService, decorators: [{
150
+ type: Injectable,
151
+ args: [{
152
+ providedIn: 'root',
153
+ }]
154
+ }], ctorParameters: function () { return []; } });
155
+
156
+ class UtilsService {
157
+ isJsonSubset(parentJson, subsetJson) {
158
+ for (let key in subsetJson) {
159
+ if (!parentJson.hasOwnProperty(key) || parentJson[key] !== subsetJson[key]) {
160
+ return false;
161
+ }
162
+ }
163
+ return true;
164
+ }
165
+ }
166
+ UtilsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UtilsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
167
+ UtilsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UtilsService, providedIn: 'root' });
168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UtilsService, decorators: [{
169
+ type: Injectable,
170
+ args: [{
171
+ providedIn: 'root',
172
+ }]
173
+ }] });
174
+
175
+ class GlobalErrorService {
176
+ constructor(snackBarService, utilService, router) {
177
+ this.snackBarService = snackBarService;
178
+ this.utilService = utilService;
179
+ this.router = router;
43
180
  this.globalError$ = new Subject();
44
181
  this.localError$ = new Subject();
182
+ this.pageLevelApiConfig = PAGE_LEVEL_API_CONFIG;
183
+ this.componentLevelApiConfig = COMPONENT_LEVEL_API_CONFIG;
184
+ }
185
+ handleSoftErrors(event) {
186
+ const xData = event.headers.get('X-Data');
187
+ if (xData) {
188
+ const parsedData = JSON.parse(xData);
189
+ const statusCode = parsedData.statusCode;
190
+ const statusMessage = parsedData.message;
191
+ if (statusCode && statusCode !== 0) {
192
+ this.snackBarService.show(statusMessage || 'Error occurred', 'error');
193
+ }
194
+ }
45
195
  }
46
196
  handleError(error, request) {
47
197
  if (this.isUnauthenticated(error) ||
48
198
  this.isUnauthorizedAccess(error) ||
49
199
  this.isNetworkUnavailable(error)) {
50
- this.globalError$.next(error);
200
+ this.publishGlobalError(error);
51
201
  }
202
+ else if (this.isServerError(error)) {
203
+ this.handleServerError(error, request);
204
+ }
205
+ else {
206
+ this.handleSoftErrors(error);
207
+ }
208
+ }
209
+ isServerError(error) {
210
+ const serverErrorCodes = [
211
+ ErrorStatusCode.InternalServerError,
212
+ ErrorStatusCode.ServiceUnavailable,
213
+ ErrorStatusCode.BadGateway,
214
+ ErrorStatusCode.RequestTimeout,
215
+ ];
216
+ return serverErrorCodes.includes(error.status);
52
217
  }
53
218
  isUnauthenticated(error) {
54
219
  return error.status === ErrorStatusCode.Unauthenticated;
@@ -59,15 +224,89 @@ class GlobalErrorService {
59
224
  isNetworkUnavailable(error) {
60
225
  return error.status === ErrorStatusCode.NetworkUnavailable;
61
226
  }
227
+ handleServerError(error, request) {
228
+ if (this.isPageLevelError(error, request)) {
229
+ this.publishGlobalError(error);
230
+ }
231
+ else if (this.isComponentLevelError(error, request)) {
232
+ this.publishLocalError(error, request);
233
+ }
234
+ else {
235
+ this.showServerSnackBarError();
236
+ }
237
+ }
238
+ publishGlobalError(error) {
239
+ this.globalError$.next(error);
240
+ }
241
+ publishLocalError(error, request) {
242
+ this.localError$.next({ error, request });
243
+ }
244
+ showServerSnackBarError() {
245
+ const message = ERROR_CONFIG.SERVER_ERROR.snackBarMessage;
246
+ this.snackBarService.show(message, 'error');
247
+ }
248
+ isPageLevelError(error, request) {
249
+ const { method, path, query, body } = this.parseRequest(request);
250
+ const pageCode = this.getPageCode();
251
+ const isConfigMatched = this.pageLevelApiConfig.some((apiConfig) => {
252
+ if (apiConfig.method !== method)
253
+ return false;
254
+ if (apiConfig.path !== path)
255
+ return false;
256
+ const isQuerySubset = this.utilService.isJsonSubset(apiConfig.query, query);
257
+ if (!isQuerySubset)
258
+ return false;
259
+ const isBodyMatch = this.utilService.isJsonSubset(apiConfig.body, body);
260
+ if (!isBodyMatch)
261
+ return false;
262
+ return apiConfig.pageCodes.includes(pageCode);
263
+ });
264
+ return isConfigMatched;
265
+ }
266
+ isComponentLevelError(error, request) {
267
+ const { method, url: path, params, body } = request;
268
+ const query = {};
269
+ params.keys().forEach((key) => {
270
+ query[key] = params.get(key);
271
+ });
272
+ const isConfigFound = this.componentLevelApiConfig.some((apiConfig) => {
273
+ if (apiConfig.method !== method)
274
+ return false;
275
+ if (!path.includes(apiConfig.path))
276
+ return false;
277
+ const isQuerySubset = this.utilService.isJsonSubset(query, apiConfig.query);
278
+ if (!isQuerySubset)
279
+ return false;
280
+ if (apiConfig.body) {
281
+ const isBodyMatch = this.utilService.isJsonSubset(apiConfig.body, body);
282
+ if (!isBodyMatch)
283
+ return false;
284
+ }
285
+ return true;
286
+ });
287
+ return isConfigFound;
288
+ }
289
+ parseRequest(request) {
290
+ const { method, url: path, params, body } = request;
291
+ const query = {};
292
+ params.keys().forEach((key) => {
293
+ query[key] = params.get(key);
294
+ });
295
+ return { method, path, query, body };
296
+ }
297
+ getPageCode() {
298
+ const currentRoute = this.router.routerState.snapshot.root.firstChild;
299
+ return currentRoute?.data?.pageCode;
300
+ }
62
301
  }
63
- GlobalErrorService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
302
+ GlobalErrorService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, deps: [{ token: SnackBarService }, { token: UtilsService }, { token: i3.Router }], target: i0.ɵɵFactoryTarget.Injectable });
64
303
  GlobalErrorService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, providedIn: 'root' });
65
304
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: GlobalErrorService, decorators: [{
66
305
  type: Injectable,
67
306
  args: [{
68
307
  providedIn: 'root',
69
308
  }]
70
- }] });
309
+ }], ctorParameters: function () { return [{ type: SnackBarService }, { type: UtilsService }, { type: i3.Router }]; } });
71
310
 
72
311
  class AuthService {
73
312
  constructor(authorizer) {
@@ -103,77 +342,110 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
103
342
  }]
104
343
  }] });
105
344
 
106
- const VCOMPLY_IMAGE_URL = 'https://cdn.v-comply.com/logo/prod/v-logo.svg';
107
- const API_TIMEOUT_TIME = 1000 * 15;
108
- const ERROR_CONFIG = {
109
- PAGE_NOT_FOUND: {
110
- imageUrl: 'https://cdn.v-comply.com/application/images/Error-page-illustration.svg',
111
- title: 'Oops!',
112
- description: "The page you're looking for doesn't exist.",
113
- details: 'Please check the URL or return to the homepage.',
114
- buttonText: 'GO TO DASHBOARD',
115
- },
116
- UNAUTHORIZED: {
117
- imageUrl: 'https://cdn.v-comply.com/application/images/Error-page-illustration.svg',
118
- title: 'Oops!',
119
- description: "You don't have permission to access this page.",
120
- details: 'If you believe this is an error, please contact',
121
- email: 'help@v-comply.com',
122
- support: 'for support',
123
- buttonText: 'CONTACT SUPPORT',
124
- },
125
- SESSION_EXPIRED: {
126
- heading: 'Session Expired!',
127
- description: 'Your session has expired. Please log in again to continue using the app.',
128
- buttonText: 'LOGIN',
129
- },
130
- };
345
+ class SnackBarComponent {
346
+ constructor(snackbarService) {
347
+ this.snackbarService = snackbarService;
348
+ this.show = false;
349
+ this.message = '--';
350
+ this.icon = '';
351
+ this.type = 'alert';
352
+ this.icons = {
353
+ success: '',
354
+ warning: '',
355
+ info: '',
356
+ alert: '',
357
+ error: '',
358
+ };
359
+ }
360
+ ngOnInit() {
361
+ this.snackbarSubscription = this.snackbarService.snackbarState.subscribe((state) => {
362
+ if (state.icon && Object.keys(this.icons).includes(state?.icon)) {
363
+ this.icon = this.icons[state.icon];
364
+ this.type = state?.icon;
365
+ }
366
+ this.message = state.message;
367
+ this.show = state.show;
368
+ });
369
+ }
370
+ setAutoClose() {
371
+ setTimeout(() => {
372
+ this.show = false;
373
+ this.close();
374
+ }, 3000);
375
+ }
376
+ close() {
377
+ this.show = false;
378
+ this.snackbarService.hide();
379
+ }
380
+ ngOnDestroy() {
381
+ this.snackbarSubscription.unsubscribe();
382
+ }
383
+ }
384
+ SnackBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarComponent, deps: [{ token: SnackBarService }], target: i0.ɵɵFactoryTarget.Component });
385
+ SnackBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SnackBarComponent, selector: "app-snack-bar", ngImport: i0, template: "<div class=\"workflow-snackbar\" *ngIf=\"show\">\r\n <div class=\"workflow-snackbar-inner\">\r\n <div class=\"workflow-snackbarText\">\r\n <!-- &#xe914; -->\r\n <i class=\"icons\" [class]=\"type\" [innerHTML]=\"icon\"></i> <span [innerHTML]=\"message\">{{ message }}</span>\r\n </div>\r\n <button (click)=\"close()\">[ <span>Close</span> ]</button>\r\n </div>\r\n </div>", styles: ["::ng-deep .workflow-snackbar{position:fixed;top:20px;left:0;right:0;display:flex;align-items:center;justify-content:center;z-index:2147483647!important;pointer-events:none;animation:slide-top .3s cubic-bezier(.25,.46,.45,.94) both}::ng-deep .workflow-snackbar.white{background-color:#fff;color:#000;z-index:20}::ng-deep .workflow-snackbar.white button{color:#f6882f;font-size:11px;font-weight:400;pointer-events:all}::ng-deep .workflow-snackbar .workflow-snackbar-inner{display:flex;max-width:500px;min-width:450px;align-items:center;justify-content:space-between;padding:10px;background:#ffffff;border-radius:3px;box-shadow:0 0 10px #0003;min-height:55px;pointer-events:auto}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText{color:#161b2f;font-size:13px;display:flex;align-items:center;width:calc(100% - 70px)}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i{background:#f1f1f1;color:#d93b41;border-radius:50px;font-size:16px;width:30px;height:30px;text-align:center;line-height:28px;margin-right:10px;min-width:30px}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.success{color:#34aa44}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.warning{color:#f0b819}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.info{color:#1e5dd3}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.alert,::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.error{color:#d93b41}::ng-deep .workflow-snackbar .workflow-snackbar-inner button{background:transparent;border:none;font-size:11px;padding:0;position:relative;color:#747576;width:65px;text-align:right;cursor:pointer;text-transform:uppercase}::ng-deep .workflow-snackbar .workflow-snackbar-inner button span{color:#1e5dd3;font-weight:500}::ng-deep .workflow-snackbar .workflow-snackbar-inner button:focus{outline:none}@keyframes slide-top{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}\n"], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
386
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarComponent, decorators: [{
387
+ type: Component,
388
+ args: [{ selector: 'app-snack-bar', template: "<div class=\"workflow-snackbar\" *ngIf=\"show\">\r\n <div class=\"workflow-snackbar-inner\">\r\n <div class=\"workflow-snackbarText\">\r\n <!-- &#xe914; -->\r\n <i class=\"icons\" [class]=\"type\" [innerHTML]=\"icon\"></i> <span [innerHTML]=\"message\">{{ message }}</span>\r\n </div>\r\n <button (click)=\"close()\">[ <span>Close</span> ]</button>\r\n </div>\r\n </div>", styles: ["::ng-deep .workflow-snackbar{position:fixed;top:20px;left:0;right:0;display:flex;align-items:center;justify-content:center;z-index:2147483647!important;pointer-events:none;animation:slide-top .3s cubic-bezier(.25,.46,.45,.94) both}::ng-deep .workflow-snackbar.white{background-color:#fff;color:#000;z-index:20}::ng-deep .workflow-snackbar.white button{color:#f6882f;font-size:11px;font-weight:400;pointer-events:all}::ng-deep .workflow-snackbar .workflow-snackbar-inner{display:flex;max-width:500px;min-width:450px;align-items:center;justify-content:space-between;padding:10px;background:#ffffff;border-radius:3px;box-shadow:0 0 10px #0003;min-height:55px;pointer-events:auto}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText{color:#161b2f;font-size:13px;display:flex;align-items:center;width:calc(100% - 70px)}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i{background:#f1f1f1;color:#d93b41;border-radius:50px;font-size:16px;width:30px;height:30px;text-align:center;line-height:28px;margin-right:10px;min-width:30px}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.success{color:#34aa44}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.warning{color:#f0b819}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.info{color:#1e5dd3}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.alert,::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.error{color:#d93b41}::ng-deep .workflow-snackbar .workflow-snackbar-inner button{background:transparent;border:none;font-size:11px;padding:0;position:relative;color:#747576;width:65px;text-align:right;cursor:pointer;text-transform:uppercase}::ng-deep .workflow-snackbar .workflow-snackbar-inner button span{color:#1e5dd3;font-weight:500}::ng-deep .workflow-snackbar .workflow-snackbar-inner button:focus{outline:none}@keyframes slide-top{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}\n"] }]
389
+ }], ctorParameters: function () { return [{ type: SnackBarService }]; } });
131
390
 
132
391
  class DialogConfig {
133
392
  }
134
393
 
135
- class SessionExpiredModalComponent {
136
- constructor(dialogConfig, routerService) {
394
+ class ErrorModalComponent {
395
+ constructor(authService, dialogConfig, routerService) {
396
+ this.authService = authService;
137
397
  this.dialogConfig = dialogConfig;
138
398
  this.routerService = routerService;
139
- this.errorConfig = ERROR_CONFIG.SESSION_EXPIRED;
399
+ this.errorType = 'session_expired';
140
400
  this.data = {
141
- header: 'Message',
401
+ heading: 'Message',
142
402
  description: 'Description',
143
403
  buttonText: 'Click Action',
144
404
  };
145
- this.data = this.dialogConfig.data;
405
+ this.setDataConfig();
406
+ }
407
+ setDataConfig() {
408
+ this.data = this.dialogConfig.data?.errorConfig;
409
+ this.errorType = this.dialogConfig.data?.errorType;
146
410
  }
147
411
  onContinueAction() {
148
- this.routerService.redirectToLogin();
412
+ if (this.errorType === 'session_expired') {
413
+ this.authService.logoutUser();
414
+ this.routerService.redirectToLogin();
415
+ }
416
+ else if (this.errorType === 'chunk_not_found') {
417
+ window.location.reload();
418
+ }
149
419
  }
150
420
  }
151
- SessionExpiredModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SessionExpiredModalComponent, deps: [{ token: DialogConfig }, { token: RouterService }], target: i0.ɵɵFactoryTarget.Component });
152
- SessionExpiredModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SessionExpiredModalComponent, selector: "lib-vc-error-session-expired-modal", ngImport: i0, template: ` <div class="error-dialog-box">
153
- <div class="error-dialog-box-top">{{ errorConfig.heading }}</div>
421
+ ErrorModalComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ErrorModalComponent, deps: [{ token: AuthService }, { token: DialogConfig }, { token: RouterService }], target: i0.ɵɵFactoryTarget.Component });
422
+ ErrorModalComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ErrorModalComponent, selector: "lib-vc-error-modal", inputs: { errorType: "errorType" }, ngImport: i0, template: ` <div class="error-dialog-box">
423
+ <div class="error-dialog-box-top">{{ data.heading }}</div>
154
424
  <div class="error-dialog-box-mid">
155
- {{ errorConfig.description }}
425
+ {{ data.description }}
156
426
  </div>
157
427
  <div class="error-dialog-box-bottom">
158
428
  <button (click)="onContinueAction()" class="logIn-btn">
159
- {{ errorConfig.buttonText }}
429
+ {{ data.buttonText }}
160
430
  </button>
161
431
  </div>
162
432
  </div>`, isInline: true, styles: [".error-dialog-box{background:#fff;border-radius:.75rem;box-shadow:0 1px 10px #0003;width:27rem}.error-dialog-box-top{color:#000;font-size:16px;font-weight:500;border-radius:.75rem .75rem 0 0;display:flex;align-items:center;height:3.375rem;padding:0 1rem;margin-bottom:1rem}.error-dialog-box-mid{color:#565a6f;font-size:13px;min-height:5.5rem;padding:0 1rem}.error-dialog-box-bottom{display:flex;justify-content:end;padding:1rem}.error-dialog-box-bottom button.logIn-btn{background:#1e5dd3;border-radius:.125rem;border:none;color:#fff;cursor:pointer;font-size:11px;height:2rem;padding:.5rem .75rem}\n"] });
163
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SessionExpiredModalComponent, decorators: [{
433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ErrorModalComponent, decorators: [{
164
434
  type: Component,
165
- args: [{ selector: 'lib-vc-error-session-expired-modal', template: ` <div class="error-dialog-box">
166
- <div class="error-dialog-box-top">{{ errorConfig.heading }}</div>
435
+ args: [{ selector: 'lib-vc-error-modal', template: ` <div class="error-dialog-box">
436
+ <div class="error-dialog-box-top">{{ data.heading }}</div>
167
437
  <div class="error-dialog-box-mid">
168
- {{ errorConfig.description }}
438
+ {{ data.description }}
169
439
  </div>
170
440
  <div class="error-dialog-box-bottom">
171
441
  <button (click)="onContinueAction()" class="logIn-btn">
172
- {{ errorConfig.buttonText }}
442
+ {{ data.buttonText }}
173
443
  </button>
174
444
  </div>
175
445
  </div>`, styles: [".error-dialog-box{background:#fff;border-radius:.75rem;box-shadow:0 1px 10px #0003;width:27rem}.error-dialog-box-top{color:#000;font-size:16px;font-weight:500;border-radius:.75rem .75rem 0 0;display:flex;align-items:center;height:3.375rem;padding:0 1rem;margin-bottom:1rem}.error-dialog-box-mid{color:#565a6f;font-size:13px;min-height:5.5rem;padding:0 1rem}.error-dialog-box-bottom{display:flex;justify-content:end;padding:1rem}.error-dialog-box-bottom button.logIn-btn{background:#1e5dd3;border-radius:.125rem;border:none;color:#fff;cursor:pointer;font-size:11px;height:2rem;padding:.5rem .75rem}\n"] }]
176
- }], ctorParameters: function () { return [{ type: DialogConfig }, { type: RouterService }]; } });
446
+ }], ctorParameters: function () { return [{ type: AuthService }, { type: DialogConfig }, { type: RouterService }]; }, propDecorators: { errorType: [{
447
+ type: Input
448
+ }] } });
177
449
 
178
450
  class InsertionDirective {
179
451
  constructor(viewContainerRef) {
@@ -267,7 +539,7 @@ class DialogComponent {
267
539
  }
268
540
  }
269
541
  DialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: DialogComponent, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.ChangeDetectorRef }, { token: DialogRef }, { token: DialogConfig }, { token: i3.Router }], target: i0.ɵɵFactoryTarget.Component });
270
- DialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: DialogComponent, selector: "app-dialog", viewQueries: [{ propertyName: "insertionPoint", first: true, predicate: InsertionDirective, descendants: true, static: true }], ngImport: i0, template: "<div\r\n class=\"overlay\"\r\n (click)=\"onOverlayClicked($event)\"\r\n [ngClass]=\"{\r\n top: position === 'TOP',\r\n right: position === 'RIGHT',\r\n bottom: position === 'BOTTOM',\r\n left: position === 'LEFT',\r\n center: position === 'CENTER',\r\n black: background === 'black',\r\n whiteBlur: background === 'whiteBlur'\r\n }\" [class.pointer-none]=\"pointer === 'none'\"\r\n>\r\n <div\r\n class=\"dialog\"\r\n [class.animate]=\"animation\"\r\n (click)=\"onDialogClicked($event)\"\r\n [ngClass]=\"{\r\n top: position === 'TOP',\r\n right: position === 'RIGHT',\r\n bottom: position === 'BOTTOM',\r\n left: position === 'LEFT',\r\n center: position === 'CENTER'\r\n }\"\r\n >\r\n <ng-template appInsertion></ng-template>\r\n </div>\r\n</div>\r\n", styles: [".overlay{display:flex;position:fixed;top:0;bottom:0;left:0;right:0;align-items:center;justify-content:center;z-index:2147483009!important}.overlay.low{z-index:1}.overlay.black{background:#161b2fcc}.overlay.whiteBlur{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.overlay.top{align-items:flex-start}.overlay.right{justify-content:flex-end}.overlay.bottom{align-items:flex-end}.overlay.left{justify-content:flex-start}.dialog{position:relative}.dialog.animate.top{animation:animate-top .2s cubic-bezier(.25,.46,.45,.94) both}@keyframes animate-top{0%{transform:translateY(-100px)}to{transform:translateY(0)}}.dialog.animate.right{animation:animate-right .2s cubic-bezier(.25,.46,.45,.94) both}@keyframes animate-right{0%{transform:translate(100%)}to{transform:translate(0)}}.pointer-none{pointer-events:none}\n"], directives: [{ type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: InsertionDirective, selector: "[appInsertion]" }] });
542
+ DialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: DialogComponent, selector: "app-dialog", viewQueries: [{ propertyName: "insertionPoint", first: true, predicate: InsertionDirective, descendants: true, static: true }], ngImport: i0, template: "<div\r\n class=\"overlay\"\r\n (click)=\"onOverlayClicked($event)\"\r\n [ngClass]=\"{\r\n top: position === 'TOP',\r\n right: position === 'RIGHT',\r\n bottom: position === 'BOTTOM',\r\n left: position === 'LEFT',\r\n center: position === 'CENTER',\r\n black: background === 'black',\r\n whiteBlur: background === 'whiteBlur'\r\n }\" [class.pointer-none]=\"pointer === 'none'\"\r\n>\r\n <div\r\n class=\"dialog\"\r\n [class.animate]=\"animation\"\r\n (click)=\"onDialogClicked($event)\"\r\n [ngClass]=\"{\r\n top: position === 'TOP',\r\n right: position === 'RIGHT',\r\n bottom: position === 'BOTTOM',\r\n left: position === 'LEFT',\r\n center: position === 'CENTER'\r\n }\"\r\n >\r\n <ng-template appInsertion></ng-template>\r\n </div>\r\n</div>\r\n", styles: [".overlay{display:flex;position:fixed;top:0;bottom:0;left:0;right:0;align-items:center;justify-content:center;z-index:2147483009!important}.overlay.low{z-index:1}.overlay.black{background:#161b2fcc}.overlay.whiteBlur{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.overlay.top{align-items:flex-start}.overlay.right{justify-content:flex-end}.overlay.bottom{align-items:flex-end}.overlay.left{justify-content:flex-start}.dialog{position:relative}.dialog.animate.top{animation:animate-top .2s cubic-bezier(.25,.46,.45,.94) both}@keyframes animate-top{0%{transform:translateY(-100px)}to{transform:translateY(0)}}.dialog.animate.right{animation:animate-right .2s cubic-bezier(.25,.46,.45,.94) both}@keyframes animate-right{0%{transform:translate(100%)}to{transform:translate(0)}}.pointer-none{pointer-events:none}\n"], directives: [{ type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: InsertionDirective, selector: "[appInsertion]" }] });
271
543
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: DialogComponent, decorators: [{
272
544
  type: Component,
273
545
  args: [{ selector: 'app-dialog', template: "<div\r\n class=\"overlay\"\r\n (click)=\"onOverlayClicked($event)\"\r\n [ngClass]=\"{\r\n top: position === 'TOP',\r\n right: position === 'RIGHT',\r\n bottom: position === 'BOTTOM',\r\n left: position === 'LEFT',\r\n center: position === 'CENTER',\r\n black: background === 'black',\r\n whiteBlur: background === 'whiteBlur'\r\n }\" [class.pointer-none]=\"pointer === 'none'\"\r\n>\r\n <div\r\n class=\"dialog\"\r\n [class.animate]=\"animation\"\r\n (click)=\"onDialogClicked($event)\"\r\n [ngClass]=\"{\r\n top: position === 'TOP',\r\n right: position === 'RIGHT',\r\n bottom: position === 'BOTTOM',\r\n left: position === 'LEFT',\r\n center: position === 'CENTER'\r\n }\"\r\n >\r\n <ng-template appInsertion></ng-template>\r\n </div>\r\n</div>\r\n", styles: [".overlay{display:flex;position:fixed;top:0;bottom:0;left:0;right:0;align-items:center;justify-content:center;z-index:2147483009!important}.overlay.low{z-index:1}.overlay.black{background:#161b2fcc}.overlay.whiteBlur{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px)}.overlay.top{align-items:flex-start}.overlay.right{justify-content:flex-end}.overlay.bottom{align-items:flex-end}.overlay.left{justify-content:flex-start}.dialog{position:relative}.dialog.animate.top{animation:animate-top .2s cubic-bezier(.25,.46,.45,.94) both}@keyframes animate-top{0%{transform:translateY(-100px)}to{transform:translateY(0)}}.dialog.animate.right{animation:animate-right .2s cubic-bezier(.25,.46,.45,.94) both}@keyframes animate-right{0%{transform:translate(100%)}to{transform:translate(0)}}.pointer-none{pointer-events:none}\n"] }]
@@ -352,24 +624,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
352
624
  }], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }]; } });
353
625
 
354
626
  class SessionExpiredComponent {
355
- constructor(authService, dialogService) {
356
- this.authService = authService;
627
+ constructor(dialogService) {
357
628
  this.dialogService = dialogService;
358
629
  this.errorConfig = ERROR_CONFIG.SESSION_EXPIRED;
359
630
  }
360
631
  ngOnInit() {
361
- this.authService.logoutUser();
362
632
  this.openSessionExpiredModal();
363
633
  }
364
634
  openSessionExpiredModal() {
365
- this.dialogService.open(SessionExpiredModalComponent, {
366
- data: this.errorConfig,
635
+ this.dialogService.open(ErrorModalComponent, {
636
+ data: {
637
+ errorType: 'session_expired',
638
+ errorConfig: this.errorConfig,
639
+ },
367
640
  position: 'center',
368
641
  background: 'whiteBlur',
369
642
  });
370
643
  }
371
644
  }
372
- SessionExpiredComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SessionExpiredComponent, deps: [{ token: AuthService }, { token: DialogService }], target: i0.ɵɵFactoryTarget.Component });
645
+ SessionExpiredComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SessionExpiredComponent, deps: [{ token: DialogService }], target: i0.ɵɵFactoryTarget.Component });
373
646
  SessionExpiredComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SessionExpiredComponent, selector: "lib-vc-error-session-expired", ngImport: i0, template: ``, isInline: true });
374
647
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SessionExpiredComponent, decorators: [{
375
648
  type: Component,
@@ -377,25 +650,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
377
650
  selector: 'lib-vc-error-session-expired',
378
651
  template: ``,
379
652
  }]
380
- }], ctorParameters: function () { return [{ type: AuthService }, { type: DialogService }]; } });
653
+ }], ctorParameters: function () { return [{ type: DialogService }]; } });
381
654
 
382
655
  class UnauthorizedComponent {
383
656
  constructor() {
657
+ this.currentYear = new Date().getFullYear();
384
658
  this.errorConfig = ERROR_CONFIG.UNAUTHORIZED;
385
- this.VcomplyImage = VCOMPLY_IMAGE_URL;
659
+ this.VcomplyLogo = VCOMPLY_LOGO_URL;
660
+ }
661
+ redirectToSupport() {
662
+ window.location.href = this.errorConfig.mail;
386
663
  }
387
- redirectToSupport() { }
388
664
  }
389
665
  UnauthorizedComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UnauthorizedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
390
666
  UnauthorizedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: UnauthorizedComponent, selector: "lib-vc-error-unauthorized", ngImport: i0, template: `
391
667
  <div class="errorPage">
392
668
  <div class="errorPage-top">
393
- <img
394
- src="https://cdn.v-comply.com/logo/prod/v-logo.svg"
395
- alt="VComply"
396
- width="24"
397
- height="24"
398
- />
669
+ <img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
399
670
  </div>
400
671
  <div class="errorPage-container">
401
672
  <div class="errorPage-inner">
@@ -403,8 +674,8 @@ UnauthorizedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0",
403
674
  <img
404
675
  [src]="errorConfig.imageUrl"
405
676
  alt="Error Image"
406
- width="256"
407
- height="256"
677
+ width="246"
678
+ height="178"
408
679
  />
409
680
  </div>
410
681
  <div class="errorPage-inner-right">
@@ -420,20 +691,18 @@ UnauthorizedComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0",
420
691
  </button>
421
692
  </div>
422
693
  </div>
694
+ <div class="errorPage-copyright">
695
+ &copy;&nbsp;{{ currentYear }}, VCOMPLY TECHNOLOGIES, INC.
696
+ </div>
423
697
  </div>
424
698
  </div>
425
- `, isInline: true, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}\n"] });
699
+ `, isInline: true, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] });
426
700
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: UnauthorizedComponent, decorators: [{
427
701
  type: Component,
428
702
  args: [{ selector: 'lib-vc-error-unauthorized', template: `
429
703
  <div class="errorPage">
430
704
  <div class="errorPage-top">
431
- <img
432
- src="https://cdn.v-comply.com/logo/prod/v-logo.svg"
433
- alt="VComply"
434
- width="24"
435
- height="24"
436
- />
705
+ <img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
437
706
  </div>
438
707
  <div class="errorPage-container">
439
708
  <div class="errorPage-inner">
@@ -441,8 +710,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
441
710
  <img
442
711
  [src]="errorConfig.imageUrl"
443
712
  alt="Error Image"
444
- width="256"
445
- height="256"
713
+ width="246"
714
+ height="178"
446
715
  />
447
716
  </div>
448
717
  <div class="errorPage-inner-right">
@@ -458,19 +727,138 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
458
727
  </button>
459
728
  </div>
460
729
  </div>
730
+ <div class="errorPage-copyright">
731
+ &copy;&nbsp;{{ currentYear }}, VCOMPLY TECHNOLOGIES, INC.
732
+ </div>
733
+ </div>
734
+ </div>
735
+ `, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] }]
736
+ }] });
737
+
738
+ class ChunkUnavailableComponent {
739
+ constructor(dialogService) {
740
+ this.dialogService = dialogService;
741
+ this.errorConfig = ERROR_CONFIG.CHUNK_UNAVAILABLE;
742
+ }
743
+ ngOnInit() {
744
+ this.openSessionExpiredModal();
745
+ }
746
+ openSessionExpiredModal() {
747
+ this.dialogService.open(ErrorModalComponent, {
748
+ data: {
749
+ errorType: 'chunk_not_found',
750
+ errorConfig: this.errorConfig,
751
+ },
752
+ position: 'center',
753
+ background: 'whiteBlur',
754
+ });
755
+ }
756
+ }
757
+ ChunkUnavailableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChunkUnavailableComponent, deps: [{ token: DialogService }], target: i0.ɵɵFactoryTarget.Component });
758
+ ChunkUnavailableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ChunkUnavailableComponent, selector: "lib-vc-error-chunk-unavailable", ngImport: i0, template: ``, isInline: true });
759
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChunkUnavailableComponent, decorators: [{
760
+ type: Component,
761
+ args: [{
762
+ selector: 'lib-vc-error-chunk-unavailable',
763
+ template: ``,
764
+ }]
765
+ }], ctorParameters: function () { return [{ type: DialogService }]; } });
766
+
767
+ class ServerErrorComponent {
768
+ constructor() {
769
+ this.errorConfig = ERROR_CONFIG.SERVER_ERROR;
770
+ this.VcomplyLogo = VCOMPLY_LOGO_URL;
771
+ }
772
+ refreshPage() {
773
+ window.location.reload();
774
+ }
775
+ }
776
+ ServerErrorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
777
+ ServerErrorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ServerErrorComponent, selector: "lib-vc-error-server-error", ngImport: i0, template: `
778
+ <div class="errorPage">
779
+ <div class="errorPage-top">
780
+ <img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
781
+ </div>
782
+ <div class="errorPage-container">
783
+ <div class="errorPage-inner">
784
+ <div class="errorPage-inner-image">
785
+ <img
786
+ [src]="errorConfig.imageUrl"
787
+ alt="Error Image"
788
+ width="246"
789
+ height="178"
790
+ />
791
+ </div>
792
+ <div class="errorPage-inner-right">
793
+ <div class="errorPage-heading">{{ errorConfig.title }}</div>
794
+ <div class="errorPage-text">{{ errorConfig.description }}</div>
795
+ <div class="errorPage-details">{{ errorConfig.details }}</div>
796
+ <button class="errorPage-btn" (click)="refreshPage()">
797
+ {{ errorConfig.buttonText }} <i class="icons">&#xe92b;</i>
798
+ </button>
799
+ </div>
800
+ </div>
461
801
  </div>
462
802
  </div>
463
- `, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}\n"] }]
803
+ `, isInline: true, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] });
804
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, decorators: [{
805
+ type: Component,
806
+ args: [{ selector: 'lib-vc-error-server-error', template: `
807
+ <div class="errorPage">
808
+ <div class="errorPage-top">
809
+ <img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
810
+ </div>
811
+ <div class="errorPage-container">
812
+ <div class="errorPage-inner">
813
+ <div class="errorPage-inner-image">
814
+ <img
815
+ [src]="errorConfig.imageUrl"
816
+ alt="Error Image"
817
+ width="246"
818
+ height="178"
819
+ />
820
+ </div>
821
+ <div class="errorPage-inner-right">
822
+ <div class="errorPage-heading">{{ errorConfig.title }}</div>
823
+ <div class="errorPage-text">{{ errorConfig.description }}</div>
824
+ <div class="errorPage-details">{{ errorConfig.details }}</div>
825
+ <button class="errorPage-btn" (click)="refreshPage()">
826
+ {{ errorConfig.buttonText }} <i class="icons">&#xe92b;</i>
827
+ </button>
828
+ </div>
829
+ </div>
830
+ </div>
831
+ </div>
832
+ `, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] }]
464
833
  }] });
465
834
 
466
835
  class VcErrorHandlersComponent {
467
- constructor(errorService) {
836
+ constructor(errorService, snackBarService) {
468
837
  this.errorService = errorService;
838
+ this.snackBarService = snackBarService;
839
+ this.errorConfig = ERROR_CONFIG.NETWORK_UNAVAILABLE;
469
840
  this.unauthorized = false;
470
841
  this.sessionExpired = false;
471
- this.networkUnavailable = false;
842
+ this.chunkUnavailable = false;
843
+ this.serverError = false;
844
+ this.isOnline = navigator.onLine;
845
+ this.onNetworkOnline = () => {
846
+ this.isOnline = true;
847
+ this.hideSnackBar();
848
+ };
849
+ this.onNetworkOffline = () => {
850
+ this.isOnline = false;
851
+ this.showOfflineSnackBar();
852
+ };
472
853
  this.subscribeGlobalError();
473
854
  }
855
+ ngOnInit() {
856
+ this.subscribeNetworkDetection();
857
+ }
858
+ ngOnDestroy() {
859
+ window.removeEventListener('online', this.onNetworkOnline);
860
+ window.removeEventListener('offline', this.onNetworkOffline);
861
+ }
474
862
  subscribeGlobalError() {
475
863
  this.errorService.globalError$.subscribe((error) => {
476
864
  this.handleError(error);
@@ -483,50 +871,81 @@ class VcErrorHandlersComponent {
483
871
  else if (error.status === ErrorStatusCode.UnauthorizedAccess) {
484
872
  this.unauthorized = true;
485
873
  }
874
+ else if (error.status === ErrorStatusCode.JSChunkUnavailable) {
875
+ this.chunkUnavailable = true;
876
+ }
486
877
  else if (error.status === ErrorStatusCode.NetworkUnavailable) {
487
- this.networkUnavailable = true;
878
+ this.handleNetworkError();
879
+ }
880
+ else if (this.errorService.isServerError(error)) {
881
+ this.serverError = true;
488
882
  }
489
883
  }
884
+ subscribeNetworkDetection() {
885
+ window.addEventListener('online', this.onNetworkOnline);
886
+ window.addEventListener('offline', this.onNetworkOffline);
887
+ }
888
+ handleNetworkError() {
889
+ if (!this.isOnline) {
890
+ this.showOfflineSnackBar();
891
+ }
892
+ }
893
+ showOfflineSnackBar() {
894
+ this.snackBarService.show(this.errorConfig.offlineMessage, 'error');
895
+ }
896
+ hideSnackBar() {
897
+ this.snackBarService.hide();
898
+ }
490
899
  }
491
- VcErrorHandlersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: VcErrorHandlersComponent, deps: [{ token: GlobalErrorService }], target: i0.ɵɵFactoryTarget.Component });
900
+ VcErrorHandlersComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: VcErrorHandlersComponent, deps: [{ token: GlobalErrorService }, { token: SnackBarService }], target: i0.ɵɵFactoryTarget.Component });
492
901
  VcErrorHandlersComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: VcErrorHandlersComponent, selector: "lib-vc-error-handlers", ngImport: i0, template: `
902
+ <app-snack-bar></app-snack-bar>
493
903
  <lib-vc-error-session-expired
494
904
  *ngIf="sessionExpired"
495
905
  ></lib-vc-error-session-expired>
496
906
  <lib-vc-error-unauthorized *ngIf="unauthorized"></lib-vc-error-unauthorized>
497
- `, isInline: true, components: [{ type: SessionExpiredComponent, selector: "lib-vc-error-session-expired" }, { type: UnauthorizedComponent, selector: "lib-vc-error-unauthorized" }], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
907
+ <lib-vc-error-chunk-unavailable
908
+ *ngIf="chunkUnavailable"
909
+ ></lib-vc-error-chunk-unavailable>
910
+ <lib-vc-error-server-error *ngIf="serverError"></lib-vc-error-server-error>
911
+ `, isInline: true, components: [{ type: SnackBarComponent, selector: "app-snack-bar" }, { type: SessionExpiredComponent, selector: "lib-vc-error-session-expired" }, { type: UnauthorizedComponent, selector: "lib-vc-error-unauthorized" }, { type: ChunkUnavailableComponent, selector: "lib-vc-error-chunk-unavailable" }, { type: ServerErrorComponent, selector: "lib-vc-error-server-error" }], directives: [{ type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
498
912
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: VcErrorHandlersComponent, decorators: [{
499
913
  type: Component,
500
914
  args: [{
501
915
  selector: 'lib-vc-error-handlers',
502
916
  template: `
917
+ <app-snack-bar></app-snack-bar>
503
918
  <lib-vc-error-session-expired
504
919
  *ngIf="sessionExpired"
505
920
  ></lib-vc-error-session-expired>
506
921
  <lib-vc-error-unauthorized *ngIf="unauthorized"></lib-vc-error-unauthorized>
922
+ <lib-vc-error-chunk-unavailable
923
+ *ngIf="chunkUnavailable"
924
+ ></lib-vc-error-chunk-unavailable>
925
+ <lib-vc-error-server-error *ngIf="serverError"></lib-vc-error-server-error>
507
926
  `,
508
927
  }]
509
- }], ctorParameters: function () { return [{ type: GlobalErrorService }]; } });
928
+ }], ctorParameters: function () { return [{ type: GlobalErrorService }, { type: SnackBarService }]; } });
510
929
 
511
930
  class PageNotFoundComponent {
512
- constructor() {
931
+ constructor(router) {
932
+ this.router = router;
513
933
  this.errorConfig = ERROR_CONFIG.PAGE_NOT_FOUND;
514
- this.VcomplyImage = VCOMPLY_IMAGE_URL;
934
+ this.VcomplyLogo = VCOMPLY_LOGO_URL;
935
+ this.currentYear = new Date().getFullYear();
515
936
  }
516
937
  redirectToHome() {
517
- // Redirect to home page
938
+ const currentUrl = window.location.href;
939
+ if (currentUrl.includes('organization')) {
940
+ this.router.navigate(['/global-dashboard/compliance_dashboard']);
941
+ }
518
942
  }
519
943
  }
520
- PageNotFoundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: PageNotFoundComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
944
+ PageNotFoundComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: PageNotFoundComponent, deps: [{ token: i3.Router }], target: i0.ɵɵFactoryTarget.Component });
521
945
  PageNotFoundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: PageNotFoundComponent, selector: "lib-vc-error-page-not-found", ngImport: i0, template: `
522
946
  <div class="errorPage">
523
947
  <div class="errorPage-top">
524
- <img
525
- src="https://cdn.v-comply.com/logo/prod/v-logo.svg"
526
- alt="VComply"
527
- width="24"
528
- height="24"
529
- />
948
+ <img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
530
949
  </div>
531
950
  <div class="errorPage-container">
532
951
  <div class="errorPage-inner">
@@ -534,8 +953,8 @@ PageNotFoundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0",
534
953
  <img
535
954
  [src]="errorConfig.imageUrl"
536
955
  alt="Error Image"
537
- width="256"
538
- height="256"
956
+ width="246"
957
+ height="178"
539
958
  />
540
959
  </div>
541
960
  <div class="errorPage-inner-right">
@@ -547,20 +966,18 @@ PageNotFoundComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0",
547
966
  </button>
548
967
  </div>
549
968
  </div>
969
+ <div class="errorPage-copyright">
970
+ &copy;&nbsp;{{ currentYear }}, VCOMPLY TECHNOLOGIES, INC.
971
+ </div>
550
972
  </div>
551
973
  </div>
552
- `, isInline: true, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}\n"] });
974
+ `, isInline: true, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] });
553
975
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: PageNotFoundComponent, decorators: [{
554
976
  type: Component,
555
977
  args: [{ selector: 'lib-vc-error-page-not-found', template: `
556
978
  <div class="errorPage">
557
979
  <div class="errorPage-top">
558
- <img
559
- src="https://cdn.v-comply.com/logo/prod/v-logo.svg"
560
- alt="VComply"
561
- width="24"
562
- height="24"
563
- />
980
+ <img [src]="VcomplyLogo" alt="VComply" width="24" height="24" />
564
981
  </div>
565
982
  <div class="errorPage-container">
566
983
  <div class="errorPage-inner">
@@ -568,8 +985,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
568
985
  <img
569
986
  [src]="errorConfig.imageUrl"
570
987
  alt="Error Image"
571
- width="256"
572
- height="256"
988
+ width="246"
989
+ height="178"
573
990
  />
574
991
  </div>
575
992
  <div class="errorPage-inner-right">
@@ -581,110 +998,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
581
998
  </button>
582
999
  </div>
583
1000
  </div>
1001
+ <div class="errorPage-copyright">
1002
+ &copy;&nbsp;{{ currentYear }}, VCOMPLY TECHNOLOGIES, INC.
1003
+ </div>
584
1004
  </div>
585
1005
  </div>
586
- `, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}\n"] }]
587
- }] });
588
-
589
- class ChunkUnavailableComponent {
590
- constructor() { }
591
- ngOnInit() {
592
- }
593
- }
594
- ChunkUnavailableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChunkUnavailableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
595
- ChunkUnavailableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ChunkUnavailableComponent, selector: "lib-chunk-unavailable", ngImport: i0, template: "<p>chunk-unavailable works!</p>\r\n", styles: [""] });
596
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ChunkUnavailableComponent, decorators: [{
597
- type: Component,
598
- args: [{ selector: 'lib-chunk-unavailable', template: "<p>chunk-unavailable works!</p>\r\n", styles: [""] }]
599
- }], ctorParameters: function () { return []; } });
600
-
601
- class ServerErrorComponent {
602
- constructor() { }
603
- ngOnInit() {
604
- }
605
- }
606
- ServerErrorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
607
- ServerErrorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: ServerErrorComponent, selector: "lib-server-error", ngImport: i0, template: "<p>server-error works!</p>\r\n", styles: [""] });
608
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: ServerErrorComponent, decorators: [{
609
- type: Component,
610
- args: [{ selector: 'lib-server-error', template: "<p>server-error works!</p>\r\n", styles: [""] }]
611
- }], ctorParameters: function () { return []; } });
612
-
613
- class SnackBarService {
614
- constructor() {
615
- this.snackbarSubject = new Subject();
616
- this.snackbarState = this.snackbarSubject.asObservable();
617
- }
618
- show(message, type) {
619
- this.snackbarSubject.next({
620
- show: true,
621
- message,
622
- icon: type,
623
- });
624
- }
625
- hide() {
626
- this.snackbarSubject.next({
627
- show: false,
628
- message: '',
629
- icon: '',
630
- });
631
- }
632
- }
633
- SnackBarService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
634
- SnackBarService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarService, providedIn: 'root' });
635
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarService, decorators: [{
636
- type: Injectable,
637
- args: [{
638
- providedIn: 'root',
639
- }]
640
- }], ctorParameters: function () { return []; } });
641
-
642
- class SnackBarComponent {
643
- constructor(snackbarService) {
644
- this.snackbarService = snackbarService;
645
- this.show = false;
646
- this.message = '--';
647
- this.icon = '&#xe914;';
648
- this.type = 'alert';
649
- this.icons = {
650
- success: '&#xe93d;',
651
- warning: '&#xe914;',
652
- info: '&#xe932;',
653
- alert: '&#xe914;',
654
- error: '&#xeaae;',
655
- };
656
- }
657
- ngOnInit() {
658
- this.snackbarSubscription = this.snackbarService.snackbarState.subscribe((state) => {
659
- if (state.icon && Object.keys(this.icons).includes(state?.icon)) {
660
- this.icon = this.icons[state.icon];
661
- this.type = state?.icon;
662
- }
663
- this.message = state.message;
664
- this.show = state.show;
665
- this.setAutoClose();
666
- });
667
- }
668
- setAutoClose() {
669
- setTimeout(() => {
670
- this.show = false;
671
- this.close();
672
- }, 3000);
673
- }
674
- close() {
675
- this.show = false;
676
- this.snackbarService.hide();
677
- }
678
- ngOnDestroy() {
679
- this.snackbarSubscription.unsubscribe();
680
- }
681
- }
682
- SnackBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarComponent, deps: [{ token: SnackBarService }], target: i0.ɵɵFactoryTarget.Component });
683
- SnackBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.0.1", type: SnackBarComponent, selector: "app-snack-bar", ngImport: i0, template: "<div class=\"workflow-snackbar\" *ngIf=\"show\">\r\n <div class=\"workflow-snackbar-inner\">\r\n <div class=\"workflow-snackbarText\">\r\n <!-- &#xe914; -->\r\n <i class=\"icons\" [class]=\"type\" [innerHTML]=\"icon\"></i> <span [innerHTML]=\"message\">{{ message }}</span>\r\n </div>\r\n <button (click)=\"close()\">[ <span>Close</span> ]</button>\r\n </div>\r\n </div>", styles: ["::ng-deep .workflow-snackbar{position:fixed;top:20px;left:0;right:0;display:flex;align-items:center;justify-content:center;z-index:2147483647!important;pointer-events:none;animation:slide-top .3s cubic-bezier(.25,.46,.45,.94) both}::ng-deep .workflow-snackbar.white{background-color:#fff;color:#000;z-index:20}::ng-deep .workflow-snackbar.white button{color:#f6882f;font-size:11px;font-weight:400;pointer-events:all}::ng-deep .workflow-snackbar .workflow-snackbar-inner{display:flex;max-width:500px;min-width:450px;align-items:center;justify-content:space-between;padding:10px;background:#ffffff;border-radius:3px;box-shadow:0 0 10px #0003;min-height:55px;pointer-events:auto}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText{color:#161b2f;font-size:13px;display:flex;align-items:center;width:calc(100% - 70px)}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i{background:#f1f1f1;color:#d93b41;border-radius:50px;font-size:16px;width:30px;height:30px;text-align:center;line-height:28px;margin-right:10px;min-width:30px}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.success{color:#34aa44}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.warning{color:#f0b819}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.info{color:#1e5dd3}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.alert,::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.error{color:#d93b41}::ng-deep .workflow-snackbar .workflow-snackbar-inner button{background:transparent;border:none;font-size:11px;padding:0;position:relative;color:#747576;width:65px;text-align:right;cursor:pointer;text-transform:uppercase}::ng-deep .workflow-snackbar .workflow-snackbar-inner button span{color:#1e5dd3;font-weight:500}::ng-deep .workflow-snackbar .workflow-snackbar-inner button:focus{outline:none}@keyframes slide-top{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}\n"], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
684
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SnackBarComponent, decorators: [{
685
- type: Component,
686
- args: [{ selector: 'app-snack-bar', template: "<div class=\"workflow-snackbar\" *ngIf=\"show\">\r\n <div class=\"workflow-snackbar-inner\">\r\n <div class=\"workflow-snackbarText\">\r\n <!-- &#xe914; -->\r\n <i class=\"icons\" [class]=\"type\" [innerHTML]=\"icon\"></i> <span [innerHTML]=\"message\">{{ message }}</span>\r\n </div>\r\n <button (click)=\"close()\">[ <span>Close</span> ]</button>\r\n </div>\r\n </div>", styles: ["::ng-deep .workflow-snackbar{position:fixed;top:20px;left:0;right:0;display:flex;align-items:center;justify-content:center;z-index:2147483647!important;pointer-events:none;animation:slide-top .3s cubic-bezier(.25,.46,.45,.94) both}::ng-deep .workflow-snackbar.white{background-color:#fff;color:#000;z-index:20}::ng-deep .workflow-snackbar.white button{color:#f6882f;font-size:11px;font-weight:400;pointer-events:all}::ng-deep .workflow-snackbar .workflow-snackbar-inner{display:flex;max-width:500px;min-width:450px;align-items:center;justify-content:space-between;padding:10px;background:#ffffff;border-radius:3px;box-shadow:0 0 10px #0003;min-height:55px;pointer-events:auto}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText{color:#161b2f;font-size:13px;display:flex;align-items:center;width:calc(100% - 70px)}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i{background:#f1f1f1;color:#d93b41;border-radius:50px;font-size:16px;width:30px;height:30px;text-align:center;line-height:28px;margin-right:10px;min-width:30px}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.success{color:#34aa44}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.warning{color:#f0b819}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.info{color:#1e5dd3}::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.alert,::ng-deep .workflow-snackbar .workflow-snackbar-inner .workflow-snackbarText i.error{color:#d93b41}::ng-deep .workflow-snackbar .workflow-snackbar-inner button{background:transparent;border:none;font-size:11px;padding:0;position:relative;color:#747576;width:65px;text-align:right;cursor:pointer;text-transform:uppercase}::ng-deep .workflow-snackbar .workflow-snackbar-inner button span{color:#1e5dd3;font-weight:500}::ng-deep .workflow-snackbar .workflow-snackbar-inner button:focus{outline:none}@keyframes slide-top{0%{transform:translateY(-100%);opacity:0}to{transform:translateY(0);opacity:1}}\n"] }]
687
- }], ctorParameters: function () { return [{ type: SnackBarService }]; } });
1006
+ `, styles: ["@import\"https://cdn.v-comply.com/design-system/css/icons/icons.css\";.errorPage{background:#161b2f;position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999}.errorPage-top{width:100%;height:3rem;display:flex;align-items:center;padding-left:.75rem}.errorPage-container{background:#f2f2f5;border-radius:.75rem;border:1px solid #e3e3e9;box-shadow:0 4px 8px #1d5dd31a;height:calc(100vh - 3.75rem);display:flex;align-items:center;justify-content:center;padding:0 4rem;margin:0 .75rem;position:relative}.errorPage-inner{display:flex;align-items:center}.errorPage-inner-image{width:16rem}.errorPage-inner-right{margin-left:2rem;width:calc(100% - 18rem)}.errorPage-inner-right .errorPage-heading{-webkit-text-fill-color:#e3e3e9;-webkit-text-stroke-color:#a9aab6;-webkit-text-stroke-width:1px;color:#e3e3e9;font-size:78px;font-weight:bold;line-height:110px;margin-bottom:1.5rem}.errorPage-inner-right .errorPage-text{color:#141724;font-size:19px;font-weight:500;line-height:1.75rem;margin-bottom:.5rem}.errorPage-inner-right .errorPage-details{color:#565a6f;font-size:13px;line-height:20px;margin-bottom:1.75rem}.errorPage-inner-right .errorPage-btn{background:#1e5dd3;border-radius:.25rem;border:none;color:#fff;display:inline-flex;align-items:center;font-size:11px;font-weight:500;line-height:2rem;padding:0 1rem}.errorPage-inner-right .errorPage-btn i{font-size:14px;margin-left:.25rem}.errorPage-copyright{font-size:11px;color:#787a8c;font-weight:500;position:absolute;bottom:8px;right:16px;line-height:16px}\n"] }]
1007
+ }], ctorParameters: function () { return [{ type: i3.Router }]; } });
688
1008
 
689
1009
  class SnackBarModule {
690
1010
  }
@@ -707,8 +1027,9 @@ class Configurations {
707
1027
  }
708
1028
 
709
1029
  class SentryErrorHandler {
710
- constructor(authorizerService, config) {
1030
+ constructor(authorizerService, errorService, config) {
711
1031
  this.authorizerService = authorizerService;
1032
+ this.errorService = errorService;
712
1033
  if (config?.sentryConfig) {
713
1034
  const SENTRY_CONFIG = config.sentryConfig;
714
1035
  Sentry.init({
@@ -728,21 +1049,23 @@ class SentryErrorHandler {
728
1049
  }
729
1050
  handleError(error) {
730
1051
  const ERROR = error?.originalError || error;
731
- this.handleChunkError(ERROR);
1052
+ this.handleChunkNotFoundError(ERROR);
732
1053
  Sentry.captureException(ERROR);
733
1054
  }
734
- handleChunkError(error) {
735
- const chunkFailedMessage = /Loading chunk [\d]+ failed/;
736
- if (chunkFailedMessage.test(error?.message)) {
737
- window.location.reload();
1055
+ handleChunkNotFoundError(error) {
1056
+ const failedMessage = /Loading chunk [\d]+ failed/;
1057
+ if (failedMessage.test(error.message)) {
1058
+ this.errorService.globalError$.next({
1059
+ status: ErrorStatusCode.JSChunkUnavailable,
1060
+ });
738
1061
  }
739
1062
  }
740
1063
  }
741
- SentryErrorHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SentryErrorHandler, deps: [{ token: i1.AuthorizerService }, { token: Configurations, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1064
+ SentryErrorHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SentryErrorHandler, deps: [{ token: i1.AuthorizerService }, { token: GlobalErrorService }, { token: Configurations, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
742
1065
  SentryErrorHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SentryErrorHandler });
743
1066
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: SentryErrorHandler, decorators: [{
744
1067
  type: Injectable
745
- }], ctorParameters: function () { return [{ type: i1.AuthorizerService }, { type: Configurations, decorators: [{
1068
+ }], ctorParameters: function () { return [{ type: i1.AuthorizerService }, { type: GlobalErrorService }, { type: Configurations, decorators: [{
746
1069
  type: Optional
747
1070
  }] }]; } });
748
1071
 
@@ -751,7 +1074,11 @@ class HttpReqInterceptor {
751
1074
  this.errorService = errorService;
752
1075
  }
753
1076
  intercept(req, next) {
754
- return next.handle(req).pipe(timeout(API_TIMEOUT_TIME), catchError((error) => {
1077
+ return next.handle(req).pipe(timeout(API_TIMEOUT_TIME), tap((event) => {
1078
+ if (event instanceof HttpResponse) {
1079
+ this.errorService.handleSoftErrors(event);
1080
+ }
1081
+ }), catchError((error) => {
755
1082
  this.errorService.handleError(error, req);
756
1083
  return throwError(error);
757
1084
  }));
@@ -779,13 +1106,13 @@ VcErrorHandlersModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", v
779
1106
  SessionExpiredComponent,
780
1107
  ChunkUnavailableComponent,
781
1108
  ServerErrorComponent,
782
- SessionExpiredModalComponent], imports: [CommonModule, DialogModule, SnackBarModule], exports: [VcErrorHandlersComponent,
1109
+ ErrorModalComponent], imports: [CommonModule, DialogModule, SnackBarModule], exports: [VcErrorHandlersComponent,
783
1110
  PageNotFoundComponent,
784
1111
  UnauthorizedComponent,
785
1112
  SessionExpiredComponent,
786
1113
  ChunkUnavailableComponent,
787
1114
  ServerErrorComponent,
788
- SessionExpiredModalComponent] });
1115
+ ErrorModalComponent] });
789
1116
  VcErrorHandlersModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.0.1", ngImport: i0, type: VcErrorHandlersModule, providers: [
790
1117
  { provide: ErrorHandler, useClass: SentryErrorHandler },
791
1118
  { provide: HTTP_INTERCEPTORS, useClass: HttpReqInterceptor, multi: true },
@@ -800,7 +1127,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
800
1127
  SessionExpiredComponent,
801
1128
  ChunkUnavailableComponent,
802
1129
  ServerErrorComponent,
803
- SessionExpiredModalComponent,
1130
+ ErrorModalComponent,
804
1131
  ],
805
1132
  imports: [CommonModule, DialogModule, SnackBarModule],
806
1133
  exports: [
@@ -810,7 +1137,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
810
1137
  SessionExpiredComponent,
811
1138
  ChunkUnavailableComponent,
812
1139
  ServerErrorComponent,
813
- SessionExpiredModalComponent,
1140
+ ErrorModalComponent,
814
1141
  ],
815
1142
  providers: [
816
1143
  { provide: ErrorHandler, useClass: SentryErrorHandler },
@@ -828,5 +1155,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.1", ngImpor
828
1155
  * Generated bundle index. Do not edit.
829
1156
  */
830
1157
 
831
- export { AuthService, ChunkUnavailableComponent, FOR_ROOT_SENTRY_OPTIONS_TOKEN, GlobalErrorService, HttpReqInterceptor, PageNotFoundComponent, RouterService, ServerErrorComponent, SessionExpiredComponent, SessionExpiredModalComponent, UnauthorizedComponent, VcErrorHandlersComponent, VcErrorHandlersModule, VcErrorHandlersService };
1158
+ export { AuthService, ChunkUnavailableComponent, ErrorModalComponent, FOR_ROOT_SENTRY_OPTIONS_TOKEN, GlobalErrorService, HttpReqInterceptor, PageNotFoundComponent, RouterService, ServerErrorComponent, SessionExpiredComponent, UnauthorizedComponent, VcErrorHandlersComponent, VcErrorHandlersModule, VcErrorHandlersService };
832
1159
  //# sourceMappingURL=vc-error-handlers.mjs.map