@yomotech/view-toolkit 0.0.30 → 0.0.32

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 (72) hide show
  1. package/ng-package.json +7 -0
  2. package/package.json +38 -49
  3. package/src/lib/app-version.ts +2 -0
  4. package/src/lib/components/autocomplete/autocomplete.css +0 -0
  5. package/src/lib/components/autocomplete/autocomplete.html +23 -0
  6. package/src/lib/components/autocomplete/autocomplete.ts +71 -0
  7. package/src/lib/components/button/button.css +0 -0
  8. package/src/lib/components/button/button.html +1 -0
  9. package/src/lib/components/button/button.ts +11 -0
  10. package/src/lib/components/date/date.css +0 -0
  11. package/src/lib/components/date/date.html +1 -0
  12. package/src/lib/components/date/date.ts +11 -0
  13. package/src/lib/components/dropdown/dropdown.css +0 -0
  14. package/src/lib/components/dropdown/dropdown.html +1 -0
  15. package/src/lib/components/dropdown/dropdown.ts +11 -0
  16. package/src/lib/components/error-message/error-message.css +0 -0
  17. package/src/lib/components/error-message/error-message.html +1 -0
  18. package/src/lib/components/error-message/error-message.ts +11 -0
  19. package/src/lib/components/label/label.css +0 -0
  20. package/src/lib/components/label/label.html +7 -0
  21. package/src/lib/components/label/label.ts +33 -0
  22. package/src/lib/components/string/string.css +0 -0
  23. package/src/lib/components/string/string.html +4 -0
  24. package/src/lib/components/string/string.ts +22 -0
  25. package/src/lib/components/textbox/textbox.css +0 -0
  26. package/src/lib/components/textbox/textbox.html +7 -0
  27. package/src/lib/components/textbox/textbox.ts +33 -0
  28. package/src/lib/components/time/time.css +0 -0
  29. package/src/lib/components/time/time.html +1 -0
  30. package/src/lib/components/time/time.ts +11 -0
  31. package/src/lib/containers/card/card.component.css +0 -0
  32. package/src/lib/containers/card/card.component.html +450 -0
  33. package/src/lib/containers/card/card.component.ts +474 -0
  34. package/src/lib/containers/form/form.component.css +101 -0
  35. package/src/lib/containers/form/form.component.html +305 -0
  36. package/src/lib/containers/form/form.component.ts +333 -0
  37. package/src/lib/containers/grid/grid.component.css +0 -0
  38. package/src/lib/containers/grid/grid.component.html +212 -0
  39. package/src/lib/containers/grid/grid.component.ts +228 -0
  40. package/src/lib/containers/header-menu/header-menu.component.css +0 -0
  41. package/src/lib/containers/header-menu/header-menu.component.html +72 -0
  42. package/src/lib/containers/header-menu/header-menu.component.ts +105 -0
  43. package/src/lib/containers/logs/logs.component.css +160 -0
  44. package/src/lib/containers/logs/logs.component.html +89 -0
  45. package/src/lib/containers/logs/logs.component.ts +29 -0
  46. package/src/lib/containers/model/model.component.css +0 -0
  47. package/src/lib/containers/model/model.component.html +351 -0
  48. package/src/lib/containers/model/model.component.ts +436 -0
  49. package/src/lib/containers/pagination/pagination.component.css +0 -0
  50. package/src/lib/containers/pagination/pagination.component.html +41 -0
  51. package/src/lib/containers/pagination/pagination.component.ts +100 -0
  52. package/src/lib/containers/side-menu/side-menu.component.css +173 -0
  53. package/src/lib/containers/side-menu/side-menu.component.html +126 -0
  54. package/src/lib/containers/side-menu/side-menu.component.ts +458 -0
  55. package/src/lib/services/app-version-reset.service.ts +59 -0
  56. package/src/lib/services/config.service.ts +144 -0
  57. package/src/lib/services/couchdb.ts +275 -0
  58. package/src/lib/services/mobile-keycloak.service.ts +116 -0
  59. package/src/lib/services/network-log.service.ts +27 -0
  60. package/src/lib/services/notification.service.ts +26 -0
  61. package/src/lib/services/request.service.ts +125 -0
  62. package/src/lib/services/utility.service.ts +600 -0
  63. package/src/lib/view-toolkit.module.ts +57 -0
  64. package/src/lib/view-toolkit.spec.ts +23 -0
  65. package/src/lib/view-toolkit.ts +15 -0
  66. package/src/public-api.ts +25 -0
  67. package/tsconfig.lib.json +17 -0
  68. package/tsconfig.lib.prod.json +11 -0
  69. package/tsconfig.spec.json +15 -0
  70. package/fesm2022/yomotech-view-toolkit.mjs +0 -3538
  71. package/fesm2022/yomotech-view-toolkit.mjs.map +0 -1
  72. package/types/yomotech-view-toolkit.d.ts +0 -644
