@verisoft/ui-primeng 18.0.0 → 18.3.1

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 (157) hide show
  1. package/{src/assets → assets}/sass/base/_typography.scss +2 -2
  2. package/assets/sass/layout/_button.scss +57 -0
  3. package/{src/assets → assets}/sass/layout/_sidemenu.scss +1 -15
  4. package/package.json +5 -4
  5. package/src/index.ts +2 -4
  6. package/src/lib/components/breadcrumb/breadcrumb.component.html +2 -2
  7. package/src/lib/components/breadcrumb/breadcrumb.component.ts +6 -1
  8. package/src/lib/components/breadcrumb/breadcrumb.pipe.ts +13 -0
  9. package/src/lib/components/button/button.component.html +2 -2
  10. package/src/lib/components/button/button.component.ts +7 -1
  11. package/src/lib/components/button/index.ts +0 -1
  12. package/src/lib/components/calendar/calendar.component.html +2 -2
  13. package/src/lib/components/calendar/calendar.component.ts +7 -2
  14. package/src/lib/components/checkbox/checkbox.component.html +1 -1
  15. package/src/lib/components/checkbox/checkbox.component.ts +5 -1
  16. package/src/lib/components/confirm-dialog/confirm-dialog.component.ts +3 -3
  17. package/src/lib/components/confirm-dialog/index.ts +0 -1
  18. package/src/lib/components/dropdown/dropdown.component.html +1 -1
  19. package/src/lib/components/dropdown/dropdown.component.ts +8 -3
  20. package/src/lib/components/errors/error.component.html +6 -0
  21. package/src/lib/components/errors/error.component.scss +3 -0
  22. package/src/lib/components/errors/error.component.ts +35 -0
  23. package/src/lib/components/errors/index.ts +1 -0
  24. package/src/lib/components/form-field/form-field.component.html +3 -8
  25. package/src/lib/components/form-field/form-field.component.ts +17 -13
  26. package/src/lib/components/header/header.component.html +2 -3
  27. package/src/lib/components/header/header.component.ts +3 -1
  28. package/src/lib/components/header/services/header-provider.service.ts +1 -1
  29. package/src/lib/components/input-group/input-group.component.html +1 -3
  30. package/src/lib/components/multiselect/multiselect.component.html +2 -1
  31. package/src/lib/components/multiselect/multiselect.component.ts +5 -3
  32. package/src/lib/components/number-input/number-input.component.html +1 -1
  33. package/src/lib/components/number-input/number-input.component.ts +3 -0
  34. package/src/lib/components/page-header/index.ts +0 -1
  35. package/src/lib/components/page-header/page-header.component.html +1 -1
  36. package/src/lib/components/page-header/page-header.component.ts +6 -34
  37. package/src/lib/components/password/password.component.html +1 -1
  38. package/src/lib/components/password/password.component.ts +3 -1
  39. package/src/lib/components/radiobutton/radiobutton.component.html +1 -1
  40. package/src/lib/components/radiobutton/radiobutton.component.ts +2 -0
  41. package/src/lib/components/section/section.component.html +1 -2
  42. package/src/lib/components/section/section.component.ts +4 -2
  43. package/src/lib/components/{action-button-group → shared-components/action-button-group}/action-button-group.component.html +2 -4
  44. package/src/lib/components/{action-button-group → shared-components/action-button-group}/action-button-group.component.ts +21 -11
  45. package/src/lib/components/{action-button-group → shared-components/action-button-group}/components/action-button/action-button.component.html +1 -2
  46. package/src/lib/components/shared-components/action-button-group/components/action-button/action-button.component.ts +71 -0
  47. package/src/lib/components/shared-components/dynamic-component/dynamic-component-factory.service.ts +142 -0
  48. package/src/lib/components/{dynamic-component → shared-components/dynamic-component}/dynamic-component.component.ts +5 -4
  49. package/src/lib/components/shared-components/dynamic-component/index.ts +2 -0
  50. package/src/lib/components/shared-components/feature-list/directives/feature-list-column.directive.ts +32 -0
  51. package/src/lib/components/shared-components/feature-list/directives/feature-list-filter-field.directive.ts +8 -0
  52. package/src/lib/components/shared-components/feature-list/feature-list-filter.pipe.ts +21 -0
  53. package/src/lib/components/shared-components/feature-list/feature-list-page.component.ts +31 -0
  54. package/src/lib/components/shared-components/feature-list/feature-list-page.model.ts +42 -0
  55. package/src/lib/components/shared-components/feature-list/feature-list.component.html +59 -0
  56. package/src/lib/components/shared-components/feature-list/feature-list.component.scss +10 -0
  57. package/src/lib/components/shared-components/feature-list/feature-list.component.ts +342 -0
  58. package/src/lib/components/shared-components/feature-list/index.ts +5 -0
  59. package/src/lib/components/shared-components/filter/directives/filter-field.directive.ts +35 -0
  60. package/src/lib/components/{filter → shared-components/filter}/filter.component.html +8 -7
  61. package/src/lib/components/{filter → shared-components/filter}/filter.component.ts +53 -26
  62. package/src/lib/components/shared-components/filter/filter.model.ts +18 -0
  63. package/src/lib/components/{filter → shared-components/filter}/index.ts +0 -1
  64. package/src/lib/components/shared-components/generic-field/generic-field.component.html +97 -0
  65. package/src/lib/components/{generic-field → shared-components/generic-field}/generic-field.component.ts +28 -10
  66. package/src/lib/components/{generic-field → shared-components/generic-field}/index.ts +0 -1
  67. package/src/lib/components/shared-components/generic-form/generic-form.component.html +46 -0
  68. package/src/lib/components/{generic-form → shared-components/generic-form}/generic-form.component.ts +11 -2
  69. package/src/lib/components/{generic-form → shared-components/generic-form}/generic-form.model.ts +11 -19
  70. package/src/lib/components/shared-components/index.ts +6 -0
  71. package/src/lib/components/side-menu/side-menu.component.html +7 -10
  72. package/src/lib/components/side-menu/side-menu.component.ts +7 -6
  73. package/src/lib/components/slider/slider.component.html +2 -2
  74. package/src/lib/components/slider/slider.component.ts +2 -0
  75. package/src/lib/components/stepper/stepper.component.html +2 -2
  76. package/src/lib/components/stepper/stepper.component.ts +16 -1
  77. package/src/lib/components/switch/switch.component.html +1 -2
  78. package/src/lib/components/switch/switch.component.ts +2 -0
  79. package/src/lib/components/tab-view/tab-menu.pipe.ts +22 -0
  80. package/src/lib/components/tab-view/tab-view-item.component.ts +2 -0
  81. package/src/lib/components/tab-view/tab-view.component.html +2 -3
  82. package/src/lib/components/tab-view/tab-view.component.ts +4 -4
  83. package/src/lib/components/tab-view/tab-view.module.ts +2 -1
  84. package/src/lib/components/table/index.ts +0 -1
  85. package/src/lib/components/table/table-filter.pipe.ts +59 -0
  86. package/src/lib/components/table/table.component.html +120 -180
  87. package/src/lib/components/table/table.component.scss +11 -0
  88. package/src/lib/components/table/table.component.ts +131 -98
  89. package/src/lib/components/table/table.models.ts +26 -0
  90. package/src/lib/components/textarea/textarea.component.html +1 -1
  91. package/src/lib/components/textarea/textarea.component.ts +2 -0
  92. package/src/lib/components/textfield/textfield.component.html +1 -1
  93. package/src/lib/components/textfield/textfield.component.ts +6 -1
  94. package/src/lib/components/tristatecheckbox/tristatecheckbox.component.html +2 -2
  95. package/src/lib/components/tristatecheckbox/tristatecheckbox.component.ts +4 -0
  96. package/src/lib/icons.ts +36 -0
  97. package/src/lib/pages/not-found-page/not-found-page.component.html +1 -2
  98. package/src/assets/sass/layout/_button.scss +0 -57
  99. package/src/lib/components/action-button-group/components/action-button/action-button.component.ts +0 -36
  100. package/src/lib/components/button/directives/shortcut.directive.ts +0 -37
  101. package/src/lib/components/confirm-dialog/services/confirm-dialog.service.ts +0 -14
  102. package/src/lib/components/dynamic-component/dynamic-component-factory.service.ts +0 -90
  103. package/src/lib/components/filter/directives/filter-field.directive.ts +0 -25
  104. package/src/lib/components/filter/directives/table-filter.directive.ts +0 -22
  105. package/src/lib/components/filter/filter.model.ts +0 -18
  106. package/src/lib/components/generic-field/generic-field.component.html +0 -54
  107. package/src/lib/components/generic-field/generic-field.model.ts +0 -9
  108. package/src/lib/components/generic-form/generic-form.component.html +0 -33
  109. package/src/lib/components/page-header/services/page-header.service.ts +0 -9
  110. package/src/lib/components/table/directives/table-store.directive.ts +0 -61
  111. package/src/lib/components/table-filter/filter.component.html +0 -205
  112. package/src/lib/components/table-filter/filter.component.scss +0 -0
  113. package/src/lib/components/table-filter/filter.component.spec.ts +0 -21
  114. package/src/lib/components/table-filter/filter.component.stories.ts +0 -23
  115. package/src/lib/services/screen-size.service.ts +0 -25
  116. /package/{src/assets → assets}/.gitkeep +0 -0
  117. /package/{src/assets → assets}/fonts/orbitron-black.ttf +0 -0
  118. /package/{src/assets → assets}/fonts/orbitron-bold.otf +0 -0
  119. /package/{src/assets → assets}/icons/complex/v-logo.svg +0 -0
  120. /package/{src/assets → assets}/images/_global/elon.jpg +0 -0
  121. /package/{src/assets → assets}/images/_global/jara.png +0 -0
  122. /package/{src/assets → assets}/images/_global/logos/v-logo.webp +0 -0
  123. /package/{src/assets → assets}/sass/base/_scrollbar.scss +0 -0
  124. /package/{src/assets → assets}/sass/layout/_app.scss +0 -0
  125. /package/{src/assets → assets}/sass/layout/_checkbox.scss +0 -0
  126. /package/{src/assets → assets}/sass/layout/_dialog.scss +0 -0
  127. /package/{src/assets → assets}/sass/layout/_dropdown.scss +0 -0
  128. /package/{src/assets → assets}/sass/layout/_formField.scss +0 -0
  129. /package/{src/assets → assets}/sass/layout/_header.scss +0 -0
  130. /package/{src/assets → assets}/sass/layout/_icons.scss +0 -0
  131. /package/{src/assets → assets}/sass/layout/_inputSwitch.scss +0 -0
  132. /package/{src/assets → assets}/sass/layout/_layout.scss +0 -0
  133. /package/{src/assets → assets}/sass/layout/_loader.scss +0 -0
  134. /package/{src/assets → assets}/sass/layout/_radiobutton.scss +0 -0
  135. /package/{src/assets → assets}/sass/layout/_snackbar.scss +0 -0
  136. /package/{src/assets → assets}/sass/layout/_tables.scss +0 -0
  137. /package/{src/assets → assets}/sass/layout/_tree.scss +0 -0
  138. /package/{src/assets → assets}/sass/layout/_tristatecheckbox.scss +0 -0
  139. /package/{src/assets → assets}/sass/main.scss +0 -0
  140. /package/{src/assets → assets}/sass/themes/_verisoft_theme.scss +0 -0
  141. /package/{src/assets → assets}/sass/utils/_mixins.scss +0 -0
  142. /package/{src/assets → assets}/sass/utils/_utils.scss +0 -0
  143. /package/{src/assets → assets}/sass/utils/_variables.scss +0 -0
  144. /package/{src/assets → assets}/sass/vendors/_bootstrap.scss +0 -0
  145. /package/{src/assets → assets}/sass/vendors/_primeng.scss +0 -0
  146. /package/src/lib/components/{action-button-group → shared-components/action-button-group}/action-button-group.component.scss +0 -0
  147. /package/src/lib/components/{action-button-group → shared-components/action-button-group}/action-button-group.component.spec.ts +0 -0
  148. /package/src/lib/components/{action-button-group → shared-components/action-button-group}/components/action-button/action-button.component.scss +0 -0
  149. /package/src/lib/components/{action-button-group → shared-components/action-button-group}/components/action-button/action-button.component.spec.ts +0 -0
  150. /package/src/lib/components/{action-button-group → shared-components/action-button-group}/index.ts +0 -0
  151. /package/src/lib/components/{filter → shared-components/filter}/filter.component.scss +0 -0
  152. /package/src/lib/components/{filter → shared-components/filter}/filter.component.spec.ts +0 -0
  153. /package/src/lib/components/{filter → shared-components/filter}/filter.component.stories.ts +0 -0
  154. /package/src/lib/components/{generic-field → shared-components/generic-field}/generic-field.component.spec.ts +0 -0
  155. /package/src/lib/components/{generic-form → shared-components/generic-form}/generic-form.component.spec.ts +0 -0
  156. /package/src/lib/components/{generic-form → shared-components/generic-form}/generic-form.model.spec.ts +0 -0
  157. /package/src/lib/components/{generic-form → shared-components/generic-form}/index.ts +0 -0
