@verisoft/ui-govcz 20.0.0 → 20.1.0

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 (228) hide show
  1. package/.eslintrc.json +60 -0
  2. package/assets/i18n/cs.json +2 -0
  3. package/assets/i18n/en.json +2 -0
  4. package/jest.config.ts +21 -0
  5. package/ng-package.json +28 -0
  6. package/package.json +9 -19
  7. package/project.json +49 -0
  8. package/src/config.d.ts +10 -0
  9. package/src/index.ts +1 -0
  10. package/src/lib/components/breadcrumb/breadcrumb.component.html +25 -0
  11. package/src/lib/components/breadcrumb/breadcrumb.component.scss +0 -0
  12. package/src/lib/components/breadcrumb/breadcrumb.component.spec.ts +21 -0
  13. package/src/lib/components/breadcrumb/breadcrumb.component.ts +28 -0
  14. package/src/lib/components/breadcrumb/index.ts +1 -0
  15. package/src/lib/components/button/button.component.html +28 -0
  16. package/src/lib/components/button/button.component.scss +21 -0
  17. package/src/lib/components/button/button.component.ts +77 -0
  18. package/src/lib/components/button/index.ts +1 -0
  19. package/src/lib/components/calendar/calendar.component.html +28 -0
  20. package/src/lib/components/calendar/calendar.component.scss +0 -0
  21. package/src/lib/components/calendar/calendar.component.ts +77 -0
  22. package/src/lib/components/calendar/index.ts +1 -0
  23. package/src/lib/components/checkbox/checkbox.component.html +23 -0
  24. package/src/lib/components/checkbox/checkbox.component.scss +0 -0
  25. package/src/lib/components/checkbox/checkbox.component.ts +61 -0
  26. package/src/lib/components/checkbox/index.ts +1 -0
  27. package/src/lib/components/confirm-dialog/confirm-dialog.component.html +50 -0
  28. package/src/lib/components/confirm-dialog/confirm-dialog.component.scss +4 -0
  29. package/src/lib/components/confirm-dialog/confirm-dialog.component.ts +79 -0
  30. package/src/lib/components/confirm-dialog/index.ts +1 -0
  31. package/src/lib/components/dropdown/dropdown-item.component.html +8 -0
  32. package/src/lib/components/dropdown/dropdown-item.component.ts +18 -0
  33. package/src/lib/components/dropdown/dropdown.component.html +91 -0
  34. package/src/lib/components/dropdown/dropdown.component.scss +108 -0
  35. package/src/lib/components/dropdown/dropdown.component.spec.ts +21 -0
  36. package/src/lib/components/dropdown/dropdown.component.ts +296 -0
  37. package/src/lib/components/dropdown/dropdown.model.ts +6 -0
  38. package/src/lib/components/dropdown/index.ts +1 -0
  39. package/src/lib/components/dropdown-button/dropdown-button.component.html +31 -0
  40. package/src/lib/components/dropdown-button/dropdown-button.component.ts +34 -0
  41. package/src/lib/components/dropdown-button/index.ts +1 -0
  42. package/src/lib/components/errors/error.component.html +11 -0
  43. package/src/lib/components/errors/error.component.scss +0 -0
  44. package/src/lib/components/errors/error.component.spec.ts +19 -0
  45. package/src/lib/components/errors/error.component.ts +29 -0
  46. package/src/lib/components/errors/index.ts +1 -0
  47. package/src/lib/components/feature-list/directives/feature-list-column.directive.ts +32 -0
  48. package/src/lib/components/feature-list/directives/feature-list-filter-field.directive.ts +8 -0
  49. package/src/lib/components/feature-list/feature-list-filter.pipe.ts +20 -0
  50. package/src/lib/components/feature-list/feature-list-page.component.ts +30 -0
  51. package/src/lib/components/feature-list/feature-list-page.model.ts +42 -0
  52. package/src/lib/components/feature-list/feature-list.component.html +67 -0
  53. package/src/lib/components/feature-list/feature-list.component.scss +10 -0
  54. package/src/lib/components/feature-list/feature-list.component.ts +360 -0
  55. package/src/lib/components/feature-list/index.ts +5 -0
  56. package/src/lib/components/filter/directives/filter-field.directive.ts +35 -0
  57. package/src/lib/components/filter/filter.component.html +78 -0
  58. package/src/lib/components/filter/filter.component.scss +32 -0
  59. package/src/lib/components/filter/filter.component.spec.ts +21 -0
  60. package/src/lib/components/filter/filter.component.stories.ts +23 -0
  61. package/src/lib/components/filter/filter.component.ts +286 -0
  62. package/src/lib/components/filter/filter.model.ts +18 -0
  63. package/src/lib/components/filter/index.ts +2 -0
  64. package/src/lib/components/form-field/form-field.component.html +14 -0
  65. package/src/lib/components/form-field/form-field.component.scss +0 -0
  66. package/src/lib/components/form-field/form-field.component.spec.ts +21 -0
  67. package/src/lib/components/form-field/form-field.component.ts +76 -0
  68. package/src/lib/components/form-field/index.ts +1 -0
  69. package/src/lib/components/header/header.component.html +122 -0
  70. package/src/lib/components/header/header.component.scss +0 -0
  71. package/src/lib/components/header/header.component.ts +90 -0
  72. package/src/lib/components/header/index.ts +1 -0
  73. package/src/lib/components/icon/icon.component.html +11 -0
  74. package/src/lib/components/icon/icon.component.scss +20 -0
  75. package/src/lib/components/icon/icon.component.ts +110 -0
  76. package/src/lib/components/icon/index.ts +2 -0
  77. package/src/lib/components/index.ts +37 -0
  78. package/src/lib/components/input-group/index.ts +1 -0
  79. package/src/lib/components/input-group/input-group.component.html +41 -0
  80. package/src/lib/components/input-group/input-group.component.scss +0 -0
  81. package/src/lib/components/input-group/input-group.component.ts +75 -0
  82. package/src/lib/components/loader/index.ts +1 -0
  83. package/src/lib/components/loader/loader.component.html +7 -0
  84. package/src/lib/components/loader/loader.component.scss +0 -0
  85. package/src/lib/components/loader/loader.component.spec.ts +21 -0
  86. package/src/lib/components/loader/loader.component.ts +33 -0
  87. package/src/lib/components/multiselect/index.ts +1 -0
  88. package/src/lib/components/multiselect/multiselect.component.html +21 -0
  89. package/src/lib/components/multiselect/multiselect.component.scss +0 -0
  90. package/src/lib/components/multiselect/multiselect.component.spec.ts +21 -0
  91. package/src/lib/components/multiselect/multiselect.component.ts +117 -0
  92. package/src/lib/components/number-input/index.ts +1 -0
  93. package/src/lib/components/number-input/number-input.component.html +48 -0
  94. package/src/lib/components/number-input/number-input.component.scss +0 -0
  95. package/src/lib/components/number-input/number-input.component.ts +80 -0
  96. package/src/lib/components/page-header/index.ts +1 -0
  97. package/src/lib/components/page-header/page-header.component.html +3 -0
  98. package/src/lib/components/page-header/page-header.component.scss +11 -0
  99. package/src/lib/components/page-header/page-header.component.spec.ts +21 -0
  100. package/src/lib/components/page-header/page-header.component.ts +27 -0
  101. package/src/lib/components/password/index.ts +1 -0
  102. package/src/lib/components/password/password.component.html +31 -0
  103. package/src/lib/components/password/password.component.scss +0 -0
  104. package/src/lib/components/password/password.component.spec.ts +21 -0
  105. package/src/lib/components/password/password.component.ts +83 -0
  106. package/src/lib/components/radiobutton/index.ts +1 -0
  107. package/src/lib/components/radiobutton/radiobutton.component.html +23 -0
  108. package/src/lib/components/radiobutton/radiobutton.component.scss +0 -0
  109. package/src/lib/components/radiobutton/radiobutton.component.ts +61 -0
  110. package/src/lib/components/search/index.ts +1 -0
  111. package/src/lib/components/search/search.component.html +23 -0
  112. package/src/lib/components/search/search.component.scss +0 -0
  113. package/src/lib/components/search/search.component.ts +45 -0
  114. package/src/lib/components/section/index.ts +1 -0
  115. package/src/lib/components/section/section.component.html +26 -0
  116. package/src/lib/components/section/section.component.scss +0 -0
  117. package/src/lib/components/section/section.component.ts +55 -0
  118. package/src/lib/components/side-menu/index.ts +2 -0
  119. package/src/lib/components/side-menu/side-menu.component.html +22 -0
  120. package/src/lib/components/side-menu/side-menu.component.scss +17 -0
  121. package/src/lib/components/side-menu/side-menu.component.ts +42 -0
  122. package/src/lib/components/side-menu/side-menu.module.ts +56 -0
  123. package/src/lib/components/snackbar/index.ts +2 -0
  124. package/src/lib/components/snackbar/services/snackbar.service.ts +73 -0
  125. package/src/lib/components/snackbar/snackbar.component.html +14 -0
  126. package/src/lib/components/snackbar/snackbar.component.scss +0 -0
  127. package/src/lib/components/snackbar/snackbar.component.spec.ts +21 -0
  128. package/src/lib/components/snackbar/snackbar.component.ts +44 -0
  129. package/src/lib/components/snackbar/snackbar.model.ts +10 -0
  130. package/src/lib/components/stepper/index.ts +1 -0
  131. package/src/lib/components/stepper/stepper.component.html +35 -0
  132. package/src/lib/components/stepper/stepper.component.scss +9 -0
  133. package/src/lib/components/stepper/stepper.component.ts +60 -0
  134. package/src/lib/components/switch/index.ts +1 -0
  135. package/src/lib/components/switch/switch.component.html +16 -0
  136. package/src/lib/components/switch/switch.component.scss +0 -0
  137. package/src/lib/components/switch/switch.component.ts +39 -0
  138. package/src/lib/components/tab-view/index.ts +2 -0
  139. package/src/lib/components/tab-view/tab-view-item.component.ts +23 -0
  140. package/src/lib/components/tab-view/tab-view.component.html +51 -0
  141. package/src/lib/components/tab-view/tab-view.component.scss +43 -0
  142. package/src/lib/components/tab-view/tab-view.component.ts +64 -0
  143. package/src/lib/components/tab-view/tab-view.module.ts +25 -0
  144. package/src/lib/components/table/index.ts +1 -0
  145. package/src/lib/components/table/table-pagination-info.component.html +9 -0
  146. package/src/lib/components/table/table-pagination-info.component.ts +22 -0
  147. package/src/lib/components/table/table.component.html +199 -0
  148. package/src/lib/components/table/table.component.scss +192 -0
  149. package/src/lib/components/table/table.component.ts +390 -0
  150. package/src/lib/components/table/table.model.ts +17 -0
  151. package/src/lib/components/table/table.models.ts +12 -0
  152. package/src/lib/components/tag/index.ts +3 -0
  153. package/src/lib/components/tag/tag.component.html +12 -0
  154. package/src/lib/components/tag/tag.component.scss +4 -0
  155. package/src/lib/components/tag/tag.component.ts +44 -0
  156. package/src/lib/components/tag/tag.model.ts +7 -0
  157. package/src/lib/components/textarea/index.ts +1 -0
  158. package/src/lib/components/textarea/textarea.component.html +50 -0
  159. package/src/lib/components/textarea/textarea.component.scss +0 -0
  160. package/src/lib/components/textarea/textarea.component.ts +77 -0
  161. package/src/lib/components/textfield/index.ts +1 -0
  162. package/src/lib/components/textfield/textfield.component.html +34 -0
  163. package/src/lib/components/textfield/textfield.component.scss +0 -0
  164. package/src/lib/components/textfield/textfield.component.ts +112 -0
  165. package/src/lib/components/tooltip/index.ts +1 -0
  166. package/src/lib/components/tooltip/tooltip.component.html +9 -0
  167. package/src/lib/components/tooltip/tooltip.component.ts +19 -0
  168. package/src/lib/icons.ts +36 -0
  169. package/src/lib/index.ts +5 -0
  170. package/src/lib/init.service.ts +11 -0
  171. package/src/lib/interceptors/http-error-message.interceptor.ts +45 -0
  172. package/src/lib/pages/bad-request-page/bad-request-page.component.html +5 -0
  173. package/src/lib/pages/bad-request-page/bad-request-page.component.scss +0 -0
  174. package/src/lib/pages/bad-request-page/bad-request-page.component.ts +14 -0
  175. package/src/lib/pages/error-page/error-page.component.html +5 -0
  176. package/src/lib/pages/error-page/error-page.component.scss +0 -0
  177. package/src/lib/pages/error-page/error-page.component.ts +31 -0
  178. package/src/lib/pages/error-page/error-page.constants.ts +19 -0
  179. package/src/lib/pages/index.ts +3 -0
  180. package/src/lib/pages/internal-server-error-page/internal-server-error-page.component.html +5 -0
  181. package/src/lib/pages/internal-server-error-page/internal-server-error-page.component.scss +0 -0
  182. package/src/lib/pages/internal-server-error-page/internal-server-error-page.component.ts +15 -0
  183. package/src/lib/pages/not-authenticated/index.ts +1 -0
  184. package/src/lib/pages/not-authenticated/not-authenticated.component.html +5 -0
  185. package/src/lib/pages/not-authenticated/not-authenticated.component.ts +13 -0
  186. package/src/lib/pages/not-authorized/index.ts +1 -0
  187. package/src/lib/pages/not-authorized/not-authorized.component.html +5 -0
  188. package/src/lib/pages/not-authorized/not-authorized.component.ts +17 -0
  189. package/src/lib/pages/not-found/index.ts +1 -0
  190. package/src/lib/pages/not-found/not-found.component.html +5 -0
  191. package/src/lib/pages/not-found/not-found.component.ts +17 -0
  192. package/src/lib/pages/not-found-page/not-found-page.component.html +6 -0
  193. package/src/lib/pages/not-found-page/not-found-page.component.scss +0 -0
  194. package/src/lib/pages/not-found-page/not-found-page.component.ts +15 -0
  195. package/src/lib/pipes/color/color.pipe.ts +24 -0
  196. package/src/lib/pipes/index.ts +3 -0
  197. package/src/lib/pipes/multiselect/multiselect-options.pipe.ts +61 -0
  198. package/src/lib/pipes/size/size.pipe.ts +24 -0
  199. package/src/sass/foundations/_colors.scss +4 -0
  200. package/src/sass/foundations/index.scss +1 -0
  201. package/src/sass/integrations/_bootstrap.scss +4 -0
  202. package/src/sass/integrations/index.scss +1 -0
  203. package/src/sass/main.scss +12 -0
  204. package/src/sass/overrides/_gov.scss +4 -0
  205. package/src/sass/overrides/index.scss +1 -0
  206. package/src/sass/tokens/_theme-dark.scss +18 -0
  207. package/src/sass/tokens/_theme-light.scss +9 -0
  208. package/src/sass/tokens/index.scss +3 -0
  209. package/src/sass/utils/_table_filter.scss +4 -0
  210. package/src/sass/utils/index.scss +2 -0
  211. package/{styles → src}/sass/vendors/_bootstrap.scss +1 -0
  212. package/src/test-setup.ts +8 -0
  213. package/tsconfig.json +30 -0
  214. package/tsconfig.lib.json +17 -0
  215. package/tsconfig.lib.prod.json +9 -0
  216. package/tsconfig.spec.json +16 -0
  217. package/fesm2022/verisoft-ui-govcz.mjs +0 -3582
  218. package/fesm2022/verisoft-ui-govcz.mjs.map +0 -1
  219. package/index.d.ts +0 -955
  220. package/styles/dist/main.css +0 -9
  221. package/styles/dist/main.css.map +0 -1
  222. package/styles/sass/main.scss +0 -10
  223. package/styles/sass/utils/_variables.scss +0 -3
  224. package/styles/sass/utils/index.scss +0 -2
  225. /package/{styles → src}/sass/header.css +0 -0
  226. /package/{styles → src}/sass/header.scss +0 -0
  227. /package/{styles → src}/sass/scrollbar.scss +0 -0
  228. /package/{styles → src}/sass/utils/_utils.scss +0 -0
