|
|
@ -0,0 +1,313 @@ |
|
|
|
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); |
|
|
|
} |
|
|
|
} |