@@ -14,15 +14,21 @@ import {
14
14
  SimpleChanges,
15
15
  } from '@angular/core';
16
16
  import {
17
- ControlValueAccessor,
18
17
  FormGroup,
19
18
  NG_VALUE_ACCESSOR,
20
19
  ReactiveFormsModule,
21
20
  } from '@angular/forms';
22
21
  import { BaseHttpService } from '@verisoft/core';
23
22
  import {
23
+ ButtonShortCutDirective,
24
24
  DEFAULT_DEBOUNCE_TIME,
25
+ DialogService,
25
26
  FieldSize,
27
+ FILTER_COMPONENT_TOKEN,
28
+ FilterCore,
29
+ GenericFieldDefinition,
30
+ isFilterEmpty,
31
+ ScreenSizeService,
26
32
  UnsubscribeComponent,
27
33
  } from '@verisoft/ui-core';
28
34
  import { BadgeModule } from 'primeng/badge';
@@ -30,20 +36,16 @@ import {
30
36
  BehaviorSubject,
31
37
  combineLatestWith,
32
38
  debounceTime,
39
+ distinctUntilChanged,
33
40
  map,
34
41
  Observable,
35
42
  startWith,
36
43
  takeUntil,
37
44
  } from 'rxjs';
38
- import { ScreenSizeService } from '../../services/screen-size.service';
39
- import { ButtonComponent, ButtonShortCutDirective } from '../button';
40
- import { DialogService } from '../confirm-dialog';
41
- import {
42
- generateFormGroup,
43
- GenericFieldDefinition,
44
- GenericFormComponent,
45
- } from '../generic-form';
46
- import { TextfieldComponent } from '../textfield';
45
+ import { Icons } from '../../../icons';
46
+ import { ButtonComponent } from '../../button';
47
+ import { TextfieldComponent } from '../../textfield';
48
+ import { generateFormGroup, GenericFormComponent } from '../generic-form';
47
49
  import { FilterFieldDirective } from './directives/filter-field.directive';