@@ -0,0 +1,212 @@
1
+ <div *ngIf="!tableitemInfo.data?.length" class="alert alert-warning col-md-12" role="alert">
2
+ {{ tableitemInfo.layoutSchema?.noRecordMessage}}
3
+ </div>
4
+ <div *ngIf="tableitemInfo.data?.length" class="reservation-container pt-5 px-3">
5
+ <nz-table #basicTable [nzData]="tableitemInfo.data" [nzBordered]="true"
6
+ [nzFrontPagination]="currenTableOptions?.pagination?.tabs"
7
+ [style]="getStyleWithoutClasses(currenTableOptions?.style).style" (scroll)="onScrollEvent($event)"
8
+ [nzLoading]="isTableDataLoad">
9
+ <thead>
10
+ <tr>
11
+ <th *ngFor="let column of tableitemInfo.layoutSchema.elements">{{ column?.label?.caption }}</th>
12
+ </tr>
13
+ </thead>
14
+ <tbody>
15
+ <tr *ngFor="let data of tableitemInfo.data; let i = index">
16
+ <td *ngFor="let col of tableitemInfo.layoutSchema.elements"
17
+ [style]="getStyleWithoutClasses(col?.scope?.style).style">
18
+ <ng-container
19
+ *ngIf="tableitemInfo.propertySchema[getScope(col.scope?.reference)] && tableitemInfo.propertySchema[getScope(col.scope?.reference)][col?.scope?.reference?.split('/').pop()]?.type === 'string'"
20
+ [class]="getStyleWithoutClasses(col?.scope?.style).classes"
21
+ [style]="getStyleWithoutClasses(col?.scope?.style).style">
22
+ <span *ngIf="col.option.protected">
23
+ <span *ngIf="col.option?.link" (click)="showLinkDetails(col.option, data)">
24
+ {{data[col.scope?.reference.split('/').pop()]}}
25
+ </span>
26
+ <span *ngIf="!col.option?.link">
27
+ <ng-container *ngIf="col?.option?.dateFormat; else string">
28
+ {{ data[col.scope?.reference.split('/').pop()] | date:'yyyy-MM-dd' }}
29
+ </ng-container>
30
+ <ng-template #string>
31
+ {{ data[col.scope?.reference.split('/').pop()] }}
32
+ </ng-template>
33
+ </span>
34
+ </span>
35
+ <span *ngIf="!col.option.protected">
36
+ <input [(ngModel)]="data[col.scope?.reference.split('/').pop()]"
37
+ class="p-inputtext p-component" />
38
+ </span>
39
+ </ng-container>
40
+
41
+ <ng-container
42
+ *ngIf="tableitemInfo.propertySchema[getScope(col.scope?.reference)] && tableitemInfo.propertySchema[getScope(col.scope?.reference)][col?.scope?.reference?.split('/').pop()]?.type === 'number'">
43
+ <span *ngIf="col.option.protected">
44
+ <span *ngIf="col.option?.innerAction?.action == 'multiply'">
45
+ {{
46
+ (data[col.option?.innerAction?.from] * data[col.option?.innerAction?.to])
47
+ | number:'1.2-2'
48
+ }}
49
+ </span>
50
+ <span *ngIf="!col.option?.innerAction">
51
+ {{data[col.scope?.reference.split('/').pop()] | currency:
52
+ tableitemInfo.propertySchema[getScope(col.scope?.reference)][col?.scope?.reference?.split('/').pop()]?.currency
53
+ :true }}
54
+ </span>
55
+ </span>
56
+ <span *ngIf="!col.option.protected">
57
+ <input [(ngModel)]="data[col.scope?.reference.split('/').pop()]" type="number"
58
+ class="p-inputtext p-component" />
59
+ </span>
60
+ </ng-container>
61
+
62
+ <ng-container
63
+ *ngIf="tableitemInfo.propertySchema[getScope(col.scope?.reference)] && tableitemInfo.propertySchema[getScope(col.scope?.reference)][col?.scope?.reference?.split('/').pop()]?.type === 'image'">
64
+ <img *ngIf="data[col.scope?.reference.split('/').pop()]"
65
+ [src]="data[col.scope?.reference.split('/').pop()]" alt="Image"
66
+ (click)="invokeTableImageClick(col, data)"
67
+ [style]="getStyleWithoutClasses(col?.scope?.style).style" />
68
+ </ng-container>
69
+
70
+ <ng-container *ngIf="!col?.scope?.reference">
71
+ <span *ngIf="col.option?.actionColumn">
72
+ <span nz-icon *ngIf="setActionColumn(col.option?.save, data)" [nzType]="col.option?.save?.icon" [nzTheme]="'twotone'"
73
+ [style]="col.option?.save?.style" [nzTwotoneColor]="'#52c41a'"
74
+ [class]="col.option?.save?.style?.classes[0]" (click)="upsertAction(col.option?.save, data)">
75
+ </span>
76
+ <span nz-icon *ngIf="setActionColumn(col.option?.delete, data)" [nzType]="col.option?.delete?.icon" [nzTheme]="'twotone'"
77
+ [style]="col.option?.delete?.style" [nzTwotoneColor]="'#FF0000'"
78
+ [class]="col.option?.delete?.style?.classes[0]"
79
+ (click)="upsertAction(col.option?.delete, data)"></span>
80
+
81
+ </span>
82
+ <span *ngIf="!col.option?.actionColumn">
83
+ <button type="submit" [style]="getStyleWithoutClasses(col?.label?.style).style"
84
+ (click)="invokeGridBtnClick(col.option, data)" [class]="col?.label?.style?.classes[0]">
85
+ {{ col.label?.caption }}
86
+ </button>
87
+ </span>
88
+ </ng-container>
89
+
90
+ <!-- For quantity column, display increment/decrement buttons -->
91
+ <ng-container
92
+ *ngIf="tableitemInfo.propertySchema[getScope(col.scope?.reference)] && tableitemInfo.propertySchema[getScope(col.scope?.reference)][col?.scope?.reference?.split('/').pop()]?.type === 'quantity'">
93
+ <div style="display: flex; align-items: center;">
94
+ <button pButton icon="pi pi-minus"
95
+ (click)="decrementQuantity(i,col.scope?.reference.split('/').pop(), col.option)"
96
+ [disabled]="data.quantity <= 0"
97
+ style="margin-right: 8px; height: 10px; width: 10px;"></button>
98
+ <span>{{ data[col.scope?.reference.split('/').pop()] }}</span>
99
+ <button pButton icon="pi pi-plus"
100
+ (click)="incrementQuantity(i, col.scope?.reference.split('/').pop(), col.option)"
101
+ style="margin-left: 8px; height: 10px; width: 10px;"></button>
102
+ </div>
103
+ </ng-container>
104
+ </td>
105
+ </tr>
106
+ </tbody>
107
+ </nz-table>
108
+ </div>
109
+
110
+ <!-- table footer -->
111
+ <div *ngIf="tableitemInfo?.footer?.formFields && tableitemInfo.data?.length"
112
+ class="table-footer flex flex-column align-items-end gap-2 pt-2 mx-4 border-top-1 border-cyan-500">
113
+ <div *ngFor="let tableField of tableitemInfo?.footer?.formFields">
114
+ <div
115
+ [ngSwitch]="tableField?.scope?.reference && tableitemInfo.propertySchema[getScope(tableField.scope?.reference)] && tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()] ?
116
+ tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.type : 'default'">
117
+
118
+ <!-- string control -->
119
+ <div *ngSwitchCase="'string'" class="form-group">
120
+ <span *ngIf="tableField.option.protected">
121
+ <h5 style="display: flex; justify-content: space-between;">
122
+ <span [style]="getStyleWithoutClasses(tableField?.label?.style).style"
123
+ [class]="tableField?.label?.style?.classes[0]">
124
+ {{
125
+ tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.caption
126
+ }}
127
+ </span>
128
+ <span>
129
+ {{
130
+ tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.value
131
+ }}
132
+ </span>
133
+ </h5>
134
+ </span>
135
+ <div *ngIf="!tableField.option.protected">
136
+ <div [class]="tableField?.layout == 'horizontal' ? 'horizontal-layout' : 'row'">
137
+ <label [style]="getStyleWithoutClasses(tableField?.label?.style).style"
138
+ [class]="tableField?.label?.style?.classes[0]">{{ tableField.label?.value ?
139
+ tableField.label?.value :
140
+ tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.caption
141
+ }}</label>
142
+ <input type="text" #inputField="ngModel" [required]="tableField.option.required"
143
+ [email]="tableField.option.email" [class]="tableField.scope?.style?.classes[0]"
144
+ [style]="getStyleWithoutClasses(tableField?.scope?.style).style"
145
+ [(ngModel)]="tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()].value"
146
+ [name]="tableField.scope?.reference"
147
+ [placeholder]="tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.placeholder" />
148
+ </div>
149
+ <!-- Error Message -->
150
+ <div *ngIf="inputField?.touched && inputField?.invalid"
151
+ [style]="getStyleWithoutClasses(tableField?.validation?.style).style">
152
+ <p class="text-danger" *ngIf="inputField?.errors?.['required']">{{tableField.label?.value ?
153
+ tableField.label?.value :
154
+ tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.caption
155
+ +
156
+ ' ' + errorMessages.required}}</p>
157
+ <p class="text-danger" *ngIf="inputField?.errors?.['email']">{{(tableField.label?.value ?
158
+ tableField.label?.value :
159
+ tableitemInfo.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.caption)
160
+ +
161
+ ' ' + errorMessages.pattern}}</p>
162
+ </div>
163
+ </div>
164
+ </div>
165
+
166
+ <!-- number control -->
167
+ <div *ngSwitchCase="'number'" class="form-group">
168
+ <span *ngIf="tableField.option.protected"
169
+ [style]="getStyleWithoutClasses(tableField?.label?.style).style"
170
+ [class]="tableField?.label?.style?.classes[0]">
171
+ <h5>{{
172
+ form.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.caption
173
+ }} {{
174
+ form.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.value
175
+ |
176
+ currency:tableField.option.currency :true: tableField.option?.decimalPoint}}
177
+ </h5>
178
+ </span>
179
+ <span *ngIf="!tableField.option.protected">
180
+ <div [class]="tableField?.layout == 'horizontal' ? 'horizontal-layout' : 'row'">
181
+ <label [style]="getStyleWithoutClasses(tableField?.label?.style).style"
182
+ [class]="tableField?.label?.style?.classes[0]">{{ tableField.label?.value ?
183
+ tableField.label?.value :
184
+ form.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.caption
185
+ }}</label>
186
+ <input type="number" [class]="tableField.scope?.style?.classes[0]"
187
+ [style]="getStyleWithoutClasses(tableField?.scope?.style).style"
188
+ [(ngModel)]="form.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()].value"
189
+ [name]="tableField.scope?.reference"
190
+ [placeholder]="form.propertySchema[getScope(tableField.scope?.reference)][tableField.scope?.reference.split('/').pop()]?.placeholder" />
191
+ </div>
192
+ </span>
193
+ </div>
194
+
195
+ <!-- button control -->
196
+ <div *ngSwitchCase="'default'">
197
+ <button type="submit" [style]="getStyleWithoutClasses(tableField.label.style).style"
198
+ (click)="invokeGridBtnClick(tableField.option, tableitemInfo.propertySchema)">
199
+ {{ tableField.label?.caption }}
200
+ </button>
201
+ </div>
202
+ </div>
203
+ </div>
204
+ </div>
205
+
206
+ <!-- bottom pagination on grid -->
207
+ <div
208
+ *ngIf="tableitemInfo.data?.length && !tableitemInfo?.layoutSchema?.pagination?.top && tableitemInfo?.layoutSchema?.pagination?.bottom">
209
+ <vl-pagination [itemInfo]="tableitemInfo" [pageSize]="pageSize" [currentPage]="currentPage" [pages]="pages"
210
+ (pageSizeChange)="invokeOnPageSizeChange($event)" (onGoToPage)="invokeGoToPage($event)">
211
+ </vl-pagination>
212
+ </div>
@@ -0,0 +1,228 @@
1
+ import { AfterViewInit, Component, EventEmitter, Input, Output, SimpleChanges } from '@angular/core';
2
+ import { RequestService } from '../../services/request.service';
3
+ import { UtilityService } from '../../services/utility.service';
4
+ import { OktaAuthStateService } from '@okta/okta-angular';
5
+ import { NotificationService } from '../../services/notification.service';
6
+ import { CommonModule } from '@angular/common';
7
+ import { FormsModule } from '@angular/forms';
8
+ import { NzTableModule } from 'ng-zorro-antd/table';
9
+ import { NzIconModule } from 'ng-zorro-antd/icon';
10
+ import { ButtonModule } from 'primeng/button';
11
+ import { PaginationComponent } from '../pagination/pagination.component';
12
+
13
+ @Component({
14
+ standalone: true,
15
+ imports: [
16
+ CommonModule,
17
+ FormsModule,
18
+ NzTableModule,
19
+ NzIconModule,
20
+ ButtonModule,
21
+ PaginationComponent
22
+ ],
23
+ selector: 'vl-grid',
24
+ templateUrl: './grid.component.html',
25
+ styleUrl: './grid.component.css'
26
+ })
27
+ export class GridComponent implements AfterViewInit {
28
+ isLogined: boolean = false;
29
+ tableitemInfoCopy: any = {};
30
+ @Input() errorMessages: any = {};
31
+ @Input() environment: any;
32
+ @Input() selectedLanguageInfo: any = {};
33
+ @Input() tableitemInfo: any = {};
34
+ @Input() form: any = {};
35
+ @Input() isTableDataLoad: boolean = false;
36
+ @Input() currenTableOptions: any = {};
37
+ @Input() projectSeleted: any = '';
38
+ @Input() pageSize: number = 5;
39
+ @Input() currentPage: number = 0;
40
+ @Input() pages: number[] = [];
41
+ @Input() userInfo: any;
42
+ @Output() onPageChange: EventEmitter<any> = new EventEmitter();
43
+ @Output() onPageSizeChange: EventEmitter<any> = new EventEmitter();
44
+ @Output() onGridScroll: EventEmitter<any> = new EventEmitter();
45
+ @Output() showGridLink: EventEmitter<any> = new EventEmitter();
46
+ @Output() gridButtonClick: EventEmitter<any> = new EventEmitter();
47
+ @Output() gridIncreamentClick: EventEmitter<any> = new EventEmitter();
48
+ @Output() gridDecreamentClick: EventEmitter<any> = new EventEmitter();
49
+ @Output() gridImgClick: EventEmitter<any> = new EventEmitter();
50
+
51
+ constructor(private requestService: RequestService,
52
+ private utilityService: UtilityService,
53
+ private notificationService: NotificationService,
54
+ private oktaAuthService: OktaAuthStateService,) {
55
+ }
56
+
57
+ ngAfterViewInit(): void {
58
+ this.authenticating();
59
+ setTimeout(() => {
60
+ if (this.environment && this.environment?.login && this.environment?.login?.type == "oktaAuth") {
61
+ this.oktaAuthService.authState$.subscribe(
62
+ (result) => {
63
+ if (result.isAuthenticated) {
64
+ this.isLogined = true;
65
+ }
66
+ }
67
+ );
68
+ }
69
+ }, 500);
70
+ }
71
+
72
+ ngOnChanges(changes: SimpleChanges): void {
73
+ setTimeout(() => {
74
+ if (changes['tableitemInfo'] && this.tableitemInfo) {
75
+ console.log('this.tableitemInfo: ', this.tableitemInfo);
76
+ console.log('this.selectedLanguageInfo?: ', this.selectedLanguageInfo);
77
+ this.tableitemInfoCopy = JSON.parse(JSON.stringify(this.tableitemInfo));
78
+ }
79
+ if (changes['SelectedLanguage'] || this.selectedLanguageInfo?.selectedLanguage) {
80
+ if (this.tableitemInfoCopy?.layoutSchema && this.tableitemInfoCopy.layoutSchema?.elements?.length) {
81
+ this.tableitemInfo.propertySchema = JSON.parse(JSON.stringify(this.tableitemInfoCopy.propertySchema));
82
+ this.tableitemInfo.propertySchema = this.translateSchema(this.tableitemInfo.propertySchema, this.selectedLanguageInfo.selectedLanguage);
83
+ if (this.tableitemInfoCopy?.footer) {
84
+ this.tableitemInfo.footer = JSON.parse(JSON.stringify(this.tableitemInfoCopy.footer));
85
+ this.tableitemInfo.footer = this.translateSchema(this.tableitemInfo.footer, this.selectedLanguageInfo.selectedLanguage);
86
+ }
87
+ this.tableitemInfoCopy.layoutSchema.elements.forEach((column: any, index: any) => {
88
+ if (column.label && column.label.caption && this.selectedLanguageInfo.selectedLanguage[column.label.caption]) {
89
+ this.tableitemInfo.layoutSchema.elements[index].label.caption = this.selectedLanguageInfo.selectedLanguage[column.label.caption];
90
+ }
91
+ });
92
+ }
93
+ }
94
+ }, 500);
95
+ }
96
+
97
+ translateSchema(schema: any, SelectedLanguage: any): any {
98
+ if (schema && typeof schema === 'object') {
99
+ for (const key of Object.keys(schema)) {
100
+ const val = schema[key];
101
+ if (val && typeof val === 'object') {
102
+ this.translateSchema(val, SelectedLanguage);
103
+ }
104
+ if (val && val.caption !== undefined && typeof val.caption === 'string') {
105
+ const original = val.caption.trim();
106
+ if (original && SelectedLanguage[original]) {
107
+ val.caption = SelectedLanguage[original];
108
+ }
109
+ }
110
+ if (val && val.value !== undefined && typeof val.value === 'string' && !val.value.includes("{{")) {
111
+ const originalVal = val.value.trim();
112
+ if (originalVal && SelectedLanguage[originalVal]) {
113
+ val.value = SelectedLanguage[originalVal];
114
+ }
115
+ }
116
+ }
117
+ }
118
+ return schema;
119
+ }
120
+
121
+
122
+ getScope(scope: any) {
123
+ let propertyScope = "";
124
+ let start = scope?.indexOf("#/") + 2;
125
+ let end = scope?.indexOf("/", start);
126
+ if (start && end) {
127
+ propertyScope = scope.substring(start, end);
128
+ }
129
+ return propertyScope;
130
+ }
131
+
132
+ getStyleWithoutClasses(styleObject: any) {
133
+ if (!styleObject) {
134
+ return { classes: '', style: {} };
135
+ }
136
+ const { classes, ...styleWithoutClasses } = styleObject;
137
+ return { classes: classes && classes.length > 0 ? classes[0] : '', style: styleWithoutClasses };
138
+ }
139
+
140
+ onScrollEvent(event: any) {
141
+ this.onGridScroll.emit(event);
142
+ }
143
+
144
+ showLinkDetails(option: any, data: any) {
145
+ this.showGridLink.emit({ option: option, data: data });
146
+ }
147
+
148
+ invokeGridBtnClick(option: any, propertySchema: any) {
149
+ this.gridButtonClick.emit({ option: option, propertySchema: propertySchema });
150
+ }
151
+
152
+ upsertAction(option: any, data: any) {
153
+ let url = option?.data_url;
154
+ if (url && url?.includes("{{")) {
155
+ const regex = /{{(.*?)}}/g;
156
+ const matches = [...url.matchAll(regex)].map(m => m[1]);
157
+ if (matches && data && data[matches[0]]) {
158
+ option.data_url = url.replace(`{{${matches[0]}}}`, data[matches[0]])
159
+ }
160
+ }
161
+ let baseUrl = this.environment?.apiUrl + option.data_url;
162
+ this.requestService.dynamicCall(option.method, {}, baseUrl, option?.passToken, this.projectSeleted, this.userInfo).subscribe((res: any) => {
163
+ console.log('res: ', res);
164
+ if (option?.reload) {
165
+ window.location.reload();
166
+ } else if (option.notifcation) {
167
+ if(option.notifcation.success){
168
+ this.notificationService.success(option.notifcation.success);
169
+ let findObj: any = this.findDynamicKeyAndValue(option);
170
+ if(findObj.keyName){
171
+ data[findObj.keyName] = "APPROVED";
172
+ }
173
+ }
174
+ }
175
+ })
176
+ }
177
+
178
+ setActionColumn(option: any, data: any) {
179
+ let showAction: boolean = true;
180
+ let findCondiontionalKey: any = this.findDynamicKeyAndValue(option);
181
+ if (findCondiontionalKey.keyName) {
182
+ showAction = data[findCondiontionalKey.keyName] === findCondiontionalKey.value ? true : false;
183
+ }
184
+ return showAction;
185
+ }
186
+
187
+ findDynamicKeyAndValue(object: Record<string, any>) {
188
+ const regex = /^\{\{(.*?)\}\}$/;
189
+ for (const key of Object.keys(object)) {
190
+ const match = key.match(regex);
191
+ if (match) {
192
+ return {
193
+ keyName: match[1].trim(),
194
+ value: object[key]
195
+ };
196
+ }
197
+ }
198
+ return null;
199
+ }
200
+
201
+ incrementQuantity(index: any, field: any, option: any) {
202
+ this.gridIncreamentClick.emit({ index: index, field: field, option: option });
203
+ }
204
+
205
+ invokeTableImageClick(column: any, data: any) {
206
+ this.gridImgClick.emit({ col: column, data: data });
207
+ }
208
+
209
+ decrementQuantity(index: any, field: any, option: any) {
210
+ this.gridDecreamentClick.emit({ index: index, field: field, option: option });
211
+ }
212
+
213
+ invokeOnPageSizeChange(pageSize: any) {
214
+ this.onPageSizeChange.emit(pageSize);
215
+ }
216
+
217
+ invokeGoToPage(page: any) {
218
+ this.onPageChange.emit(page);
219
+ }
220
+
221
+ authenticating() {
222
+ this.utilityService.getStorage(`${this.projectSeleted}Logined`).then((logined: any) => {
223
+ if (logined == "true") {
224
+ this.isLogined = true;
225
+ }
226
+ })
227
+ }
228
+ }
@@ -0,0 +1,72 @@
1
+ <header *ngIf="headerItems.length > 0" [ngStyle]="getStyle(headerLayout?.style)">
2
+
3
+ <ng-container *ngFor="let header of headerItems"
4
+ [ngSwitch]="header.scope?.reference ? header.scope?.reference.split('/').pop() : 'default'">
5
+
6
+ <!-- Logo -->
7
+ <ng-container *ngSwitchCase="'logo'">
8
+ <div *ngIf="isVisible(header)" [ngStyle]="getStyle(header?.option?.style)">
9
+
10
+ <img [src]="header.option.src" [alt]="header.alt || 'Logo'"
11
+ [ngStyle]="getStyle(header?.scope?.style)" />
12
+ </div>
13
+ </ng-container>
14
+
15
+ <!-- Search -->
16
+ <ng-container *ngSwitchCase="'searchInput'">
17
+ <div *ngIf="isVisible(header)" [ngStyle]="getStyle(header?.option?.style)">
18
+
19
+ <input #search type="text" [placeholder]="header.option.placeholder"
20
+ (keyup.enter)="invokeSearchedItems(header.option, search)"
21
+ [ngStyle]="getStyle(header?.scope?.style)" />
22
+
23
+ <button *ngIf="header.option.button !== false" type="button"
24
+ (click)="invokeSearchedItems(header.option, search)" [ngStyle]="getStyle(header?.buttonStyle)">
25
+ <ng-container *ngIf="!header.caption; else searchTextContent">
26
+ <i nz-icon [nzType]="header.icon" nzTheme="outline"></i>
27
+ </ng-container>
28
+
29
+ <ng-template #searchTextContent>
30
+ {{ header.caption }}
31
+ </ng-template>
32
+ </button>
33
+ </div>
34
+ </ng-container>
35
+
36
+ <!-- Cart -->
37
+ <ng-container *ngSwitchCase="'cart'">
38
+ <div *ngIf="isVisible(header)" [ngStyle]="getStyle(header?.option?.style)"
39
+ (click)="invokeShowtableContent(header.option)">
40
+
41
+ <span [ngStyle]="getStyle(header?.priceStyle)">
42
+ {{ cartInfo.totalPrice | currency : header.option?.currency ? header.option.currency : 'USD' }}
43
+ </span>
44
+
45
+ <span [ngStyle]="getStyle(header?.quantityStyle)">
46
+ {{ cartInfo.quantity }}
47
+ </span>
48
+
49
+ <i [class]="header.icon" [ngStyle]="getStyle(header?.iconStyle)">
50
+ </i>
51
+ </div>
52
+ </ng-container>
53
+
54
+ <!-- Default Button -->
55
+ <ng-container *ngSwitchCase="'default'">
56
+ <div *ngIf="shouldShowDefaultButton(header)" [ngStyle]="getStyle(header?.option?.style)">
57
+
58
+ <button type="button" (click)="invokeHeaderButtonClick(header.option)"
59
+ [ngStyle]="getStyle(header?.buttonStyle)">
60
+ <ng-container *ngIf="!header.label; else buttonTextContent">
61
+ <i nz-icon [nzType]="header.icon" nzTheme="outline"></i>
62
+ </ng-container>
63
+
64
+ <ng-template #buttonTextContent>
65
+ {{ header.label }}
66
+ </ng-template>
67
+ </button>
68
+ </div>
69
+ </ng-container>
70
+
71
+ </ng-container>
72
+ </header>
@@ -0,0 +1,105 @@
1
+ import { AfterViewInit, Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { OktaAuthStateService } from '@okta/okta-angular';
3
+ import { Platform } from '@angular/cdk/platform';
4
+ import { CommonModule } from '@angular/common';
5
+ import { NzIconModule } from 'ng-zorro-antd/icon';
6
+ import { RequestService } from '../../services/request.service';
7
+ import { UtilityService } from '../../services/utility.service';
8
+
9
+ @Component({
10
+ standalone: true,
11
+ imports: [
12
+ CommonModule,
13
+ NzIconModule
14
+ ],
15
+ selector: 'vl-header-menu',
16
+ templateUrl: './header-menu.component.html',
17
+ styleUrl: './header-menu.component.css'
18
+ })
19
+ export class HeaderMenuComponent implements AfterViewInit {
20
+ isLogined: boolean = false;
21
+
22
+ @Input() headerItems: any[] = [];
23
+ @Input() headerLayout: any = {};
24
+ @Input() environment: any;
25
+ @Input() projectSeleted: any;
26
+ @Input() cartInfo: any = {
27
+ items: [],
28
+ totalPrice: 0,
29
+ quantity: 0
30
+ };
31
+
32
+ @Output() buttonClick: EventEmitter<any> = new EventEmitter();
33
+ @Output() showTableContent: EventEmitter<any> = new EventEmitter();
34
+ @Output() searchItems: EventEmitter<any> = new EventEmitter();
35
+
36
+ constructor(
37
+ private oktaAuthService: OktaAuthStateService,
38
+ private requestService: RequestService,
39
+ private utilityService: UtilityService,
40
+ private platform: Platform
41
+ ) {}
42
+
43
+ ngAfterViewInit(): void {
44
+ setTimeout(() => {
45
+ if (this.environment && this.environment?.login && this.environment?.login?.type == "oktaAuth") {
46
+ if (this.platform.ANDROID || this.platform.IOS) {
47
+ this.utilityService.getLocalStorage(`loginedUser`).then((logined: any) => {
48
+ if (logined && logined.token) {
49
+ this.requestService.getLoginUser(logined?.token).subscribe(() => {
50
+ this.isLogined = true;
51
+ });
52
+ }
53
+ });
54
+ }
55
+
56
+ this.oktaAuthService.authState$.subscribe((result) => {
57
+ if (result.isAuthenticated) {
58
+ this.isLogined = true;
59
+ }
60
+ });
61
+ }
62
+ }, 500);
63
+ }
64
+
65
+ getStyle(styleObject: any): Record<string, any> {
66
+ if (!styleObject || typeof styleObject !== 'object') {
67
+ return {};
68
+ }
69
+
70
+ const { classes, ...styleWithoutClasses } = styleObject;
71
+ return styleWithoutClasses;
72
+ }
73
+
74
+ isVisible(header: any): boolean {
75
+ return header?.option?.visible !== false;
76
+ }
77
+
78
+ shouldShowDefaultButton(header: any): boolean {
79
+ if (!this.isVisible(header)) {
80
+ return false;
81
+ }
82
+
83
+ if (header?.option?.islogin === true) {
84
+ return this.isLogined;
85
+ }
86
+
87
+ if (header?.option?.islogin === false) {
88
+ return !this.isLogined;
89
+ }
90
+
91
+ return true;
92
+ }
93
+
94
+ invokeSearchedItems(option: any, search: any) {
95
+ this.searchItems.emit({ option: option, search: search });
96
+ }
97
+
98
+ invokeHeaderButtonClick(option: any) {
99
+ this.buttonClick.emit(option);
100
+ }
101
+
102
+ invokeShowtableContent(option: any) {
103
+ this.showTableContent.emit(option);
104
+ }
105
+ }