Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { BaseEditFieldComponent } from './base-row-field.component';

describe('BaseEditFieldComponent', () => {
Expand All @@ -13,10 +12,26 @@ describe('BaseEditFieldComponent', () => {

fixture = TestBed.createComponent(BaseEditFieldComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should normalize label on init', () => {
fixture.componentRef.setInput('label', 'user_first_name');
component.ngOnInit();
expect(component.normalizedLabel()).toBeTruthy();
});

it('should set normalizedLabel from label input', () => {
fixture.componentRef.setInput('label', 'test_field');
component.ngOnInit();
expect(component.normalizedLabel()).toBeDefined();
expect(typeof component.normalizedLabel()).toBe('string');
});

it('should have onFieldChange event emitter', () => {
expect(component.onFieldChange).toBeDefined();
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, computed, input, OnInit, output } from '@angular/core';
import { TableField, TableForeignKey, WidgetStructure } from 'src/app/models/table';
import { normalizeFieldName } from '../../../../lib/normalize';

Expand All @@ -10,20 +10,18 @@ import { normalizeFieldName } from '../../../../lib/normalize';
imports: [CommonModule],
})
export class BaseEditFieldComponent implements OnInit {
@Input() key: string;
@Input() label: string;
@Input() required: boolean;
@Input() readonly: boolean;
@Input() structure: TableField;
@Input() disabled: boolean;
@Input() widgetStructure: WidgetStructure;
@Input() relations: TableForeignKey;
readonly key = input<string>();
readonly label = input<string>();
readonly required = input<boolean>(false);
readonly readonly = input<boolean>(false);
readonly structure = input<TableField>();
readonly disabled = input<boolean>(false);
readonly widgetStructure = input<WidgetStructure>();
readonly relations = input<TableForeignKey>();

@Output() onFieldChange = new EventEmitter<any>();
readonly onFieldChange = output<any>();

public normalizedLabel: string;
readonly normalizedLabel = computed(() => normalizeFieldName(this.label() || ''));

ngOnInit(): void {
this.normalizedLabel = normalizeFieldName(this.label);
}
ngOnInit(): void {}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="static-text">
<span>{{normalizedLabel}}</span>
<span>{{normalizedLabel()}}</span>
<span class="static-text__value"
attr.data-testid="record-{{label}}-binary-data-caption">
attr.data-testid="record-{{label()}}-binary-data-caption">
binary data
</span>
</div>
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
<div *ngIf="isRadiogroup; else checkboxElement" class="radio-line">
<label id="">{{normalizedLabel}}</label>
<mat-button-toggle-group name="{{label}}-{{key}}"
attr.data-testid="record-{{label}}-boolean-radio-group"
[hideSingleSelectionIndicator]="true"
[disabled]="disabled"
[value]="value">
<mat-button-toggle [value]=true (click)="onToggleChange(true)">Yes</mat-button-toggle>
<mat-button-toggle [value]=false (click)="onToggleChange(false)">No</mat-button-toggle>
</mat-button-toggle-group>
</div>

<ng-template #checkboxElement>
@if (isRadiogroup) {
<div class="radio-line">
<label id="">{{normalizedLabel}}</label>
<mat-button-toggle-group name="{{label}}-{{key}}"
attr.data-testid="record-{{label}}-boolean-radio-group"
<label id="">{{normalizedLabel()}}</label>
<mat-button-toggle-group name="{{label()}}-{{key()}}"
attr.data-testid="record-{{label()}}-boolean-radio-group"
[hideSingleSelectionIndicator]="true"
[disabled]="disabled"
[disabled]="disabled()"
[value]="value()">
<mat-button-toggle [value]=true (click)="onToggleChange(true)">Yes</mat-button-toggle>
<mat-button-toggle [value]=false (click)="onToggleChange(false)">No</mat-button-toggle>
</mat-button-toggle-group>
</div>
} @else {
<div class="radio-line">
<label id="">{{normalizedLabel()}}</label>
<mat-button-toggle-group name="{{label()}}-{{key()}}"
attr.data-testid="record-{{label()}}-boolean-radio-group"
[hideSingleSelectionIndicator]="true"
[disabled]="disabled()"
[(ngModel)]="value"
(ngModelChange)="onFieldChange.emit($event)">
<mat-button-toggle [value]=true>Yes</mat-button-toggle>
<mat-button-toggle [value]=false>No</mat-button-toggle>
</mat-button-toggle-group>
</div>
</ng-template>
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,40 +37,40 @@ describe('BooleanEditComponent', () => {
});

it('should set value in true when input value contain anything', () => {
component.value = 'anything';
component.structure = fakeStructure;
fixture.componentRef.setInput('value', 'anything');
fixture.componentRef.setInput('structure', fakeStructure);
component.ngOnInit();

expect(component.value).toBeTruthy();
expect(component.value()).toBeTruthy();
});

it('should set value in felse when input value is 0', () => {
component.value = 0;
component.structure = fakeStructure;
fixture.componentRef.setInput('value', 0);
fixture.componentRef.setInput('structure', fakeStructure);
component.ngOnInit();

expect(component.value).toBeFalsy();
expect(component.value()).toBeFalsy();
});

it('should set value in null when input value is undefined', () => {
component.value = undefined;
component.structure = fakeStructure;
fixture.componentRef.setInput('value', undefined);
fixture.componentRef.setInput('structure', fakeStructure);
component.ngOnInit();

expect(component.value).toEqual(null);
expect(component.value()).toEqual(null);
});

it('should set isRadiogroup in false if allow_null is false', () => {
component.value = undefined;
component.structure = fakeStructure;
fixture.componentRef.setInput('value', undefined);
fixture.componentRef.setInput('structure', fakeStructure);
component.ngOnInit();

expect(component.isRadiogroup).toEqual(false);
});

it('should set isRadiogroup in true if allow_null is true', () => {
component.value = undefined;
component.structure = {
fixture.componentRef.setInput('value', undefined);
fixture.componentRef.setInput('structure', {
column_name: 'banned',
column_default: '0',
data_type: 'tinyint',
Expand All @@ -79,7 +79,7 @@ describe('BooleanEditComponent', () => {
auto_increment: false,
allow_null: true,
character_maximum_length: 1,
};
});
component.ngOnInit();

expect(component.isRadiogroup).toEqual(true);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
import { Component, inject, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { DBtype } from 'src/app/models/connection';
Expand All @@ -13,48 +13,43 @@ import { BaseEditFieldComponent } from '../base-row-field/base-row-field.compone
imports: [CommonModule, FormsModule, MatButtonToggleModule],
})
export class BooleanEditComponent extends BaseEditFieldComponent {
@Input() value: boolean | number | string | null;
readonly value = model<boolean | number | string | null>();

public isRadiogroup: boolean;
connectionType: DBtype;

constructor(private _connections: ConnectionsService) {
super();
}
private _connections = inject(ConnectionsService);

ngOnInit(): void {
super.ngOnInit();
this.connectionType = this._connections.currentConnection.type;

if (this.value) {
this.value = true;
} else if (this.value === 0 || this.value === '' || this.value === false) {
this.value = false;
const val = this.value();
if (val) {
this.value.set(true);
} else if (val === 0 || val === '' || val === false) {
this.value.set(false);
} else {
this.value = null;
this.value.set(null);
}

this.onFieldChange.emit(this.value);
this.onFieldChange.emit(this.value());

// Parse widget parameters if available
let parsedParams = null;
if (this.widgetStructure?.widget_params) {
parsedParams =
typeof this.widgetStructure.widget_params === 'string'
? JSON.parse(this.widgetStructure.widget_params)
: this.widgetStructure.widget_params;
const ws = this.widgetStructure();
if (ws?.widget_params) {
parsedParams = typeof ws.widget_params === 'string' ? JSON.parse(ws.widget_params) : ws.widget_params;
}

// Check allow_null from either structure or widget params
this.isRadiogroup = this.structure?.allow_null || !!parsedParams?.allow_null;
this.isRadiogroup = this.structure()?.allow_null || !!parsedParams?.allow_null;
}

onToggleChange(optionValue: boolean): void {
if (this.value === optionValue) {
this.value = null;
if (this.value() === optionValue) {
this.value.set(null);
} else {
this.value = optionValue;
this.value.set(optionValue);
}
this.onFieldChange.emit(this.value);
this.onFieldChange.emit(this.value());
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<span class="mat-body-1">{{ normalizedLabel }} {{ required ? '*' : '' }}</span>
<span class="mat-body-1">{{ normalizedLabel() }} {{ required() ? '*' : '' }}</span>

<div class="code-editor-box ph-no-capture">
<ngs-code-editor
[theme]="codeEditorTheme"
[codeModel]="mutableCodeModel"
[options]="codeEditorOptions"
[readOnly]="readonly"
[readOnly]="readonly()"
(valueChanged)="onFieldChange.emit($event)">
</ngs-code-editor>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ describe('CodeEditComponent', () => {
fixture = TestBed.createComponent(CodeEditComponent);
component = fixture.componentInstance;

component.widgetStructure = {
fixture.componentRef.setInput('widgetStructure', {
widget_params: {
language: 'css',
},
} as any;
component.label = 'styles';
component.value = '.container { display: flex; }';
} as any);
fixture.componentRef.setInput('label', 'styles');
fixture.componentRef.setInput('value', '.container { display: flex; }');

fixture.detectChanges();
});
Expand Down Expand Up @@ -69,21 +69,21 @@ describe('CodeEditComponent', () => {
});

it('should support different languages', () => {
component.widgetStructure = {
fixture.componentRef.setInput('widgetStructure', {
widget_params: {
language: 'javascript',
},
} as any;
component.label = 'script';
component.value = 'console.log("hello");';
} as any);
fixture.componentRef.setInput('label', 'script');
fixture.componentRef.setInput('value', 'console.log("hello");');
component.ngOnInit();

expect((component.mutableCodeModel as any).language).toBe('javascript');
});

it('should normalize label from base class', () => {
component.label = 'custom_styles';
fixture.componentRef.setInput('label', 'custom_styles');
component.ngOnInit();
expect(component.normalizedLabel).toBeDefined();
expect(component.normalizedLabel()).toBeDefined();
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CommonModule } from '@angular/common';
import { Component, Input } from '@angular/core';
import { Component, inject, model } from '@angular/core';
import { CodeEditorModule } from '@ngstack/code-editor';
import { UiSettingsService } from 'src/app/services/ui-settings.service';
import { BaseEditFieldComponent } from '../base-row-field/base-row-field.component';
Expand All @@ -11,7 +11,9 @@ import { BaseEditFieldComponent } from '../base-row-field/base-row-field.compone
imports: [CommonModule, CodeEditorModule],
})
export class CodeEditComponent extends BaseEditFieldComponent {
@Input() value;
readonly value = model<any>();

private _uiSettings = inject(UiSettingsService);

public mutableCodeModel: Object;
public codeEditorOptions = {
Expand All @@ -22,16 +24,12 @@ export class CodeEditComponent extends BaseEditFieldComponent {
};
public codeEditorTheme = 'vs-dark';

constructor(private _uiSettings: UiSettingsService) {
super();
}

ngOnInit(): void {
super.ngOnInit();
this.mutableCodeModel = {
language: `${this.widgetStructure.widget_params.language}`,
uri: `${this.label}.json`,
value: this.value,
language: `${this.widgetStructure().widget_params.language}`,
uri: `${this.label()}.json`,
value: this.value(),
};

this.codeEditorTheme = this._uiSettings.isDarkMode ? 'vs-dark' : 'vs';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<div class="color-edit-container">
<mat-form-field class="color-form-field" appearance="outline">
<mat-label>{{normalizedLabel}}</mat-label>
<input matInput type="text" name="{{label}}-{{key}}"
[required]="required" [disabled]="disabled" [readonly]="readonly"
attr.data-testid="record-{{label}}-color"
<mat-label>{{normalizedLabel()}}</mat-label>
<input matInput type="text" name="{{label()}}-{{key()}}"
[required]="required()" [disabled]="disabled()" [readonly]="readonly()"
attr.data-testid="record-{{label()}}-color"
[(ngModel)]="value" (ngModelChange)="onTextInputChange()"
placeholder="e.g. #000000, rgb(0,0,0), hsl(0,0%,0%)">
<div matSuffix class="color-picker-container">
<input type="color"
<input type="color"
class="color-picker-input"
[value]="normalizedColorForPicker"
[disabled]="disabled || readonly"
[disabled]="disabled() || readonly()"
(change)="onColorPickerChange($event)"
title="Choose color">
</div>
Expand Down
Loading
Loading