import {Component, Input, OnInit, ViewChild} from '@angular/core'; import {ApiService} from '../../../service/api.service'; import {AlertController, LoadingController, ModalController} from '@ionic/angular'; import {ColumnsComponent} from './columns/columns.component'; import {AgGridAngular} from 'ag-grid-angular'; import {NumericEditorComponent} from './editors/numeric/numeric-editor.component'; import {ParagraphEditorComponent} from './editors/paragraph/paragraph-editor.component'; import {BooleanEditorComponent} from './editors/boolean/boolean-editor.component'; import {SelectEditorComponent} from './editors/select/select-editor.component'; import {MultiSelectEditorComponent} from './editors/select/multiselect-editor.component'; import {DatetimeEditorComponent} from './editors/datetime/datetime-editor.component'; import {DatetimeRendererComponent} from './renderers/datetime-renderer.component'; import {CurrencyRendererComponent} from './renderers/currency-renderer.component'; import {BooleanRendererComponent} from './renderers/boolean-renderer.component'; import {EditorNodeContract} from '../../nodes/EditorNode.contract'; import {EditorService} from '../../../service/editor.service'; @Component({ selector: 'editor-database', templateUrl: './database.component.html', styleUrls: ['./database.component.scss'], }) export class DatabaseComponent extends EditorNodeContract implements OnInit { @Input() nodeId: string; @ViewChild('agGridElement') agGridElement: AgGridAngular; public dbRecord: any; public pendingSetup = true; public dirty = false; public lastClickRow = -1; public dbName = ''; protected dbId!: string; public get readonly() { return !this.node || !this.editorService.canEdit(); } constructor( protected api: ApiService, protected modals: ModalController, protected alerts: AlertController, protected loader: LoadingController, public readonly editorService: EditorService, ) { super(); } title = 'app'; columnDefs = []; rowData = []; public isDirty(): boolean | Promise { return this.dirty; } public needsSave(): boolean | Promise { return this.dirty; } public needsLoad(): boolean | Promise { return this.node && this.pendingSetup; } public writeChangesToNode(): void | Promise { this.node.Value.Mode = 'database'; } ngOnInit() { this.editorService.registerNodeEditor(this.nodeId, this).then(() => { }); } onCellValueChanged() { this.dirty = true; this.editorService.triggerSave(); } async onManageColumns() { if ( this.readonly ) { return; } const modal = await this.modals.create({ component: ColumnsComponent, componentProps: {columnSets: this.columnDefs}, }); modal.onDidDismiss().then(result => { this.setColumns(result.data); }); await modal.present(); } onInsertRow() { if ( this.readonly ) { return; } this.rowData.push({}); this.agGridElement.api.setRowData(this.rowData); this.dirty = true; this.editorService.triggerSave(); } async onRemoveRow() { if ( this.readonly ) { return; } const alert = await this.alerts.create({ header: 'Are you sure?', message: `You are about to delete row ${this.lastClickRow + 1}. This cannot be undone.`, buttons: [ { text: 'Keep It', role: 'cancel', }, { text: 'Delete It', handler: () => { this.rowData = this.rowData.filter((x, i) => { return i !== this.lastClickRow; }); this.agGridElement.api.setRowData(this.rowData); this.lastClickRow = -1; this.dirty = true; this.editorService.triggerSave(); }, } ], }); await alert.present(); } onRowClicked($event) { this.lastClickRow = $event.rowIndex; } setColumns(data) { this.columnDefs = data.map(x => { x.editable = !this.readonly; // Set editors and renderers for different types if ( x.Type === 'text' ) { x.editor = 'agTextCellEditor'; } else if ( x.Type === 'number' ) { x.cellEditorFramework = NumericEditorComponent; } else if ( x.Type === 'paragraph' ) { x.cellEditorFramework = ParagraphEditorComponent; } else if ( x.Type === 'boolean' ) { x.cellRendererFramework = BooleanRendererComponent; x.cellEditorFramework = BooleanEditorComponent; } else if ( x.Type === 'select' ) { x.cellEditorFramework = SelectEditorComponent; } else if ( x.Type === 'multiselect' ) { x.cellEditorFramework = MultiSelectEditorComponent; } else if ( x.Type === 'datetime' ) { x.cellEditorFramework = DatetimeEditorComponent; x.cellRendererFramework = DatetimeRendererComponent; } else if ( x.Type === 'currency' ) { x.cellEditorFramework = NumericEditorComponent; x.cellRendererFramework = CurrencyRendererComponent; } else if ( x.Type === 'index' ) { x.editable = false; } return x; }); this.agGridElement.api.setColumnDefs(this.columnDefs); this.dirty = true; this.editorService.triggerSave(); } public async performLoad(): Promise { if ( !this.node.Value ) { this.node.Value = {}; } // Load the database record itself if ( !this.node.Value.Value && this.editorService.canEdit() ) { await new Promise((res, rej) => { this.api.post(`/db/${this.page.UUID}/${this.node.UUID}/create`).subscribe({ next: result => { this.dbRecord = result.data; this.dbName = result.data.Name; this.node.Value.Mode = 'database'; this.node.Value.Value = result.data.UUID; this.node.value = result.data.UUID; res(); }, error: rej, }); }); } else { await new Promise((res, rej) => { this.api.get(`/db/${this.page.UUID}/${this.node.UUID}/get/${this.node.Value.Value}`).subscribe({ next: result => { this.dbRecord = result.data; this.dbName = result.data.Name; res(); }, error: rej, }); }); } // Load the columns await new Promise((res, rej) => { this.api.get(`/db/${this.page.UUID}/${this.node.UUID}/get/${this.node.Value.Value}/columns`).subscribe({ next: result => { this.setColumns(result.data); res(); }, error: rej, }); }); // Load the data await new Promise((res, rej) => { this.api.get(`/db/${this.page.UUID}/${this.node.UUID}/get/${this.node.Value.Value}/data`).subscribe({ next: result => { this.rowData = result.data.map(x => x.RowData); this.agGridElement.api.setRowData(this.rowData); res(); }, error: rej, }); }); this.pendingSetup = false; this.dirty = false; } public performDelete(): void | Promise { return new Promise((res, rej) => { this.api.post(`/db/${this.page.UUID}/${this.node.UUID}/drop/${this.node.Value.Value}`).subscribe({ next: result => { res(); }, error: rej, }); }); } public async performSave(): Promise { // Save the columns first await new Promise((res, rej) => { this.api.post(`/db/${this.page.UUID}/${this.node.UUID}/set/${this.node.Value.Value}/columns`, {columns: this.columnDefs}).subscribe({ next: result => { res(); }, error: rej, }); }); // Save the data await new Promise((res, rej) => { this.api.post(`/db/${this.page.UUID}/${this.node.UUID}/set/${this.node.Value.Value}/data`, this.rowData).subscribe({ next: result => { this.rowData = result.data.map(x => x.RowData); this.agGridElement.api.setRowData(this.rowData); res(); }, error: rej, }); }); // Save the name await new Promise((res, rej) => { this.api.post(`/db/${this.page.UUID}/${this.node.UUID}/set/${this.node.Value.Value}/name`, { Name: this.dbName }).subscribe({ next: result => { res(); }, error: rej, }); }); this.dirty = false; } }