verben-ng-ui 0.0.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 (190) hide show
  1. package/README.md +24 -0
  2. package/ng-package.json +10 -0
  3. package/package.json +34 -0
  4. package/src/lib/Verbena-input/error.service.ts +23 -0
  5. package/src/lib/Verbena-input/verbena-input.component.css +59 -0
  6. package/src/lib/Verbena-input/verbena-input.component.html +64 -0
  7. package/src/lib/Verbena-input/verbena-input.component.spec.ts +25 -0
  8. package/src/lib/Verbena-input/verbena-input.component.ts +162 -0
  9. package/src/lib/Verbena-input/verbena-input.module.ts +12 -0
  10. package/src/lib/components/TemplateDirective.directive.ts +10 -0
  11. package/src/lib/components/card/card.component.css +20 -0
  12. package/src/lib/components/card/card.component.html +23 -0
  13. package/src/lib/components/card/card.component.spec.ts +23 -0
  14. package/src/lib/components/card/card.component.ts +33 -0
  15. package/src/lib/components/card/card.module.ts +10 -0
  16. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.css +3 -0
  17. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.html +1 -0
  18. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.spec.ts +23 -0
  19. package/src/lib/components/card-data-view/card-data-view-footer/card-data-view-footer.component.ts +10 -0
  20. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.css +7 -0
  21. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.html +1 -0
  22. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.spec.ts +23 -0
  23. package/src/lib/components/card-data-view/card-data-view-header/card-data-view-header.component.ts +10 -0
  24. package/src/lib/components/card-data-view/card-data-view.component.css +39 -0
  25. package/src/lib/components/card-data-view/card-data-view.component.html +29 -0
  26. package/src/lib/components/card-data-view/card-data-view.component.spec.ts +23 -0
  27. package/src/lib/components/card-data-view/card-data-view.component.ts +66 -0
  28. package/src/lib/components/card-data-view/card-data-view.module.ts +20 -0
  29. package/src/lib/components/card-data-view/card-data.ts +7 -0
  30. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.css +15 -0
  31. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.html +4 -0
  32. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.spec.ts +23 -0
  33. package/src/lib/components/card-data-view/left-card-data/left-card-data.component.ts +19 -0
  34. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.css +0 -0
  35. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.html +4 -0
  36. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.spec.ts +23 -0
  37. package/src/lib/components/card-data-view/left-card-data-view/left-card-data-view.component.ts +12 -0
  38. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.css +3 -0
  39. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.html +1 -0
  40. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.spec.ts +23 -0
  41. package/src/lib/components/card-data-view/right-card-data-view/right-card-data-view.component.ts +10 -0
  42. package/src/lib/components/chip/ChipChangeEvent.ts +4 -0
  43. package/src/lib/components/chip/chip.component.css +94 -0
  44. package/src/lib/components/chip/chip.component.html +49 -0
  45. package/src/lib/components/chip/chip.component.spec.ts +23 -0
  46. package/src/lib/components/chip/chip.component.ts +209 -0
  47. package/src/lib/components/chip/chip.module.ts +24 -0
  48. package/src/lib/components/chip/documentation.md +26 -0
  49. package/src/lib/components/data-export/data-export.component.css +0 -0
  50. package/src/lib/components/data-export/data-export.component.html +90 -0
  51. package/src/lib/components/data-export/data-export.component.spec.ts +23 -0
  52. package/src/lib/components/data-export/data-export.component.ts +158 -0
  53. package/src/lib/components/data-export/data-export.module.ts +13 -0
  54. package/src/lib/components/data-export/data-export.service.spec.ts +16 -0
  55. package/src/lib/components/data-export/data-export.service.ts +152 -0
  56. package/src/lib/components/data-export/data-export.types.ts +21 -0
  57. package/src/lib/components/data-table/column.directive.spec.ts +8 -0
  58. package/src/lib/components/data-table/column.directive.ts +19 -0
  59. package/src/lib/components/data-table/data-table.component.css +0 -0
  60. package/src/lib/components/data-table/data-table.component.html +55 -0
  61. package/src/lib/components/data-table/data-table.component.spec.ts +21 -0
  62. package/src/lib/components/data-table/data-table.component.ts +336 -0
  63. package/src/lib/components/data-table/data-table.module.ts +11 -0
  64. package/src/lib/components/data-table/data-table.types.ts +13 -0
  65. package/src/lib/components/data-table/style.types.ts +55 -0
  66. package/src/lib/components/data-view/data-view-click-outside.directive.ts +44 -0
  67. package/src/lib/components/data-view/data-view.component.css +74 -0
  68. package/src/lib/components/data-view/data-view.component.html +161 -0
  69. package/src/lib/components/data-view/data-view.component.spec.ts +23 -0
  70. package/src/lib/components/data-view/data-view.component.ts +136 -0
  71. package/src/lib/components/data-view/data-view.module.ts +16 -0
  72. package/src/lib/components/date-picker/date-picker.component.css +65 -0
  73. package/src/lib/components/date-picker/date-picker.component.html +60 -0
  74. package/src/lib/components/date-picker/date-picker.component.specs.ts +23 -0
  75. package/src/lib/components/date-picker/date-picker.component.ts +143 -0
  76. package/src/lib/components/date-picker/date-picker.module.ts +12 -0
  77. package/src/lib/components/drop-down/DropdownChangeEvent.ts +4 -0
  78. package/src/lib/components/drop-down/DropdownLoadEvent.ts +19 -0
  79. package/src/lib/components/drop-down/DropdownMenuItem.ts +42 -0
  80. package/src/lib/components/drop-down/documentation.md +69 -0
  81. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.css +123 -0
  82. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.html +133 -0
  83. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.spec.ts +23 -0
  84. package/src/lib/components/drop-down/drop-down-item/drop-down-item.component.ts +88 -0
  85. package/src/lib/components/drop-down/drop-down.component.css +317 -0
  86. package/src/lib/components/drop-down/drop-down.component.html +177 -0
  87. package/src/lib/components/drop-down/drop-down.component.spec.ts +23 -0
  88. package/src/lib/components/drop-down/drop-down.component.ts +757 -0
  89. package/src/lib/components/drop-down/drop-down.module.ts +24 -0
  90. package/src/lib/components/image/image.component.css +12 -0
  91. package/src/lib/components/image/image.component.html +18 -0
  92. package/src/lib/components/image/image.component.spec.ts +23 -0
  93. package/src/lib/components/image/image.component.ts +45 -0
  94. package/src/lib/components/image/image.module.ts +11 -0
  95. package/src/lib/components/notification/notification.component.css +3 -0
  96. package/src/lib/components/notification/notification.component.html +19 -0
  97. package/src/lib/components/notification/notification.component.spec.ts +23 -0
  98. package/src/lib/components/notification/notification.component.ts +77 -0
  99. package/src/lib/components/notification/notification.module.ts +14 -0
  100. package/src/lib/components/shared.module.ts +9 -0
  101. package/src/lib/components/sort-table/sort-table.component.css +67 -0
  102. package/src/lib/components/sort-table/sort-table.component.html +164 -0
  103. package/src/lib/components/sort-table/sort-table.component.spec.ts +23 -0
  104. package/src/lib/components/sort-table/sort-table.component.ts +204 -0
  105. package/src/lib/components/sort-table/sort-table.module.ts +11 -0
  106. package/src/lib/components/svg/svg.component.css +0 -0
  107. package/src/lib/components/svg/svg.component.html +1 -0
  108. package/src/lib/components/svg/svg.component.spec.ts +23 -0
  109. package/src/lib/components/svg/svg.component.ts +64 -0
  110. package/src/lib/components/svg/svg.module.ts +10 -0
  111. package/src/lib/components/table-filter/table-filter.component.css +93 -0
  112. package/src/lib/components/table-filter/table-filter.component.html +293 -0
  113. package/src/lib/components/table-filter/table-filter.component.spec.ts +23 -0
  114. package/src/lib/components/table-filter/table-filter.component.ts +221 -0
  115. package/src/lib/components/table-filter/table-filter.module.ts +25 -0
  116. package/src/lib/components/tooltip/tooltip.component.css +8 -0
  117. package/src/lib/components/tooltip/tooltip.component.html +13 -0
  118. package/src/lib/components/tooltip/tooltip.component.spec.ts +23 -0
  119. package/src/lib/components/tooltip/tooltip.component.ts +84 -0
  120. package/src/lib/components/tooltip/tooltip.module.ts +11 -0
  121. package/src/lib/components/verben-mail/verben-mail.component.config.ts +11 -0
  122. package/src/lib/components/verben-mail/verben-mail.component.css +71 -0
  123. package/src/lib/components/verben-mail/verben-mail.component.html +139 -0
  124. package/src/lib/components/verben-mail/verben-mail.component.ts +151 -0
  125. package/src/lib/components/verben-mail/verben-mail.module.ts +18 -0
  126. package/src/lib/components/visible-column/visible-column.component.css +83 -0
  127. package/src/lib/components/visible-column/visible-column.component.html +77 -0
  128. package/src/lib/components/visible-column/visible-column.component.spec.ts +23 -0
  129. package/src/lib/components/visible-column/visible-column.component.ts +106 -0
  130. package/src/lib/components/visible-column/visible-column.module.ts +11 -0
  131. package/src/lib/config.ts +37 -0
  132. package/src/lib/control-options/control-options.directive.ts +129 -0
  133. package/src/lib/control-options/control-options.module.ts +10 -0
  134. package/src/lib/convert-to-integer/convert-to-integer.directive.ts +28 -0
  135. package/src/lib/convert-to-integer/convert-to-integer.module.ts +10 -0
  136. package/src/lib/convert-to-integer/public-api.ts +1 -0
  137. package/src/lib/convert-to-number/convert-to-number.directive.ts +22 -0
  138. package/src/lib/convert-to-number/convert-to-number.module.ts +8 -0
  139. package/src/lib/convert-to-number/public-api.ts +1 -0
  140. package/src/lib/email-validator/email-validator.directive.ts +24 -0
  141. package/src/lib/email-validator/email-validator.module.ts +14 -0
  142. package/src/lib/models/column-filter.ts +5 -0
  143. package/src/lib/models/data-filter.ts +8 -0
  144. package/src/lib/models/mail-model.ts +8 -0
  145. package/src/lib/models/sort-filter.ts +0 -0
  146. package/src/lib/models/table-filter.ts +34 -0
  147. package/src/lib/number-range/number-range.directive.ts +35 -0
  148. package/src/lib/number-range/number-range.module.ts +11 -0
  149. package/src/lib/phone-number/phone-number.directive.ts +22 -0
  150. package/src/lib/phone-number/phone-number.module.ts +10 -0
  151. package/src/lib/phone-number/public-api.ts +1 -0
  152. package/src/lib/required-input/required-input.directive.ts +18 -0
  153. package/src/lib/required-input/required-input.module.ts +8 -0
  154. package/src/lib/theme-switcher/theme-switcher.directive.spec.ts +8 -0
  155. package/src/lib/theme-switcher/theme-switcher.directive.ts +70 -0
  156. package/src/lib/theme-switcher/theme-switcher.module.ts +8 -0
  157. package/src/lib/validate/error-message.service.ts +104 -0
  158. package/src/lib/validate/validate.directive.ts +110 -0
  159. package/src/lib/validate/validate.module.ts +17 -0
  160. package/src/lib/validate-input/validate-input.directive.ts +8 -0
  161. package/src/lib/validate-input/validate-input.module.ts +8 -0
  162. package/src/lib/verben-ng-ui.component.spec.ts +23 -0
  163. package/src/lib/verben-ng-ui.component.ts +16 -0
  164. package/src/lib/verben-ng-ui.service.spec.ts +16 -0
  165. package/src/lib/verben-ng-ui.service.ts +9 -0
  166. package/src/lib/verbena-badge/verbena-badge.component.css +16 -0
  167. package/src/lib/verbena-badge/verbena-badge.component.html +13 -0
  168. package/src/lib/verbena-badge/verbena-badge.component.spec.ts +25 -0
  169. package/src/lib/verbena-badge/verbena-badge.component.ts +18 -0
  170. package/src/lib/verbena-badge/verbena-badge.module.ts +10 -0
  171. package/src/lib/verbena-button/verbena-button.component.css +20 -0
  172. package/src/lib/verbena-button/verbena-button.component.html +25 -0
  173. package/src/lib/verbena-button/verbena-button.component.spec.ts +25 -0
  174. package/src/lib/verbena-button/verbena-button.component.ts +92 -0
  175. package/src/lib/verbena-button/verbena-button.module.ts +11 -0
  176. package/src/lib/verbena-switch/verbena-switch.component.css +45 -0
  177. package/src/lib/verbena-switch/verbena-switch.component.html +8 -0
  178. package/src/lib/verbena-switch/verbena-switch.component.spec.ts +25 -0
  179. package/src/lib/verbena-switch/verbena-switch.component.ts +31 -0
  180. package/src/lib/verbena-switch/verbena-switch.module.ts +10 -0
  181. package/src/lib/verbena-textarea/verbena-textarea.component.css +0 -0
  182. package/src/lib/verbena-textarea/verbena-textarea.component.html +19 -0
  183. package/src/lib/verbena-textarea/verbena-textarea.component.spec.ts +33 -0
  184. package/src/lib/verbena-textarea/verbena-textarea.component.ts +44 -0
  185. package/src/lib/verbena-textarea/verbena-textarea.module.ts +11 -0
  186. package/src/public-api.ts +122 -0
  187. package/src/styles.css +103 -0
  188. package/tsconfig.lib.json +15 -0
  189. package/tsconfig.lib.prod.json +11 -0
  190. package/tsconfig.spec.json +15 -0
