@verisoft/ui-govcz 20.1.0 → 20.1.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 (26) hide show
  1. package/package.json +4 -4
  2. package/src/lib/components/shared-components/action-button-group/action-button-group.component.html +25 -0
  3. package/src/lib/components/shared-components/action-button-group/action-button-group.component.scss +0 -0
  4. package/src/lib/components/shared-components/action-button-group/action-button-group.component.spec.ts +21 -0
  5. package/src/lib/components/shared-components/action-button-group/action-button-group.component.ts +111 -0
  6. package/src/lib/components/shared-components/action-button-group/components/action-button/action-button.component.html +10 -0
  7. package/src/lib/components/shared-components/action-button-group/components/action-button/action-button.component.scss +0 -0
  8. package/src/lib/components/shared-components/action-button-group/components/action-button/action-button.component.spec.ts +21 -0
  9. package/src/lib/components/shared-components/action-button-group/components/action-button/action-button.component.ts +69 -0
  10. package/src/lib/components/shared-components/action-button-group/index.ts +2 -0
  11. package/src/lib/components/shared-components/dynamic-component/dynamic-component-factory.service.ts +142 -0
  12. package/src/lib/components/shared-components/dynamic-component/dynamic-component.component.ts +56 -0
  13. package/src/lib/components/shared-components/dynamic-component/index.ts +2 -0
  14. package/src/lib/components/shared-components/generic-field/generic-field.component.html +98 -0
  15. package/src/lib/components/shared-components/generic-field/generic-field.component.spec.ts +21 -0
  16. package/src/lib/components/shared-components/generic-field/generic-field.component.ts +90 -0
  17. package/src/lib/components/shared-components/generic-field/index.ts +1 -0
  18. package/src/lib/components/shared-components/generic-form/generic-form.component.html +46 -0
  19. package/src/lib/components/shared-components/generic-form/generic-form.component.spec.ts +21 -0
  20. package/src/lib/components/shared-components/generic-form/generic-form.component.ts +56 -0
  21. package/src/lib/components/shared-components/generic-form/generic-form.model.spec.ts +82 -0
  22. package/src/lib/components/shared-components/generic-form/generic-form.model.ts +68 -0
  23. package/src/lib/components/shared-components/generic-form/index.ts +2 -0
  24. package/src/lib/components/shared-components/index.ts +4 -0
  25. package/styles/dist/main.css +13 -0
  26. package/styles/dist/main.css.map +1 -0
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@verisoft/ui-govcz",
3
- "version": "20.1.0",
3
+ "version": "20.1.1",
4
4
  "peerDependencies": {
5
- "@verisoft/security-core": "~20.1.0",
6
- "@verisoft/core": "~20.1.0",
7
- "@verisoft/ui-core": "~20.1.0",
5
+ "@verisoft/security-core": "~20.1.1",
6
+ "@verisoft/core": "~20.1.1",
7
+ "@verisoft/ui-core": "~20.1.1",
8
8
  "@angular/core": "~20.2.0",
9
9
  "@angular/common": "~20.2.0",
10
10
  "@angular/forms": "~20.2.0",
@@ -0,0 +1,25 @@
1
+ <div
2
+ class="v-action-button-group align-items-center justify-content-center justify-content-md-end"
3
+ >
4
+ <div class="v-action-button-group__actions d-flex gap-2">
5
+ @for (action of visibleActions; track action) {
6
+ <v-action-button
7
+ [disabled]="action.disabled"
8
+ [icon]="action.icon"
9
+ [id]="action.id"
10
+ [outlined]="action.outlined"
11
+ [raised]="action.raised"
12
+ [toolTip]="action.toolTip || action.label"
13
+ [severity]="action.severity"
14
+ [size]="action.size"
15
+ (click)="fireClick(action, $event)"
16
+ ></v-action-button>
17
+ } @if (actions.length > visibleActions.length) {
18
+ <v-dropdown-button
19
+ [label]="label"
20
+ [icon]="menuIcon"
21
+ [items]="menuItems"
22
+ />
23
+ }
24
+ </div>
25
+ </div>
@@ -0,0 +1,21 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { ActionButtonGroupComponent } from './action-button-group.component';
3
+
4
+ describe('ActionButtonGroupComponent', () => {
5
+ let component: ActionButtonGroupComponent;
6
+ let fixture: ComponentFixture<ActionButtonGroupComponent>;
7
+
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [ActionButtonGroupComponent],
11
+ }).compileComponents();
12
+
13
+ fixture = TestBed.createComponent(ActionButtonGroupComponent);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+ });
@@ -0,0 +1,111 @@
1
+ import {
2
+ AfterContentInit,
3
+ ChangeDetectionStrategy,
4
+ ChangeDetectorRef,
5
+ Component,
6
+ ContentChildren,
7
+ Input,
8
+ QueryList,
9
+ } from '@angular/core';
10
+ import {
11
+ ACTION_BUTTON_GROUP_COMPONENT_TOKEN,
12
+ ActionButton,
13
+ ActionButtonGroupCore,
14
+ IconPositionType,
15
+ MenuItem,
16
+ queryListChanged,
17
+ ScreenSizeService,
18
+ UnsubscribeComponent,
19
+ } from '@verisoft/ui-core';
20
+ import {
21
+ combineLatestWith,
22
+ takeUntil,
23
+ } from 'rxjs';
24
+ import { Icons } from '../../../icons';
25
+ import { DropdownButtonComponent } from '../../dropdown-button';
26
+ import { ActionButtonComponent } from './components/action-button/action-button.component';
27
+
28
+ @Component({
29
+ selector: 'v-action-button-group',
30
+ imports: [ActionButtonComponent, DropdownButtonComponent],
31
+ templateUrl: './action-button-group.component.html',
32
+ styleUrl: './action-button-group.component.scss',
33
+ changeDetection: ChangeDetectionStrategy.OnPush,
34
+ providers: [
35
+ {
36
+ provide: ACTION_BUTTON_GROUP_COMPONENT_TOKEN,
37
+ useExisting: ActionButtonGroupComponent,
38
+ },
39
+ ]
40
+ })
41
+ export class ActionButtonGroupComponent
42
+ extends UnsubscribeComponent
43
+ implements AfterContentInit, ActionButtonGroupCore {
44
+ @ContentChildren(ActionButtonComponent)
45
+ actions!: QueryList<ActionButtonComponent>;
46
+
47
+ @Input() maxItems = 3;
48
+
49
+ @Input() maxItemsMobile = 0;
50
+
51
+ @Input() items: ActionButton[] = [];
52
+
53
+ @Input() menuIconPos: IconPositionType = 'right';
54
+
55
+ @Input() menuIcon = Icons.action;
56
+
57
+ @Input() label?: string;
58
+
59
+ @Input() icon?: string;
60
+
61
+ icons = Icons;
62
+ allItems: ActionButton[] = [];
63
+ visibleActions: ActionButton[] = [];
64
+ menuItems: MenuItem[] = [];
65
+
66
+ constructor(
67
+ private readonly changeDetectorRef: ChangeDetectorRef,
68
+ readonly screenSizeService: ScreenSizeService
69
+ ) {
70
+ super();
71
+ }
72
+
73
+ ngAfterContentInit(): void {
74
+ this.subscribeItemChange();
75
+ }
76
+
77
+ fireClick(item: ActionButton, event: MouseEvent) {
78
+ event.stopPropagation();
79
+ item.click.emit();
80
+ }
81
+
82
+ private subscribeItemChange(): void {
83
+ const screenResize$ = this.screenSizeService.isMobileBlock;
84
+
85
+ const actions$ = queryListChanged(this.actions);
86
+
87
+ screenResize$
88
+ .pipe(takeUntil(this.destroyed$), combineLatestWith(actions$))
89
+ .subscribe(([isMobile, actions]) => {
90
+ this.computeItems(actions, isMobile);
91
+ });
92
+ }
93
+
94
+ private computeItems(actions: ActionButton[], isMobile: boolean) {
95
+ const allItems = [...(this.items ?? []), ...actions];
96
+ const maxItems = isMobile ? this.maxItemsMobile : this.maxItems;
97
+ this.visibleActions = allItems.slice(0, maxItems);
98
+ this.menuItems = allItems.slice(maxItems).map(this.convertToMenuItem);
99
+ this.changeDetectorRef.detectChanges();
100
+ }
101
+
102
+ private convertToMenuItem(item: ActionButton): MenuItem {
103
+ return {
104
+ label: item.label,
105
+ icon: item.icon,
106
+ command: () => {
107
+ item.click.emit();
108
+ },
109
+ };
110
+ }
111
+ }
@@ -0,0 +1,10 @@
1
+ <v-button
2
+ [label]="label"
3
+ [disabled]="disabled"
4
+ [icon]="icon"
5
+ [outlined]="outlined"
6
+ tooltipPosition="bottom"
7
+ [size]="size"
8
+ [severity]="severity"
9
+ (click)="handleClick($event)"
10
+ />
@@ -0,0 +1,21 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { ActionButtonComponent } from './action-button.component';
3
+
4
+ describe('ActionButtonComponent', () => {
5
+ let component: ActionButtonComponent;
6
+ let fixture: ComponentFixture<ActionButtonComponent>;
7
+
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [ActionButtonComponent],
11
+ }).compileComponents();
12
+
13
+ fixture = TestBed.createComponent(ActionButtonComponent);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+ });
@@ -0,0 +1,69 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ EventEmitter,
5
+ inject,
6
+ Input,
7
+ OnChanges,
8
+ Output,
9
+ SimpleChanges,
10
+ } from '@angular/core';
11
+ import {
12
+ ACTION_BUTTON_GROUP_COMPONENT_TOKEN,
13
+ ActionButton,
14
+ ActionButtonGroupCore,
15
+ ControlSeverityType,
16
+ FieldSizeType,
17
+ } from '@verisoft/ui-core';
18
+ import { Observable, Subject } from 'rxjs';
19
+ import { Icons } from '../../../../../icons';
20
+ import { ButtonComponent } from '../../../../button';
21
+
22
+ @Component({
23
+ selector: 'v-action-button',
24
+ imports: [ButtonComponent],
25
+ templateUrl: './action-button.component.html',
26
+ styleUrl: './action-button.component.scss',
27
+ changeDetection: ChangeDetectionStrategy.OnPush
28
+ })
29
+ export class ActionButtonComponent implements ActionButton, OnChanges {
30
+ @Input() disabled = false;
31
+ @Input() toolTip?: string;
32
+ @Input() id?: string;
33
+ @Input() icon?: string;
34
+ @Input() outlined = false;
35
+ @Input() raised = false;
36
+ @Input() severity?: ControlSeverityType;
37
+ @Input() label?: string;
38
+ @Input() size?: FieldSizeType;
39
+ // eslint-disable-next-line @angular-eslint/no-output-native
40
+ @Output() click = new EventEmitter<MouseEvent>();
41
+
42
+ icons = Icons
43
+
44
+ private propertyChangeSubject = new Subject();
45
+
46
+ propertyChanged: Observable<unknown> =
47
+ this.propertyChangeSubject.asObservable();
48
+
49
+ buttonGroup: ActionButtonGroupCore | null = inject<ActionButtonGroupCore>(
50
+ ACTION_BUTTON_GROUP_COMPONENT_TOKEN,
51
+ {
52
+ optional: true,
53
+ }
54
+ );
55
+
56
+ ngOnChanges(changes: SimpleChanges): void {
57
+ const isValueChange = Object.keys(changes).some(
58
+ (x) => !changes[x].firstChange
59
+ );
60
+ if (isValueChange) {
61
+ this.propertyChangeSubject.next(null);
62
+ }
63
+ }
64
+
65
+ handleClick(event: MouseEvent) {
66
+ event.stopPropagation();
67
+ this.click.emit(event);
68
+ }
69
+ }
@@ -0,0 +1,2 @@
1
+ export * from './action-button-group.component';
2
+ export * from './components/action-button/action-button.component';
@@ -0,0 +1,142 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import {
3
+ Injectable,
4
+ ViewContainerRef,
5
+ Type,
6
+ ComponentFactoryResolver,
7
+ Injector,
8
+ ComponentRef,
9
+ ComponentFactory,
10
+ OnChanges,
11
+ SimpleChanges,
12
+ SimpleChange,
13
+ EventEmitter,
14
+ OnDestroy,
15
+ } from '@angular/core';
16
+ import { ExtendedComponent } from '@verisoft/ui-core';
17
+ import { Subscription } from 'rxjs';
18
+
19
+ @Injectable({
20
+ providedIn: 'root',
21
+ })
22
+ export class DynamicComponentFactoryService implements OnDestroy {
23
+ constructor(private componentFactoryResolver: ComponentFactoryResolver) { }
24
+
25
+ ngOnDestroy(): void {
26
+ this.unsubscribeComponentEvents(this);
27
+ }
28
+
29
+ async createDynamicComponent<TComponent>(
30
+ componentType: Type<TComponent>,
31
+ viewContainerRef: ViewContainerRef,
32
+ inputs: ExtendedComponent<TComponent>,
33
+ injector: Injector | undefined = undefined
34
+ ) {
35
+ const componentFactory =
36
+ this.componentFactoryResolver.resolveComponentFactory(componentType);
37
+ viewContainerRef.clear();
38
+ const component = viewContainerRef.createComponent(
39
+ componentFactory,
40
+ undefined,
41
+ injector
42
+ );
43
+ this.setComponentDataInt(componentFactory, component, inputs);
44
+ this.fireComponentEvents(component.instance, inputs);
45
+ return component;
46
+ }
47
+
48
+ setComponentData<TComponent>(
49
+ component: ComponentRef<TComponent>,
50
+ inputs: Partial<TComponent>
51
+ ) {
52
+ const factory = this.componentFactoryResolver.resolveComponentFactory(
53
+ component.componentType
54
+ );
55
+
56
+ this.setComponentDataInt(factory, component, inputs);
57
+ }
58
+
59
+ private unsubscribeComponentEvents<TComponent>(instance: TComponent) {
60
+ const subscriptionStoreKey = '__outputSubscriptions__';
61
+ const subscriptions = (instance as any)[subscriptionStoreKey] as Map<string, Subscription>;
62
+
63
+ if (subscriptions) {
64
+ subscriptions.forEach((sub) => sub.unsubscribe());
65
+ subscriptions.clear();
66
+ }
67
+ }
68
+
69
+ private fireComponentEvents<TComponent>(
70
+ instance: TComponent,
71
+ inputs: ExtendedComponent<TComponent>
72
+ ) {
73
+ if (!instance || typeof instance !== 'object') return;
74
+
75
+ this.fireInputComponentEvents(instance, inputs);
76
+ this.fireOutputComponentEvents(instance, inputs);
77
+ }
78
+
79
+ private setComponentDataInt<TComponent>(
80
+ factory: ComponentFactory<TComponent>,
81
+ component: ComponentRef<TComponent>,
82
+ inputs: Partial<TComponent>
83
+ ) {
84
+ if (inputs) {
85
+ const propertyNames = factory.inputs.map((x) => x.propName);
86
+ const inputsHash = new Set(propertyNames);
87
+ Object.keys(inputs)
88
+ .filter((x) => inputsHash.has(x))
89
+ .forEach((x) => {
90
+ (<{ [key: string]: unknown }>component.instance)[x] = (<
91
+ { [key: string]: unknown }
92
+ >inputs)[x];
93
+ });
94
+ }
95
+ }
96
+
97
+ private fireInputComponentEvents<TComponent>(
98
+ instance: TComponent,
99
+ inputs: ExtendedComponent<TComponent>
100
+ ) {
101
+ const onChangeComponent = instance as unknown as OnChanges;
102
+ if (onChangeComponent.ngOnChanges && inputs) {
103
+ const changeEventArgs = Object.keys(inputs).reduce((changes: SimpleChanges, key: string) => {
104
+ const inputValue = (inputs as { [key: string]: unknown })[key];
105
+ changes[key] = new SimpleChange(undefined, inputValue, true);
106
+ return changes;
107
+ }, {} as SimpleChanges);
108
+
109
+ onChangeComponent.ngOnChanges(changeEventArgs);
110
+ }
111
+ }
112
+
113
+ private fireOutputComponentEvents<TComponent>(
114
+ instance: TComponent & object,
115
+ inputs: ExtendedComponent<TComponent>
116
+ ) {
117
+ const outputs = Object.keys(inputs).filter((key) => {
118
+ const emitter = (instance as Record<string, any>)[key];
119
+ return emitter instanceof EventEmitter;
120
+ });
121
+
122
+ const subscriptionStoreKey = '__outputSubscriptions__';
123
+ if (!(subscriptionStoreKey in instance)) {
124
+ (instance as any)[subscriptionStoreKey] = new Map<string, Subscription>();
125
+ }
126
+ const subscriptions = (instance as any)[subscriptionStoreKey] as Map<string, Subscription>;
127
+
128
+ for (const outputKey of outputs) {
129
+ const eventEmitter = (instance as Record<string, any>)[outputKey] as EventEmitter<any>;
130
+ const callback = inputs[outputKey] as (value: any) => void;
131
+
132
+ if (eventEmitter && typeof callback === 'function') {
133
+ if (subscriptions.has(outputKey)) {
134
+ subscriptions.get(outputKey)!.unsubscribe();
135
+ }
136
+
137
+ const subscription = eventEmitter.subscribe((value: any) => callback(value));
138
+ subscriptions.set(outputKey, subscription);
139
+ }
140
+ }
141
+ }
142
+ }
@@ -0,0 +1,56 @@
1
+ import {
2
+ AfterViewInit,
3
+ ChangeDetectionStrategy,
4
+ ChangeDetectorRef,
5
+ Component,
6
+ inject,
7
+ Injector,
8
+ Input,
9
+ OnChanges,
10
+ Type,
11
+ ViewChild,
12
+ ViewContainerRef,
13
+ } from '@angular/core';
14
+ import { ExtendedComponent } from '@verisoft/ui-core';
15
+ import { DynamicComponentFactoryService } from './dynamic-component-factory.service';
16
+
17
+ @Component({
18
+ selector: 'v-dynamic-component',
19
+ standalone: true,
20
+ changeDetection: ChangeDetectionStrategy.OnPush,
21
+ template: `<ng-container #dynamicContainer></ng-container>`,
22
+ })
23
+ export class DynamicComponent<TComponent> implements AfterViewInit, OnChanges {
24
+ @Input() componentType!: Type<TComponent>;
25
+
26
+ @Input() data!: ExtendedComponent<TComponent>;
27
+
28
+ @ViewChild('dynamicContainer', { read: ViewContainerRef, static: true })
29
+ container!: ViewContainerRef;
30
+
31
+ private factoryServices = inject(DynamicComponentFactoryService);
32
+
33
+ private changeDetectorRef = inject(ChangeDetectorRef);
34
+
35
+ private injector = inject(Injector);
36
+
37
+ ngOnChanges(): void {
38
+ this.createComponent();
39
+ }
40
+
41
+ ngAfterViewInit(): void {
42
+ this.createComponent();
43
+ this.changeDetectorRef.detectChanges();
44
+ }
45
+
46
+ private createComponent() {
47
+ if (this.container) {
48
+ this.factoryServices.createDynamicComponent(
49
+ this.componentType,
50
+ this.container,
51
+ this.data,
52
+ this.injector
53
+ );
54
+ }
55
+ }
56
+ }
@@ -0,0 +1,2 @@
1
+ export * from './dynamic-component-factory.service';
2
+ export * from './dynamic-component.component';
@@ -0,0 +1,98 @@
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-checkbox
79
+ [label]="label"
80
+ [testId]="testId"
81
+ [formControl]="formControl"
82
+ [indeterminate]="true"
83
+ />
84
+ } @else if (type === fieldTypes.simplecheckbox) {
85
+ <v-checkbox
86
+ [label]="label"
87
+ [testId]="testId"
88
+ [formControl]="formControl"
89
+ />
90
+ } @else if (type === fieldTypes.calendar) {
91
+ <v-calendar
92
+ [label]="!floatLabel ? label : ''"
93
+ [floatLabel]="floatLabel ? label : ''"
94
+ [testId]="testId"
95
+ [formControl]="formControl"
96
+ [icon]="icons.calendar"
97
+ />
98
+ }
@@ -0,0 +1,21 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+ import { GenericFieldComponent } from './generic-field.component';
3
+
4
+ describe('GenericFieldComponent', () => {
5
+ let component: GenericFieldComponent<string>;
6
+ let fixture: ComponentFixture<GenericFieldComponent<string>>;
7
+
8
+ beforeEach(async () => {
9
+ await TestBed.configureTestingModule({
10
+ imports: [GenericFieldComponent],
11
+ }).compileComponents();
12
+
13
+ fixture = TestBed.createComponent(GenericFieldComponent<string>);
14
+ component = fixture.componentInstance;
15
+ fixture.detectChanges();
16
+ });
17
+
18
+ it('should create', () => {
19
+ expect(component).toBeTruthy();
20
+ });
21
+ });