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
@@ -0,0 +1,294 @@
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
+ }
@@ -0,0 +1,3 @@
1
+ <ngx-recaptcha2 [siteKey]="siteKey" [size]="recaptchaSize" [hl]="lang" [theme]="theme" [type]="recaptchaType"
2
+ [useGlobalDomain]="useGlobalDomain" [formControl]="formControl">
3
+ </ngx-recaptcha2>
@@ -0,0 +1,42 @@
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
+ }
@@ -0,0 +1,10 @@
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>
@@ -0,0 +1,69 @@
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
+ }
@@ -0,0 +1,11 @@
1
+ <div class="form-floating {{containerClasses}}">
2
+ <textarea #input id="{{id}}" class="form-control {{classes}}" [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
+ </textarea>
7
+ <label for="{{id}}">{{label}}</label>
8
+ <div class="invalid-feedback" *ngIf="errorMessage !== null">
9
+ {{errorMsg}}
10
+ </div>
11
+ </div>
@@ -0,0 +1,69 @@
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-textarea-input',
14
+ templateUrl: './textarea-input.component.html',
15
+ styleUrls: ['./textarea-input.component.scss'],
16
+ })
17
+ export class TextareaInputComponent implements OnInit {
18
+ @ViewChild('input', { static: true }) input: ElementRef<any> =
19
+ new ElementRef<any>(null);
20
+ @Input() id!: string;
21
+ @Input() placeholder = 'please enter text';
22
+ @Input() label: string = 'textarea input';
23
+ @Input() required = false;
24
+ @Input() patternErrorMsg = 'invalid pattern';
25
+ @Input() pattern!: string;
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
+ }
@@ -1,5 +1,6 @@
1
1
  import { ApiResponse } from "./apiResponse";
2
+
2
3
  export interface ApiException extends ApiResponse {
3
4
  innerException: string;
4
5
  stackTrace: string;
5
- }
6
+ }
@@ -0,0 +1,4 @@
1
+ export interface ApiResponse {
2
+ statusCode: number;
3
+ message: string;
4
+ }
@@ -0,0 +1,4 @@
1
+ export interface Breadcrumbs {
2
+ nodeName: string;
3
+ nodeUrl: string | null;
4
+ }
@@ -0,0 +1,6 @@
1
+ export interface DecodedToken {
2
+ nameid?: string;
3
+ given_name?: string;
4
+ email?: string;
5
+ exp?: number;
6
+ }
@@ -0,0 +1,4 @@
1
+ export interface ExceptionUrl {
2
+ path: string;
3
+ method: string;
4
+ }
@@ -0,0 +1,29 @@
1
+ export interface GenerateForm {
2
+ columns: Column[];
3
+ }
4
+
5
+ export interface Column {
6
+ arabicLabel: string;
7
+ englishName: string;
8
+ validationPattern?: string;
9
+ inputClasses?: string;
10
+ containerClasses?: string;
11
+ valueField?: string;
12
+ textField?: string;
13
+ patternErrorMsg?: string;
14
+ type: string;
15
+ size?: number;
16
+ required: boolean;
17
+ data?: Data[] | any[];
18
+ acceptedFiles?: string;
19
+ multipleFile?: number;
20
+ apiUrl?: string;
21
+ autoUploadFile?: boolean;
22
+ apiURlMethod?: string;
23
+ authorization?: string;
24
+ }
25
+
26
+ export interface Data {
27
+ id: number;
28
+ description: string;
29
+ }
@@ -0,0 +1,4 @@
1
+ export interface PagedResult<T> {
2
+ data: T[];
3
+ count: number;
4
+ }
@@ -0,0 +1,7 @@
1
+ export interface User {
2
+ id: string;
3
+ email: string;
4
+ displayName: string;
5
+ token: string;
6
+ imageUrl: string;
7
+ }
@@ -0,0 +1,15 @@
1
+ import { Component, OnInit } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'lib-ipa-library',
5
+ template: ``,
6
+ styles: []
7
+ })
8
+ export class NgIpaFormComponent implements OnInit {
9
+
10
+ constructor() { }
11
+
12
+ ngOnInit(): void {
13
+ }
14
+
15
+ }
@@ -0,0 +1,63 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
4
+ import { ToastrModule } from 'ngx-toastr';
5
+ import { DropzoneModule } from 'ngx-dropzone-wrapper';
6
+ import { NgxCaptchaModule } from 'ngx-captcha';
7
+ import { PipesModule } from './pipes/pipes.module';
8
+ import { NgbDatepickerModule } from '@ng-bootstrap/ng-bootstrap';
9
+ import { NgSelectModule } from '@ng-select/ng-select';
10
+
11
+ import { TextInputComponent } from './ipa-form/text-input/text-input.component';
12
+ import { TextareaInputComponent } from './ipa-form/textarea-input/textarea-input.component';
13
+ import { DropdownInputComponent } from './ipa-form/dropdown-input/dropdown-input.component';
14
+ import { LoaderComponent } from './core/components/loading/loading.component';
15
+ import { GenerateFormComponent } from './generate-form/generate-form.component';
16
+ import { FileUploadComponent } from './ipa-form/file-upload/file-upload.component';
17
+ import { DatepickerComponent } from './ipa-form/datepicker/datepicker.component';
18
+ import { HijriDatepickerComponent } from './ipa-form/datepicker/hijri-datepicker/hijri-datepicker.component';
19
+ import { GregorianDatepickerComponent } from './ipa-form/datepicker/gregorian-datepicker/gregorian-datepicker.component';
20
+ import { ShareButtonModule } from './share-button/share-button.module';
21
+ import { RecaptchaComponent } from './ipa-form/recaptcha/recaptcha.component';
22
+
23
+ @NgModule({
24
+ declarations: [
25
+ TextInputComponent,
26
+ TextareaInputComponent,
27
+ DropdownInputComponent,
28
+ LoaderComponent,
29
+ GenerateFormComponent,
30
+ FileUploadComponent,
31
+ DatepickerComponent,
32
+ HijriDatepickerComponent,
33
+ GregorianDatepickerComponent,
34
+ RecaptchaComponent,
35
+ ],
36
+ imports: [
37
+ CommonModule,
38
+ FormsModule,
39
+ ReactiveFormsModule,
40
+ ToastrModule,
41
+ DropzoneModule,
42
+ NgxCaptchaModule,
43
+ PipesModule,
44
+ NgbDatepickerModule,
45
+ ShareButtonModule,
46
+ NgSelectModule,
47
+ ],
48
+ exports: [
49
+ TextInputComponent,
50
+ TextareaInputComponent,
51
+ DropdownInputComponent,
52
+ LoaderComponent,
53
+ GenerateFormComponent,
54
+ FileUploadComponent,
55
+ PipesModule,
56
+ HijriDatepickerComponent,
57
+ GregorianDatepickerComponent,
58
+ ShareButtonModule,
59
+ RecaptchaComponent,
60
+ NgSelectModule,
61
+ ],
62
+ })
63
+ export class NgIPALibraryModule {}
@@ -0,0 +1,15 @@
1
+ import { Pipe, PipeTransform } from '@angular/core';
2
+ import momentHijri from 'moment-hijri';
3
+ @Pipe({
4
+ name: 'hijriDate',
5
+ })
6
+ export class HijriDatePipe implements PipeTransform {
7
+ transform(
8
+ date: string,
9
+ format: string = 'iYYYY-iMM-iDD',
10
+ lang: 'ar' | 'en' = 'en'
11
+ ): string {
12
+ momentHijri.locale(lang);
13
+ return momentHijri(date).format(format);
14
+ }
15
+ }