@@ -0,0 +1,209 @@
1
+ import {
2
+ AfterContentInit,
3
+ Component,
4
+ ContentChildren,
5
+ EventEmitter,
6
+ HostBinding,
7
+ HostListener,
8
+ Input,
9
+ OnInit,
10
+ Output,
11
+ QueryList,
12
+ Self,
13
+ TemplateRef,
14
+ } from '@angular/core';
15
+ import { DropDownItemComponent } from '../drop-down/drop-down-item/drop-down-item.component';
16
+ import { ControlValueAccessor, FormsModule, NgControl } from '@angular/forms';
17
+ import { CommonModule } from '@angular/common';
18
+ import { ChipChangeEvent } from './ChipChangeEvent';
19
+ import { SharedModule } from '../shared.module';
20
+ import { TemplateDirective } from '../TemplateDirective.directive';
21
+ import { SvgModule } from '../svg/svg.module';
22
+
23
+ @Component({
24
+ selector: 'verben-chip',
25
+ standalone: true,
26
+ imports: [
27
+ CommonModule,
28
+ DropDownItemComponent,
29
+ SharedModule,
30
+ FormsModule,
31
+ SvgModule,
32
+ ],
33
+ templateUrl: './chip.component.html',
34
+ styleUrl: './chip.component.css',
35
+ })
36
+ export class ChipComponent
37
+ implements ControlValueAccessor, OnInit, AfterContentInit
38
+ {
39
+ // INPUTS
40
+ @Input() width: string = '100%';
41
+ @Input() placeholder: string = '';
42
+ @Input() max?: number;
43
+ @Input() styleClass: string = '';
44
+ @Input() separator: string = ',';
45
+ @Input() disabled: boolean = false;
46
+ @Input() required: boolean = false;
47
+ @Input() invalidMessage?: string;
48
+ @Input() errorPosition: string = '';
49
+
50
+ // OUTPUTS
51
+ @Output() onChange: EventEmitter<ChipChangeEvent> = new EventEmitter();
52
+ // @Output() onClear: EventEmitter<Event> = new EventEmitter();
53
+
54
+ onItemChange: (value: any) => void = () => {};
55
+ onTouched: () => void = () => {};
56
+ isInvalid: boolean = false;
57
+
58
+ //TEMPLATING
59
+ @ContentChildren(TemplateDirective) templates!: QueryList<TemplateDirective>;
60
+ @HostBinding('class.focused') isFocused = false;
61
+ isInputFocused = false;
62
+
63
+ @HostListener('focus') onFocus() {
64
+ this.isFocused = true;
65
+ }
66
+
67
+ @HostListener('blur') onBlur() {
68
+ this.isFocused = false;
69
+ }
70
+
71
+ onInputFocus() {
72
+ this.isFocused = true;
73
+ }
74
+
75
+ onInputBlur() {
76
+ this.isFocused = false;
77
+ }
78
+
79
+ itemTemplate: TemplateRef<any> | null = null;
80
+
81
+ chips: string[] = [];
82
+ chipInput: string = '';
83
+
84
+ constructor(@Self() private ngControl: NgControl) {
85
+ if (this.ngControl) {
86
+ this.ngControl.valueAccessor = this; // Assign this component as the value accessor
87
+ this.ngControl?.statusChanges?.subscribe((status) => {
88
+ this.isInvalid = this.ngControl.touched
89
+ ? status === 'INVALID' && this.ngControl.touched
90
+ : false;
91
+ });
92
+ }
93
+ }
94
+
95
+ ngOnInit(): void {}
96
+ ngAfterContentInit(): void {
97
+ this.templates.forEach((templateDirective) => {
98
+ if (templateDirective.vTemplate === 'item') {
99
+ this.itemTemplate = templateDirective.template;
100
+ }
101
+ });
102
+ }
103
+
104
+ onKeyDown(event: KeyboardEvent): void {
105
+ if (this.disabled) {
106
+ return;
107
+ }
108
+ const inputValue = (event.target as HTMLInputElement).value;
109
+ // Check for 'Enter' key or custom separator
110
+ if (event.key === 'Enter' || event.key == this.separator) {
111
+ event.preventDefault();
112
+ this.addChips(inputValue);
113
+ }
114
+
115
+ // Handle 'Backspace' key when input is empty
116
+ if (
117
+ event.key === 'Backspace' &&
118
+ inputValue.length === 0 &&
119
+ this.chips.length > 0
120
+ ) {
121
+ this.removeLastChip();
122
+ }
123
+ }
124
+
125
+ addChips(inputValue: string): void {
126
+ if (this.disabled) {
127
+ return;
128
+ }
129
+ // Split by separator and trim each part
130
+ const values = inputValue
131
+ .split(this.separator)
132
+ .map((value) => value.trim());
133
+
134
+ values.forEach((value) => {
135
+ if (value.length > 0) {
136
+ if (this.max && this.chips.length == this.max) {
137
+ return;
138
+ }
139
+ this.chips.push(value); // Add chip
140
+ }
141
+ });
142
+ if (this.isInvalid) {
143
+ this.isInvalid = false;
144
+ }
145
+
146
+ this.chipInput = ''; // Clear input
147
+ this.onTouched();
148
+ this.onChange.emit({ value: this.chips });
149
+ }
150
+
151
+ removeChip(index: number, event: Event): void {
152
+ if (this.disabled) {
153
+ return;
154
+ }
155
+ this.chips.splice(index, 1);
156
+ if (this.chips.length == 0) {
157
+ if (this.required == true) {
158
+ this.isInvalid = true;
159
+ }
160
+ }
161
+ this.onTouched();
162
+ this.onChange.emit({ originalEvent: event, value: this.chips });
163
+ }
164
+
165
+ removeLastChip(): void {
166
+ if (this.disabled) {
167
+ return;
168
+ }
169
+ this.chips.pop(); // Remove the last chip
170
+ if (this.chips.length == 0) {
171
+ if (this.required == true) {
172
+ this.isInvalid = true;
173
+ }
174
+ }
175
+ this.onTouched();
176
+ this.onChange.emit({ originalEvent: event, value: this.chips });
177
+ }
178
+
179
+ // clearSelection(event: Event) {
180
+ // if (this.disabled) {
181
+ // return;
182
+ // }
183
+ // this.chips = [];
184
+ // if (this.required == true) {
185
+ // this.isInvalid = true;
186
+ // }
187
+ // this.onTouched();
188
+ // this.onChange.emit({ originalEvent: event, value: this.chips });
189
+ // }
190
+
191
+ writeValue(obj: string[]): void {
192
+ this.chips = obj;
193
+ this.onTouched();
194
+ this.onChange.emit({ value: this.chips });
195
+ }
196
+ registerOnChange(fn: any): void {
197
+ this.onItemChange = fn;
198
+ }
199
+ registerOnTouched(fn: any): void {
200
+ this.onTouched = fn;
201
+ }
202
+ setDisabledState?(isDisabled: boolean): void {
203
+ this.disabled = isDisabled;
204
+ }
205
+
206
+ get placeholderState(): string | undefined {
207
+ return this.chips && this.chips.length == 0 ? this.placeholder : '';
208
+ }
209
+ }
@@ -0,0 +1,24 @@
1
+ import { forwardRef, NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { ChipComponent } from './chip.component';
4
+ import { NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
5
+ import { SharedModule } from '../shared.module';
6
+
7
+ @NgModule({
8
+ declarations: [],
9
+ imports: [ChipComponent],
10
+ exports: [ChipComponent],
11
+ providers: [
12
+ {
13
+ provide: NG_VALUE_ACCESSOR,
14
+ useExisting: forwardRef(() => ChipComponent),
15
+ multi: true,
16
+ },
17
+ {
18
+ provide: NG_VALIDATORS,
19
+ useExisting: forwardRef(() => ChipComponent),
20
+ multi: true,
21
+ },
22
+ ],
23
+ })
24
+ export class ChipModule {}
@@ -0,0 +1,26 @@
1
+ SELECTOR - <verbena-chip></verbena-chip>
2
+
3
+ INPUTS
4
+ width: string- sets the width of the chip.
5
+ placeholder: string - Any value you want the chip to display when nothing has been added.
6
+ max: number - Allows you to set the maximum number of chips that can be added.
7
+ styleClass: string - Optional class addition that would be added to the chip.
8
+ separator: string - By Default, pressing enter triggers conversion of current text to chip. This allows you to set another input value that does similarly e.g ','.
9
+ disabled: boolean (default = false) - Sets the disabled state of the chip.
10
+ required: boolean (default = false) - If set as true, display visual cues when no chip is added and the chip is marked as touched.
11
+ invalidMessage: string - Specifies message to be shown when the dropdown is invalid. If not set, no message is shown.
12
+ errorPosition: string - Specifies the position you want the dropdown's invalid message to show relative to the dropdown. Has 3 options - 'top', 'left' and 'right'. If none of these is set, it defaults to bottom.
13
+
14
+ OUTPUTS
15
+ onChange: EventEmitter<ChipChangeEvent> - emitted when changes are made to the selected option or options.
16
+
17
+ TEMPLATING
18
+ item - Configure how chip items look.
19
+ <ng-template let-item vTemplate="item">
20
+ {{item}} Test Selected Template
21
+ </ng-template>
22
+
23
+ OBJECTS
24
+ ChipChangeEvent - Sent when the chip value changes.
25
+ originalEvent: Event - Event captured.
26
+ value: any - Selected option or options.
@@ -0,0 +1,90 @@
1
+ <h2>Export Configuration</h2>
2
+
3
+ <h3>Create Operation</h3>
4
+ <form [formGroup]="operationForm" (ngSubmit)="onSubmitOperation()">
5
+ <input formControlName="name" placeholder="Operation Name" />
6
+ <select formControlName="field1">
7
+ <option value="">Select Field 1</option>
8
+ <option *ngFor="let prop of baseProperties" [value]="prop">
9
+ {{ prop }}
10
+ </option>
11
+ </select>
12
+ <select formControlName="operator">
13
+ <option value="">Select Operator</option>
14
+ <option value="add">+</option>
15
+ <option value="subtract">-</option>
16
+ <option value="multiply">*</option>
17
+ <option value="divide">/</option>
18
+ </select>
19
+ <select formControlName="field2">
20
+ <option value="">Select Field 2</option>
21
+ <option *ngFor="let prop of baseProperties" [value]="prop">
22
+ {{ prop }}
23
+ </option>
24
+ </select>
25
+ <button type="submit" [disabled]="!operationForm.valid">Add Operation</button>
26
+ </form>
27
+
28
+ <h3>Operations</h3>
29
+ <div
30
+ *ngFor="let operation of exportService.getOperations()"
31
+ class="operation-item"
32
+ >
33
+ <span
34
+ >{{ operation.name }}: {{ operation.field1 }} {{ operation.operator }}
35
+ {{ operation.field2 }}</span
36
+ >
37
+ <div>
38
+ <button (click)="editOperation(operation)">Edit</button>
39
+ <button (click)="removeOperation(operation.id)">Remove</button>
40
+ </div>
41
+ </div>
42
+
43
+ <h3>Create Profile</h3>
44
+ <form [formGroup]="profileForm" (ngSubmit)="onSubmitProfile()">
45
+ <input formControlName="name" placeholder="Profile Name" />
46
+ <div formArrayName="items" class="checkbox-group">
47
+ <label
48
+ *ngFor="let item of exportService.getAllItems(); let i = index"
49
+ class="checkbox-label"
50
+ >
51
+ <input type="checkbox" [formControlName]="i" />
52
+ {{ item.name }} ({{ item.type }})
53
+ </label>
54
+ </div>
55
+ <button type="submit" [disabled]="!profileForm.valid">Save Profile</button>
56
+ </form>
57
+
58
+ <h3>Profiles</h3>
59
+ <ul>
60
+ <li *ngFor="let profile of exportService.getProfiles()">
61
+ <span>{{ profile.name }}</span>
62
+ <div>
63
+ <button *ngIf="profile.id !== 'default'" (click)="editProfile(profile)">
64
+ Edit
65
+ </button>
66
+ <button
67
+ *ngIf="profile.id !== 'default'"
68
+ (click)="removeProfile(profile.id)"
69
+ >
70
+ Remove
71
+ </button>
72
+ </div>
73
+ </li>
74
+ </ul>
75
+
76
+ <button (click)="resetAll()">Reset All</button>
77
+
78
+ <h3>Export</h3>
79
+ <form [formGroup]="profileSelectionForm">
80
+ <div formArrayName="selectedProfiles" class="checkbox-group">
81
+ <label
82
+ *ngFor="let profile of exportService.getProfiles(); let i = index"
83
+ class="checkbox-label"
84
+ >
85
+ <input type="checkbox" [formControlName]="i" />
86
+ {{ profile.name }}
87
+ </label>
88
+ </div>
89
+ </form>
90
+ <button (click)="exportData()">Export Selected Profiles</button>
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { DataExportComponent } from './data-export.component';
4
+
5
+ describe('DataExportComponent', () => {
6
+ let component: DataExportComponent;
7
+ let fixture: ComponentFixture<DataExportComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [DataExportComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(DataExportComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,158 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ EventEmitter,
5
+ Input,
6
+ Output,
7
+ } from '@angular/core';
8
+ import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
9
+ import { DataExportService } from './data-export.service';
10
+ import { ExportProfile, Operation } from './data-export.types';
11
+
12
+ @Component({
13
+ selector: 'lib-data-export',
14
+ templateUrl: './data-export.component.html',
15
+ styleUrl: './data-export.component.css',
16
+ changeDetection: ChangeDetectionStrategy.OnPush,
17
+ })
18
+ export class DataExportComponent {
19
+ @Input() data!: any[];
20
+ @Output() exportDataEvent = new EventEmitter<Record<string, any>[]>();
21
+
22
+ profileForm!: FormGroup;
23
+ operationForm!: FormGroup;
24
+ profileSelectionForm!: FormGroup;
25
+ baseProperties: string[] = [];
26
+ allProperties: string[] = [];
27
+
28
+ constructor(
29
+ private fb: FormBuilder,
30
+ public exportService: DataExportService
31
+ ) {}
32
+
33
+ ngOnInit() {
34
+ this.initForms();
35
+ this.updateProperties();
36
+ }
37
+
38
+ private initForms() {
39
+ this.initProfileForm();
40
+ this.initOperationForm();
41
+ this.initProfileSelectionForm();
42
+ }
43
+
44
+ private initProfileForm() {
45
+ const itemControls = this.exportService.getAllItems().map(() => false);
46
+ this.profileForm = this.fb.group({
47
+ name: ['', Validators.required],
48
+ items: this.fb.array(itemControls),
49
+ });
50
+ }
51
+
52
+ private initOperationForm() {
53
+ this.operationForm = this.fb.group({
54
+ name: ['', Validators.required],
55
+ field1: ['', Validators.required],
56
+ operator: ['', Validators.required],
57
+ field2: ['', Validators.required],
58
+ });
59
+ }
60
+
61
+ private initProfileSelectionForm() {
62
+ const profileControls = this.exportService.getProfiles().map(() => false);
63
+ this.profileSelectionForm = this.fb.group({
64
+ selectedProfiles: this.fb.array(profileControls),
65
+ });
66
+ }
67
+
68
+ private updateProperties() {
69
+ if (this.data && this.data.length > 0) {
70
+ const baseProperties = Object.keys(this.data[0]);
71
+ this.exportService.setBaseProperties(baseProperties);
72
+ }
73
+ this.allProperties = this.exportService
74
+ .getAllItems()
75
+ .map((item) => item.id);
76
+ this.initProfileForm();
77
+ }
78
+
79
+ onSubmitOperation() {
80
+ if (this.operationForm.valid) {
81
+ const operation: Operation = {
82
+ id: Date.now().toString(),
83
+ ...this.operationForm.value,
84
+ };
85
+ this.exportService.addOperation(operation);
86
+ this.operationForm.reset();
87
+ this.updateProperties();
88
+ }
89
+ }
90
+
91
+ onSubmitProfile() {
92
+ if (this.profileForm.valid) {
93
+ const formValue = this.profileForm.value;
94
+ const selectedItems = this.exportService
95
+ .getAllItems()
96
+ .filter((_, i) => formValue.items[i]);
97
+ const newProfile: ExportProfile = {
98
+ id: Date.now().toString(),
99
+ name: formValue.name,
100
+ items: selectedItems,
101
+ };
102
+ this.exportService.addProfile(newProfile);
103
+ this.profileForm.reset();
104
+ this.initProfileSelectionForm();
105
+ }
106
+ }
107
+
108
+ editProfile(profile: ExportProfile) {
109
+ this.profileForm.patchValue({
110
+ name: profile.name,
111
+ items: this.exportService
112
+ .getAllItems()
113
+ .map((item) =>
114
+ profile.items.some((profileItem) => profileItem.id === item.id)
115
+ ),
116
+ });
117
+ }
118
+
119
+ editOperation(operation: Operation) {
120
+ this.operationForm.patchValue(operation);
121
+ }
122
+
123
+ removeOperation(id: string) {
124
+ this.exportService.removeOperation(id);
125
+ this.updateProperties();
126
+ }
127
+
128
+ removeProfile(id: string) {
129
+ this.exportService.removeProfile(id);
130
+ this.initProfileSelectionForm();
131
+ }
132
+
133
+ resetAll() {
134
+ this.exportService.resetAll();
135
+ this.initForms();
136
+ this.updateProperties();
137
+ }
138
+
139
+ exportData() {
140
+ const selectedProfiles = this.exportService
141
+ .getProfiles()
142
+ .filter(
143
+ (_, i) =>
144
+ (this.profileSelectionForm.get('selectedProfiles') as FormArray).at(i)
145
+ .value
146
+ );
147
+
148
+ if (selectedProfiles.length > 0) {
149
+ const exportedData = this.exportService.exportData(
150
+ this.data,
151
+ selectedProfiles
152
+ );
153
+ this.exportDataEvent.emit(exportedData);
154
+ } else {
155
+ console.log('No profiles selected for export');
156
+ }
157
+ }
158
+ }
@@ -0,0 +1,13 @@
1
+ import { NgModule } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { DataExportService } from './data-export.service';
4
+ import { DataExportComponent } from './data-export.component';
5
+ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
6
+
7
+ @NgModule({
8
+ declarations: [DataExportComponent],
9
+ imports: [CommonModule, FormsModule, ReactiveFormsModule],
10
+ providers: [],
11
+ exports: [DataExportComponent],
12
+ })
13
+ export class DataExportModule {}
@@ -0,0 +1,16 @@
1
+ import { TestBed } from '@angular/core/testing';
2
+
3
+ import { DataExportService } from './data-export.service';
4
+
5
+ describe('DataExportService', () => {
6
+ let service: DataExportService;
7
+
8
+ beforeEach(() => {
9
+ TestBed.configureTestingModule({});
10
+ service = TestBed.inject(DataExportService);
11
+ });
12
+
13
+ it('should be created', () => {
14
+ expect(service).toBeTruthy();
15
+ });
16
+ });