ng-ipa-library 0.7.6 → 0.7.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundles/ng-ipa-library.umd.js +2092 -0
- package/bundles/ng-ipa-library.umd.js.map +1 -0
- package/esm2015/lib/core/components/loading/loading.component.js +27 -0
- package/esm2015/lib/core/interceptors/error.interceptor.js +46 -0
- package/esm2015/lib/core/interceptors/loading.interceptor.js +58 -0
- package/esm2015/lib/core/interceptors/token.interceptor.js +69 -0
- package/esm2015/lib/core/services/auth.service.js +48 -0
- package/esm2015/lib/core/services/error.service.js +22 -0
- package/esm2015/lib/core/services/loader.service.js +24 -0
- package/esm2015/lib/generate-form/generate-form.component.js +120 -0
- package/esm2015/lib/ipa-form/datepicker/datepicker.component.js +70 -0
- package/esm2015/lib/ipa-form/datepicker/gregorian-datepicker/gregorian-datepicker.component.js +28 -0
- package/esm2015/lib/ipa-form/datepicker/gregorian-datepicker/gregorian18n.js +38 -0
- package/esm2015/lib/ipa-form/datepicker/hijri-datepicker/IslamicI18n.js +38 -0
- package/esm2015/lib/ipa-form/datepicker/hijri-datepicker/hijri-datepicker.component.js +28 -0
- package/esm2015/lib/ipa-form/dropdown-input/dropdown-input.component.js +81 -0
- package/esm2015/lib/ipa-form/file-upload/file-upload.component.js +128 -0
- package/esm2015/lib/ipa-form/ipa-form.service.js +251 -0
- package/esm2015/lib/ipa-form/recaptcha/recaptcha.component.js +59 -0
- package/esm2015/lib/ipa-form/text-input/text-input.component.js +76 -0
- package/esm2015/lib/ipa-form/textarea-input/textarea-input.component.js +73 -0
- package/esm2015/lib/models/apiException.js +2 -0
- package/esm2015/lib/models/apiResponse.js +2 -0
- package/esm2015/lib/models/breadcrumbs.model.js +2 -0
- package/esm2015/lib/models/decodedToken.model.js +2 -0
- package/esm2015/lib/models/exceptionUrl.model.js +2 -0
- package/esm2015/lib/models/generateForm.model.js +2 -0
- package/esm2015/lib/models/pagedResult.js +2 -0
- package/esm2015/lib/models/user.model.js +2 -0
- package/esm2015/lib/ng-ipa-library.module.js +109 -0
- package/esm2015/lib/pipes/hijri-date.pipe.js +18 -0
- package/esm2015/lib/pipes/pipes.module.js +16 -0
- package/esm2015/lib/services/breadcrumbs.service.js +151 -0
- package/esm2015/lib/services/common.service.js +66 -0
- package/esm2015/lib/share-button/share-button.component.js +37 -0
- package/esm2015/lib/share-button/share-button.module.js +52 -0
- package/esm2015/ng-ipa-library.js +5 -0
- package/esm2015/public-api.js +39 -0
- package/fesm2015/ng-ipa-library.js +1629 -0
- package/fesm2015/ng-ipa-library.js.map +1 -0
- package/lib/core/components/loading/loading.component.d.ts +12 -0
- package/lib/core/interceptors/error.interceptor.d.ts +14 -0
- package/lib/core/interceptors/loading.interceptor.d.ts +14 -0
- package/lib/core/interceptors/token.interceptor.d.ts +15 -0
- package/lib/core/services/auth.service.d.ts +15 -0
- package/lib/core/services/error.service.d.ts +10 -0
- package/lib/core/services/loader.service.d.ts +12 -0
- package/lib/generate-form/generate-form.component.d.ts +32 -0
- package/lib/ipa-form/datepicker/datepicker.component.d.ts +31 -0
- package/lib/ipa-form/datepicker/gregorian-datepicker/gregorian-datepicker.component.d.ts +6 -0
- package/lib/ipa-form/datepicker/gregorian-datepicker/gregorian18n.d.ts +11 -0
- package/lib/ipa-form/datepicker/hijri-datepicker/IslamicI18n.d.ts +11 -0
- package/lib/ipa-form/datepicker/hijri-datepicker/hijri-datepicker.component.d.ts +6 -0
- package/lib/ipa-form/dropdown-input/dropdown-input.component.d.ts +31 -0
- package/lib/ipa-form/file-upload/file-upload.component.d.ts +36 -0
- package/lib/ipa-form/ipa-form.service.d.ts +49 -0
- package/lib/ipa-form/recaptcha/recaptcha.component.d.ts +22 -0
- package/lib/ipa-form/text-input/text-input.component.d.ts +30 -0
- package/lib/ipa-form/textarea-input/textarea-input.component.d.ts +29 -0
- package/{src/lib/models/apiException.ts → lib/models/apiException.d.ts} +1 -2
- package/lib/models/apiResponse.d.ts +4 -0
- package/lib/models/breadcrumbs.model.d.ts +4 -0
- package/lib/models/decodedToken.model.d.ts +6 -0
- package/lib/models/exceptionUrl.model.d.ts +4 -0
- package/lib/models/generateForm.model.d.ts +27 -0
- package/lib/models/pagedResult.d.ts +4 -0
- package/lib/models/user.model.d.ts +7 -0
- package/lib/ng-ipa-library.module.d.ts +25 -0
- package/lib/pipes/hijri-date.pipe.d.ts +7 -0
- package/lib/pipes/pipes.module.d.ts +7 -0
- package/lib/services/breadcrumbs.service.d.ts +18 -0
- package/lib/services/common.service.d.ts +8 -0
- package/lib/share-button/share-button.component.d.ts +11 -0
- package/lib/share-button/share-button.module.d.ts +13 -0
- package/ng-ipa-library.d.ts +5 -0
- package/package.json +30 -24
- package/{src/public-api.ts → public-api.d.ts} +0 -16
- package/karma.conf.js +0 -44
- package/ng-package.json +0 -43
- package/src/lib/core/components/loading/loading.component.html +0 -3
- package/src/lib/core/components/loading/loading.component.scss +0 -3
- package/src/lib/core/components/loading/loading.component.ts +0 -23
- package/src/lib/core/interceptors/error.interceptor.ts +0 -61
- package/src/lib/core/interceptors/loading.interceptor.ts +0 -69
- package/src/lib/core/interceptors/token.interceptor.ts +0 -77
- package/src/lib/core/services/auth.service.ts +0 -48
- package/src/lib/core/services/error.service.ts +0 -19
- package/src/lib/core/services/loader.service.ts +0 -21
- package/src/lib/generate-form/generate-form.component.html +0 -85
- package/src/lib/generate-form/generate-form.component.scss +0 -0
- package/src/lib/generate-form/generate-form.component.ts +0 -119
- package/src/lib/ipa-form/datepicker/datepicker.component.html +0 -21
- package/src/lib/ipa-form/datepicker/datepicker.component.scss +0 -13
- package/src/lib/ipa-form/datepicker/datepicker.component.ts +0 -67
- package/src/lib/ipa-form/datepicker/gregorian-datepicker/gregorian-datepicker.component.ts +0 -15
- package/src/lib/ipa-form/datepicker/gregorian-datepicker/gregorian18n.ts +0 -38
- package/src/lib/ipa-form/datepicker/hijri-datepicker/IslamicI18n.ts +0 -38
- package/src/lib/ipa-form/datepicker/hijri-datepicker/hijri-datepicker.component.ts +0 -14
- package/src/lib/ipa-form/dropdown-input/dropdown-input.component.html +0 -22
- package/src/lib/ipa-form/dropdown-input/dropdown-input.component.scss +0 -0
- package/src/lib/ipa-form/dropdown-input/dropdown-input.component.ts +0 -68
- package/src/lib/ipa-form/file-upload/file-upload.component.html +0 -37
- package/src/lib/ipa-form/file-upload/file-upload.component.scss +0 -45
- package/src/lib/ipa-form/file-upload/file-upload.component.ts +0 -109
- package/src/lib/ipa-form/ipa-form.service.ts +0 -294
- package/src/lib/ipa-form/recaptcha/recaptcha.component.html +0 -3
- package/src/lib/ipa-form/recaptcha/recaptcha.component.scss +0 -0
- package/src/lib/ipa-form/recaptcha/recaptcha.component.ts +0 -42
- package/src/lib/ipa-form/text-input/text-input.component.html +0 -10
- package/src/lib/ipa-form/text-input/text-input.component.scss +0 -0
- package/src/lib/ipa-form/text-input/text-input.component.ts +0 -69
- package/src/lib/ipa-form/textarea-input/textarea-input.component.html +0 -11
- package/src/lib/ipa-form/textarea-input/textarea-input.component.scss +0 -0
- package/src/lib/ipa-form/textarea-input/textarea-input.component.ts +0 -69
- package/src/lib/models/apiResponse.ts +0 -4
- package/src/lib/models/breadcrumbs.model.ts +0 -4
- package/src/lib/models/decodedToken.model.ts +0 -6
- package/src/lib/models/exceptionUrl.model.ts +0 -4
- package/src/lib/models/generateForm.model.ts +0 -29
- package/src/lib/models/pagedResult.ts +0 -4
- package/src/lib/models/user.model.ts +0 -7
- package/src/lib/ng-ipa-library.component.ts +0 -15
- package/src/lib/ng-ipa-library.module.ts +0 -63
- package/src/lib/pipes/hijri-date.pipe.ts +0 -15
- package/src/lib/pipes/pipes.module.ts +0 -8
- package/src/lib/services/breadcrumbs.service.ts +0 -189
- package/src/lib/services/common.service.ts +0 -63
- package/src/lib/share-button/share-button.component.html +0 -3
- package/src/lib/share-button/share-button.component.scss +0 -0
- package/src/lib/share-button/share-button.component.ts +0 -23
- package/src/lib/share-button/share-button.module.ts +0 -32
- package/src/test.ts +0 -26
- package/tsconfig.lib.json +0 -20
- package/tsconfig.lib.prod.json +0 -10
- package/tsconfig.spec.json +0 -17
|
@@ -1,77 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
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>
|
|
File without changes
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
|
2
|
-
import {
|
|
3
|
-
FormArray,
|
|
4
|
-
FormControl,
|
|
5
|
-
FormGroup,
|
|
6
|
-
Validators,
|
|
7
|
-
} from '@angular/forms';
|
|
8
|
-
import { IPAFormService } from '../ipa-form/ipa-form.service';
|
|
9
|
-
import { Column, GenerateForm } from '../models/generateForm.model';
|
|
10
|
-
|
|
11
|
-
@Component({
|
|
12
|
-
selector: 'ipa-generate-form',
|
|
13
|
-
templateUrl: './generate-form.component.html',
|
|
14
|
-
styleUrls: ['./generate-form.component.scss'],
|
|
15
|
-
})
|
|
16
|
-
export class GenerateFormComponent implements OnInit {
|
|
17
|
-
@Input() generateForm!: FormGroup;
|
|
18
|
-
@Input() form!: GenerateForm;
|
|
19
|
-
|
|
20
|
-
// recaptcha inputs
|
|
21
|
-
@Input() siteKey!: string;
|
|
22
|
-
@Input() recaptchaSize: 'compact' | 'normal' = 'normal';
|
|
23
|
-
@Input() lang = 'ar';
|
|
24
|
-
@Input() recaptchaType: 'image' | 'audio' = 'image';
|
|
25
|
-
@Input() theme: 'light' | 'dark' = 'light';
|
|
26
|
-
@Input() useGlobalDomain = true;
|
|
27
|
-
|
|
28
|
-
// file upload outputs
|
|
29
|
-
@Output() successUpload = new EventEmitter();
|
|
30
|
-
@Output() fileAdded = new EventEmitter();
|
|
31
|
-
@Output() fileDeleted = new EventEmitter();
|
|
32
|
-
|
|
33
|
-
errorMsg!: string | null;
|
|
34
|
-
|
|
35
|
-
constructor(private validationService: IPAFormService) {}
|
|
36
|
-
|
|
37
|
-
ngOnInit(): void {
|
|
38
|
-
this.createForm();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get formControls() {
|
|
42
|
-
return this.generateForm.get('items') as FormArray;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
getErrorMessage(formControlName: string): string | null {
|
|
46
|
-
const formControl = this.generateForm.controls[
|
|
47
|
-
formControlName
|
|
48
|
-
] as FormControl;
|
|
49
|
-
this.errorMsg = this.validationService.getErrorMessage(formControl);
|
|
50
|
-
return this.errorMsg;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
SuccessUpload(event: any) {
|
|
54
|
-
this.successUpload.emit(event);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
FileAdded(file: any, formControlName: string) {
|
|
58
|
-
this.generateForm.controls[formControlName].patchValue(file);
|
|
59
|
-
this.fileAdded.emit(file);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
FileDeleted(event: any, formControlName: string) {
|
|
63
|
-
this.generateForm.controls[formControlName].patchValue(null);
|
|
64
|
-
this.fileDeleted.emit(event);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private createForm() {
|
|
68
|
-
this.form.columns.forEach((column) => {
|
|
69
|
-
if (column.type === 'checkbox') {
|
|
70
|
-
this.addCheckboxControl(column);
|
|
71
|
-
} else {
|
|
72
|
-
this.generateForm.addControl(
|
|
73
|
-
column.englishName,
|
|
74
|
-
new FormControl(null, [
|
|
75
|
-
column.required ? Validators.required : Validators.nullValidator,
|
|
76
|
-
Validators.maxLength(column.size!),
|
|
77
|
-
column.type === 'number'
|
|
78
|
-
? Validators.min(1)
|
|
79
|
-
: Validators.nullValidator,
|
|
80
|
-
])
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
private addCheckboxControl(column: Column) {
|
|
87
|
-
let checkboxGroup = new FormArray(
|
|
88
|
-
column.data!.map((item) => {
|
|
89
|
-
return new FormGroup({
|
|
90
|
-
[column.valueField!]: new FormControl(item[column.valueField!]),
|
|
91
|
-
[column.textField!]: new FormControl(item[column.textField!]),
|
|
92
|
-
checkbox: new FormControl(false, Validators.required),
|
|
93
|
-
});
|
|
94
|
-
})
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
this.generateForm.addControl(
|
|
98
|
-
column.englishName,
|
|
99
|
-
new FormControl(
|
|
100
|
-
null,
|
|
101
|
-
column.required ? Validators.required : Validators.nullValidator
|
|
102
|
-
)
|
|
103
|
-
);
|
|
104
|
-
this.generateForm.addControl('items', checkboxGroup);
|
|
105
|
-
checkboxGroup.valueChanges.subscribe((value) => {
|
|
106
|
-
if (this.getCheckboxSelectedValues(value)) {
|
|
107
|
-
this.generateForm.controls[column.englishName].patchValue(value);
|
|
108
|
-
} else {
|
|
109
|
-
this.generateForm.controls[column.englishName].patchValue(null);
|
|
110
|
-
this.generateForm.controls[column.englishName].markAsTouched();
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private getCheckboxSelectedValues(items: any[]) {
|
|
116
|
-
let selectedItems = items.filter((item) => item.checkbox);
|
|
117
|
-
return selectedItems.length > 0 ? selectedItems : null;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<div class="form-floating input-group {{containerClasses}}">
|
|
2
|
-
<input id="{{id}}"
|
|
3
|
-
[ngClass]="{'is-invalid is-invalid:focus': (controlDir.control?.invalid && (controlDir.control?.dirty || controlDir.control?.touched)) && errorMsg,'is-valid is-valid:focus': (controlDir.control?.valid && (controlDir.control?.dirty || controlDir.control?.touched) && (errorMsg || controlDir.value))}"
|
|
4
|
-
class="form-control {{classes}}" [formControl]="formControl" [firstDayOfWeek]="7" ngbDatepicker
|
|
5
|
-
#d="ngbDatepicker" [maxDate]="maxDate" [minDate]="minDate" [footerTemplate]="footerTemplate"
|
|
6
|
-
[required]="required" style="outline: unset; z-index: unset !important;" autocomplete="off" (blur)="onTouched()" title="{{label}}">
|
|
7
|
-
<label for="{{id}}">{{label}}</label>
|
|
8
|
-
<span class="input-group-text calenderBtn" (click)="d.toggle()">
|
|
9
|
-
<i class="far fa-calendar-alt fa-lg"></i>
|
|
10
|
-
</span>
|
|
11
|
-
<div class="invalid-feedback" *ngIf="errorMessage !== null">
|
|
12
|
-
{{errorMsg}}
|
|
13
|
-
</div>
|
|
14
|
-
<ng-template #footerTemplate style="text-align: center;">
|
|
15
|
-
<hr>
|
|
16
|
-
<button type="button" class="btn btn-primary btn-sm m-2 " style="width: auto; float: right;"
|
|
17
|
-
(click)="formControl.patchValue(today);d.navigateTo(today);">اليوم</button>
|
|
18
|
-
<button type="button" class="btn btn-secondary btn-sm m-2" style="width: auto; float: left;"
|
|
19
|
-
(click)="formControl.patchValue(null);d.close()">مسح</button>
|
|
20
|
-
</ng-template>
|
|
21
|
-
</div>
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
.calenderBtn {
|
|
2
|
-
cursor: pointer;
|
|
3
|
-
background-color: transparent;
|
|
4
|
-
color: #6c757d;
|
|
5
|
-
border-top-left-radius: .25rem !important;
|
|
6
|
-
border-bottom-left-radius: .25rem !important;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
.calenderBtn:hover {
|
|
10
|
-
color: #fff;
|
|
11
|
-
background-color: #6c757d;
|
|
12
|
-
transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out;
|
|
13
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Component, Input, OnInit, Self } from '@angular/core';
|
|
2
|
-
import { FormControl, NgControl } from '@angular/forms';
|
|
3
|
-
import {
|
|
4
|
-
NgbCalendar,
|
|
5
|
-
NgbDateStruct,
|
|
6
|
-
NgbInputDatepickerConfig,
|
|
7
|
-
} from '@ng-bootstrap/ng-bootstrap';
|
|
8
|
-
import { IPAFormService } from '../ipa-form.service';
|
|
9
|
-
|
|
10
|
-
@Component({
|
|
11
|
-
selector: 'ipa-datepicker',
|
|
12
|
-
templateUrl: './datepicker.component.html',
|
|
13
|
-
styleUrls: ['./datepicker.component.scss'],
|
|
14
|
-
})
|
|
15
|
-
export class DatepickerComponent implements OnInit {
|
|
16
|
-
@Input() id!: string;
|
|
17
|
-
@Input() label = 'datepicker';
|
|
18
|
-
@Input() patternErrorMsg = 'invalid pattern';
|
|
19
|
-
@Input() required = false;
|
|
20
|
-
@Input() maxDate!: NgbDateStruct;
|
|
21
|
-
@Input() minDate!: NgbDateStruct;
|
|
22
|
-
@Input() classes!: string;
|
|
23
|
-
@Input() containerClasses!: string;
|
|
24
|
-
today = this.calendar.getToday();
|
|
25
|
-
formControl: FormControl = new FormControl('');
|
|
26
|
-
errorMsg!: string | null;
|
|
27
|
-
|
|
28
|
-
constructor(
|
|
29
|
-
private ipaFormService: IPAFormService,
|
|
30
|
-
private calendar: NgbCalendar,
|
|
31
|
-
@Self() public controlDir: NgControl,
|
|
32
|
-
config: NgbInputDatepickerConfig
|
|
33
|
-
) {
|
|
34
|
-
this.controlDir.valueAccessor = this;
|
|
35
|
-
config.container = 'body';
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
ngOnInit(): void {
|
|
39
|
-
const control = this.controlDir.control;
|
|
40
|
-
const validators = control?.validator ? [control.validator] : [];
|
|
41
|
-
|
|
42
|
-
control?.setValidators(validators);
|
|
43
|
-
control?.updateValueAndValidity();
|
|
44
|
-
this.formControl = control as FormControl;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
onChange(event: any): void {}
|
|
48
|
-
|
|
49
|
-
onTouched(): void {}
|
|
50
|
-
writeValue(obj: any): void {}
|
|
51
|
-
|
|
52
|
-
registerOnChange(fn: any): void {
|
|
53
|
-
this.onChange = fn;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
registerOnTouched(fn: any): void {
|
|
57
|
-
this.onTouched = fn;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
get errorMessage(): string | null {
|
|
61
|
-
this.errorMsg = this.ipaFormService.getErrorMessage(
|
|
62
|
-
this.formControl,
|
|
63
|
-
this.patternErrorMsg
|
|
64
|
-
);
|
|
65
|
-
return this.errorMsg;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Component } from '@angular/core';
|
|
2
|
-
import { NgbCalendar, NgbCalendarGregorian, NgbDatepickerI18n } from '@ng-bootstrap/ng-bootstrap';
|
|
3
|
-
import { DatepickerComponent } from '../datepicker.component';
|
|
4
|
-
import { Gregorian18n } from './gregorian18n';
|
|
5
|
-
|
|
6
|
-
@Component({
|
|
7
|
-
selector: 'ipa-gregorian-datepicker',
|
|
8
|
-
templateUrl: '../datepicker.component.html',
|
|
9
|
-
styleUrls: ['../datepicker.component.scss'],
|
|
10
|
-
providers: [
|
|
11
|
-
{ provide: NgbCalendar, useClass: NgbCalendarGregorian},
|
|
12
|
-
{ provide: NgbDatepickerI18n, useClass: Gregorian18n },
|
|
13
|
-
],
|
|
14
|
-
})
|
|
15
|
-
export class GregorianDatepickerComponent extends DatepickerComponent {}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { TranslationWidth } from '@angular/common';
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
import { NgbDatepickerI18n, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
|
|
4
|
-
|
|
5
|
-
const WEEKDAYS = ['ن', 'ث', 'ر', 'خ', 'ج', 'س', 'ح'];
|
|
6
|
-
const MONTHS = [
|
|
7
|
-
'يناير',
|
|
8
|
-
'فبراير',
|
|
9
|
-
'مارس',
|
|
10
|
-
'أبريل',
|
|
11
|
-
'مايو',
|
|
12
|
-
'يونيو',
|
|
13
|
-
'يوليو',
|
|
14
|
-
'اغسطس',
|
|
15
|
-
'سبتمبر',
|
|
16
|
-
'أكتوبر',
|
|
17
|
-
'نوفمبر',
|
|
18
|
-
'ديسمبر',
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
@Injectable()
|
|
22
|
-
export class Gregorian18n extends NgbDatepickerI18n {
|
|
23
|
-
getMonthShortName(month: number) {
|
|
24
|
-
return MONTHS[month - 1];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getMonthFullName(month: number) {
|
|
28
|
-
return MONTHS[month - 1];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getWeekdayLabel(weekday: number, width?: TranslationWidth) {
|
|
32
|
-
return WEEKDAYS[weekday - 1];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
getDayAriaLabel(date: NgbDateStruct): string {
|
|
36
|
-
return `${date.day}-${date.month}-${date.year}`;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { TranslationWidth } from '@angular/common';
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
import { NgbDatepickerI18n, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
|
|
4
|
-
|
|
5
|
-
const WEEKDAYS = ['ن', 'ث', 'ر', 'خ', 'ج', 'س', 'ح'];
|
|
6
|
-
const MONTHS = [
|
|
7
|
-
'محرم',
|
|
8
|
-
'صفر',
|
|
9
|
-
'ربيع الأول',
|
|
10
|
-
'ربيع الآخر',
|
|
11
|
-
'جمادى الأولى',
|
|
12
|
-
'جمادى الآخرة',
|
|
13
|
-
'رجب',
|
|
14
|
-
'شعبان',
|
|
15
|
-
'رمضان',
|
|
16
|
-
'شوال',
|
|
17
|
-
'ذو القعدة',
|
|
18
|
-
'ذو الحجة',
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
@Injectable()
|
|
22
|
-
export class IslamicI18n extends NgbDatepickerI18n {
|
|
23
|
-
getMonthShortName(month: number) {
|
|
24
|
-
return MONTHS[month - 1];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
getMonthFullName(month: number) {
|
|
28
|
-
return MONTHS[month - 1];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getWeekdayLabel(weekday: number, width?: TranslationWidth) {
|
|
32
|
-
return WEEKDAYS[weekday - 1];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
getDayAriaLabel(date: NgbDateStruct): string {
|
|
36
|
-
return `${date.day}-${date.month}-${date.year}`;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { Component } from '@angular/core';
|
|
2
|
-
import { NgbCalendar, NgbCalendarIslamicUmalqura, NgbDatepickerI18n } from '@ng-bootstrap/ng-bootstrap';
|
|
3
|
-
import { DatepickerComponent } from '../datepicker.component';
|
|
4
|
-
import { IslamicI18n } from './IslamicI18n';
|
|
5
|
-
@Component({
|
|
6
|
-
selector: 'ipa-hijri-datepicker',
|
|
7
|
-
templateUrl: '../datepicker.component.html',
|
|
8
|
-
styleUrls: ['../datepicker.component.scss'],
|
|
9
|
-
providers: [
|
|
10
|
-
{ provide: NgbCalendar, useClass: NgbCalendarIslamicUmalqura },
|
|
11
|
-
{ provide: NgbDatepickerI18n, useClass: IslamicI18n },
|
|
12
|
-
],
|
|
13
|
-
})
|
|
14
|
-
export class HijriDatepickerComponent extends DatepickerComponent {}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<div class="form-floating {{containerClasses}}"
|
|
2
|
-
[ngClass]="{'was-validated': (controlDir.control?.dirty || controlDir.control?.touched) && required}">
|
|
3
|
-
|
|
4
|
-
<!-- searchable is false -->
|
|
5
|
-
<ng-container *ngIf="!searchable">
|
|
6
|
-
<select #select id="{{id}}" class="form-select {{classes}}" [required]="required" [formControl]="formControl">
|
|
7
|
-
<option *ngFor="let item of items" [value]="valueField ? item[valueField] : item">
|
|
8
|
-
{{textField ? item[textField] : item}}</option>
|
|
9
|
-
</select>
|
|
10
|
-
<label for="{{id}}">{{label}}</label>
|
|
11
|
-
</ng-container>
|
|
12
|
-
|
|
13
|
-
<!-- searchable is true -->
|
|
14
|
-
<ng-select *ngIf="searchable" #select dir="rtl" class="{{classes}}" [formControl]="formControl" [items]="items"
|
|
15
|
-
[placeholder]="label" [notFoundText]="notFoundText" [required]="required" [bindValue]="valueField"
|
|
16
|
-
[bindLabel]="textField"
|
|
17
|
-
[ngClass]="{'is-invalid is-invalid:focus': (controlDir.control?.invalid && (controlDir.control?.dirty || controlDir.control?.touched)) && errorMsg,'is-valid is-valid:focus': (controlDir.control?.valid && (controlDir.control?.dirty || controlDir.control?.touched) && (errorMsg || controlDir.value))}">
|
|
18
|
-
</ng-select>
|
|
19
|
-
<div class="invalid-feedback" *ngIf="errorMessage !== null">
|
|
20
|
-
{{errorMsg}}
|
|
21
|
-
</div>
|
|
22
|
-
</div>
|
|
File without changes
|