ng-ipa-library 0.7.2 → 0.7.6

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 (135) hide show
  1. package/karma.conf.js +44 -0
  2. package/ng-package.json +43 -0
  3. package/package.json +24 -31
  4. package/src/lib/core/components/loading/loading.component.html +3 -0
  5. package/src/lib/core/components/loading/loading.component.scss +3 -0
  6. package/src/lib/core/components/loading/loading.component.ts +23 -0
  7. package/src/lib/core/interceptors/error.interceptor.ts +61 -0
  8. package/src/lib/core/interceptors/loading.interceptor.ts +69 -0
  9. package/src/lib/core/interceptors/token.interceptor.ts +77 -0
  10. package/src/lib/core/services/auth.service.ts +48 -0
  11. package/src/lib/core/services/error.service.ts +19 -0
  12. package/src/lib/core/services/loader.service.ts +21 -0
  13. package/src/lib/generate-form/generate-form.component.html +85 -0
  14. package/src/lib/generate-form/generate-form.component.scss +0 -0
  15. package/src/lib/generate-form/generate-form.component.ts +119 -0
  16. package/src/lib/ipa-form/datepicker/datepicker.component.html +21 -0
  17. package/src/lib/ipa-form/datepicker/datepicker.component.scss +13 -0
  18. package/src/lib/ipa-form/datepicker/datepicker.component.ts +67 -0
  19. package/src/lib/ipa-form/datepicker/gregorian-datepicker/gregorian-datepicker.component.ts +15 -0
  20. package/src/lib/ipa-form/datepicker/gregorian-datepicker/gregorian18n.ts +38 -0
  21. package/src/lib/ipa-form/datepicker/hijri-datepicker/IslamicI18n.ts +38 -0
  22. package/src/lib/ipa-form/datepicker/hijri-datepicker/hijri-datepicker.component.ts +14 -0
  23. package/src/lib/ipa-form/dropdown-input/dropdown-input.component.html +22 -0
  24. package/src/lib/ipa-form/dropdown-input/dropdown-input.component.scss +0 -0
  25. package/src/lib/ipa-form/dropdown-input/dropdown-input.component.ts +68 -0
  26. package/src/lib/ipa-form/file-upload/file-upload.component.html +37 -0
  27. package/src/lib/ipa-form/file-upload/file-upload.component.scss +45 -0
  28. package/src/lib/ipa-form/file-upload/file-upload.component.ts +109 -0
  29. package/src/lib/ipa-form/ipa-form.service.ts +294 -0
  30. package/src/lib/ipa-form/recaptcha/recaptcha.component.html +3 -0
  31. package/src/lib/ipa-form/recaptcha/recaptcha.component.scss +0 -0
  32. package/src/lib/ipa-form/recaptcha/recaptcha.component.ts +42 -0
  33. package/src/lib/ipa-form/text-input/text-input.component.html +10 -0
  34. package/src/lib/ipa-form/text-input/text-input.component.scss +0 -0
  35. package/src/lib/ipa-form/text-input/text-input.component.ts +69 -0
  36. package/src/lib/ipa-form/textarea-input/textarea-input.component.html +11 -0
  37. package/src/lib/ipa-form/textarea-input/textarea-input.component.scss +0 -0
  38. package/src/lib/ipa-form/textarea-input/textarea-input.component.ts +69 -0
  39. package/{lib/models/apiException.d.ts → src/lib/models/apiException.ts} +2 -1
  40. package/src/lib/models/apiResponse.ts +4 -0
  41. package/src/lib/models/breadcrumbs.model.ts +4 -0
  42. package/src/lib/models/decodedToken.model.ts +6 -0
  43. package/src/lib/models/exceptionUrl.model.ts +4 -0
  44. package/src/lib/models/generateForm.model.ts +29 -0
  45. package/src/lib/models/pagedResult.ts +4 -0
  46. package/src/lib/models/user.model.ts +7 -0
  47. package/src/lib/ng-ipa-library.component.ts +15 -0
  48. package/src/lib/ng-ipa-library.module.ts +63 -0
  49. package/src/lib/pipes/hijri-date.pipe.ts +15 -0
  50. package/src/lib/pipes/pipes.module.ts +8 -0
  51. package/src/lib/services/breadcrumbs.service.ts +189 -0
  52. package/src/lib/services/common.service.ts +63 -0
  53. package/src/lib/share-button/share-button.component.html +3 -0
  54. package/src/lib/share-button/share-button.component.scss +0 -0
  55. package/src/lib/share-button/share-button.component.ts +23 -0
  56. package/src/lib/share-button/share-button.module.ts +32 -0
  57. package/{public-api.d.ts → src/public-api.ts} +16 -1
  58. package/src/test.ts +26 -0
  59. package/tsconfig.lib.json +20 -0
  60. package/tsconfig.lib.prod.json +10 -0
  61. package/tsconfig.spec.json +17 -0
  62. package/bundles/ng-ipa-library.umd.js +0 -2101
  63. package/bundles/ng-ipa-library.umd.js.map +0 -1
  64. package/esm2015/lib/core/components/loading/loading.component.js +0 -27
  65. package/esm2015/lib/core/interceptors/error.interceptor.js +0 -46
  66. package/esm2015/lib/core/interceptors/loading.interceptor.js +0 -58
  67. package/esm2015/lib/core/interceptors/token.interceptor.js +0 -69
  68. package/esm2015/lib/core/services/auth.service.js +0 -48
  69. package/esm2015/lib/core/services/error.service.js +0 -22
  70. package/esm2015/lib/core/services/loader.service.js +0 -24
  71. package/esm2015/lib/generate-form/generate-form.component.js +0 -120
  72. package/esm2015/lib/ipa-form/datepicker/datepicker.component.js +0 -70
  73. package/esm2015/lib/ipa-form/datepicker/gregorian-datepicker/gregorian-datepicker.component.js +0 -28
  74. package/esm2015/lib/ipa-form/datepicker/gregorian-datepicker/gregorian18n.js +0 -38
  75. package/esm2015/lib/ipa-form/datepicker/hijri-datepicker/IslamicI18n.js +0 -38
  76. package/esm2015/lib/ipa-form/datepicker/hijri-datepicker/hijri-datepicker.component.js +0 -28
  77. package/esm2015/lib/ipa-form/dropdown-input/dropdown-input.component.js +0 -81
  78. package/esm2015/lib/ipa-form/file-upload/file-upload.component.js +0 -128
  79. package/esm2015/lib/ipa-form/ipa-form.service.js +0 -251
  80. package/esm2015/lib/ipa-form/recaptcha/recaptcha.component.js +0 -59
  81. package/esm2015/lib/ipa-form/text-input/text-input.component.js +0 -76
  82. package/esm2015/lib/ipa-form/textarea-input/textarea-input.component.js +0 -73
  83. package/esm2015/lib/models/apiException.js +0 -2
  84. package/esm2015/lib/models/apiResponse.js +0 -2
  85. package/esm2015/lib/models/breadcrumbs.model.js +0 -2
  86. package/esm2015/lib/models/decodedToken.model.js +0 -2
  87. package/esm2015/lib/models/exceptionUrl.model.js +0 -2
  88. package/esm2015/lib/models/generateForm.model.js +0 -2
  89. package/esm2015/lib/models/pagedResult.js +0 -2
  90. package/esm2015/lib/models/user.model.js +0 -2
  91. package/esm2015/lib/ng-ipa-library.module.js +0 -112
  92. package/esm2015/lib/pipes/hijri-date.pipe.js +0 -18
  93. package/esm2015/lib/pipes/pipes.module.js +0 -16
  94. package/esm2015/lib/services/breadcrumbs.service.js +0 -151
  95. package/esm2015/lib/services/common.service.js +0 -66
  96. package/esm2015/lib/share-button/share-button.component.js +0 -37
  97. package/esm2015/lib/share-button/share-button.module.js +0 -52
  98. package/esm2015/ng-ipa-library.js +0 -5
  99. package/esm2015/public-api.js +0 -40
  100. package/fesm2015/ng-ipa-library.js +0 -1633
  101. package/fesm2015/ng-ipa-library.js.map +0 -1
  102. package/lib/core/components/loading/loading.component.d.ts +0 -12
  103. package/lib/core/interceptors/error.interceptor.d.ts +0 -14
  104. package/lib/core/interceptors/loading.interceptor.d.ts +0 -14
  105. package/lib/core/interceptors/token.interceptor.d.ts +0 -15
  106. package/lib/core/services/auth.service.d.ts +0 -15
  107. package/lib/core/services/error.service.d.ts +0 -10
  108. package/lib/core/services/loader.service.d.ts +0 -12
  109. package/lib/generate-form/generate-form.component.d.ts +0 -32
  110. package/lib/ipa-form/datepicker/datepicker.component.d.ts +0 -31
  111. package/lib/ipa-form/datepicker/gregorian-datepicker/gregorian-datepicker.component.d.ts +0 -6
  112. package/lib/ipa-form/datepicker/gregorian-datepicker/gregorian18n.d.ts +0 -11
  113. package/lib/ipa-form/datepicker/hijri-datepicker/IslamicI18n.d.ts +0 -11
  114. package/lib/ipa-form/datepicker/hijri-datepicker/hijri-datepicker.component.d.ts +0 -6
  115. package/lib/ipa-form/dropdown-input/dropdown-input.component.d.ts +0 -31
  116. package/lib/ipa-form/file-upload/file-upload.component.d.ts +0 -36
  117. package/lib/ipa-form/ipa-form.service.d.ts +0 -49
  118. package/lib/ipa-form/recaptcha/recaptcha.component.d.ts +0 -22
  119. package/lib/ipa-form/text-input/text-input.component.d.ts +0 -30
  120. package/lib/ipa-form/textarea-input/textarea-input.component.d.ts +0 -29
  121. package/lib/models/apiResponse.d.ts +0 -4
  122. package/lib/models/breadcrumbs.model.d.ts +0 -4
  123. package/lib/models/decodedToken.model.d.ts +0 -6
  124. package/lib/models/exceptionUrl.model.d.ts +0 -4
  125. package/lib/models/generateForm.model.d.ts +0 -27
  126. package/lib/models/pagedResult.d.ts +0 -4
  127. package/lib/models/user.model.d.ts +0 -7
  128. package/lib/ng-ipa-library.module.d.ts +0 -25
  129. package/lib/pipes/hijri-date.pipe.d.ts +0 -7
  130. package/lib/pipes/pipes.module.d.ts +0 -7
  131. package/lib/services/breadcrumbs.service.d.ts +0 -18
  132. package/lib/services/common.service.d.ts +0 -8
  133. package/lib/share-button/share-button.component.d.ts +0 -11
  134. package/lib/share-button/share-button.module.d.ts +0 -13
  135. package/ng-ipa-library.d.ts +0 -5
