bpm-core 0.0.128 → 0.0.130

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 (78) hide show
  1. package/README.md +75 -5
  2. package/cli/deploy/build.js +1 -1
  3. package/cli/deploy/git-operations-handler.js +1 -1
  4. package/cli/deploy/index.js +1 -1
  5. package/cli/generate/index.js +10 -0
  6. package/cli/generate/mock/form-node.js +77 -0
  7. package/cli/generate/mock/index.js +209 -0
  8. package/cli/generate/mock/lov.js +18 -0
  9. package/cli/generate/new/angular-template/.editorconfig +13 -0
  10. package/cli/generate/new/angular-template/README.md +7 -0
  11. package/cli/generate/new/angular-template/angular.json.ejs +167 -0
  12. package/cli/generate/new/angular-template/build.sh +6 -0
  13. package/cli/generate/new/angular-template/extra-webpack.config.js.ejs +5 -0
  14. package/cli/generate/new/angular-template/karma.conf.js +44 -0
  15. package/cli/generate/new/angular-template/package.json.ejs +67 -0
  16. package/cli/generate/new/angular-template/protractor.conf.js +28 -0
  17. package/cli/generate/new/angular-template/src/app/app.component.html +35 -0
  18. package/cli/generate/new/angular-template/src/app/app.component.scss +0 -0
  19. package/cli/generate/new/angular-template/src/app/app.component.ts +81 -0
  20. package/cli/generate/new/angular-template/src/app/config/segment-dynamic-loader.config.ts.ejs +8 -0
  21. package/cli/generate/new/angular-template/src/app/i18n/ar.ts.ejs +18 -0
  22. package/cli/generate/new/angular-template/src/app/i18n/en.ts.ejs +18 -0
  23. package/cli/generate/new/angular-template/src/app/page-components/@@comp-template@@/@@.component.html.ejs +33 -0
  24. package/cli/generate/new/angular-template/src/app/page-components/@@comp-template@@/@@.component.ts.ejs +128 -0
  25. package/cli/generate/new/angular-template/src/app/page-components/@@comp-template@@/_html-field.ejs +97 -0
  26. package/cli/generate/new/angular-template/src/app/page-components/@@comp-template@@/_html-table.ejs +27 -0
  27. package/cli/generate/new/angular-template/src/app/page-components/@@comp-template@@/_ts-field.ejs +3 -0
  28. package/cli/generate/new/angular-template/src/app/shared/pipes/translate.pipe.ts +32 -0
  29. package/cli/generate/new/angular-template/src/app/shared/services/i18n.service.ts +32 -0
  30. package/cli/generate/new/angular-template/src/app/shared/services/segment-dynamic-loader.service.ts.ejs +49 -0
  31. package/cli/generate/new/angular-template/src/app/shared/services/state-machine.service.ts +119 -0
  32. package/cli/generate/new/angular-template/src/app/shared/types/lov.enum.ts.ejs +7 -0
  33. package/cli/generate/new/angular-template/src/app/templates/print-section/print-section.component.html +5 -0
  34. package/cli/generate/new/angular-template/src/app/templates/print-section/print-section.component.scss +0 -0
  35. package/cli/generate/new/angular-template/src/app/templates/print-section/print-section.component.ts.ejs +156 -0
  36. package/cli/generate/new/angular-template/src/app/templates/print.ts.ejs +392 -0
  37. package/cli/generate/new/angular-template/src/environments/environment.local.ts.ejs +40 -0
  38. package/cli/generate/new/angular-template/src/environments/environment.prod.ts +25 -0
  39. package/cli/generate/new/angular-template/src/environments/environment.ts +25 -0
  40. package/cli/generate/new/angular-template/src/favicon.ico +0 -0
  41. package/cli/generate/new/angular-template/src/index.html.ejs +14 -0
  42. package/cli/generate/new/angular-template/src/main.ts +49 -0
  43. package/cli/generate/new/angular-template/src/polyfills.ts +65 -0
  44. package/cli/generate/new/angular-template/src/styles.scss.ejs +121 -0
  45. package/cli/generate/new/angular-template/src/test.ts +26 -0
  46. package/cli/generate/new/angular-template/tsconfig.app.json +15 -0
  47. package/cli/generate/new/angular-template/tsconfig.json +50 -0
  48. package/cli/generate/new/angular-template/tsconfig.spec.json +18 -0
  49. package/cli/generate/new/angular-template/tslint.json +143 -0
  50. package/cli/generate/new/copy-and-generate.js +120 -0
  51. package/cli/generate/new/field.js +4 -0
  52. package/cli/generate/new/index.js +47 -0
  53. package/cli/generate/new/service-data.js +284 -0
  54. package/cli/index.js +2 -0
  55. package/fesm2022/bpm-core.mjs +248 -255
  56. package/fesm2022/bpm-core.mjs.map +1 -1
  57. package/lib/components/shared-components/form-field/attachment-section/attachment-section.component.d.ts +1 -2
  58. package/lib/components/shared-components/form-field/control-value-accessor.directive.d.ts +4 -4
  59. package/lib/components/shared-components/form-field/index.d.ts +0 -1
  60. package/lib/components/shared-components/form-field/input/input.component.d.ts +3 -2
  61. package/lib/components/shared-components/form-field/input-number/input-number.component.d.ts +2 -0
  62. package/lib/components/shared-components/form-field/radio/radio.component.d.ts +39 -2
  63. package/lib/components/shared-components/form-field/search-employee/search-employee.component.d.ts +5 -5
  64. package/lib/components/shared-components/form-field/shared-imports.d.ts +0 -3
  65. package/lib/components/shared-components/form-field/textarea/textarea.component.d.ts +76 -1
  66. package/lib/components/shared-components/table/table.component.d.ts +3 -3
  67. package/lib/{components/shared-components/form-field/input → directives}/input-map-filter/input-filters.d.ts +1 -0
  68. package/lib/{components/shared-components/form-field/input → directives}/input-map-filter/input-map-filter.directive.d.ts +4 -1
  69. package/lib/testComponent/request-details-section/request-details-section.component.d.ts +9 -4
  70. package/package.json +7 -2
  71. package/public-api.d.ts +1 -0
  72. package/lib/directives/ar.directive.d.ts +0 -11
  73. package/lib/directives/en.directive.d.ts +0 -11
  74. package/lib/directives/number.directive.d.ts +0 -14
  75. /package/cli/{deploy → utilities}/utilities.js +0 -0
  76. /package/lib/{components/shared-components/form-field/input → directives}/input-map-filter/index.d.ts +0 -0
  77. /package/lib/{components/shared-components/form-field/input → directives}/input-map-filter/input-mappers.d.ts +0 -0
  78. /package/lib/{components/shared-components/form-field/input → directives}/input-map-filter/types.d.ts +0 -0