@@ -0,0 +1,286 @@
1
+ import { AsyncPipe } from '@angular/common';
2
+ import {
3
+ AfterContentInit,
4
+ ChangeDetectionStrategy,
5
+ ChangeDetectorRef,
6
+ Component,
7
+ ContentChildren,
8
+ forwardRef,
9
+ inject,
10
+ Input,
11
+ OnChanges,
12
+ OnInit,
13
+ QueryList,
14
+ SimpleChanges,
15
+ } from '@angular/core';
16
+ import {
17
+ FormControl,
18
+ FormGroup,
19
+ NG_VALUE_ACCESSOR,
20
+ ReactiveFormsModule,
21
+ } from '@angular/forms';
22
+ import { TranslateModule } from '@ngx-translate/core';
23
+ import { BaseHttpService } from '@verisoft/core';
24
+ import {
25
+ ButtonShortCutDirective,
26
+ DEFAULT_DEBOUNCE_TIME,
27
+ DialogService,
28
+ FieldSize,
29
+ FILTER_COMPONENT_TOKEN,
30
+ FilterCore,
31
+ GenericFieldDefinition,
32
+ GovButtonType,
33
+ GovButtonTypeType,
34
+ isFilterEmpty,
35
+ ScreenSizeService,
36
+ UnsubscribeComponent,
37
+ } from '@verisoft/ui-core';
38
+ import {
39
+ BehaviorSubject,
40
+ combineLatestWith,
41
+ debounceTime,
42
+ distinctUntilChanged,
43
+ map,
44
+ Observable,
45
+ startWith,
46
+ takeUntil,
47
+ } from 'rxjs';
48
+ import { Icons } from '../../icons';
49
+ import { ButtonComponent } from '../button';
50
+ import { TextfieldComponent } from '../textfield';
51
+ import { generateFormGroup, GenericFormComponent } from '../shared-components/generic-form';
52
+ import { FilterFieldDirective } from './directives/filter-field.directive';
53
+ import { getFilledControlCount } from './filter.model';
54
+
55
+ type FilterValueType = { [key: string]: unknown };
56
+
57
+ @Component({
58
+ selector: 'v-filter',
59
+ imports: [
60
+ AsyncPipe,
61
+ ReactiveFormsModule,
62
+ TranslateModule,
63
+ TextfieldComponent,
64
+ GenericFormComponent,
65
+ ButtonComponent,
66
+ ButtonShortCutDirective,
67
+ ],
68
+ providers: [
69
+ {
70
+ provide: NG_VALUE_ACCESSOR,
71
+ useExisting: forwardRef(() => FilterComponent),
72
+ multi: true,
73
+ },
74
+ {
75
+ provide: FILTER_COMPONENT_TOKEN,
76
+ useExisting: FilterComponent,
77
+ },
78
+ ],
79
+ templateUrl: './filter.component.html',
80
+ styleUrl: './filter.component.scss',
81
+ changeDetection: ChangeDetectionStrategy.OnPush
82
+ })
83
+ export class FilterComponent<T extends object>
84
+ extends UnsubscribeComponent
85
+ implements OnChanges, OnInit, AfterContentInit, FilterCore
86
+ {
87
+ @ContentChildren(FilterFieldDirective)
88
+ fieldDeclarations!: QueryList<FilterFieldDirective>;
89
+
90
+ @Input() fields: GenericFieldDefinition[] = [];
91
+
92
+ @Input() filters: GenericFieldDefinition[] = [];
93
+
94
+ @Input() title?: string;
95
+
96
+ @Input() total?: number;
97
+
98
+ @Input() recordsText = 'FILTER.RECORDS';
99
+
100
+ @Input() showRecords = true;
101
+
102
+ @Input() fulltextFieldName = 'searchField';
103
+
104
+ @Input() showFulltext = true;
105
+
106
+ @Input() showFilters = true;
107
+
108
+ @Input() autoBind = true;
109
+
110
+ @Input() applyLabel = 'Apply';
111
+
112
+ @Input() clearLabel = 'Clear';
113
+
114
+ @Input() buttonType: GovButtonTypeType = GovButtonType.solid;
115
+
116
+ @Input() buttonOutlined = false;
117
+
118
+ @Input() debounceTime?: number = DEFAULT_DEBOUNCE_TIME;
119
+
120
+ @Input() defaultExpanded = false;
121
+
122
+ icons = Icons;
123
+
124
+ protected isExpanded = false;
125
+
126
+ fieldDefinitios$?: Observable<GenericFieldDefinition[]>;
127
+
128
+ formGroup$?: Observable<FormGroup>;
129
+
130
+ simpleFormFieldDefinitions$?: Observable<GenericFieldDefinition[]>;
131
+
132
+ private get searchField(): GenericFieldDefinition {
133
+ return {
134
+ name: this.fulltextFieldName,
135
+ };
136
+ }
137
+
138
+ private onTouch?: () => void;
139
+
140
+ private onChange?: (value: FilterValueType | undefined) => void;
141
+
142
+ private inputFields$ = new BehaviorSubject<
143
+ GenericFieldDefinition[] | undefined
144
+ >([...this.fields ?? [], ...this.filters ?? []]);
145
+
146
+ FieldSize = FieldSize;
147
+
148
+ protected screenSizeService = inject(ScreenSizeService);
149
+ protected changeDetectorRef = inject(ChangeDetectorRef);
150
+ protected dialogService = inject(DialogService);
151
+
152
+ service!: BaseHttpService<T>;
153
+
154
+ formGroup = new FormGroup({});
155
+
156
+ filledFiltersCount$: Observable<string> = this.formGroup.valueChanges.pipe(
157
+ startWith(this.formGroup),
158
+ map(() => getFilledControlCount(this.formGroup).toString())
159
+ );
160
+
161
+ private lastFormFields: GenericFieldDefinition[] = [];
162
+
163
+ ngOnInit(): void {
164
+ this.isExpanded = this.defaultExpanded;
165
+ this.formGroup.valueChanges
166
+ .pipe(
167
+ takeUntil(this.destroyed$),
168
+ debounceTime(this.debounceTime ?? DEFAULT_DEBOUNCE_TIME),
169
+ map((x) => this.convertFilter(x)),
170
+ distinctUntilChanged()
171
+ )
172
+ .subscribe((value) => {
173
+ this.onChange?.(value);
174
+ });
175
+ }
176
+
177
+ ngOnChanges(changes: SimpleChanges): void {
178
+ if (changes['total']) {
179
+ this.changeDetectorRef.markForCheck();
180
+ }
181
+ if (changes['fields'] || changes['filters']) {
182
+ this.inputFields$.next([...this.fields ?? [], ...this.filters ?? []]);
183
+ }
184
+ }
185
+
186
+ ngAfterContentInit(): void {
187
+ const fieldDeclaratios$: Observable<GenericFieldDefinition[]> =
188
+ this.fieldDeclarations.changes.pipe(
189
+ startWith({}),
190
+ map(() => this.fieldDeclarations.toArray())
191
+ );
192
+
193
+ this.fieldDefinitios$ = this.inputFields$.pipe(
194
+ combineLatestWith(fieldDeclaratios$),
195
+ map(([inputs, views]) => {
196
+ this.lastFormFields = [this.searchField, ...(inputs ?? []), ...views];
197
+ return this.lastFormFields;
198
+ })
199
+ );
200
+
201
+ this.simpleFormFieldDefinitions$ = this.fieldDefinitios$.pipe(
202
+ map((fields) => {
203
+ return fields
204
+ .filter((x) => x.name !== this.fulltextFieldName)
205
+ .map((x) => ({ ...x, floatLabel: false, size: x.size ?? FieldSize.medium }));
206
+ })
207
+ );
208
+
209
+ this.formGroup$ = this.fieldDefinitios$.pipe(
210
+ map((fields) => {
211
+ const group = generateFormGroup(fields, this.formGroup, undefined, false);
212
+ if (!group.get(this.fulltextFieldName) && this.showFulltext) {
213
+ group.addControl(this.fulltextFieldName, new FormControl(''));
214
+ }
215
+ return group;
216
+ })
217
+ );
218
+
219
+ this.changeDetectorRef.detectChanges();
220
+ }
221
+
222
+ protected toggleFilters() {
223
+ this.isExpanded = !this.isExpanded;
224
+ }
225
+
226
+ protected openSearch() {
227
+ this.dialogService.showDialog({
228
+ headerIcon: 'pi pi-search',
229
+ severity: 'primary',
230
+ innerHTML: '<p>Search</p>',
231
+ confirmButtonFn: () => this.submitValue(),
232
+ confirmButtonText: 'Apply',
233
+ cancelButtonFn: () => this.clear(),
234
+ cancelButtonText: 'Clear all',
235
+ showCancelButton: true,
236
+ closable: false,
237
+ });
238
+ }
239
+
240
+ writeValue(data: FilterValueType): void {
241
+ this.formGroup.patchValue(data);
242
+ }
243
+
244
+ registerOnChange(fn: (value: FilterValueType | undefined) => void): void {
245
+ this.onChange = fn;
246
+ }
247
+
248
+ registerOnTouched(fn: () => void): void {
249
+ this.onTouch = fn;
250
+ }
251
+
252
+ setDisabledState?(isDisabled: boolean): void {
253
+ isDisabled ? this.formGroup.disable() : this.formGroup.enable();
254
+ }
255
+
256
+ submitValue() {
257
+ if (!this.autoBind) {
258
+ this.onChange?.(this.formGroup.value);
259
+ }
260
+ }
261
+
262
+ setFilterValues(dialogFormGroup: FormGroup) {
263
+ this.formGroup.setValue(dialogFormGroup.value);
264
+ this.submitValue();
265
+ }
266
+
267
+ clear() {
268
+ this.formGroup.reset();
269
+ this.submitValue();
270
+ }
271
+
272
+ private convertFilter(
273
+ value: FilterValueType | undefined
274
+ ): FilterValueType | undefined {
275
+ if (value == undefined) {
276
+ return undefined;
277
+ }
278
+
279
+ const isEmpty = isFilterEmpty(value);
280
+ if (isEmpty) {
281
+ return undefined;
282
+ }
283
+
284
+ return value;
285
+ }
286
+ }
@@ -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
+ }
@@ -0,0 +1,2 @@
1
+ export * from './filter.component';
2
+ export * from './directives/filter-field.directive';
@@ -0,0 +1,14 @@
1
+ <gov-form-control>
2
+ @if (label) {
3
+ <gov-form-label
4
+ [slot]="labelSlot"
5
+ [size]="size | govSize"
6
+ >
7
+ {{ label }}
8
+ </gov-form-label>
9
+ }
10
+ <gov-form-group>
11
+ <ng-content />
12
+ </gov-form-group>
13
+ <v-validation-message [ngControl]="ngControl"></v-validation-message>
14
+ </gov-form-control>
@@ -0,0 +1,21 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { FormFieldComponent } from './form-field.component';
3
+
4
+ describe('FormFieldComponent', () => {
5
+ let component: FormFieldComponent<any>;
6
+ let fixture: ComponentFixture<FormFieldComponent<any>>;
7
+
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [FormFieldComponent],
11
+ }).compileComponents();
12
+
13
+ fixture = TestBed.createComponent(FormFieldComponent);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+ });
@@ -0,0 +1,76 @@
1
+
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ Input,
6
+ Optional,
7
+ Self,
8
+ } from '@angular/core';
9
+ import {
10
+ ControlValueAccessor,
11
+ NgControl,
12
+ ReactiveFormsModule,
13
+ } from '@angular/forms';
14
+ import { GovDesignSystemModule } from '@gov-design-system-ce/angular';
15
+ import {
16
+ BaseFormInputComponent,
17
+ FieldSize,
18
+ FieldSizeType,
19
+ FieldType,
20
+ IconPositionType,
21
+ IconPosition,
22
+ FormFieldCore,
23
+ FORM_FIELD_COMPONENT_TOKEN,
24
+ FieldTypeType,
25
+ SlotPosition,
26
+ SlotPositionType,
27
+ } from '@verisoft/ui-core';
28
+ import { Icons } from '../../icons';
29
+ import { GovSizePipe } from '../../pipes';
30
+ import { ErrorComponent } from '../errors';
31
+
32
+ @Component({
33
+ selector: 'v-form-field',
34
+ imports: [
35
+ ReactiveFormsModule,
36
+ GovDesignSystemModule,
37
+ GovSizePipe,
38
+ ErrorComponent
39
+ ],
40
+ templateUrl: './form-field.component.html',
41
+ styleUrl: './form-field.component.scss',
42
+ changeDetection: ChangeDetectionStrategy.OnPush,
43
+ providers: [
44
+ {
45
+ provide: FORM_FIELD_COMPONENT_TOKEN,
46
+ useExisting: FormFieldComponent,
47
+ },
48
+ ]
49
+ })
50
+ export class FormFieldComponent
51
+ extends BaseFormInputComponent
52
+ implements ControlValueAccessor, FormFieldCore
53
+ {
54
+ constructor(@Optional() @Self() ngControl: NgControl) {
55
+ super(ngControl);
56
+ }
57
+
58
+ @Input() floatLabel!: boolean;
59
+ @Input() type: FieldTypeType = FieldType.text;
60
+ @Input() minlength = 0;
61
+ @Input() maxlength = 524288;
62
+ @Input() prefix!: string;
63
+ @Input() sufix!: string;
64
+ @Input() message!: string;
65
+ @Input() name! : string;
66
+ @Input() role! : string;
67
+ @Input() autocorrect: 'on' | 'off' = 'on';
68
+ @Input() size: FieldSizeType | undefined = FieldSize.medium;
69
+ @Input() icon!: string;
70
+ @Input() iconPos: IconPositionType = IconPosition.right;
71
+ @Input() display!: 'flex' | 'block';
72
+ @Input() labelSlot: SlotPositionType = SlotPosition.top;
73
+ @Input() messageSlot: SlotPositionType = SlotPosition.bottom;
74
+
75
+ icons = Icons;
76
+ }
@@ -0,0 +1 @@
1
+ export * from './form-field.component';
@@ -0,0 +1,122 @@
1
+ <header class="gov-header">
2
+ <div class="gov-header__divider">
3
+ <div class="gov-header__content">
4
+ <gov-flex
5
+ justify-content="space-between"
6
+ align-items="center"
7
+ responsive="false"
8
+ >
9
+ <a
10
+ href="/"
11
+ class="gov-header__logo"
12
+ aria-label="Zpět na úvodní stránku"
13
+ >
14
+ <gov-flex
15
+ align-items="center"
16
+ gap="s"
17
+ responsive="false"
18
+ >
19
+ @if (logoUrl) {
20
+ <img
21
+ class="gov-header__logo-img"
22
+ src="{{ logoUrl }}"
23
+ width="125px"
24
+ height="43px"
25
+ alt="GAČR Logo"
26
+ >
27
+ }
28
+ </gov-flex>
29
+ </a>
30
+ </gov-flex>
31
+ <gov-flex
32
+ class="gov-header__action"
33
+ justify-content="space-between"
34
+ align-items="center"
35
+ gap="s"
36
+ >
37
+ <gov-button
38
+ color="primary"
39
+ size="m"
40
+ type="base"
41
+ >{{ userName }}</gov-button>
42
+ <ng-content></ng-content>
43
+ <ng-container *ngTemplateOutlet="
44
+ this.actionTemplate;
45
+ "></ng-container>
46
+ </gov-flex>
47
+ </div>
48
+ </div>
49
+ <div class="gov-header__navigation">
50
+ <nav
51
+ class="gov-navigation"
52
+ aria-label="Main navigation"
53
+ id="main-navigation"
54
+ >
55
+ <ul>
56
+ @for (tab of tabsService.menuItems$ | async; track tab; let index = $index) {
57
+ <li
58
+ *hasPermission="tab.data?.permissions ?? []"
59
+ class="gov-navigation--has-megamenu"
60
+ >
61
+ <gov-button
62
+ type="base"
63
+ color="primary"
64
+ size="l"
65
+ [attr.aria-label]="tab.label"
66
+ (gov-click)="
67
+ showOrHide(index, tab.children?.length ?? 0);
68
+ canRedirect(tab.url, !tab.children?.length)
69
+ "
70
+ >
71
+ {{ tab.label }}
72
+ @if (tab.children?.length) {
73
+ <gov-icon
74
+ slot="icon-end"
75
+ size="s"
76
+ [name]="canBeShown(index) ? 'chevron-up' : 'chevron-down'"
77
+ ></gov-icon>
78
+ }
79
+ </gov-button>
80
+ @if (canBeShown(index)) {
81
+ <ul
82
+ id="megamenu{{index}}"
83
+ class="gov-mega-menu gov-header__submenu"
84
+ [attr.aria-hidden]="canBeShown(index)"
85
+ >
86
+ @for (child of tab.children; track child) {
87
+ <li
88
+ *hasPermission="child.data?.permissions ?? []"
89
+ class="gov-mega-menu__heading"
90
+ >
91
+ <a
92
+ [routerLink]="child.url"
93
+ (click)="showOrHide(index)"
94
+ >
95
+ @if (child.icon) {
96
+ <gov-icon
97
+ [name]="child.icon"
98
+ size="m"
99
+ ></gov-icon>
100
+ }
101
+ <span>{{ child.label }}</span>
102
+ </a>
103
+ @if (child.children) { @for(miniChild of child.children; track miniChild) {
104
+ <ul>
105
+ <li *hasPermission="miniChild.data?.permissions ?? []">
106
+ <a
107
+ [routerLink]="miniChild.url"
108
+ (click)="showOrHide(index)"
109
+ >{{ miniChild.label }}</a>
110
+ </li>
111
+ </ul>
112
+ } }
113
+ </li>
114
+ }
115
+ </ul>
116
+ }
117
+ </li>
118
+ }
119
+ </ul>
120
+ </nav>
121
+ </div>
122
+ </header>
@@ -0,0 +1,90 @@
1
+ import { AsyncPipe, CommonModule } from "@angular/common";
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ ContentChild,
6
+ inject,
7
+ Input,
8
+ TemplateRef,
9
+ } from "@angular/core";
10
+ import { Router, RouterModule } from "@angular/router";
11
+ import { GovDesignSystemModule } from "@gov-design-system-ce/angular";
12
+ import { HasPermissionDirective } from "@verisoft/security-core";
13
+ import {
14
+ HEADER_COMPONENT_TOKEN,
15
+ HeaderCore,
16
+ MenuItem,
17
+ SideMenuService,
18
+ } from "@verisoft/ui-core";
19
+ import { Icons } from "../../icons";
20
+
21
+ @Component({
22
+ selector: "v-header",
23
+ styleUrl: "./header.component.scss",
24
+ templateUrl: './header.component.html',
25
+ imports: [
26
+ CommonModule,
27
+ GovDesignSystemModule,
28
+ AsyncPipe,
29
+ RouterModule,
30
+ HasPermissionDirective,
31
+ ],
32
+ changeDetection: ChangeDetectionStrategy.OnPush,
33
+ providers: [
34
+ {
35
+ provide: HEADER_COMPONENT_TOKEN,
36
+ useExisting: HeaderComponent
37
+ }
38
+ ]
39
+ })
40
+ export class HeaderComponent
41
+ implements HeaderCore {
42
+
43
+ @Input() title!: string;
44
+
45
+ @Input() userName!: string;
46
+
47
+ @Input() logoUrl!: string;
48
+
49
+ @Input() userRole!: any;
50
+
51
+ @Input() menuRef!: HTMLDivElement;
52
+
53
+ @Input() items: MenuItem[] = [];
54
+
55
+ @ContentChild('action', { static: false })
56
+ actionTemplate!: TemplateRef<{ $implicit: any }>;
57
+
58
+ protected icons = Icons;
59
+ protected menuVisible = false;
60
+ private openedIndexes: number[] = [];
61
+
62
+ protected readonly tabsService = inject(SideMenuService);
63
+ private readonly router = inject(Router);
64
+
65
+ toggleMenu() {
66
+ this.menuVisible = !this.menuVisible;
67
+ }
68
+
69
+ protected canRedirect(url?: string, canRedirect?: boolean) {
70
+ if (url && canRedirect) {
71
+ this.router.navigateByUrl(url);
72
+ }
73
+ }
74
+
75
+ protected showOrHide(index: number, children?: number): void {
76
+ if (children === 0) {
77
+ return;
78
+ }
79
+
80
+ if (!this.openedIndexes.includes(index)) {
81
+ this.openedIndexes = [...[], index];
82
+ } else if (this.openedIndexes.includes(index)) {
83
+ this.openedIndexes = this.openedIndexes.filter(x => x !== index);
84
+ }
85
+ }
86
+
87
+ protected canBeShown(index: number) {
88
+ return this.openedIndexes.includes(index);
89
+ }
90
+ }
@@ -0,0 +1 @@
1
+ export * from './header.component'
@@ -0,0 +1,11 @@
1
+ @if (library() === 'native') {
2
+ <gov-icon
3
+ [name]="name()"
4
+ [size]="govSize"
5
+ [class]="govClasses"
6
+ />
7
+ } @else if (library() === 'bootstrap') {
8
+ <i [class]="bootstrapClasses"></i>
9
+ }
10
+
11
+
@@ -0,0 +1,20 @@
1
+ :host {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ }
6
+
7
+ // Bootstrap icon sizes
8
+ .icon-small {
9
+ font-size: 0.875rem;
10
+ }
11
+
12
+ .icon-medium {
13
+ font-size: 1rem;
14
+ }
15
+
16
+ .icon-large {
17
+ font-size: 1.5rem;
18
+ }
19
+
20
+