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,68 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
ElementRef,
|
|
4
|
-
Input,
|
|
5
|
-
OnInit,
|
|
6
|
-
Self,
|
|
7
|
-
ViewChild,
|
|
8
|
-
} from '@angular/core';
|
|
9
|
-
import { FormControl, NgControl } from '@angular/forms';
|
|
10
|
-
import { IPAFormService } from '../ipa-form.service';
|
|
11
|
-
|
|
12
|
-
@Component({
|
|
13
|
-
selector: 'ipa-dropdown-input',
|
|
14
|
-
templateUrl: './dropdown-input.component.html',
|
|
15
|
-
styleUrls: ['./dropdown-input.component.scss'],
|
|
16
|
-
})
|
|
17
|
-
export class DropdownInputComponent implements OnInit {
|
|
18
|
-
@ViewChild('select', { static: true }) input!: HTMLSelectElement;
|
|
19
|
-
@Input() id!: string;
|
|
20
|
-
@Input() label: string = 'text input';
|
|
21
|
-
@Input() items: any[] = [];
|
|
22
|
-
@Input() textField!: string;
|
|
23
|
-
@Input() valueField!: string;
|
|
24
|
-
@Input() required = false;
|
|
25
|
-
@Input() searchable = false;
|
|
26
|
-
@Input() notFoundText = 'لا يوجد بيانات';
|
|
27
|
-
@Input() classes!: string;
|
|
28
|
-
@Input() containerClasses!: string;
|
|
29
|
-
formControl: FormControl = new FormControl('');
|
|
30
|
-
errorMsg!: string | null;
|
|
31
|
-
|
|
32
|
-
constructor(
|
|
33
|
-
private validationService: IPAFormService,
|
|
34
|
-
@Self() public controlDir: NgControl
|
|
35
|
-
) {
|
|
36
|
-
this.controlDir.valueAccessor = this;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
ngOnInit(): void {
|
|
40
|
-
const control = this.controlDir.control;
|
|
41
|
-
const validators = control?.validator ? [control.validator] : [];
|
|
42
|
-
|
|
43
|
-
control?.setValidators(validators);
|
|
44
|
-
control?.updateValueAndValidity();
|
|
45
|
-
this.formControl = control as FormControl;
|
|
46
|
-
this.formControl.patchValue(null);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
onChange(event: any): void {}
|
|
50
|
-
|
|
51
|
-
onTouched(): void {}
|
|
52
|
-
writeValue(obj: any): void {
|
|
53
|
-
if (this.input) this.input.value = obj || '';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
registerOnChange(fn: any): void {
|
|
57
|
-
this.onChange = fn;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
registerOnTouched(fn: any): void {
|
|
61
|
-
this.onTouched = fn;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
get errorMessage(): string | null {
|
|
65
|
-
this.errorMsg = this.validationService.getErrorMessage(this.formControl);
|
|
66
|
-
return this.errorMsg;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<div class="file-upload">
|
|
2
|
-
<div class="upload-overlay" [dropzone]="config" (error)="onUploadError($event)"
|
|
3
|
-
(queueComplete)="operationCompleted($event)" (success)="onUploadSuccess($event)" (dragenter)="dragEnter = true"
|
|
4
|
-
(dragLeave)="dragEnter = false" (drop)="dragEnter = false" (dragEnd)="dragEnter = false"
|
|
5
|
-
[class.active-border]="dragEnter" (sending)="sending($event)" (reset)="reset($event)"
|
|
6
|
-
(addedFile)="fileWasAdded($event)">
|
|
7
|
-
</div>
|
|
8
|
-
<div class="upload-btn-wrapper">
|
|
9
|
-
<div>
|
|
10
|
-
<div class="subtitle mb-2">
|
|
11
|
-
{{label}}
|
|
12
|
-
<span *ngIf="required" class="required">*</span>
|
|
13
|
-
</div>
|
|
14
|
-
<hr>
|
|
15
|
-
<span style="font-size: 12px;">قم بسحب الملف أو اضغط هنا</span>
|
|
16
|
-
<i class="fas fa-upload upload-icon mr-2"></i>
|
|
17
|
-
</div>
|
|
18
|
-
<div *ngIf="acceptedFiles.length > 0" class="allowed-extensions">
|
|
19
|
-
الصيغة المسموح بها:
|
|
20
|
-
<span class="extensions">{{ acceptedFiles }}</span>
|
|
21
|
-
</div>
|
|
22
|
-
<div class="allowed-extensions">
|
|
23
|
-
اقصى حجم للمرفق:
|
|
24
|
-
<span class="extensions">{{ maxFileSize }} MB</span>
|
|
25
|
-
</div>
|
|
26
|
-
</div>
|
|
27
|
-
</div>
|
|
28
|
-
<div id="attachment-status" style="text-align: center; margin-top:10px;">
|
|
29
|
-
<span style="font-size: 14px; margin: auto; font-weight:bold;" *ngFor="let file of currentFiles">
|
|
30
|
-
{{ file.name }} <i (click)="deleteFile(file)" class="fas fa-trash"
|
|
31
|
-
style="color:firebrick; cursor: pointer;"></i>
|
|
32
|
-
<br>
|
|
33
|
-
</span>
|
|
34
|
-
<ul class="list-unstyled">
|
|
35
|
-
<li class="text-danger" style="font-size: 12px;" *ngFor="let error of errors">{{error}}</li>
|
|
36
|
-
</ul>
|
|
37
|
-
</div>
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
.subtitle {
|
|
2
|
-
border-bottom: none;
|
|
3
|
-
display: block;
|
|
4
|
-
line-height: 2;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
.file-upload {
|
|
8
|
-
border: dashed 1px #ccc;
|
|
9
|
-
display: block;
|
|
10
|
-
min-height: 150px;
|
|
11
|
-
border-radius: 15px;
|
|
12
|
-
width: 350px;
|
|
13
|
-
cursor: pointer;
|
|
14
|
-
position: relative;
|
|
15
|
-
margin: auto;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.upload-overlay {
|
|
19
|
-
position: absolute;
|
|
20
|
-
width: 100%;
|
|
21
|
-
height: 100%;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.upload-btn-wrapper {
|
|
25
|
-
text-align: center;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
.upload-icon {
|
|
29
|
-
margin-right: 5px;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
.list-unstyled {
|
|
33
|
-
margin: 10px !important;
|
|
34
|
-
padding: 14px !important;
|
|
35
|
-
list-style: none;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.allowed-extensions {
|
|
39
|
-
color: #4d7297;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.required {
|
|
43
|
-
color: #dc3545;
|
|
44
|
-
font-size: 20px;
|
|
45
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
|
2
|
-
import { ToastrService } from 'ngx-toastr';
|
|
3
|
-
import { DropzoneConfigInterface, DropzoneDirective } from 'ngx-dropzone-wrapper';
|
|
4
|
-
|
|
5
|
-
@Component({
|
|
6
|
-
selector: 'ipa-file-upload',
|
|
7
|
-
templateUrl: './file-upload.component.html',
|
|
8
|
-
styleUrls: ['./file-upload.component.scss']
|
|
9
|
-
})
|
|
10
|
-
export class FileUploadComponent implements OnInit {
|
|
11
|
-
@ViewChild(DropzoneDirective, { static: false })
|
|
12
|
-
dropzoneDir!: DropzoneDirective;
|
|
13
|
-
@Input() label = '';
|
|
14
|
-
@Input() required = false;
|
|
15
|
-
@Input() acceptedFiles = '';
|
|
16
|
-
@Input() multiple = 1; // set maxFiles (NOT uploadMultiple)in the config object,
|
|
17
|
-
@Input() maxFileSize = 2;
|
|
18
|
-
@Input() method = 'POST';
|
|
19
|
-
@Input() autoUpload = false;
|
|
20
|
-
@Input() apiUrl = 'apiUrl';
|
|
21
|
-
@Input() authorization!: string;
|
|
22
|
-
@Output() successUpload = new EventEmitter();
|
|
23
|
-
@Output() fileAdded = new EventEmitter();
|
|
24
|
-
@Output() fileDeleted = new EventEmitter();
|
|
25
|
-
dragEnter = false;
|
|
26
|
-
errors: string[] = [];
|
|
27
|
-
config!: DropzoneConfigInterface;
|
|
28
|
-
filesAdded: File[] = [];
|
|
29
|
-
currentFiles: File[] = [];
|
|
30
|
-
|
|
31
|
-
constructor(
|
|
32
|
-
// private authService: AuthService,
|
|
33
|
-
private toastrService: ToastrService
|
|
34
|
-
) {}
|
|
35
|
-
|
|
36
|
-
ngOnInit(): void {
|
|
37
|
-
this.label = 'رفع ' + this.label;
|
|
38
|
-
this.config = {
|
|
39
|
-
url: this.apiUrl,
|
|
40
|
-
method: this.method,
|
|
41
|
-
headers: {
|
|
42
|
-
Authorization: 'Bearer ' + this.authorization,
|
|
43
|
-
},
|
|
44
|
-
maxFilesize: this.maxFileSize,
|
|
45
|
-
maxFiles: this.multiple,
|
|
46
|
-
uploadMultiple: this.multiple > 1,
|
|
47
|
-
dictInvalidFileType: 'صيغة الملف غير مسموح بها',
|
|
48
|
-
dictFileTooBig: 'الحجم تجاوز الحد المسموح',
|
|
49
|
-
dictMaxFilesExceeded:
|
|
50
|
-
'الرجاء حذف الملفات الموجودة حاليا لتتمكن من رفع هذا الملف',
|
|
51
|
-
acceptedFiles: this.acceptedFiles,
|
|
52
|
-
autoProcessQueue: this.autoUpload,
|
|
53
|
-
previewTemplate: '<span></span>',
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
operationCompleted(e: any): void {
|
|
58
|
-
if (this.filesAdded.length > 0) {
|
|
59
|
-
this.successUpload.emit(this.filesAdded);
|
|
60
|
-
this.filesAdded = [];
|
|
61
|
-
}
|
|
62
|
-
this.dropzoneDir.reset();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
onUploadSuccess(e: any): void {
|
|
66
|
-
const file = e[0];
|
|
67
|
-
if (file.status === 'success') {
|
|
68
|
-
this.filesAdded.push(file);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
this.toastrService.success('تم تحميل المرفقات بنجاح');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
onUploadError(e: any): void {
|
|
75
|
-
if (e[1]) {
|
|
76
|
-
this.errors = [];
|
|
77
|
-
this.errors.push(`${e[1]} (${e[0].name})`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
fileWasAdded(e: File): void {
|
|
82
|
-
const myDropzone = this.dropzoneDir.dropzone();
|
|
83
|
-
if (this.multiple === 1) {
|
|
84
|
-
this.currentFiles = [];
|
|
85
|
-
this.filesAdded = [];
|
|
86
|
-
this.errors = [];
|
|
87
|
-
const files = myDropzone.files;
|
|
88
|
-
if (files.length > 1) {
|
|
89
|
-
myDropzone.removeFile(files[0]);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
this.currentFiles.push(e);
|
|
93
|
-
this.fileAdded.emit(e);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
sending(e: any): void {
|
|
97
|
-
this.errors = [];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
reset(e: any): void {}
|
|
101
|
-
|
|
102
|
-
deleteFile(file: any): void {
|
|
103
|
-
this.currentFiles = this.currentFiles.filter(
|
|
104
|
-
(x) => x.name !== file.name && x.size !== file.size
|
|
105
|
-
);
|
|
106
|
-
this.errors = [];
|
|
107
|
-
this.fileDeleted.emit();
|
|
108
|
-
}
|
|
109
|
-
}
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
import { AbstractControl, FormControl, ValidationErrors } from '@angular/forms';
|
|
3
|
-
import momentHijri from 'moment-hijri';
|
|
4
|
-
import { Moment } from 'moment';
|
|
5
|
-
import { NgbDateParserFormatter } from '@ng-bootstrap/ng-bootstrap';
|
|
6
|
-
|
|
7
|
-
@Injectable({
|
|
8
|
-
providedIn: 'root',
|
|
9
|
-
})
|
|
10
|
-
export class IPAFormService {
|
|
11
|
-
constructor(private parserFormatter: NgbDateParserFormatter) {}
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* check link is valid.
|
|
15
|
-
*/
|
|
16
|
-
static linkValidation(control: AbstractControl): ValidationErrors | null {
|
|
17
|
-
const isValidLink =
|
|
18
|
-
/^((https?:\/\/)[\w-]+(\.[a-z-]+)+\.?(:\d+)?(\/\S*)?)$/.test(
|
|
19
|
-
control.value
|
|
20
|
-
);
|
|
21
|
-
return isValidLink || !control.value ? null : { link: true };
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* check mp4 link is valid.
|
|
26
|
-
*/
|
|
27
|
-
static mp4LinkValidation(control: AbstractControl): ValidationErrors | null {
|
|
28
|
-
const isValidLink =
|
|
29
|
-
/^((https?:\/\/)[\w-]+(\.[a-z-]+)+\.?(:\d+)?(\/\S*)?(\/[\w\u0600-\u06FF]+\.mp4))$/.test(
|
|
30
|
-
control.value
|
|
31
|
-
);
|
|
32
|
-
return isValidLink || !control.value ? null : { linkMP4: true };
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* check mobile number is valid.
|
|
37
|
-
*/
|
|
38
|
-
static mobileNo(control: AbstractControl): ValidationErrors | null {
|
|
39
|
-
const isValidLink = /^05\d{8}$/.test(control.value);
|
|
40
|
-
return isValidLink || !control.value ? null : { mobileNo: true };
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* check email is valid.
|
|
45
|
-
*/
|
|
46
|
-
static email(control: AbstractControl): ValidationErrors | null {
|
|
47
|
-
const isValidLink =
|
|
48
|
-
/^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/.test(
|
|
49
|
-
control.value
|
|
50
|
-
);
|
|
51
|
-
return isValidLink || !control.value ? null : { Email: true };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* check national ID or iqama ID is valid.
|
|
56
|
-
*/
|
|
57
|
-
static checkID(control: AbstractControl): ValidationErrors | null {
|
|
58
|
-
let isValid = false;
|
|
59
|
-
const value = control.value;
|
|
60
|
-
if (
|
|
61
|
-
IPAFormService.nationalIdValidate(value) ||
|
|
62
|
-
IPAFormService.iqamaIdValidate(value)
|
|
63
|
-
) {
|
|
64
|
-
isValid = true;
|
|
65
|
-
} else {
|
|
66
|
-
isValid = false;
|
|
67
|
-
}
|
|
68
|
-
return isValid || !value ? null : { checkId: true };
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
getErrorMessage(control: FormControl, patternErrorMsg = ''): string | null {
|
|
72
|
-
for (const propertyName in control?.errors) {
|
|
73
|
-
if (
|
|
74
|
-
control?.errors.hasOwnProperty(propertyName) &&
|
|
75
|
-
(control.touched || control.dirty)
|
|
76
|
-
) {
|
|
77
|
-
return this.getValidatorErrorMessage(
|
|
78
|
-
propertyName,
|
|
79
|
-
control.errors[propertyName],
|
|
80
|
-
patternErrorMsg
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* convert gregorian date to hijri date (Based on Umm al-Qura calculations).
|
|
89
|
-
* @param date: gregorian date
|
|
90
|
-
* @param format: iDD => day: ١٥, iMM => month: ٠٤, iMMM => month: ربيع ٢,
|
|
91
|
-
* iMMMM => ربيع الثاني, iYY => year: ٤٢, iYYYY => year: ١٤٤٢,
|
|
92
|
-
* dd => ن, ddd => إثنين, dddd => الإثنين
|
|
93
|
-
* @example 'iYYYY/iM/iDهـ الموافق YYYY/M/Dم'
|
|
94
|
-
* '١٤٤٢/٠٤/١٥هـ الموافق ٢٠٢٠/١١/٣٠'
|
|
95
|
-
*/
|
|
96
|
-
convertToHijriDate(
|
|
97
|
-
date: string,
|
|
98
|
-
format = 'iYYYY-iMM-iDD',
|
|
99
|
-
lang = 'ar-SA'
|
|
100
|
-
): string {
|
|
101
|
-
momentHijri.locale(lang);
|
|
102
|
-
return momentHijri(date).format(format);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
convertToGregorianDate(
|
|
106
|
-
date: Moment,
|
|
107
|
-
format = 'YYYY-MM-DD',
|
|
108
|
-
lang = 'en'
|
|
109
|
-
): string {
|
|
110
|
-
momentHijri.locale(lang);
|
|
111
|
-
const m = momentHijri.iConvert.toGregorian(
|
|
112
|
-
date.year(),
|
|
113
|
-
date.month(),
|
|
114
|
-
date.date()
|
|
115
|
-
);
|
|
116
|
-
return momentHijri(new Date(m.gy, m.gm, m.gd)).format(format);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
getCurrentHijriDate() {
|
|
120
|
-
momentHijri.locale('en');
|
|
121
|
-
return momentHijri().format('iYYYY/iMM/iDD');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
private getValidatorErrorMessage(
|
|
125
|
-
validatorName: string,
|
|
126
|
-
validatorValue: any,
|
|
127
|
-
patternErrorMsg: string
|
|
128
|
-
): string {
|
|
129
|
-
if (validatorName === 'pattern') {
|
|
130
|
-
validatorValue = this.addPatternMsg(validatorValue, patternErrorMsg);
|
|
131
|
-
}
|
|
132
|
-
const config: any = {
|
|
133
|
-
required: 'هذا الحقل مطلوب',
|
|
134
|
-
pattern: `${validatorValue.message}`,
|
|
135
|
-
Email: 'خطأ في البريد الالكتروني (example@ipa.edu.sa)',
|
|
136
|
-
maxlength: `تجاوز عدد الحقل المسموح بها (${validatorValue.requiredLength}) حرف`,
|
|
137
|
-
minlength: `على الأقل عدد ${validatorValue.requiredLength} حرف.`,
|
|
138
|
-
min: `رقم اكبر من أو يساوي ${validatorValue.min}`,
|
|
139
|
-
max: `رقم اصغر من أو يساوي ${validatorValue.max}`,
|
|
140
|
-
ngbDate: this.getNgbDatepickerErrorMsg(validatorValue),
|
|
141
|
-
checkId: 'رقم الهوية أو الاقامة غير صحيح',
|
|
142
|
-
link: 'الرابط غير صحيح (http://google.com)',
|
|
143
|
-
linkMP4: 'الرابط غير صحيح (http://example.com/a.mp4)',
|
|
144
|
-
mobileNo: 'خطأ في رقم الجوال (05xxxxxxxx)',
|
|
145
|
-
};
|
|
146
|
-
return config[validatorName];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private addPatternMsg(validatorValue: any, patternErrorMsg: string) {
|
|
150
|
-
let pattern = {
|
|
151
|
-
...validatorValue,
|
|
152
|
-
message: patternErrorMsg,
|
|
153
|
-
};
|
|
154
|
-
return pattern;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private getNgbDatepickerErrorMsg(validatorValue: any): string {
|
|
158
|
-
let msg = '';
|
|
159
|
-
if (validatorValue.maxDate) {
|
|
160
|
-
msg = `التاريخ المدخل "${this.parserFormatter.format(
|
|
161
|
-
validatorValue.maxDate.actual
|
|
162
|
-
)}" اكبر من تاريخ اليوم "${this.parserFormatter.format(
|
|
163
|
-
validatorValue.maxDate.maxDate
|
|
164
|
-
)}"`;
|
|
165
|
-
} else if (validatorValue.minDate) {
|
|
166
|
-
msg = `التاريخ المدخل "${this.parserFormatter.format(
|
|
167
|
-
validatorValue.minDate.actual
|
|
168
|
-
)}" يجب ان يكون اكبر من أو يساوي تاريخ البداية "${this.parserFormatter.format(
|
|
169
|
-
validatorValue.minDate.minDate
|
|
170
|
-
)}"`;
|
|
171
|
-
} else if (validatorValue.invalid) {
|
|
172
|
-
msg = `التاريخ المدخل غير صحيح ${validatorValue.invalid}.`;
|
|
173
|
-
}
|
|
174
|
-
return msg;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
private static convertToEn(value: string) {
|
|
178
|
-
let newValue = '';
|
|
179
|
-
for (let i = 0; i < value.length; i++) {
|
|
180
|
-
let ch = value.charCodeAt(i);
|
|
181
|
-
if (ch >= 1584 && ch <= 1650) {
|
|
182
|
-
let newChar = ch - 1584;
|
|
183
|
-
newValue = newValue + String.fromCharCode(newChar);
|
|
184
|
-
} else {
|
|
185
|
-
newValue = newValue + String.fromCharCode(ch);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return newValue;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
private static nationalIdValidate(civilId: string): boolean {
|
|
192
|
-
if (civilId) {
|
|
193
|
-
let strID = this.convertToEn(civilId);
|
|
194
|
-
let digits = '';
|
|
195
|
-
let counter = 0;
|
|
196
|
-
while (counter < 9) {
|
|
197
|
-
if ((counter + 1) % 2 == 0) {
|
|
198
|
-
digits = digits + strID.substring(counter, counter + 1);
|
|
199
|
-
} else {
|
|
200
|
-
digits =
|
|
201
|
-
digits + (+strID.substring(counter, counter + 1) * 2).toString();
|
|
202
|
-
}
|
|
203
|
-
counter++;
|
|
204
|
-
}
|
|
205
|
-
let intSum = 0;
|
|
206
|
-
let intSumTemp = 0;
|
|
207
|
-
let strSum;
|
|
208
|
-
let intOddSumDigit;
|
|
209
|
-
let CheckDigit;
|
|
210
|
-
counter = 0;
|
|
211
|
-
while (counter < digits.length) {
|
|
212
|
-
intSumTemp = +digits.charAt(counter) * 1;
|
|
213
|
-
intSum += intSumTemp;
|
|
214
|
-
counter++;
|
|
215
|
-
}
|
|
216
|
-
strSum = intSum.toString();
|
|
217
|
-
if (strSum.length == 1) {
|
|
218
|
-
intOddSumDigit = intSum;
|
|
219
|
-
} else {
|
|
220
|
-
intOddSumDigit = strSum.substring(strSum.length, strSum.length - 1);
|
|
221
|
-
}
|
|
222
|
-
if (intOddSumDigit == 0) {
|
|
223
|
-
CheckDigit = 0;
|
|
224
|
-
} else {
|
|
225
|
-
CheckDigit = (10 - +intOddSumDigit).toString();
|
|
226
|
-
}
|
|
227
|
-
let PublicID = this.convertToEn(civilId);
|
|
228
|
-
if (
|
|
229
|
-
CheckDigit ==
|
|
230
|
-
PublicID.substring(PublicID.length - 1, PublicID.length) &&
|
|
231
|
-
strID.length == 10 &&
|
|
232
|
-
strID.substring(0, 1) == '1'
|
|
233
|
-
) {
|
|
234
|
-
return true;
|
|
235
|
-
} else {
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
private static iqamaIdValidate(civilId: string): boolean {
|
|
244
|
-
if (civilId) {
|
|
245
|
-
let strID = this.convertToEn(civilId);
|
|
246
|
-
let digits = '';
|
|
247
|
-
let counter = 0;
|
|
248
|
-
while (counter < 9) {
|
|
249
|
-
if ((counter + 1) % 2 == 0) {
|
|
250
|
-
digits = digits + strID.substring(counter, counter + 1);
|
|
251
|
-
} else {
|
|
252
|
-
digits =
|
|
253
|
-
digits + (+strID.substring(counter, counter + 1) * 2).toString();
|
|
254
|
-
}
|
|
255
|
-
counter++;
|
|
256
|
-
}
|
|
257
|
-
let intSum = 0;
|
|
258
|
-
let intSumTemp = 0;
|
|
259
|
-
let strSum;
|
|
260
|
-
let intOddSumDigit;
|
|
261
|
-
let CheckDigit;
|
|
262
|
-
counter = 0;
|
|
263
|
-
while (counter < digits.length) {
|
|
264
|
-
intSumTemp = +digits.charAt(counter) * 1;
|
|
265
|
-
intSum += intSumTemp;
|
|
266
|
-
counter++;
|
|
267
|
-
}
|
|
268
|
-
strSum = intSum.toString();
|
|
269
|
-
if (strSum.length == 1) {
|
|
270
|
-
intOddSumDigit = intSum;
|
|
271
|
-
} else {
|
|
272
|
-
intOddSumDigit = strSum.substring(strSum.length, strSum.length - 1);
|
|
273
|
-
}
|
|
274
|
-
if (intOddSumDigit == 0) {
|
|
275
|
-
CheckDigit = 0;
|
|
276
|
-
} else {
|
|
277
|
-
CheckDigit = (10 - +intOddSumDigit).toString();
|
|
278
|
-
}
|
|
279
|
-
let PublicID = this.convertToEn(civilId);
|
|
280
|
-
if (
|
|
281
|
-
CheckDigit ==
|
|
282
|
-
PublicID.substring(PublicID.length - 1, PublicID.length) &&
|
|
283
|
-
strID.length == 10 &&
|
|
284
|
-
strID.substring(0, 1) == '2'
|
|
285
|
-
) {
|
|
286
|
-
return true;
|
|
287
|
-
} else {
|
|
288
|
-
return false;
|
|
289
|
-
}
|
|
290
|
-
} else {
|
|
291
|
-
return false;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
File without changes
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Component, Input, OnInit, Self } from '@angular/core';
|
|
2
|
-
import { FormControl, NgControl } from '@angular/forms';
|
|
3
|
-
|
|
4
|
-
@Component({
|
|
5
|
-
selector: 'ipa-recaptcha',
|
|
6
|
-
templateUrl: './recaptcha.component.html',
|
|
7
|
-
styleUrls: ['./recaptcha.component.scss'],
|
|
8
|
-
})
|
|
9
|
-
export class RecaptchaComponent implements OnInit {
|
|
10
|
-
@Input() siteKey = '6LefJQYdAAAAAIlxmfkjNlWidMk8VukIZcs6lO5e';
|
|
11
|
-
@Input() recaptchaSize: 'compact' | 'normal' = 'normal';
|
|
12
|
-
@Input() lang = 'ar';
|
|
13
|
-
@Input() recaptchaType: 'image' | 'audio' = 'image';
|
|
14
|
-
@Input() theme: 'light' | 'dark' = 'light';
|
|
15
|
-
@Input() useGlobalDomain = true;
|
|
16
|
-
formControl: FormControl = new FormControl('');
|
|
17
|
-
constructor(@Self() public controlDir: NgControl) {
|
|
18
|
-
this.controlDir.valueAccessor = this;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
ngOnInit(): void {
|
|
22
|
-
const control = this.controlDir.control;
|
|
23
|
-
const validators = control?.validator ? [control.validator] : [];
|
|
24
|
-
|
|
25
|
-
control?.setValidators(validators);
|
|
26
|
-
control?.updateValueAndValidity();
|
|
27
|
-
this.formControl = control as FormControl;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
onChange(event: any): void {}
|
|
31
|
-
|
|
32
|
-
onTouched(): void {}
|
|
33
|
-
writeValue(obj: any): void {}
|
|
34
|
-
|
|
35
|
-
registerOnChange(fn: any): void {
|
|
36
|
-
this.onChange = fn;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
registerOnTouched(fn: any): void {
|
|
40
|
-
this.onTouched = fn;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
<div class="form-floating {{containerClasses}}">
|
|
2
|
-
<input #input id="{{id}}" class="form-control {{classes}}" [type]="type" [required]="required" pattern="{{pattern}}"
|
|
3
|
-
placeholder="{{placeholder}}" [formControl]="formControl" (input)="onChange(controlDir.control?.value)"
|
|
4
|
-
(blur)="onTouched()"
|
|
5
|
-
[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))}">
|
|
6
|
-
<label for="{{id}}">{{label}}</label>
|
|
7
|
-
<div class="invalid-feedback" *ngIf="errorMessage !== null">
|
|
8
|
-
{{errorMsg}}
|
|
9
|
-
</div>
|
|
10
|
-
</div>
|
|
File without changes
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
ElementRef,
|
|
4
|
-
Input,
|
|
5
|
-
OnInit,
|
|
6
|
-
Self,
|
|
7
|
-
ViewChild,
|
|
8
|
-
} from '@angular/core';
|
|
9
|
-
import { FormControl, NgControl } from '@angular/forms';
|
|
10
|
-
import { IPAFormService } from '../ipa-form.service';
|
|
11
|
-
|
|
12
|
-
@Component({
|
|
13
|
-
selector: 'ipa-text-input',
|
|
14
|
-
templateUrl: './text-input.component.html',
|
|
15
|
-
styleUrls: ['./text-input.component.scss'],
|
|
16
|
-
})
|
|
17
|
-
export class TextInputComponent implements OnInit {
|
|
18
|
-
@ViewChild('input', { static: true }) input!: ElementRef;
|
|
19
|
-
@Input() id!: string;
|
|
20
|
-
@Input() type = 'text';
|
|
21
|
-
@Input() placeholder = 'please enter text';
|
|
22
|
-
@Input() label: string = 'text input';
|
|
23
|
-
@Input() required = false;
|
|
24
|
-
@Input() patternErrorMsg = 'invalid pattern';
|
|
25
|
-
@Input() pattern = '';
|
|
26
|
-
@Input() classes!: string;
|
|
27
|
-
@Input() containerClasses!: string;
|
|
28
|
-
formControl: FormControl = new FormControl('');
|
|
29
|
-
errorMsg!: string | null;
|
|
30
|
-
|
|
31
|
-
constructor(
|
|
32
|
-
private validationService: IPAFormService,
|
|
33
|
-
@Self() public controlDir: NgControl
|
|
34
|
-
) {
|
|
35
|
-
this.controlDir.valueAccessor = this;
|
|
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
|
-
this.input.nativeElement.value = obj || '';
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
registerOnChange(fn: any): void {
|
|
55
|
-
this.onChange = fn;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
registerOnTouched(fn: any): void {
|
|
59
|
-
this.onTouched = fn;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
get errorMessage(): string | null {
|
|
63
|
-
this.errorMsg = this.validationService.getErrorMessage(
|
|
64
|
-
this.formControl,
|
|
65
|
-
this.patternErrorMsg
|
|
66
|
-
);
|
|
67
|
-
return this.errorMsg;
|
|
68
|
-
}
|
|
69
|
-
}
|