@@ -0,0 +1,44 @@
1
+ // Karma configuration file, see link for more information
2
+ // https://karma-runner.github.io/1.0/config/configuration-file.html
3
+
4
+ module.exports = function (config) {
5
+ config.set({
6
+ basePath: '',
7
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
8
+ plugins: [
9
+ require('karma-jasmine'),
10
+ require('karma-chrome-launcher'),
11
+ require('karma-jasmine-html-reporter'),
12
+ require('karma-coverage'),
13
+ require('@angular-devkit/build-angular/plugins/karma')
14
+ ],
15
+ client: {
16
+ jasmine: {
17
+ // you can add configuration options for Jasmine here
18
+ // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19
+ // for example, you can disable the random execution with `random: false`
20
+ // or set a specific seed with `seed: 4321`
21
+ },
22
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
23
+ },
24
+ jasmineHtmlReporter: {
25
+ suppressAll: true // removes the duplicated traces
26
+ },
27
+ coverageReporter: {
28
+ dir: require('path').join(__dirname, './coverage/contractor-service'),
29
+ subdir: '.',
30
+ reporters: [
31
+ { type: 'html' },
32
+ { type: 'text-summary' }
33
+ ]
34
+ },
35
+ reporters: ['progress', 'kjhtml'],
36
+ port: 9876,
37
+ colors: true,
38
+ logLevel: config.LOG_INFO,
39
+ autoWatch: true,
40
+ browsers: ['Chrome'],
41
+ singleRun: false,
42
+ restartOnFileChange: true
43
+ });
44
+ };
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "<%=serviceCode%>",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "scripts": {
6
+ "ng": "ng",
7
+ "start": "ng serve",
8
+ "build": "ng build --configuration production",
9
+ "test": "ng test",
10
+ "lint": "ng lint",
11
+ "e2e": "ng e2e"
12
+ },
13
+ "private": true,
14
+ "dependencies": {
15
+ "@angular-builders/custom-webpack": "^19.0.0",
16
+ "@angular/animations": "^19.0.0",
17
+ "@angular/cdk": "^19.0.0",
18
+ "@angular/common": "^19.0.0",
19
+ "@angular/compiler": "^19.0.0",
20
+ "@angular/core": "^19.0.0",
21
+ "@angular/forms": "^19.0.0",
22
+ "@angular/localize": "^19.0.0",
23
+ "@angular/material": "^19.0.0",
24
+ "@angular/platform-browser": "^19.0.0",
25
+ "@angular/platform-browser-dynamic": "^19.0.0",
26
+ "@angular/platform-server": "^19.0.0",
27
+ "@angular/router": "^19.0.0",
28
+ "@ncstate/sat-popover": "^13.1.0",
29
+ "basic-ui-components": "^0.0.6992",
30
+ "bootstrap": "^5.3.3",
31
+ "bpm-core": "^0.0.124",
32
+ "date-fns": "^4.1.0",
33
+ "express": "^4.18.2",
34
+ "file-saver": "^2.0.5",
35
+ "google-libphonenumber": "^3.2.42",
36
+ "handlebars": "^4.7.7",
37
+ "handlebars-loader": "^1.7.2",
38
+ "intl-tel-input": "^24.5.0",
39
+ "moment": "^2.29.4",
40
+ "moment-hijri": "^2.30.0",
41
+ "ng-dynamic-component": "^10.7.0",
42
+ "ngx-bootstrap": "^19.0.2",
43
+ "ngx-intl-tel-input-gg": "^1.0.12",
44
+ "ngx-mask": "^18.0.0",
45
+ "ngx-scrollbar": "^15.1.3",
46
+ "ngx-toastr": "^19.0.0",
47
+ "rxjs": "~7.8.0",
48
+ "tslib": "^2.3.0",
49
+ "zone.js": "~0.14.10"
50
+ },
51
+ "devDependencies": {
52
+ "@angular-devkit/build-angular": "^19.0.0",
53
+ "@angular/cli": "^19.0.0",
54
+ "@angular/compiler-cli": "^19.0.0",
55
+ "@types/express": "^4.17.17",
56
+ "@types/jasmine": "~5.1.0",
57
+ "@types/node": "^18.18.0",
58
+ "jasmine-core": "~5.2.0",
59
+ "karma": "~6.4.0",
60
+ "karma-chrome-launcher": "~3.2.0",
61
+ "karma-coverage": "~2.2.0",
62
+ "karma-jasmine": "~5.1.0",
63
+ "karma-jasmine-html-reporter": "~2.1.0",
64
+ "ng-packagr": "^18.2.1",
65
+ "typescript": "~5.5.2"
66
+ }
67
+ }
@@ -0,0 +1,28 @@
1
+ // Protractor configuration file, see link for more information
2
+ // https://github.com/angular/protractor/blob/master/lib/config.ts
3
+
4
+ const { SpecReporter } = require('jasmine-spec-reporter');
5
+
6
+ exports.config = {
7
+ allScriptsTimeout: 11000,
8
+ specs: [
9
+ './e2e/**/*.e2e-spec.ts'
10
+ ],
11
+ capabilities: {
12
+ 'browserName': 'chrome'
13
+ },
14
+ directConnect: true,
15
+ baseUrl: 'http://localhost:4200/',
16
+ framework: 'jasmine',
17
+ jasmineNodeOpts: {
18
+ showColors: true,
19
+ defaultTimeoutInterval: 30000,
20
+ print: function() {}
21
+ },
22
+ onPrepare() {
23
+ require('ts-node').register({
24
+ project: 'e2e/tsconfig.e2e.json'
25
+ });
26
+ jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27
+ }
28
+ };
@@ -0,0 +1,35 @@
1
+ <core-layout>
2
+ @if (!loading['form']) {
3
+ @if (noError) {
4
+ <core-service-header
5
+ [isLoading]="false"
6
+ [formTitle]="'formTitle' | translate"
7
+ [form]="form">
8
+ <app-print-section [form]="form">
9
+ </app-print-section>
10
+ </core-service-header>
11
+ <app-workflow-section
12
+ workflow
13
+ [segmentDynamicLoaderService]="segmentDynamicLoader"
14
+ [form]="form" [sections]="form?.['sections']">
15
+ <app-request-details-section
16
+ [section]="form.sections[0]" [form]="form" [lov]="form?.lovs" className="form-section"
17
+ [isReadOnly]="form.sections[0].header.readOnly"></app-request-details-section>
18
+ </app-workflow-section>
19
+ } @else {
20
+ @if (errorMessage?.length) {
21
+ <ds-message></ds-message>
22
+ @for (item of errorMessage; track $index) {
23
+ <div class="d-flex justify-content-center">
24
+ <span class="fc-coral fs-18" [innerHTML]="item?.['message']"></span>
25
+ </div>
26
+ }
27
+ } @else {
28
+ <ds-message label="{{'errorOccurred' | translate}}"></ds-message>
29
+ }
30
+ }
31
+ } @else {
32
+ <core-service-header header [formTitle]="'formTitle' | translate" [isLoading]="true">
33
+ </core-service-header>
34
+ }
35
+ </core-layout>
@@ -0,0 +1,81 @@
1
+ import {AfterViewInit, Component, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA} from '@angular/core';
2
+ import {
3
+ CoreService,
4
+ Form,
5
+ LayoutComponent,
6
+ ServiceHeaderComponent,
7
+ SidenavService,
8
+ WorkflowSectionComponent,
9
+ CoreI18nService
10
+ } from 'bpm-core';
11
+ import {DynamicComponentInjectorToken} from 'ng-dynamic-component';
12
+ import {RequestDetailsSectionComponent} from "./page-components/request-details-section/request-details-section.component";
13
+ import {SegmentDynamicLoaderService} from './shared/services/segment-dynamic-loader.service';
14
+ import {DOCUMENT, isPlatformBrowser} from "@angular/common";
15
+ import { Inject, PLATFORM_ID} from '@angular/core';
16
+ import {Router} from "@angular/router";
17
+ import {PrintSectionComponent} from "./templates/print-section/print-section.component";
18
+ import {I18nService} from "./shared/services/i18n.service";
19
+ import { TranslatePipe } from './shared/pipes/translate.pipe';
20
+
21
+ @Component({
22
+ selector: 'app-wm-root',
23
+ standalone: true,
24
+ templateUrl: './app.component.html',
25
+ styleUrl: './app.component.scss',
26
+ imports: [
27
+ LayoutComponent,
28
+ ServiceHeaderComponent,
29
+ WorkflowSectionComponent,
30
+ RequestDetailsSectionComponent,
31
+ PrintSectionComponent,
32
+ TranslatePipe
33
+ ],
34
+ schemas: [CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA],
35
+ providers: [
36
+ {provide: DynamicComponentInjectorToken, useValue: { /* your value here */}}
37
+ ]
38
+
39
+ })
40
+ export class AppComponent implements AfterViewInit {
41
+ loading = {
42
+ form: false
43
+ }
44
+ form: Form
45
+ noError = true;
46
+ errorMessage: [];
47
+ constructor(
48
+ public segmentDynamicLoader: SegmentDynamicLoaderService,
49
+ @Inject(DOCUMENT) private readonly document: Document,
50
+ private readonly router: Router,
51
+ private readonly sidenavService: SidenavService,
52
+ public i18n: I18nService,
53
+ private readonly coreService: CoreService,
54
+ @Inject(PLATFORM_ID) private readonly platformId: any
55
+ ) {
56
+ this.loading['form'] = true
57
+ this.coreService.loadForm().subscribe({
58
+ next: (form: any) => {
59
+ if (form instanceof Form) {
60
+ this.form = form;
61
+ } else {
62
+ this.noError = false;
63
+ }
64
+ this.loading['form'] = false;
65
+ },
66
+ error: (err) => {
67
+ this.noError = false;
68
+ this.loading['form'] = false;
69
+ this.errorMessage = err?.error?.meta?.messages;
70
+ }
71
+ });
72
+ }
73
+
74
+ ngAfterViewInit() {
75
+ if (isPlatformBrowser(this.platformId)) {
76
+ const direction = this.i18n.getLanguage() == 'en' ? 'ltr' : 'rtl';
77
+ document.documentElement.setAttribute('dir', direction);
78
+ }
79
+ }
80
+
81
+ }
@@ -0,0 +1,8 @@
1
+ <% const config = getSegmentDynamicLoaderConfig() -%>
2
+ <%- config.imports %>
3
+
4
+ export default {
5
+ roleToApprovalSectionMapping: {
6
+ <%- config.roleToCompClass -%>
7
+ }
8
+ }
@@ -0,0 +1,18 @@
1
+ export default {
2
+ "fileName": "اسم الملف",
3
+ "fileDescription": "وصف الملف",
4
+ "comment": "ملاحظات",
5
+ "reset": "إعادة تهيئة",
6
+ "businessPhone": "هاتف العمل",
7
+ "nationality": "الجنسية",
8
+ "generalDepartmentName": "الإدارة العامة",
9
+ "departmentName": "القسم",
10
+ "humanResourcesLocation": "شئون الموظفين",
11
+ "employeeEmail": "البريد الإلكتروني",
12
+ "generalDepartmentCode": "رمز الإدارة العامة",
13
+ "jobPosition": "الوظيفة",
14
+ "fullName": "الإسم",
15
+ "requestDetailsTitle": "تفاصيل الطلب",
16
+ <% const arStr = JSON.stringify(ar); -%>
17
+ <%- arStr.substring(1, arStr.length - 1) %>
18
+ }
@@ -0,0 +1,18 @@
1
+ export default {
2
+ "fileName": "File Name",
3
+ "fileDescription": "File Description",
4
+ "comment":"Comments",
5
+ "reset": "Reset",
6
+ "departmentName": "Department",
7
+ "generalDepartmentName": "General Dep.Name",
8
+ "nationality": "Nationality",
9
+ "businessPhone": "Business Phone",
10
+ "fullName":"Full Name",
11
+ "jobPosition": "Job Position",
12
+ "generalDepartmentCode": "General Dep. Code",
13
+ "employeeEmail": "Email",
14
+ "humanResourcesLocation": "HR location",
15
+ "requestDetailsTitle":"Request Details",
16
+ <% const enStr = JSON.stringify(en); -%>
17
+ <%- enStr.substring(1, enStr.length - 1) %>
18
+ }
@@ -0,0 +1,33 @@
1
+ <div>
2
+ <form
3
+ [ngClass]="{
4
+ 'form-section-divide form-section': !section?.header?.readOnly,
5
+ 'info-section': section?.header?.readOnly
6
+ }"
7
+ [formGroup]="formGroup"
8
+ >
9
+ <% fields.forEach((field) => { -%>
10
+ <% if(field.componentName === 'table'){ %>
11
+ <%- include('_html-table', {field: field}) %>
12
+ <% } else { %>
13
+ <%- include('_html-field', {item: field}) %>
14
+ <% } %>
15
+ <% }); -%>
16
+ </form>
17
+ </div>
18
+
19
+ @if (!section?.header?.readOnly) {
20
+ <div class="mt-4">
21
+ <lib-action-buttons
22
+ [lovOptions]="lov?.['decision']?.options"
23
+ [lovType]="lov?.['decision']?.type"
24
+ [section]="section"
25
+ [form]="form"
26
+ [sections]="form.sections"
27
+ [showApprovalCycle]="true"
28
+ [customCall]="false"
29
+ [fieldsForm]="formGroup"
30
+ (resetFormEmit)="resetForm()"
31
+ />
32
+ </div>
33
+ }
@@ -0,0 +1,128 @@
1
+
2
+ <% importsManager.addImport(['Component', 'inject', 'Input', 'OnInit', 'CUSTOM_ELEMENTS_SCHEMA'], '@angular/core') -%>
3
+ <% importsManager.addImport(['FormControl', 'FormBuilder', 'Validators'], '@angular/forms') -%>
4
+ <% importsManager.addImport('ReactiveFormsModule', '@angular/forms', true) -%>
5
+ <% importsManager.addImport(['Section', 'Form', 'ActionStateService'], 'bpm-core') -%>
6
+ <% importsManager.addImport('ActionButtonsComponent', 'bpm-core', true) -%>
7
+ <% importsManager.addImport('TranslatePipe', 'src/app/shared/pipes/translate.pipe', true) -%>
8
+ <% importsManager.addImport('NgClass', '@angular/common', true) -%>
9
+
10
+ <% for(const field of fields){ -%>
11
+ <% if(field.componentName === 'table'){ -%>
12
+ interface <%= changeCase.pascalCase(field.arrayName + 'Item') %> {
13
+ <% for(const col of field.tableColumns){ -%>
14
+ <%= col.fieldName %>: <%= getFieldType(col) %>;
15
+ <% } -%>
16
+ }
17
+ <% } -%>
18
+ <% } -%>
19
+
20
+ @Component({
21
+ selector: 'app-<%= componentNameKebab %>',
22
+ templateUrl: './<%= componentNameKebab %>.component.html',
23
+ standalone: true,
24
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
25
+ imports: []
26
+ })
27
+ export class <%= componentNamePascal %>Component implements OnInit {
28
+ @Input() isReadOnly: boolean;
29
+ @Input() section: Section;
30
+ @Input() form: Form;
31
+ @Input() lov: any;
32
+ formGroup: ReturnType<typeof this.createForm>;
33
+ private fb = inject(FormBuilder);
34
+ private actionStateService = inject(ActionStateService);
35
+
36
+ ngOnInit(){
37
+ this.formGroup = this.createForm();
38
+ this.setFormValuesUsingSectionDetails();
39
+ if(!this.isReadOnly){
40
+ this.subscribeFormChanges();
41
+ this.formGroup.updateValueAndValidity();
42
+ }
43
+ }
44
+
45
+ createForm() {
46
+ return this.fb.group({
47
+ <% for(const field of fields){ -%>
48
+ <% if(field.componentName === 'table'){ -%>
49
+ <%=field.arrayName%>: this.fb.array<ReturnType<typeof this.<%= changeCase.camelCase(`new ${field.arrayName} Item`) %>>>([]),
50
+ <% } else { -%>
51
+ <%- include('_ts-field', {field: field, defaultValue: undefined}) -%>
52
+ <% } -%>
53
+ <% } -%>
54
+ });
55
+ }
56
+
57
+ resetForm() {
58
+ this.actionStateService.resetAction$.next();
59
+ }
60
+
61
+ <% for(const field of fields){ -%>
62
+ <% if(field.visibilityCheckCode){ -%>
63
+ get <%= changeCase.camelCase(`is ${field.fieldName || field.headerName} visible`) %>(): boolean {
64
+ return <%-field.visibilityCheckCode%>;
65
+ }
66
+ <% } -%>
67
+ <% } -%>
68
+
69
+ private subscribeFormChanges() {
70
+ this.formGroup.valueChanges.subscribe((value) => {
71
+ this.section.body.details = {
72
+ ...this.section.body.details,
73
+ ...this.formGroup.value,
74
+ };
75
+ <% if(fields.some(item => item.visibilityCheckCode)){ importsManager.addImport('updateValueAndValidity', 'bpm-core')-%>
76
+ updateValueAndValidity(this.formGroup);
77
+ <% } -%>
78
+ this.lov?.["decision"]?.options?.forEach((option) => {
79
+ let isActionValid = this.checkValidity(option.value);
80
+ this.actionStateService.setActionValid(option.value, isActionValid);
81
+ });
82
+ });
83
+ }
84
+
85
+ private checkValidity(action: string): boolean {
86
+ <% if(fields.some(item => item.fieldName === 'comment')){ -%>
87
+ switch (action) {
88
+ case "SENDBACK":
89
+ case "REJECT":
90
+ return !!this.formGroup.value?.comment;
91
+ default:
92
+ return this.formGroup.valid;
93
+ }
94
+ <% } else { -%>
95
+ return this.formGroup.valid;
96
+ <% } -%>
97
+ }
98
+
99
+ private setFormValuesUsingSectionDetails(){
100
+ this.formGroup.patchValue(this.section.body.details);
101
+ <% for(const field of fields){ -%>
102
+ <% if(field.componentName === 'table'){ -%>
103
+ <% const tableArrConstName = changeCase.camelCase(field.arrayName); -%>
104
+ <% const typeName = changeCase.pascalCase(field.arrayName + 'Item'); -%>
105
+ <% const addNewItemMethodName = changeCase.camelCase(`new ${field.arrayName} Item`); -%>
106
+ const <%= tableArrConstName %>: <%=typeName%>[] = this.section.body.details?.<%= field.arrayName %>;
107
+ if(<%= tableArrConstName %>?.length){
108
+ <%= tableArrConstName %>.forEach(item => {
109
+ this.formGroup.controls.<%= field.arrayName %>.push(this.<%=addNewItemMethodName%>(item))
110
+ })
111
+ }
112
+ <% } -%>
113
+ <% } -%>
114
+ }
115
+
116
+ <% for(const field of fields){ -%>
117
+ <% if(field.componentName === 'table'){ -%>
118
+ private <%= changeCase.camelCase(`new ${field.arrayName} Item`) %>(item?: <%= changeCase.pascalCase(field.arrayName + 'Item') %>) {
119
+ return this.fb.group({
120
+ <% for(const col of field.tableColumns){ -%>
121
+ <%- include('_ts-field', {field: col, defaultValue: `item?.${col.fieldName}`}) -%>
122
+ <% } -%>
123
+ });
124
+ }
125
+ <% } -%>
126
+ <% } -%>
127
+
128
+ }
@@ -0,0 +1,97 @@
1
+ <% if (item.visibilityCheckCode) { -%>
2
+ <% importsManager.addImport(getEnumName(item), '../../shared/types/lov.enum') -%>
3
+ @if(<%= changeCase.camelCase(`is ${item.fieldName || item.headerName} visible`) %>){
4
+ <% } -%>
5
+ <% switch(item.componentName){
6
+ case 'input': -%>
7
+ <app-input
8
+ <%- getCommonAttributes(item) -%>
9
+ <% if(item.maxLength){ -%>
10
+ maxLength="<%=item.maxLength%>"
11
+ <% } -%>
12
+ >
13
+ </app-input>
14
+ <% break; case 'textarea': -%>
15
+ <app-textarea
16
+ <%- getCommonAttributes(item) -%>
17
+ <% if(item.maxLength){ -%>
18
+ maxLength="<%=item.maxLength%>"
19
+ <% } -%>
20
+ >
21
+ </app-textarea>
22
+ <% break; case 'input-number': -%>
23
+ <app-input-number
24
+ <%- getCommonAttributes(item) -%>
25
+ >
26
+ </app-input-number>
27
+ <% break; case 'input-currency': -%>
28
+ <app-input-currency
29
+ <%- getCommonAttributes(item) -%>
30
+ >
31
+ </app-input-currency>
32
+ <% break; case 'select': -%>
33
+ <app-custom-searchable
34
+ <%- getCommonAttributes(item) -%>
35
+ [options]="lov?.<%=item.lovName%>?.options"
36
+ [key]="'value'"
37
+ [displayedLabel]="'description'"
38
+ >
39
+ </app-custom-searchable>
40
+ <% break; case 'attachment-section': -%>
41
+ <app-attachment-section
42
+ class="section-item full"
43
+ formControlName="<%=item.fieldName%>"
44
+ <% if(item.label){ %>
45
+ [label]="'<%=changeCase.camelCase(item.label)%>' | translate"
46
+ <% } %>
47
+ [mandatory]="<%=item.required%>"
48
+ [isReadOnly]="<%=item.readOnly ? 'true' : 'section?.header?.readOnly'%>"
49
+ >
50
+ </app-attachment-section>
51
+ <% break; case 'file-uploader': -%>
52
+ <app-file-uploader
53
+ <%- getCommonAttributes(item) -%>
54
+ <% if(item.maxLength){ -%>
55
+ [maxLength]="<%=item.maxLength%>"
56
+ <% } -%>
57
+ <% if(item.multiple){ -%>
58
+ [multiple]="true"
59
+ [displayedFiles]="formGroup.value?.<%=item.fieldName%>"
60
+ <% } -%>
61
+ >
62
+ </app-file-uploader>
63
+ <% break; case 'datepicker': -%>
64
+ <app-datepicker
65
+ <%- getCommonAttributes(item) -%>
66
+ <% if(item.minDate){ -%>
67
+ minDate="<%=item.minDate%>"
68
+ <% } -%>
69
+ <% if(item.maxDate){ -%>
70
+ maxDate="<%=item.maxDate%>"
71
+ <% } -%>
72
+ <% if(item.customMinDate){ -%>
73
+ customMinDate="<%=item.customMinDate%>"
74
+ <% } -%>
75
+ <% if(item.customMaxDate){ -%>
76
+ customMaxDate="<%=item.customMaxDate%>"
77
+ <% } -%>
78
+ >
79
+ </app-datepicker>
80
+ <% break; case 'panel-start': -%>
81
+ <div class="header-line full fs-12 fw-medium mb-2">
82
+ {{ "<%=changeCase.camelCase(item.headerName)%>" | translate }}
83
+ </div>
84
+ <% break; case 'hint': -%>
85
+ <ds-alert class="mb-3 full" type="<%=item.type%>" icon="<%=item.type === 'danger' ? 'close-circle' : 'info'%>">
86
+ {{'<%=changeCase.camelCase(item.headerName)%>' | translate}}
87
+ </ds-alert>
88
+ <% break; case 'search-employee': -%>
89
+ <app-search-employee
90
+ <%- getCommonAttributes(item) -%>
91
+ >
92
+ </app-search-employee>
93
+ <% break; -%>
94
+ <% } -%>
95
+ <% if (item.visibilityCheckCode) { -%>
96
+ }
97
+ <% } %>
@@ -0,0 +1,27 @@
1
+ <div class="section-item full mt-2">
2
+ <% if(field.label){ -%>
3
+ <div class="header-line full fs-12 fw-medium mb-1">{{ "<%=changeCase.camelCase(field.label)%>" | translate }}</div>
4
+ <% } -%>
5
+ <div class="gray-table-wrapper">
6
+ <table>
7
+ <thead>
8
+ <tr>
9
+ <% field.tableColumns.forEach((column) => { -%>
10
+ <th>{{'<%=changeCase.camelCase(column.label)%>' | translate}}</th>
11
+ <% }); -%>
12
+ </tr>
13
+ </thead>
14
+ <tbody formArrayName="<%=field.arrayName%>">
15
+ @for (item of section.body.details.<%=field.arrayName%>; track $index) {
16
+ <tr [formGroupName]="$index">
17
+ <% field.tableColumns.forEach((column) => { -%>
18
+ <td>
19
+ <%- include('_html-field', {item: column}) %>
20
+ </td>
21
+ <% }); -%>
22
+ </tr>
23
+ }
24
+ </tbody>
25
+ </table>
26
+ </div>
27
+ </div>
@@ -0,0 +1,3 @@
1
+ <% if(field.fieldName){ -%>
2
+ <%= field.fieldName %>: new FormControl<<%- getFieldType(field) %>>(<%- defaultValue || 'null' %><% if(field.required){ -%>, <%- getValidators(field) %><% } %>),
3
+ <% } -%>
@@ -0,0 +1,32 @@
1
+ import { Pipe, PipeTransform } from '@angular/core';
2
+ import * as en from '../../../app/i18n/en';
3
+ import * as ar from '../../../app/i18n/ar';
4
+
5
+ @Pipe({
6
+ name: 'translate',
7
+ standalone:true
8
+ })
9
+ export class TranslatePipe implements PipeTransform {
10
+ private coreLocales: { [key: string]: { [key: string]: string } };
11
+ public language: string;
12
+
13
+ constructor() {
14
+ // this.language = "en";
15
+ this.language = (window as any).wmConfig.language;
16
+ this.coreLocales = { en: en.default, ar: ar.default };
17
+ }
18
+
19
+ transform(key) {
20
+ let result = null;
21
+ try {
22
+ result = this.coreLocales[this.language][key];
23
+ } catch (e) {
24
+ result = null;
25
+ }
26
+ return result || key;
27
+ }
28
+
29
+ getLanguage() {
30
+ return this.language;
31
+ }
32
+ }
@@ -0,0 +1,32 @@
1
+ import { Injectable } from '@angular/core';
2
+ import * as en from '../../../app/i18n/en';
3
+ import * as ar from '../../../app/i18n/ar';
4
+
5
+ @Injectable({
6
+ providedIn: 'any',
7
+ })
8
+ export class I18nService {
9
+ private readonly locales: {[key: string]: {[key: string]: string}};
10
+ private readonly language : string;
11
+
12
+ constructor() {
13
+ this.language = (window as any).wmConfig.language;
14
+ // this.language = "en";
15
+ this.locales = {en: en.default, ar: ar.default};
16
+ }
17
+
18
+ translate(key) {
19
+ let result = null;
20
+ try {
21
+ result = this.locales[this.language][key];
22
+ }
23
+ catch(e) {
24
+ result = null;
25
+ }
26
+ return result || key;
27
+ }
28
+
29
+ getLanguage() {
30
+ return this.language;
31
+ }
32
+ }