package/karma.conf.js ADDED
@@ -0,0 +1,44 @@
1
+ // Karma configuration file, see link for more information
2
+ // https://karma-runner.github.io/1.0/config/configuration-file.html
3
+
4
+ module.exports = function (config) {
5
+ config.set({
6
+ basePath: '',
7
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
8
+ plugins: [
9
+ require('karma-jasmine'),
10
+ require('karma-chrome-launcher'),
11
+ require('karma-jasmine-html-reporter'),
12
+ require('karma-coverage'),
13
+ require('@angular-devkit/build-angular/plugins/karma')
14
+ ],
15
+ client: {
16
+ jasmine: {
17
+ // you can add configuration options for Jasmine here
18
+ // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19
+ // for example, you can disable the random execution with `random: false`
20
+ // or set a specific seed with `seed: 4321`
21
+ },
22
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
23
+ },
24
+ jasmineHtmlReporter: {
25
+ suppressAll: true // removes the duplicated traces
26
+ },
27
+ coverageReporter: {
28
+ dir: require('path').join(__dirname, '../../coverage/ng-ipa-library'),
29
+ subdir: '.',
30
+ reporters: [
31
+ { type: 'html' },
32
+ { type: 'text-summary' }
33
+ ]
34
+ },
35
+ reporters: ['progress', 'kjhtml'],
36
+ port: 9876,
37
+ colors: true,
38
+ logLevel: config.LOG_INFO,
39
+ autoWatch: true,
40
+ browsers: ['Chrome'],
41
+ singleRun: false,
42
+ restartOnFileChange: true
43
+ });
44
+ };
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/ng-ipa-library",
4
+ "allowedNonPeerDependencies": [
5
+ "ngx-toastr",
6
+ "ngx-dropzone-wrapper",
7
+ "ngx-captcha",
8
+ "moment-hijri",
9
+ "@types/moment-hijri",
10
+ "@ng-bootstrap/ng-bootstrap",
11
+ "@ng-bootstrap/ng-bootstrap",
12
+ "@fortawesome/angular-fontawesome",
13
+ "@fortawesome/fontawesome-svg-core",
14
+ "@fortawesome/free-brands-svg-icons",
15
+ "@fortawesome/free-solid-svg-icons",
16
+ "ngx-sharebuttons",
17
+ "@angular/cdk",
18
+ "@ng-select/ng-select"
19
+ ],
20
+ "lib": {
21
+ "entryFile": "src/public-api.ts",
22
+ "umdModuleIds": {
23
+ "ngx-toastr": "ngx-toastr",
24
+ "ngx-dropzone-wrapper": "ngx-dropzone-wrapper",
25
+ "ngx-captcha": "ngx-captcha",
26
+ "moment-hijri": "moment-hijri",
27
+ "@types/moment-hijri": "@types/moment-hijri",
28
+ "@ng-bootstrap/ng-bootstrap": "@ng-bootstrap/ng-bootstrap",
29
+ "@fortawesome/angular-fontawesome": "@fortawesome/angular-fontawesome",
30
+ "@fortawesome/fontawesome-svg-core": "@fortawesome/fontawesome-svg-core",
31
+ "@fortawesome/free-brands-svg-icons": "@fortawesome/free-brands-svg-icons",
32
+ "@fortawesome/free-solid-svg-icons": "@fortawesome/free-solid-svg-icons",
33
+ "ngx-sharebuttons": "ngx-sharebuttons",
34
+ "ngx-sharebuttons/icons": "ngx-sharebuttons/icons",
35
+ "ngx-sharebuttons/popup": "ngx-sharebuttons/popup",
36
+ "@angular/cdk": "@angular/cdk",
37
+ "@ng-select/ng-select": "@ng-select/ng-select"
38
+ }
39
+ },
40
+ "assets": [
41
+ "src/lib/assets/ngIPAStyle.scss"
42
+ ]
43
+ }
package/package.json CHANGED
@@ -1,31 +1,24 @@
1
- {
2
- "name": "ng-ipa-library",
3
- "version": "0.7.2",
4
- "peerDependencies": {
5
- "@angular/common": "~12.2.9",
6
- "@angular/core": "~12.2.9"
7
- },
8
- "dependencies": {
9
- "tslib": "^2.2.0",
10
- "ngx-toastr": "^14.1.0",
11
- "ngx-captcha": "^10.0.0",
12
- "ngx-dropzone-wrapper": "^10.0.1",
13
- "moment-hijri": "^2.1.2",
14
- "@types/moment-hijri": "^2.1.0",
15
- "@ng-bootstrap/ng-bootstrap": "^11.0.0-beta.2",
16
- "@fortawesome/angular-fontawesome": "^0.9.0",
17
- "@fortawesome/fontawesome-svg-core": "^1.2.36",
18
- "@fortawesome/free-brands-svg-icons": "^5.15.4",
19
- "@fortawesome/free-solid-svg-icons": "^5.15.4",
20
- "ngx-sharebuttons": "^9.0.0",
21
- "@angular/cdk": "^12.2.9",
22
- "@ng-select/ng-select": "^7.4.0"
23
- },
24
- "main": "bundles/ng-ipa-library.umd.js",
25
- "module": "fesm2015/ng-ipa-library.js",
26
- "es2015": "fesm2015/ng-ipa-library.js",
27
- "esm2015": "esm2015/ng-ipa-library.js",
28
- "fesm2015": "fesm2015/ng-ipa-library.js",
29
- "typings": "ng-ipa-library.d.ts",
30
- "sideEffects": false
31
- }
1
+ {
2
+ "name": "ng-ipa-library",
3
+ "version": "0.7.6",
4
+ "peerDependencies": {
5
+ "@angular/common": "~12.2.9",
6
+ "@angular/core": "~12.2.9"
7
+ },
8
+ "dependencies": {
9
+ "tslib": "^2.2.0",
10
+ "ngx-toastr": "^14.1.0",
11
+ "@ng-select/ng-select": "^7.4.0",
12
+ "ngx-captcha": "^10.0.0",
13
+ "ngx-dropzone-wrapper": "^10.0.1",
14
+ "moment-hijri": "^2.1.2",
15
+ "@types/moment-hijri": "^2.1.0",
16
+ "@ng-bootstrap/ng-bootstrap": "^11.0.0-beta.2",
17
+ "@fortawesome/angular-fontawesome": "^0.9.0",
18
+ "@fortawesome/fontawesome-svg-core": "^1.2.36",
19
+ "@fortawesome/free-brands-svg-icons": "^5.15.4",
20
+ "@fortawesome/free-solid-svg-icons": "^5.15.4",
21
+ "ngx-sharebuttons": "^9.0.0",
22
+ "@angular/cdk": "^12.2.9"
23
+ }
24
+ }
@@ -0,0 +1,3 @@
1
+ <div id="cover-spin" *ngIf="loading">
2
+ <div class="spinner"></div>
3
+ </div>
@@ -0,0 +1,3 @@
1
+ #cover-spin {
2
+ display: flex;
3
+ }
@@ -0,0 +1,23 @@
1
+ import { AfterViewInit, ChangeDetectorRef, Component } from '@angular/core';
2
+ import { LoaderService } from '../../services/loader.service';
3
+
4
+ @Component({
5
+ selector: 'ipa-loader',
6
+ templateUrl: './loading.component.html',
7
+ styleUrls: ['./loading.component.scss'],
8
+ })
9
+ export class LoaderComponent implements AfterViewInit {
10
+ loading!: boolean;
11
+
12
+ constructor(
13
+ private loaderService: LoaderService,
14
+ private cdr: ChangeDetectorRef
15
+ ) {}
16
+
17
+ ngAfterViewInit(): void {
18
+ this.loaderService.isLoading.subscribe((v) => {
19
+ this.loading = v;
20
+ this.cdr.detectChanges();
21
+ });
22
+ }
23
+ }
@@ -0,0 +1,61 @@
1
+ import { Injectable } from '@angular/core';
2
+ import {
3
+ HttpRequest,
4
+ HttpHandler,
5
+ HttpEvent,
6
+ HttpInterceptor,
7
+ } from '@angular/common/http';
8
+ import { Observable, throwError } from 'rxjs';
9
+ import { catchError } from 'rxjs/operators';
10
+ import { ErrorService } from '../services/error.service';
11
+ import { ApiException } from '../../models/apiException';
12
+ import { IndividualConfig, ToastrService } from 'ngx-toastr';
13
+
14
+ @Injectable()
15
+ export class ErrorInterceptor implements HttpInterceptor {
16
+ constructor(
17
+ private errorService: ErrorService,
18
+ private toastrService: ToastrService
19
+ ) {}
20
+
21
+ intercept(
22
+ req: HttpRequest<unknown>,
23
+ next: HttpHandler
24
+ ): Observable<HttpEvent<unknown>> {
25
+ if (this.isException(req)) {
26
+ return next.handle(req);
27
+ }
28
+
29
+ return next.handle(req).pipe(
30
+ catchError((error) => {
31
+ const response = error.error as ApiException;
32
+ const toastrConfig: Partial<IndividualConfig> = {
33
+ disableTimeOut: true,
34
+ };
35
+ switch (response.statusCode) {
36
+ case 500:
37
+ this.toastrService.error(
38
+ response?.innerException + ' ' + response?.stackTrace,
39
+ response.message,
40
+ toastrConfig
41
+ );
42
+ break;
43
+
44
+ default:
45
+ this.toastrService.error(response.message, '', toastrConfig);
46
+ break;
47
+ }
48
+ return throwError(error);
49
+ })
50
+ );
51
+ }
52
+
53
+ isException(req: HttpRequest<any>): boolean {
54
+ for (const url of this.errorService.urls) {
55
+ if (req.url.includes(url.path) && req.method === url.method) {
56
+ return true;
57
+ }
58
+ }
59
+ return false;
60
+ }
61
+ }
@@ -0,0 +1,69 @@
1
+ import { Injectable } from '@angular/core';
2
+ import {
3
+ HttpRequest,
4
+ HttpHandler,
5
+ HttpEvent,
6
+ HttpInterceptor,
7
+ HttpResponse,
8
+ } from '@angular/common/http';
9
+ import { Observable } from 'rxjs';
10
+ import { LoaderService } from '../services/loader.service';
11
+
12
+ @Injectable()
13
+ export class LoadingInterceptor implements HttpInterceptor {
14
+ private requests: HttpRequest<any>[] = [];
15
+
16
+ constructor(private loaderService: LoaderService) {}
17
+
18
+ removeRequest(req: HttpRequest<any>): void {
19
+ const i = this.requests.indexOf(req);
20
+ if (i >= 0) {
21
+ this.requests.splice(i, 1);
22
+ }
23
+ this.loaderService.isLoading.next(this.requests.length > 0);
24
+ }
25
+
26
+ intercept(
27
+ req: HttpRequest<unknown>,
28
+ next: HttpHandler
29
+ ): Observable<HttpEvent<unknown>> {
30
+ if (this.isException(req)) {
31
+ return next.handle(req);
32
+ }
33
+ this.requests.push(req);
34
+
35
+ this.loaderService.isLoading.next(true);
36
+ return new Observable((observer) => {
37
+ const subscription = next.handle(req).subscribe(
38
+ (event) => {
39
+ if (event instanceof HttpResponse) {
40
+ this.removeRequest(req);
41
+ observer.next(event);
42
+ }
43
+ },
44
+ (err) => {
45
+ this.removeRequest(req);
46
+ observer.error(err);
47
+ },
48
+ () => {
49
+ this.removeRequest(req);
50
+ observer.complete();
51
+ }
52
+ );
53
+ // remove request from queue when cancelled
54
+ return () => {
55
+ this.removeRequest(req);
56
+ subscription.unsubscribe();
57
+ };
58
+ });
59
+ }
60
+
61
+ isException(req: HttpRequest<any>): boolean {
62
+ for (const url of this.loaderService.urls) {
63
+ if (req.url.includes(url.path) && req.method === url.method) {
64
+ return true;
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+ }
@@ -0,0 +1,77 @@
1
+ import { Injectable } from '@angular/core';
2
+ import {
3
+ HttpRequest,
4
+ HttpHandler,
5
+ HttpEvent,
6
+ HttpInterceptor,
7
+ HttpClient,
8
+ } from '@angular/common/http';
9
+ import { Observable } from 'rxjs';
10
+ import { AuthService } from '../services/auth.service';
11
+ import { DecodedToken } from '../../models/decodedToken.model';
12
+ import { User } from '../../models/user.model';
13
+
14
+ @Injectable()
15
+ export class TokenInterceptor implements HttpInterceptor {
16
+ refresh = true;
17
+ constructor(private authService: AuthService, private http: HttpClient) {}
18
+
19
+ intercept(
20
+ request: HttpRequest<unknown>,
21
+ next: HttpHandler
22
+ ): Observable<HttpEvent<unknown>> {
23
+ if (this.isException(request)) {
24
+ return next.handle(request);
25
+ }
26
+ const token = this.authService.getToken();
27
+ if (token) {
28
+ this.isTokenExpired(token);
29
+ request = request.clone({
30
+ setHeaders: {
31
+ Authorization: `Bearer ${token}`,
32
+ },
33
+ });
34
+ }
35
+ return next.handle(request);
36
+ }
37
+
38
+ private isTokenExpired(token: string) {
39
+ const redirectPath = location.pathname;
40
+ const decodedToken = this.authService.getDecodedToken() as DecodedToken;
41
+ const expDate = new Date((decodedToken.exp ?? 0) * 1000);
42
+ if (expDate < new Date()) {
43
+ location.replace('/ar/login?redirect=' + redirectPath);
44
+ return;
45
+ } else {
46
+ if (this.authService.currentUserUrl) {
47
+ if (this.refresh) {
48
+ this.http
49
+ .get<User>(this.authService.currentUserUrl + `/api/users?refresh`, {
50
+ headers: { Authorization: `Bearer ${token}` },
51
+ })
52
+ .subscribe((user) => {
53
+ localStorage.setItem('token', user.token);
54
+ this.refresh = false;
55
+ setTimeout(() => {
56
+ this.refresh = true;
57
+ }, 60 * 1000);
58
+ });
59
+ }
60
+ } else {
61
+ throw new Error(
62
+ "provide current base user api url using this function authService.setCurrentUserUrl('https://...')"
63
+ );
64
+ }
65
+ }
66
+ }
67
+
68
+ private isException(request: HttpRequest<any>): boolean {
69
+ if (
70
+ request.url.includes('/api/users?refresh') &&
71
+ request.method === 'GET'
72
+ ) {
73
+ return true;
74
+ }
75
+ return false;
76
+ }
77
+ }
@@ -0,0 +1,48 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ import { DecodedToken } from '../../models/decodedToken.model';
4
+
5
+ @Injectable({
6
+ providedIn: 'root',
7
+ })
8
+ export class AuthService {
9
+ public currentUser = new BehaviorSubject<DecodedToken>({ exp: 0 });
10
+ currentUserUrl = '';
11
+ constructor() {}
12
+
13
+ getToken(): string {
14
+ return localStorage.getItem('token') ?? '';
15
+ }
16
+
17
+ getDecodedToken(): any {
18
+ return this.decodeJwt(this.getToken());
19
+ }
20
+
21
+ setCurrentUser(): void {
22
+ const decodedToken = this.getDecodedToken() as DecodedToken;
23
+ this.currentUser.next({
24
+ nameid: decodedToken.nameid,
25
+ email: decodedToken.email,
26
+ given_name: decodedToken.given_name,
27
+ exp: decodedToken.exp,
28
+ });
29
+ }
30
+
31
+ setCurrentUserUrl(url: string) {
32
+ this.currentUserUrl = url;
33
+ }
34
+
35
+ private decodeJwt(token: string): any {
36
+ const base64Url = token.split('.')[1];
37
+ const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
38
+ const jsonPayload = decodeURIComponent(
39
+ atob(base64)
40
+ .split('')
41
+ .map((c) => {
42
+ return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
43
+ })
44
+ .join('')
45
+ );
46
+ return JSON.parse(jsonPayload);
47
+ }
48
+ }
@@ -0,0 +1,19 @@
1
+ import { HttpRequest } from '@angular/common/http';
2
+ import { Injectable } from '@angular/core';
3
+ import { ExceptionUrl } from '../../models/exceptionUrl.model';
4
+
5
+ @Injectable({
6
+ providedIn: 'root'
7
+ })
8
+ export class ErrorService {
9
+ urls: ExceptionUrl[] = [];
10
+ constructor() {}
11
+
12
+ setExceptionUrls(urls: ExceptionUrl[]) {
13
+ this.urls = urls;
14
+ }
15
+
16
+ addExceptionUrl(url: ExceptionUrl) {
17
+ this.urls.push(url);
18
+ }
19
+ }
@@ -0,0 +1,21 @@
1
+ import { HttpRequest } from '@angular/common/http';
2
+ import { Injectable } from '@angular/core';
3
+ import { BehaviorSubject } from 'rxjs';
4
+ import { ExceptionUrl } from '../../models/exceptionUrl.model';
5
+
6
+ @Injectable({
7
+ providedIn: 'root',
8
+ })
9
+ export class LoaderService {
10
+ public isLoading = new BehaviorSubject(false);
11
+ urls: ExceptionUrl[] = [];
12
+ constructor() {}
13
+
14
+ setExceptionUrls(urls: ExceptionUrl[]) {
15
+ this.urls = urls;
16
+ }
17
+
18
+ addExceptionUrl(url: ExceptionUrl) {
19
+ this.urls.push(url);
20
+ }
21
+ }
@@ -0,0 +1,85 @@
1
+ <form [formGroup]="generateForm">
2
+ <ng-container *ngFor="let column of form.columns">
3
+ <div [ngSwitch]="column.type">
4
+ <!-- TEXTAREA -->
5
+ <div *ngSwitchCase="'textArea'">
6
+ <ipa-textarea-input [formControlName]="column.englishName" [id]="column.englishName"
7
+ [label]="column.arabicLabel" [required]="column.required" [pattern]="column.validationPattern!"
8
+ [patternErrorMsg]="column.patternErrorMsg!" [classes]="column.inputClasses!"
9
+ [containerClasses]="column.containerClasses!"></ipa-textarea-input>
10
+ </div>
11
+
12
+ <!-- DROP DOWN LIST -->
13
+ <div *ngSwitchCase="'select'">
14
+ <ipa-dropdown-input [formControlName]="column.englishName" [id]="column.englishName"
15
+ [label]="column.arabicLabel" [items]="column.data!" [valueField]="column.valueField!"
16
+ [textField]="column.textField!" [required]="column.required" [classes]="column.inputClasses!"
17
+ [containerClasses]="column.containerClasses!">
18
+ </ipa-dropdown-input>
19
+ </div>
20
+
21
+ <!-- CHECKBOX -->
22
+ <div *ngSwitchCase="'checkbox'">
23
+ <label [for]="column.englishName">{{column.arabicLabel}}</label>
24
+ <div [formArrayName]="'items'" *ngFor="let control of formControls.controls; let i = index">
25
+ <div [formGroupName]="i" [id]="column.englishName">
26
+ <div class="form-check">
27
+ <input [id]="column.englishName+control.value[column.valueField!]" class="form-check-input" type="checkbox"
28
+ formControlName="checkbox">
29
+ <label class="form-check-label" [for]="column.englishName+control.value[column.valueField!]">
30
+ {{control.value[column.textField!]}}
31
+ </label>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div class="invalid-feedback" style="display: block !important;"
36
+ *ngIf="getErrorMessage(column.englishName) !== null">
37
+ {{errorMsg}}
38
+ </div>
39
+ </div>
40
+
41
+ <!-- RADIO -->
42
+ <div *ngSwitchCase="'radio'">
43
+ <label [for]="column.englishName">{{column.arabicLabel}}</label>
44
+ <div *ngFor="let item of column.data; let i = index" [id]="column.englishName">
45
+ <div class="form-check">
46
+ <input [id]="column.englishName+item[column.valueField!]" class="form-check-input" type="radio"
47
+ [formControlName]="column.englishName" [value]="item[column.valueField!]">
48
+ <label class="form-check-label" [for]="column.englishName+item[column.valueField!]">
49
+ {{item[column.textField!]}}
50
+ </label>
51
+ </div>
52
+ </div>
53
+ <div class="invalid-feedback" style="display: block !important;"
54
+ *ngIf="getErrorMessage(column.englishName) !== null">
55
+ {{errorMsg}}
56
+ </div>
57
+ </div>
58
+
59
+ <!-- FILE UPLOAD -->
60
+ <div *ngSwitchCase="'file'">
61
+ <ipa-file-upload [label]="column.arabicLabel" [acceptedFiles]="column.acceptedFiles!"
62
+ [multiple]="column.multipleFile!" [maxFileSize]="column.size!" [method]="column.apiURlMethod!"
63
+ [autoUpload]="column.autoUploadFile!" [apiUrl]="column.apiUrl?? 'apiUrl' " [authorization]="column.authorization!"
64
+ ngDefaultControl [formControlName]="column.englishName" (successUpload)="SuccessUpload($event)"
65
+ (fileAdded)="FileAdded($event, column.englishName)"
66
+ (fileDeleted)="FileDeleted($event, column.englishName)"></ipa-file-upload>
67
+ </div>
68
+
69
+ <!-- recaptcha -->
70
+ <div *ngSwitchCase="'recaptcha'">
71
+ <ipa-recaptcha [recaptchaSize]="recaptchaSize" [lang]="lang" [theme]="theme"
72
+ [recaptchaType]="recaptchaType" [useGlobalDomain]="useGlobalDomain"
73
+ formControlName="{{column.englishName}}"></ipa-recaptcha>
74
+ </div>
75
+
76
+ <!-- DEFAULT -->
77
+ <div *ngSwitchDefault>
78
+ <ipa-text-input [formControlName]="column.englishName" [id]="column.englishName" [type]="column.type"
79
+ [label]="column.arabicLabel" [required]="column.required" [pattern]="column.validationPattern!"
80
+ [patternErrorMsg]="column.patternErrorMsg!" [classes]="column.inputClasses!"
81
+ [containerClasses]="column.containerClasses!"></ipa-text-input>
82
+ </div>
83
+ </div>
84
+ </ng-container>
85
+ </form>