parent
c69aed2488
commit
5eb68b9338
@ -0,0 +1,92 @@
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<div class="title"><i [ngClass]="typeIcons.db + ' mr-10'"></i> Link Form to Database</div>
|
||||
<button
|
||||
class="clear-btn"
|
||||
style="padding: 0 20px; background: #4CB963;"
|
||||
(click)="dismiss(true)"
|
||||
title="Save changes and close"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
<button title="Close without saving" class="close" (click)="dismiss(false)">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ion-grid style="width: 100%; padding: 20px; height: 100%;">
|
||||
<ion-col size="12">
|
||||
<ion-item>
|
||||
<ion-label position="floating">Destination Database</ion-label>
|
||||
<ionic-selectable
|
||||
[items]="databases"
|
||||
itemTextField="name"
|
||||
itemValueField="uuid"
|
||||
[canSearch]="true"
|
||||
[title]="'Select a destination database for form submissions'"
|
||||
(onChange)="onDatabaseChange()"
|
||||
[(ngModel)]="selectedDatabase"
|
||||
>
|
||||
<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-col size="12" *ngIf="selectedDatabase">
|
||||
<ion-row>
|
||||
<ion-col size="12">
|
||||
<h3>Form-to-Database Mapping</h3>
|
||||
<p>In order for the form to save properly, define a mapping of which form fields should be stored in which database fields.</p>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row *ngFor="let item of mapping" style="border: 1px solid #999999; border-radius: 3px; margin: 15px 0;">
|
||||
<ion-col>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Form Field (Source)</ion-label>
|
||||
<ionic-selectable
|
||||
[items]="formFields"
|
||||
itemTextField="label"
|
||||
itemValueField="NodeId"
|
||||
[canSearch]="true"
|
||||
[title]="'Select the form field for this mapping'"
|
||||
[(ngModel)]="item.formNode"
|
||||
></ionic-selectable>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Database Column (Destination)</ion-label>
|
||||
<ionic-selectable
|
||||
[items]="selectedDatabaseColumns"
|
||||
itemTextField="name"
|
||||
itemValueField="uuid"
|
||||
[canSearch]="true"
|
||||
[title]="'Select the database column for this mapping'"
|
||||
[(ngModel)]="item.databaseColumn"
|
||||
></ionic-selectable>
|
||||
</ion-item>
|
||||
</ion-col>
|
||||
<ion-col size="1">
|
||||
<button
|
||||
class="clear-btn"
|
||||
style="padding: 15px; height: 100%; color: red; border: 2px solid white; border-radius: 3px;"
|
||||
title="Delete this mapping"
|
||||
(click)="onMappingDelete(item)"
|
||||
>
|
||||
<i class="fa fa-trash"></i>
|
||||
</button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row *ngIf="selectedDatabase">
|
||||
<ion-col size="12">
|
||||
<button
|
||||
style="width: 100%; background: none; color: #999999; border: 1px solid #999999; border-radius: 3px; padding: 10px;"
|
||||
(click)="onAddMappingClick($event)"
|
||||
>
|
||||
<i class="fa fa-plus mr-10"></i> Add Mapping
|
||||
</button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-col>
|
||||
</ion-grid>
|
||||
</div>
|
@ -0,0 +1,35 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.header {
|
||||
background: lightgrey;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.title {
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.close {
|
||||
padding: 10px 15px;
|
||||
background: #ff6666;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.revert {
|
||||
color: red;
|
||||
background: #eaeaea;
|
||||
}
|
||||
}
|
||||
|
||||
.contents {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {AlertController, ModalController} from '@ionic/angular';
|
||||
import {EditorService} from '../../../service/editor.service';
|
||||
import {debug} from '../../../utility';
|
||||
import {NodeTypeIcons} from '../../../structures/node-types';
|
||||
import {Database, DatabaseColumn} from '../../../structures/db-api';
|
||||
import {DbApiService} from '../../../service/db-api.service';
|
||||
import HostRecord from '../../../structures/HostRecord';
|
||||
|
||||
export interface FormDatabaseMap {
|
||||
formNodeId?: string;
|
||||
databaseColumnId?: string;
|
||||
|
||||
formNode?: any;
|
||||
databaseColumn?: DatabaseColumn;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'noded-form-database-link',
|
||||
templateUrl: './database-link.component.html',
|
||||
styleUrls: ['./database-link.component.scss'],
|
||||
})
|
||||
export class DatabaseLinkComponent implements OnInit {
|
||||
@Input() pageId: string;
|
||||
@Input() editorUUID: string;
|
||||
|
||||
public readonly typeIcons = NodeTypeIcons;
|
||||
public databases: Database[] = [];
|
||||
public selectedDatabase?: Database;
|
||||
public selectedDatabaseColumns: DatabaseColumn[] = [];
|
||||
public mapping: FormDatabaseMap[] = [];
|
||||
public formFields: any[] = [];
|
||||
|
||||
constructor(
|
||||
protected alerts: AlertController,
|
||||
protected modals: ModalController,
|
||||
protected editorService: EditorService,
|
||||
protected dbApi: DbApiService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
debug('Database link component', this);
|
||||
this.editorService = this.editorService.getEditor(this.editorUUID);
|
||||
|
||||
this.databases = await this.dbApi.getDatabases();
|
||||
|
||||
this.formFields = this.editorService.immutableNodes
|
||||
.filter(x => x.isForm())
|
||||
.map(x => {
|
||||
const data = {...x.AdditionalData};
|
||||
data.NodeId = x.UUID;
|
||||
return data;
|
||||
});
|
||||
|
||||
const meta = this.editorService.metadata;
|
||||
if ( meta?.formDatabaseId ) {
|
||||
this.selectedDatabase = this.databases.find(x => x.uuid === meta.formDatabaseId);
|
||||
await this.onDatabaseChange();
|
||||
}
|
||||
|
||||
if ( Array.isArray(meta?.formMapping) ) {
|
||||
this.mapping = meta.formMapping.map(x => {
|
||||
return {
|
||||
formNode: this.formFields.find(field => field.NodeId === x.formNodeId),
|
||||
databaseColumn: this.selectedDatabaseColumns.find(column => column.uuid === x.databaseColumnId),
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onAddMappingClick(event) {
|
||||
this.mapping.push({} as FormDatabaseMap);
|
||||
}
|
||||
|
||||
async onDatabaseChange() {
|
||||
this.mapping = [];
|
||||
this.selectedDatabaseColumns = await this.selectedDatabase.columns();
|
||||
}
|
||||
|
||||
onMappingDelete(item) {
|
||||
this.mapping = this.mapping.filter(x => x !== item);
|
||||
}
|
||||
|
||||
dismiss(save = false) {
|
||||
if ( save ) {
|
||||
const merge = {
|
||||
formDatabaseId: this.selectedDatabase?.uuid,
|
||||
formMapping: this.mapping.map(x => {
|
||||
return {
|
||||
formNodeId: x.formNode?.NodeId || x.formNodeId,
|
||||
databaseColumnId: x.databaseColumn?.uuid || x.databaseColumnId,
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
this.editorService.metadata = {
|
||||
...this.editorService.metadata,
|
||||
...merge,
|
||||
};
|
||||
|
||||
this.editorService.triggerSave();
|
||||
}
|
||||
|
||||
this.modals.dismiss();
|
||||
}
|
||||
}
|
Loading…
Reference in new issue