You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
frontend/src/app/components/nodes/form-input/options/form-input-options.componen...

314 lines
14 KiB

import {Component, Input, OnInit} from '@angular/core';
import {EditorService} from '../../../../service/editor.service';
import {ModalController} from '@ionic/angular';
import HostRecord from '../../../../structures/HostRecord';
import {debug} from '../../../../utility';
import {DbApiService} from '../../../../service/db-api.service';
import {Database, DatabaseColumn} from '../../../../structures/db-api';
import {NodeTypeIcons} from '../../../../structures/node-types';
@Component({
selector: 'noded-node-form-input-options',
template: `
<ion-header>
<ion-toolbar>
<ion-title>Edit Form Input</ion-title>
<ion-buttons slot="end">
<ion-button (click)="dismissModal(true)">
<ion-icon name="save"></ion-icon>
</ion-button>
<ion-button (click)="dismissModal(false)">
<ion-icon name="close"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<ion-grid>
<ion-row>
<ion-col size="12">
<ion-item>
<ion-label [position]="'floating'">Label Text</ion-label>
<ion-input [(ngModel)]="label"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col size="12">
<ion-item>
<ion-label [position]="'floating'">Placeholder Text</ion-label>
<ion-input [(ngModel)]="placeholder"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row>
<ion-col size="12">
<ion-item>
<ion-checkbox slot="start" [(ngModel)]="required">
</ion-checkbox>
Required
</ion-item>
</ion-col>
</ion-row>
<ion-row *ngIf="node.type === 'form_input_select' || node.type === 'form_input_multiselect'">
<ion-col size="12" [title]="'Defines where the options for the select field should come from'">
<ion-item>
<ion-label [position]="'floating'">Select Options Source</ion-label>
<ion-select
[(ngModel)]="selectSource"
style="width: 100%;"
>
<ion-select-option value="local">Static Options</ion-select-option>
<ion-select-option value="database">Database Values</ion-select-option>
</ion-select>
</ion-item>
</ion-col>
</ion-row>
<ion-row
*ngIf="
(node.type === 'form_input_select' || node.type === 'form_input_multiselect')
&& this.selectSource === 'database'"
>
<ion-col size="12">
<ion-item>
<ion-label position="floating">Source Database</ion-label>
<ionic-selectable
[items]="databases"
itemTextField="name"
itemValueField="uuid"
[canSearch]="true"
[title]="'Select a source database'"
[(ngModel)]="selectedDatabase"
(onChange)="onSelectDatabaseChange()"
>
<ng-template ionicSelectableItemTemplate let-port="item" let-isPortSelected="itemIsSelected">
<div><i [ngClass]="typeIcons.db" style="margin-right: 15px;"></i>{{ port.name }}</div>
</ng-template>
</ionic-selectable>
</ion-item>
</ion-col>
</ion-row>
<ion-row
*ngIf="
(node.type === 'form_input_select' || node.type === 'form_input_multiselect')
&& this.selectSource === 'database' && this.selectedDatabase"
>
<ion-col size="6">
<ion-item>
<ion-label position="floating">Display Column</ion-label>
<ionic-selectable
[items]="selectedDatabaseColumns"
itemTextField="name"
itemValueField="uuid"
[canSearch]="true"
[title]="'Select the column to be used as the display value'"
[(ngModel)]="selectDatabaseDisplayColumn"
></ionic-selectable>
</ion-item>
</ion-col>
<ion-col size="6">
<ion-item>
<ion-label position="floating">Value Column</ion-label>
<ionic-selectable
[items]="selectedDatabaseColumns"
itemTextField="name"
itemValueField="uuid"
[canSearch]="true"
[title]="'Select the column to be used as the record value'"
[(ngModel)]="selectDatabaseValueColumn"
></ionic-selectable>
</ion-item>
</ion-col>
</ion-row>
<ion-row
*ngIf="
(node.type === 'form_input_select' || node.type === 'form_input_multiselect')
&& this.selectSource === 'local'"
>
<ion-header style="display: flex; padding-top: 20px;">
<h5 style="flex: 1;">Options</h5>
<button [title]="'Add new option'" (click)="onAddSelectOption()">
<i class="fa fa-plus"></i>
</button>
</ion-header>
<ion-grid>
<ion-row *ngFor="let option of selectStaticOptions">
<ion-col size="5">
<ion-item>
<ion-label position="floating">Display</ion-label>
<ion-input [(ngModel)]="option.display"></ion-input>
</ion-item>
</ion-col>
<ion-col size="5">
<ion-item>
<ion-label position="floating">Value</ion-label>
<ion-input [(ngModel)]="option.value"></ion-input>
</ion-item>
</ion-col>
<ion-col size="2">
<button [title]="'Remove this option'" style="height: 100px; padding: 10px; color: red;" (click)="onRemoveSelectOption(option)">
<i class="fa fa-trash"></i>
</button>
</ion-col>
</ion-row>
</ion-grid>
</ion-row>
<ion-row *ngIf="node.type === 'form_input_password' || node.type === 'form_input_text'">
<ion-col size="6">
<ion-item>
<ion-label [position]="'floating'">Min Length</ion-label>
<ion-input type="'number'" [(ngModel)]="minLength"></ion-input>
</ion-item>
</ion-col>
<ion-col size="6">
<ion-item>
<ion-label [position]="'floating'">Max Length</ion-label>
<ion-input type="'number'" [(ngModel)]="maxLength"></ion-input>
</ion-item>
</ion-col>
</ion-row>
<ion-row *ngIf="node.type === 'form_input_number'">
<ion-col size="6">
<ion-item>
<ion-label [position]="'floating'">Min</ion-label>
<ion-input type="'number'" [(ngModel)]="min"></ion-input>
</ion-item>
</ion-col>
<ion-col size="6">
<ion-item>
<ion-label [position]="'floating'">Max</ion-label>
<ion-input type="'number'" [(ngModel)]="max"></ion-input>
</ion-item>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
`,
})
export class FormInputOptionsComponent implements OnInit {
@Input() node: HostRecord;
@Input() editorUUID: string;
public typeIcons = NodeTypeIcons;
public label = '';
public placeholder = '';
public required = false;
public minLength?: number;
public maxLength?: number;
public min?: number;
public max?: number;
public selectSource?: 'local'|'database';
public selectDatabaseDisplayColumn?: DatabaseColumn;
public selectDatabaseValueColumn?: DatabaseColumn;
public selectStaticOptions: { display: string, value: string }[] = [];
public databases: Database[] = [];
public selectedDatabase?: Database;
public selectedDatabaseColumns: DatabaseColumn[] = [];
constructor(
public editorService: EditorService,
public readonly dbApi: DbApiService,
public readonly modal: ModalController,
) { }
async ngOnInit() {
debug('Form input options', this);
this.editorService = this.editorService.getEditor(this.editorUUID);
this.label = this.node.AdditionalData.label;
this.placeholder = this.node.AdditionalData.placeholder;
this.required = this.node.AdditionalData.required;
if ( this.node.type === 'form_input_password' || this.node.type === 'form_input_text' ) {
this.minLength = this.node.AdditionalData.minLength;
this.maxLength = this.node.AdditionalData.maxLength;
}
if ( this.node.type === 'form_input_number' ) {
this.min = this.node.AdditionalData.min;
this.max = this.node.AdditionalData.max;
}
if ( this.node.type === 'form_input_select' || this.node.type === 'form_input_multiselect' ) {
this.selectSource = this.node.AdditionalData.selectSource;
this.databases = await this.dbApi.getDatabases();
if ( this.selectSource === 'database' ) {
this.selectedDatabase = this.databases.find(x => x.uuid === this.node.AdditionalData.selectSourceDatabaseId);
await this.onSelectDatabaseChange();
this.selectDatabaseValueColumn = this.selectedDatabaseColumns.find(x => {
return x.field === this.node.AdditionalData.selectDatabaseValueColumnId;
});
this.selectDatabaseDisplayColumn = this.selectedDatabaseColumns.find(x => {
return x.field === this.node.AdditionalData.selectDatabaseDisplayColumnId;
});
} else if ( this.selectSource === 'local' ) {
this.selectStaticOptions = this.node.AdditionalData.selectStaticOptions || [];
}
}
}
dismissModal(success = true) {
if ( success ) {
this.node.AdditionalData.label = this.label;
this.node.AdditionalData.placeholder = this.placeholder;
this.node.AdditionalData.required = !!this.required;
}
if ( this.node.type === 'form_input_password' || this.node.type === 'form_input_text' ) {
this.node.AdditionalData.minLength = this.minLength;
this.node.AdditionalData.maxLength = this.maxLength;
}
if ( this.node.type === 'form_input_number' ) {
this.node.AdditionalData.min = this.min;
this.node.AdditionalData.max = this.max;
}
if ( this.node.type === 'form_input_select' || this.node.type === 'form_input_multiselect' ) {
this.node.AdditionalData.selectSource = this.selectSource;
if ( this.selectSource === 'database' ) {
this.node.AdditionalData.selectSourceDatabaseId = this.selectedDatabase?.uuid;
this.node.AdditionalData.selectDatabaseValueColumnId = this.selectDatabaseValueColumn?.field;
this.node.AdditionalData.selectDatabaseDisplayColumnId = this.selectDatabaseDisplayColumn?.field;
} else if ( this.selectSource === 'local' ) {
this.node.AdditionalData.selectStaticOptions = this.selectStaticOptions;
}
}
this.modal.dismiss(success);
}
async onSelectDatabaseChange() {
if ( this.selectedDatabase ) {
this.selectedDatabaseColumns = await this.selectedDatabase.columns();
} else {
this.selectedDatabaseColumns = [];
}
this.selectDatabaseDisplayColumn = undefined;
this.selectDatabaseValueColumn = undefined;
}
onAddSelectOption() {
this.selectStaticOptions.push({
display: '',
value: '',
});
}
onRemoveSelectOption(option: any) {
this.selectStaticOptions = this.selectStaticOptions.filter(x => x !== option);
}
}