48
50
  import { getFilledControlCount } from './filter.model';
49
51
 
@@ -67,6 +69,10 @@ type FilterValueType = { [key: string]: unknown };
67
69
  useExisting: forwardRef(() => FilterComponent),
68
70
  multi: true,
69
71
  },
72
+ {
73
+ provide: FILTER_COMPONENT_TOKEN,
74
+ useExisting: FilterComponent,
75
+ },
70
76
  ],
71
77
  templateUrl: './filter.component.html',
72
78
  styleUrl: './filter.component.scss',
@@ -74,13 +80,15 @@ type FilterValueType = { [key: string]: unknown };
74
80
  })
75
81
  export class FilterComponent<T extends object>
76
82
  extends UnsubscribeComponent
77
- implements OnChanges, OnInit, AfterContentInit, ControlValueAccessor
83
+ implements OnChanges, OnInit, AfterContentInit, FilterCore
78
84
  {
79
85
  @ContentChildren(FilterFieldDirective)
80
86
  fieldDeclarations!: QueryList<FilterFieldDirective>;
81
87
 
82
88
  @Input() fields: GenericFieldDefinition[] = [];
83
89
 
90
+ @Input() filters: GenericFieldDefinition[] = [];
91
+
84
92
  @Input() title?: string;
85
93
 
86
94
  @Input() fulltextFieldName = 'searchField';
@@ -93,9 +101,9 @@ export class FilterComponent<T extends object>
93
101
 
94
102
  @Input() debounceTime?: number = DEFAULT_DEBOUNCE_TIME;
95
103
 
96
- fieldDefinitios$?: Observable<GenericFieldDefinition[]>;
104
+ icons = Icons;
97
105
 
98
- filledFiltersCount$?: Observable<string>;
106
+ fieldDefinitios$?: Observable<GenericFieldDefinition[]>;
99
107
 
100
108
  formGroup$?: Observable<FormGroup>;
101
109
 
@@ -107,11 +115,11 @@ export class FilterComponent<T extends object>
107
115
 
108
116
  private onTouch?: () => void;
109
117
 
110
- private onChange?: (value: FilterValueType) => void;
118
+ private onChange?: (value: FilterValueType | undefined) => void;
111
119
 
112
120
  private inputFields$ = new BehaviorSubject<
113
121
  GenericFieldDefinition[] | undefined
114
- >(this.fields);
122
+ >([...this.fields ?? [], ...this.filters ?? []]);
115
123
 
116
124
  FieldSize = FieldSize;
117
125
 
@@ -123,20 +131,27 @@ export class FilterComponent<T extends object>
123
131
 
124
132
  formGroup = new FormGroup({});
125
133
 
134
+ filledFiltersCount$: Observable<string> = this.formGroup.valueChanges.pipe(
135
+ startWith(this.formGroup),
136
+ map(() => getFilledControlCount(this.formGroup).toString())
137
+ );
138
+
126
139
  private lastFormFields: GenericFieldDefinition[] = [];
127
140
 
128
141
  ngOnInit(): void {
129
142
  this.formGroup.valueChanges
130
143
  .pipe(
131
144
  takeUntil(this.destroyed$),
132
- debounceTime(this.debounceTime ?? DEFAULT_DEBOUNCE_TIME)
145
+ debounceTime(this.debounceTime ?? DEFAULT_DEBOUNCE_TIME),
146
+ map((x) => this.convertFilter(x)),
147
+ distinctUntilChanged()
133
148
  )
134
149
  .subscribe((value) => this.onChange?.(value));
135
150
  }
136
151
 
137
152
  ngOnChanges(changes: SimpleChanges): void {
138
- if (changes['fields']) {
139
- this.inputFields$.next(this.fields);
153
+ if (changes['fields'] || changes['filters']) {
154
+ this.inputFields$.next([...this.fields ?? [], ...this.filters ?? []]);
140
155
  }
141
156
  }
142
157
 
@@ -170,10 +185,6 @@ export class FilterComponent<T extends object>
170
185
  )
171
186
  );
172
187
 
173
- this.filledFiltersCount$ = this.formGroup$.pipe(
174
- map((formGroup: FormGroup) => getFilledControlCount(formGroup).toString())
175
- );
176
-
177
188
  this.changeDetectorRef.detectChanges();
178
189
  }
179
190
 
@@ -181,7 +192,7 @@ export class FilterComponent<T extends object>
181
192
  const fields = this.lastFormFields.map((x) => ({
182
193
  ...x,
183
194
  label:
184
- x.name === this.fulltextFieldName ? 'Full Text' : x.label || x.name,
195
+ x.name === this.fulltextFieldName ? 'Fulltext' : x.label ?? x.name,
185
196
  }));
186
197
 
187
198
  const formGroup = generateFormGroup(
@@ -192,7 +203,8 @@ export class FilterComponent<T extends object>
192
203
  );
193
204
  formGroup.patchValue(this.formGroup.value);
194
205
  this.dialogService.showDialog({
195
- headerIcon: 'pi pi-filter',
206
+ title: 'Set filters',
207
+ headerIcon: this.icons.filter,
196
208
  severity: 'primary',
197
209
  componentType: GenericFormComponent,
198
210
  data: {
@@ -213,7 +225,7 @@ export class FilterComponent<T extends object>
213
225
  this.dialogService.showDialog({
214
226
  headerIcon: 'pi pi-search',
215
227
  severity: 'primary',
216
- innerHTML: 'hovno',
228
+ innerHTML: '<p>Search</p>',
217
229
  confirmButtonFn: () => this.submitValue(),
218
230
  confirmButtonText: 'Apply',
219
231
  cancelButtonFn: () => this.clear(),
@@ -227,7 +239,7 @@ export class FilterComponent<T extends object>
227
239
  this.formGroup.patchValue(data);
228
240
  }
229
241
 
230
- registerOnChange(fn: (value: FilterValueType) => void): void {
242
+ registerOnChange(fn: (value: FilterValueType | undefined) => void): void {
231
243
  this.onChange = fn;
232
244
  }
233
245
 
@@ -254,4 +266,19 @@ export class FilterComponent<T extends object>
254
266
  this.formGroup.reset();
255
267
  this.submitValue();
256
268
  }
269
+
270
+ private convertFilter(
271
+ value: FilterValueType | undefined
272
+ ): FilterValueType | undefined {
273
+ if (value == undefined) {
274
+ return undefined;
275
+ }
276
+
277
+ const isEmpty = isFilterEmpty(value);
278
+ if (isEmpty) {
279
+ return undefined;
280
+ }
281
+
282
+ return value;
283
+ }
257
284
  }
@@ -0,0 +1,18 @@
1
+ import { FormGroup } from '@angular/forms';
2
+
3
+ export function getFilledControlCount(formGroup: FormGroup): number {
4
+ let count = 0;
5
+ Object.keys(formGroup.controls).forEach((key) => {
6
+ const control = formGroup.get(key);
7
+ if (control?.value) {
8
+ if (typeof control.value === 'boolean') {
9
+ count++;
10
+ }
11
+ if (typeof control.value === 'string' && control.value.trim() !== '') {
12
+ count++;
13
+ }
14
+ }
15
+ });
16
+
17
+ return count;
18
+ }
@@ -1,3 +1,2 @@
1
1
  export * from './filter.component';
2
- export * from './directives/table-filter.directive';
3
2
  export * from './directives/filter-field.directive';
@@ -0,0 +1,97 @@
1
+ @if (!type || type === fieldTypes.text) {
2
+ <v-textfield
3
+ [label]="label"
4
+ [floatLabel]="floatLabel === true"
5
+ [size]="size"
6
+ [formControl]="formControl"
7
+ />
8
+ } @else if (type === fieldTypes.dropdown && !datasource) {
9
+ <v-dropdown
10
+ [label]="!floatLabel ? label : ''"
11
+ [floatLabel]="floatLabel ? label : ''"
12
+ [testId]="testId"
13
+ [options]="options"
14
+ [optionLabel]="optionLabel"
15
+ [optionValue]="optionValue ?? optionLabel"
16
+ [loading]="loading"
17
+ [forceMinWidth]="true"
18
+ [formControl]="formControl"
19
+ [showFilter]="showFilter ?? false"
20
+ [localSearch]="localSearch ?? false"
21
+ (changeEvent)="changed.emit($event)"
22
+ (clearEvent)="cleared.emit($event)"
23
+ (lazyLoadEvent)="lazyLoad.emit($any($event))"
24
+ (showEvent)="showed.emit($event)"
25
+ />
26
+ } @else if (type === fieldTypes.dropdown && datasource) {
27
+ <v-dropdown
28
+ useDatasource
29
+ [forceMinWidth]="true"
30
+ [datasource]="datasource"
31
+ [optionLabel]="optionLabel"
32
+ [optionValue]="optionValue ?? optionLabel"
33
+ [label]="!floatLabel ? label : ''"
34
+ [floatLabel]="floatLabel ? label : ''"
35
+ [testId]="testId"
36
+ [loading]="loading"
37
+ [formControl]="formControl"
38
+ [showFilter]="showFilter ?? false"
39
+ [filterField]="filterField ?? 'fulltext'"
40
+ [localSearch]="localSearch ?? false"
41
+ (changeEvent)="changed.emit($event)"
42
+ (clearEvent)="cleared.emit($event)"
43
+ (lazyLoadEvent)="lazyLoad.emit($any($event))"
44
+ (showEvent)="showed.emit($event)"
45
+ />
46
+ } @else if (type === fieldTypes.multiselect && !datasource) {
47
+ <v-multiselect
48
+ [label]="!floatLabel ? label : ''"
49
+ [floatLabel]="floatLabel ? label : ''"
50
+ [testId]="testId"
51
+ [options]="options"
52
+ [optionLabel]="optionLabel"
53
+ [optionValue]="optionValue ?? optionLabel"
54
+ [loading]="loading"
55
+ [formControl]="formControl"
56
+ (changeEvent)="changed.emit($event)"
57
+ (clearEvent)="cleared.emit($event)"
58
+ (lazyLoadEvent)="lazyLoad.emit($any($event))"
59
+ (showEvent)="showed.emit($event)"
60
+ />
61
+ } @else if (type === fieldTypes.multiselect && datasource) {
62
+ <v-multiselect
63
+ useDatasource
64
+ [datasource]="datasource"
65
+ [optionLabel]="optionLabel"
66
+ [optionValue]="optionValue ?? optionLabel"
67
+ [label]="!floatLabel ? label : ''"
68
+ [floatLabel]="floatLabel ? label : ''"
69
+ [testId]="testId"
70
+ [loading]="loading"
71
+ [formControl]="formControl"
72
+ (changeEvent)="changed.emit($event)"
73
+ (clearEvent)="cleared.emit($event)"
74
+ (lazyLoadEvent)="lazyLoad.emit($any($event))"
75
+ (showEvent)="showed.emit($event)"
76
+ />
77
+ } @else if (type === fieldTypes.checkbox) {
78
+ <v-tristatecheckbox
79
+ [label]="label"
80
+ [testId]="testId"
81
+ [formControl]="formControl"
82
+ />
83
+ } @else if (type === fieldTypes.simplecheckbox) {
84
+ <v-checkbox
85
+ [label]="label"
86
+ [testId]="testId"
87
+ [formControl]="formControl"
88
+ />
89
+ } @else if (type === fieldTypes.calendar) {
90
+ <v-calendar
91
+ [label]="!floatLabel ? label : ''"
92
+ [floatLabel]="floatLabel ? label : ''"
93
+ [testId]="testId"
94
+ [formControl]="formControl"
95
+ [icon]="icons.calendar"
96
+ />
97
+ }
@@ -1,3 +1,4 @@
1
+ import { CommonModule } from '@angular/common';
1
2
  import {
2
3
  ChangeDetectionStrategy,
3
4
  Component,
@@ -7,34 +8,42 @@ import {
7
8
  } from '@angular/core';
8
9
  import { ReactiveFormsModule } from '@angular/forms';
9
10
  import {
11
+ DatasourceType,
10
12
  FilterEvent,
11
13
  LazyLoadEvent,
12
14
  } from '@verisoft/core';
13
15
  import {
14
16
  BaseFormInputComponent,
17
+ DatasourceDirective,
15
18
  FieldSize,
16
19
  FieldSizeType,
17
20
  GENERIC_FIELD_COMPONENT_TOKEN,
18
21
  GenericFieldCore,
22
+ GenericFieldType,
23
+ GenericFieldTypeType,
19
24
  } from '@verisoft/ui-core';
20
- import { CalendarComponent } from '../calendar/calendar.component';
21
- import { DropdownComponent } from '../dropdown';
22
- import { MultiselectComponent } from '../multiselect/multiselect.component';
23
- import { TextfieldComponent } from '../textfield/textfield.component';
24
- import { TristatecheckboxComponent } from '../tristatecheckbox';
25
- import { GenericFieldType, GenericFieldTypeType } from './generic-field.model';
25
+ import { Icons } from '../../../icons';
26
+ import { CalendarComponent } from '../../calendar';
27
+ import { CheckboxComponent } from '../../checkbox';
28
+ import { DropdownComponent } from '../../dropdown';
29
+ import { MultiselectComponent } from '../../multiselect';
30
+ import { TextfieldComponent } from '../../textfield';
31
+ import { TristatecheckboxComponent } from '../../tristatecheckbox';
26
32
 
27
33
  @Component({
28
34
  selector: 'v-generic-field',
29
35
  standalone: true,
30
36
  imports: [
37
+ CommonModule,
31
38
  DropdownComponent,
32
39
  CalendarComponent,
33
40
  TristatecheckboxComponent,
34
41
  MultiselectComponent,
35
42
  TextfieldComponent,
36
43
  ReactiveFormsModule,
37
- ],
44
+ CheckboxComponent,
45
+ DatasourceDirective,
46
+ ],
38
47
  providers: [
39
48
  {
40
49
  provide: GENERIC_FIELD_COMPONENT_TOKEN,
@@ -52,11 +61,11 @@ export class GenericFieldComponent<T>
52
61
 
53
62
  @Input() floatLabel?: boolean;
54
63
 
55
- @Input() optionLabel?: string;
64
+ @Input() optionLabel: string | undefined;
56
65
 
57
- @Input() optionValue?: string;
66
+ @Input() optionValue: string | undefined;
58
67
 
59
- @Input() options?: T[];
68
+ @Input() options: T[] | undefined;
60
69
 
61
70
  @Input() size?: FieldSizeType = FieldSize.medium;
62
71
 
@@ -66,6 +75,14 @@ export class GenericFieldComponent<T>
66
75
 
67
76
  @Input() filter = true;
68
77
 
78
+ @Input() datasource?: DatasourceType<T>
79
+
80
+ @Input() filterField?: string;
81
+
82
+ @Input() showFilter?: boolean;
83
+
84
+ @Input() localSearch?: boolean;
85
+
69
86
  @Output() changed = new EventEmitter<any>();
70
87
  @Output() showed = new EventEmitter<any>();
71
88
  @Output() cleared = new EventEmitter<any>();
@@ -73,4 +90,5 @@ export class GenericFieldComponent<T>
73
90
  @Output() filtered = new EventEmitter<FilterEvent>();
74
91
 
75
92
  fieldTypes = GenericFieldType;
93
+ icons = Icons;
76
94
  }
@@ -1,2 +1 @@
1
1
  export * from './generic-field.component';
2
- export * from './generic-field.model';
@@ -0,0 +1,46 @@
1
+ @if (formGroupComputed) {
2
+ <div
3
+ class="v-generic-form"
4
+ [ngClass]="showAsRow ? 'd-flex flex-row' : 'row'"
5
+ [formGroup]="formGroupComputed"
6
+ >
7
+ @for(field of fields; track field) { @if (columnClass) {
8
+ <div class="v-generic-form__column {{ columnClass }}">
9
+ <v-generic-field
10
+ [type]="field.type"
11
+ [label]="field.label ?? 'NOT SET' | translate"
12
+ [floatLabel]="field.floatLabel"
13
+ [testId]="field.testId"
14
+ [options]="field.options"
15
+ [optionLabel]="field.optionLabel"
16
+ [optionValue]="field.optionValue ?? field.optionLabel"
17
+ [options]="field.options"
18
+ [size]="field.size"
19
+ [formControlName]="field.name"
20
+ [datasource]="field.datasource"
21
+ [showFilter]="field.showFilter"
22
+ [filterField]="field.filterField"
23
+ [localSearch]="field.localSearch"
24
+ ></v-generic-field>
25
+ </div>
26
+ } @else {
27
+ <v-generic-field
28
+ class="me-4"
29
+ [type]="field.type"
30
+ [label]="field.label ?? 'NOT SET' | translate"
31
+ [floatLabel]="field.floatLabel"
32
+ [testId]="field.testId"
33
+ [options]="field.options"
34
+ [optionLabel]="field.optionLabel"
35
+ [optionValue]="field.optionValue ?? field.optionLabel"
36
+ [options]="field.options"
37
+ [size]="field.size"
38
+ [formControlName]="field.name"
39
+ [datasource]="field.datasource"
40
+ [showFilter]="field.showFilter"
41
+ [filterField]="field.filterField"
42
+ [localSearch]="field.localSearch"
43
+ ></v-generic-field>
44
+ } }
45
+ </div>
46
+ }
@@ -1,3 +1,4 @@
1
+ import { CommonModule } from '@angular/common';
1
2
  import {
2
3
  ChangeDetectionStrategy,
3
4
  Component,
@@ -6,17 +7,23 @@ import {
6
7
  SimpleChanges,
7
8
  } from '@angular/core';
8
9
  import { ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
10
+ import { TranslateModule } from '@ngx-translate/core';
11
+ import { GenericFieldDefinition } from '@verisoft/ui-core';
9
12
  import { GenericFieldComponent } from '../generic-field';
10
13
  import {
11
14
  generateFormGroup,
12
- GenericFieldDefinition,
13
15
  getColumnClass,
14
16
  } from './generic-form.model';
15
17
 
16
18
  @Component({
17
19
  selector: 'v-generic-form',
18
20
  standalone: true,
19
- imports: [GenericFieldComponent, ReactiveFormsModule],
21
+ imports: [
22
+ CommonModule,
23
+ GenericFieldComponent,
24
+ ReactiveFormsModule,
25
+ TranslateModule,
26
+ ],
20
27
  templateUrl: './generic-form.component.html',
21
28
  changeDetection: ChangeDetectionStrategy.OnPush,
22
29
  })
@@ -27,6 +34,8 @@ export class GenericFormComponent implements OnChanges {
27
34
 
28
35
  @Input() columns?: number;
29
36
 
37
+ @Input() showAsRow!: boolean;
38
+
30
39
  formGroupComputed!: UntypedFormGroup;
31
40
 
32
41
  columnClass?: string;
@@ -1,24 +1,8 @@
1
1
  import {
2
2
  UntypedFormControl,
3
3
  UntypedFormGroup,
4
- ValidatorFn,
5
4
  } from '@angular/forms';
6
- import { FieldSizeType } from '@verisoft/ui-core';
7
- import { GenericFieldTypeType } from '../generic-field';
8
-
9
- export interface GenericFieldDefinition {
10
- validator?: ValidatorFn[];
11
- type?: GenericFieldTypeType;
12
- label?: string;
13
- floatLabel?: boolean;
14
- name: string;
15
- optionLabel?: string;
16
- optionValue?: string;
17
- options?: unknown[];
18
- value?: unknown;
19
- testId?: string;
20
- size?: FieldSizeType;
21
- }
5
+ import { GenericFieldDefinition } from '@verisoft/ui-core';
22
6
 
23
7
  export function generateFormGroup(
24
8
  fields: GenericFieldDefinition[] | undefined,
@@ -38,9 +22,17 @@ export function generateFormGroup(
38
22
  field.name,
39
23
  new UntypedFormControl(field.value, field.validator)
40
24
  );
41
- } else {
25
+ } else if (control && control.value !== field.value) {
26
+ control.setValue(field.value);
27
+ control.setValidators(field.validator ?? null);
28
+ }
29
+ else {
42
30
  control.setValidators(field.validator ?? null);
43
31
  }
32
+
33
+ if (field.readonly && (control || formGroup.get(field.name))) {
34
+ formGroup.get(field.name)?.disable();
35
+ }
44
36
  });
45
37
  if (!inputGroupChanged) {
46
38
  for (const field in formGroup.controls) {
@@ -71,6 +63,6 @@ export function getColumnClass(value?: number): string | undefined {
71
63
  case 6:
72
64
  return 'col-12 col-md-2';
73
65
  }
74
-
66
+
75
67
  return 'col-12 col-md-1';
76
68
  }
@@ -0,0 +1,6 @@
1
+ export * from './action-button-group';
2
+ export * from './filter';
3
+ export * from './feature-list';
4
+ export * from './generic-field';
5
+ export * from './generic-form';
6
+ export * from './dynamic-component';
@@ -16,16 +16,14 @@
16
16
  </ng-container>
17
17
  <div
18
18
  [ngClass]="{
19
- 'v-side-menu-body__mobile':
20
- screenSizeService.isMobileBlock | async,
21
- 'v-side-menu-body':
22
- (screenSizeService.isMobileBlock | async) === false
19
+ 'v-side-menu-body__mobile': screenSizeService.isMobileBlock | async,
20
+ 'v-side-menu-body': (screenSizeService.isMobileBlock | async) === false
23
21
  }"
24
22
  class="text-center"
25
23
  >
26
24
  <p-tree
27
25
  selectionMode="single"
28
- [value]="menuService.menuItems$ | async"
26
+ [value]="items"
29
27
  (onNodeExpand)="onSelectionChange($event)"
30
28
  (onNodeCollapse)="onSelectionChange($event)"
31
29
  (onNodeSelect)="onNodeSelect($event)"
@@ -36,13 +34,12 @@
36
34
  class="text-center py-3 d-flex justify-content-end flex-column support"
37
35
  >
38
36
  <hr class="mx-4 divider" />
39
- <p-button
37
+ <v-button
40
38
  class="support-button"
41
- label="Support"
42
- [text]="true"
39
+ [label]="isMinimalized ? undefined : 'Support'"
43
40
  severity="primary"
44
- icon="pi pi-question-circle"
45
- ></p-button>
41
+ [icon]="icons.questionCircle"
42
+ ></v-button>
46
43
  </div>
47
44
  </div>
48
45
  <div
@@ -12,11 +12,11 @@ import {
12
12
  } from '@angular/core';
13
13
  import { Router, RouterModule } from '@angular/router';
14
14
  import { TranslateModule } from '@ngx-translate/core';
15
- import { ISideMenu, MenuItem, SideMenuService, UnsubscribeComponent } from '@verisoft/ui-core';
15
+ import { MenuItem, ScreenSizeService, SideMenuCore, SideMenuService, UnsubscribeComponent } from '@verisoft/ui-core';
16
16
  import { AvatarModule } from 'primeng/avatar';
17
- import { ButtonModule } from 'primeng/button';
18
17
  import { TreeModule, TreeNodeSelectEvent } from 'primeng/tree';
19
- import { ScreenSizeService } from '../../services/screen-size.service';
18
+ import { Icons } from '../../icons';
19
+ import { ButtonComponent } from '../button';
20
20
 
21
21
  @Component({
22
22
  selector: 'v-side-menu',
@@ -26,7 +26,7 @@ import { ScreenSizeService } from '../../services/screen-size.service';
26
26
  AsyncPipe,
27
27
  NgIf,
28
28
  TreeModule,
29
- ButtonModule,
29
+ ButtonComponent,
30
30
  TranslateModule,
31
31
  AvatarModule,
32
32
  RouterModule,
@@ -37,9 +37,9 @@ import { ScreenSizeService } from '../../services/screen-size.service';
37
37
  })
38
38
  export class SideMenuComponent
39
39
  extends UnsubscribeComponent
40
- implements ISideMenu, AfterContentInit
40
+ implements SideMenuCore, AfterContentInit
41
41
  {
42
- @Input() item: MenuItem[] = [];
42
+ @Input() items: MenuItem[] = [];
43
43
  @Input() logoUrl = '';
44
44
  @Input() userName!: string;
45
45
  @Input() userRole!: any | any[] | undefined;
@@ -50,6 +50,7 @@ export class SideMenuComponent
50
50
 
51
51
  menuService = inject(SideMenuService);
52
52
  router = inject(Router);
53
+ icons = Icons;
53
54
 
54
55
  protected screenSizeService = inject(ScreenSizeService);
55
56
  protected logoRouterLink!: string;
@@ -4,7 +4,6 @@
4
4
  [label]="label"
5
5
  [tooltip]="tooltip"
6
6
  [required]="isRequired()"
7
- [ngControl]="ngControl"
8
7
  [testId]="testId"
9
8
  >
10
9
  <p-slider
@@ -15,5 +14,6 @@
15
14
  [min]="min"
16
15
  [max]="max"
17
16
  />
17
+ <v-validation-message [ngControl]="ngControl"></v-validation-message>
18
18
  </v-form-field>
19
- </div>
19
+ </div>
@@ -14,6 +14,7 @@ import {
14
14
  } from '@angular/forms';
15
15
  import { BaseFormInputComponent, BaseInputControls, SLIDER_COMPONENT_TOKEN, SliderCore } from '@verisoft/ui-core';
16
16
  import { SliderModule } from 'primeng/slider';
17
+ import { ErrorComponent } from '../errors';
17
18
  import { FormFieldComponent } from '../form-field';
18
19
 
19
20
  @Component({
@@ -24,6 +25,7 @@ import { FormFieldComponent } from '../form-field';
24
25
  SliderModule,
25
26
  ReactiveFormsModule,
26
27
  FormFieldComponent,
28
+ ErrorComponent
27
29
  ],
28
30
  templateUrl: './slider.component.html',
29
31
  changeDetection: ChangeDetectionStrategy.OnPush,