|
|
|
import {Component, Input, OnInit, ViewChild} from '@angular/core';
|
|
|
|
import {ApiService, ResourceNotAvailableOfflineError} 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';
|
|
|
|
import {WysiwygEditorComponent} from './editors/wysiwyg/wysiwyg-editor.component';
|
|
|
|
import {debounce, debug, uuid_v4} from '../../../utility';
|
|
|
|
import {DateTimeFilterComponent} from './filters/date-time.filter';
|
|
|
|
import {DatabasePageComponent} from './database-page.component';
|
|
|
|
import {PageLinkRendererComponent} from './renderers/page-link-renderer.component';
|
|
|
|
import {LinkRendererComponent} from './renderers/link-renderer.component';
|
|
|
|
import {PageLinkEditorComponent} from './editors/page-link/page-link-editor.component';
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: 'editor-database',
|
|
|
|
templateUrl: './database.component.html',
|
|
|
|
styleUrls: ['./database.component.scss'],
|
|
|
|
})
|
|
|
|
export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
|
|
|
@Input() nodeId: string;
|
|
|
|
@Input() editorUUID?: string;
|
|
|
|
@Input() fullPage = false;
|
|
|
|
@ViewChild('agGridElement') agGridElement: AgGridAngular;
|
|
|
|
|
|
|
|
frameworkComponents = {
|
|
|
|
agDateInput: DateTimeFilterComponent
|
|
|
|
};
|
|
|
|
|
|
|
|
public dbRecord: any;
|
|
|
|
public pendingSetup = true;
|
|
|
|
public dirty = false;
|
|
|
|
public lastClickRow = -1;
|
|
|
|
public dbName = '';
|
|
|
|
public notAvailableOffline = false;
|
|
|
|
public pages = [];
|
|
|
|
protected dbId!: string;
|
|
|
|
protected isInitialLoad = false;
|
|
|
|
protected triggerSaveDebounce = debounce(() => {
|
|
|
|
if ( this.agGridElement.api.getCellEditorInstances().length < 1 ) {
|
|
|
|
this.editorService.triggerSave();
|
|
|
|
} else {
|
|
|
|
this.triggerSaveDebounce();
|
|
|
|
}
|
|
|
|
}, 1000);
|
|
|
|
|
|
|
|
protected gridReady = false;
|
|
|
|
protected deferredUIActivation = false;
|
|
|
|
|
|
|
|
title = 'app';
|
|
|
|
columnDefs = [];
|
|
|
|
rowData = [];
|
|
|
|
|
|
|
|
public isDark() {
|
|
|
|
return document.body.classList.contains('dark');
|
|
|
|
}
|
|
|
|
|
|
|
|
public get readonly() {
|
|
|
|
return !this.node || !this.editorService.canEdit();
|
|
|
|
}
|
|
|
|
|
|
|
|
constructor(
|
|
|
|
protected api: ApiService,
|
|
|
|
protected modals: ModalController,
|
|
|
|
protected alerts: AlertController,
|
|
|
|
protected loader: LoadingController,
|
|
|
|
public editorService: EditorService,
|
|
|
|
) { super(); }
|
|
|
|
|
|
|
|
public isDirty(): boolean | Promise<boolean> {
|
|
|
|
return this.dirty;
|
|
|
|
}
|
|
|
|
|
|
|
|
public needsSave(): boolean | Promise<boolean> {
|
|
|
|
return this.dirty;
|
|
|
|
}
|
|
|
|
|
|
|
|
public needsLoad(): boolean | Promise<boolean> {
|
|
|
|
return this.node && this.pendingSetup;
|
|
|
|
}
|
|
|
|
|
|
|
|
public writeChangesToNode(): void | Promise<void> {
|
|
|
|
this.node.Value.Mode = 'database';
|
|
|
|
}
|
|
|
|
|
|
|
|
async ngOnInit() {
|
|
|
|
this.pages = this.flattenItems(await this.api.getMenuItems(true));
|
|
|
|
this.editorService = this.editorService.getEditor(this.editorUUID);
|
|
|
|
this.editorService.registerNodeEditor(this.nodeId, this).then(() => {
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
protected flattenItems(items: any[], level = 0) {
|
|
|
|
let newItems = [];
|
|
|
|
|
|
|
|
for ( const item of items ) {
|
|
|
|
item.level = level;
|
|
|
|
newItems.push(item);
|
|
|
|
|
|
|
|
if ( Array.isArray(item.children) ) {
|
|
|
|
newItems = [...newItems, ...this.flattenItems(item.children, level + 1)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newItems;
|
|
|
|
}
|
|
|
|
|
|
|
|
onGridReady($event) {
|
|
|
|
this.gridReady = true;
|
|
|
|
if ( this.deferredUIActivation && !this.pendingSetup ) {
|
|
|
|
this.performUIActivation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onColumnResize($event) {
|
|
|
|
if ( $event.source === 'uiColumnDragged' && $event.finished ) {
|
|
|
|
debug('Column resized: ', $event);
|
|
|
|
const state = $event.columnApi.getColumnState().find(x => x.colId === $event.column.colId );
|
|
|
|
if ( state ) {
|
|
|
|
const colDef = this.columnDefs.find(x => x.field === $event.column.colId);
|
|
|
|
if ( colDef ) {
|
|
|
|
colDef.width = state.width;
|
|
|
|
this.dirty = true;
|
|
|
|
this.triggerSaveDebounce();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onRowDragEnd($event) {
|
|
|
|
if ( !this.isInitialLoad && this.editorService.canEdit() ) {
|
|
|
|
this.dirty = true;
|
|
|
|
this.triggerSaveDebounce();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
onCellValueChanged() {
|
|
|
|
if ( !this.isInitialLoad ) {
|
|
|
|
this.dirty = true;
|
|
|
|
this.triggerSaveDebounce();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async onManageColumns() {
|
|
|
|
if ( this.readonly ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const modal = await this.modals.create({
|
|
|
|
component: ColumnsComponent,
|
|
|
|
componentProps: {columnSets: this.columnDefs.slice(1)},
|
|
|
|
cssClass: 'modal-med',
|
|
|
|
});
|
|
|
|
|
|
|
|
modal.onDidDismiss().then(result => {
|
|
|
|
if ( result?.data ) {
|
|
|
|
this.setColumns(result.data);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
const modalState = {
|
|
|
|
modal : true,
|
|
|
|
desc : 'Manage Columns'
|
|
|
|
};
|
|
|
|
|
|
|
|
history.pushState(modalState, null);
|
|
|
|
|
|
|
|
await modal.present();
|
|
|
|
}
|
|
|
|
|
|
|
|
onInsertRow() {
|
|
|
|
if ( this.readonly ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.rowData.push({});
|
|
|
|
this.agGridElement.api.setRowData(this.rowData);
|
|
|
|
this.dirty = true;
|
|
|
|
this.triggerSaveDebounce();
|
|
|
|
}
|
|
|
|
|
|
|
|
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.triggerSaveDebounce();
|
|
|
|
},
|
|
|
|
}
|
|
|
|
],
|
|
|
|
});
|
|
|
|
|
|
|
|
await alert.present();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onRowClicked($event) {
|
|
|
|
this.lastClickRow = $event.rowIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
setColumns(data, triggerSave = true) {
|
|
|
|
this.columnDefs = [{
|
|
|
|
width: 20,
|
|
|
|
// rowDrag: !this.readonly,
|
|
|
|
// rowDragText: (params, dragItemCount) => `${dragItemCount} ${dragItemCount === 1 ? 'row' : 'rows'}`,
|
|
|
|
}, ...data.map(x => {
|
|
|
|
x.editable = !this.readonly;
|
|
|
|
x.minWidth = 150;
|
|
|
|
x.resizable = true;
|
|
|
|
x._parentEditorUUID = this.editorUUID;
|
|
|
|
|
|
|
|
if ( x.additionalData?.width ) {
|
|
|
|
x.width = x.additionalData.width;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( x.additionalData?.pinned ) {
|
|
|
|
x.pinned = x.additionalData.pinned;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set editors and renderers for different types
|
|
|
|
if ( x.Type === 'text' ) {
|
|
|
|
x.editor = 'agTextCellEditor';
|
|
|
|
x.filter = 'agTextColumnFilter';
|
|
|
|
} else if ( x.Type === 'number' ) {
|
|
|
|
x.cellEditorFramework = NumericEditorComponent;
|
|
|
|
x.filter = 'agNumberColumnFilter';
|
|
|
|
} else if ( x.Type === 'paragraph' ) {
|
|
|
|
x.cellEditorFramework = ParagraphEditorComponent;
|
|
|
|
x.filter = 'agTextColumnFilter';
|
|
|
|
} else if ( x.Type === 'boolean' ) {
|
|
|
|
x.cellRendererFramework = BooleanRendererComponent;
|
|
|
|
x.cellEditorFramework = BooleanEditorComponent;
|
|
|
|
x.suppressSizeToFit = true;
|
|
|
|
} else if ( x.Type === 'select' ) {
|
|
|
|
x.cellEditorFramework = SelectEditorComponent;
|
|
|
|
x.filter = 'agTextColumnFilter';
|
|
|
|
} else if ( x.Type === 'multiselect' ) {
|
|
|
|
x.cellEditorFramework = MultiSelectEditorComponent;
|
|
|
|
x.filter = 'agTextColumnFilter';
|
|
|
|
} else if ( x.Type === 'datetime' ) {
|
|
|
|
x.cellEditorFramework = DatetimeEditorComponent;
|
|
|
|
x.cellRendererFramework = DatetimeRendererComponent;
|
|
|
|
x.filter = 'agDateColumnFilter';
|
|
|
|
x.filterParams = {
|
|
|
|
buttons: ['apply', 'clear'],
|
|
|
|
displayFormat: x.additionalData.format,
|
|
|
|
comparator: (filterDate: Date, cellValue) => {
|
|
|
|
if ( !cellValue ) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const cellDate = new Date(cellValue);
|
|
|
|
|
|
|
|
if ( x.additionalData.format === 'YYYY-MM-DD' ) {
|
|
|
|
cellDate.setHours(0);
|
|
|
|
cellDate.setMinutes(0);
|
|
|
|
cellDate.setSeconds(0);
|
|
|
|
cellDate.setMilliseconds(0);
|
|
|
|
} else if ( x.additionalData.format === 'h:mm a' ) {
|
|
|
|
cellDate.setFullYear(filterDate.getFullYear());
|
|
|
|
cellDate.setMonth(filterDate.getMonth());
|
|
|
|
cellDate.setDate(filterDate.getDate());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now that both parameters are Date objects, we can compare
|
|
|
|
if (cellDate < filterDate) {
|
|
|
|
return -1;
|
|
|
|
} else if (cellDate > filterDate) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
} else if ( x.Type === 'currency' ) {
|
|
|
|
x.cellEditorFramework = NumericEditorComponent;
|
|
|
|
x.cellRendererFramework = CurrencyRendererComponent;
|
|
|
|
x.filter = 'agNumberColumnFilter';
|
|
|
|
} else if ( x.Type === 'index' ) {
|
|
|
|
x.editable = false;
|
|
|
|
x.suppressSizeToFit = true;
|
|
|
|
x.filter = 'agNumberColumnFilter';
|
|
|
|
if ( !x.width ) {
|
|
|
|
x.width = 80;
|
|
|
|
}
|
|
|
|
x.minWidth = 80;
|
|
|
|
} else if ( x.Type === 'wysiwyg' ) {
|
|
|
|
x.cellEditorFramework = WysiwygEditorComponent;
|
|
|
|
x.filter = 'agTextColumnFilter';
|
|
|
|
} else if ( x.Type === 'page_link' ) {
|
|
|
|
x.cellRendererFramework = PageLinkRendererComponent;
|
|
|
|
x.cellEditorFramework = PageLinkEditorComponent;
|
|
|
|
x.filter = 'agTextColumnFilter';
|
|
|
|
|
|
|
|
if ( !x.cellEditorParams ) {
|
|
|
|
x.cellEditorParams = {} as any;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !x.cellRendererParams ) {
|
|
|
|
x.cellRendererParams = {} as any;
|
|
|
|
}
|
|
|
|
|
|
|
|
x.cellEditorParams._pagesData = this.pages;
|
|
|
|
x.cellRendererParams._pagesData = this.pages;
|
|
|
|
} else if ( x.Type === 'link' ) {
|
|
|
|
x.cellRendererFramework = LinkRendererComponent;
|
|
|
|
x.editor = 'agTextCellEditor';
|
|
|
|
x.filter = 'agTextColumnFilter';
|
|
|
|
}
|
|
|
|
|
|
|
|
return x;
|
|
|
|
})];
|
|
|
|
|
|
|
|
this.agGridElement.api.setColumnDefs([]);
|
|
|
|
this.agGridElement.api.setColumnDefs(this.columnDefs);
|
|
|
|
this.agGridElement.api.sizeColumnsToFit();
|
|
|
|
if ( triggerSave ) {
|
|
|
|
this.dirty = true;
|
|
|
|
this.triggerSaveDebounce();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public onResized() {
|
|
|
|
this.agGridElement.api.sizeColumnsToFit();
|
|
|
|
}
|
|
|
|
|
|
|
|
public async performLoad(): Promise<void> {
|
|
|
|
this.isInitialLoad = true;
|
|
|
|
|
|
|
|
if ( !this.node.Value ) {
|
|
|
|
this.node.Value = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load the database record itself
|
|
|
|
if ( !this.node.Value.Value && this.editorService.canEdit() ) {
|
|
|
|
this.dbRecord = await this.api.createDatabase(this.page.UUID, this.node.UUID);
|
|
|
|
this.dbName = this.dbRecord.Name;
|
|
|
|
this.node.Value.Mode = 'database';
|
|
|
|
this.node.Value.Value = this.dbRecord.UUID;
|
|
|
|
this.node.value = this.dbRecord.UUID;
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
this.dbRecord = await this.api.getDatabase(
|
|
|
|
this.page.UUID, this.node.UUID, this.node.Value.Value, this.node.associatedTypeVersionNum);
|
|
|
|
this.dbName = this.dbRecord.Name;
|
|
|
|
this.notAvailableOffline = false;
|
|
|
|
} catch (e: unknown) {
|
|
|
|
if ( e instanceof ResourceNotAvailableOfflineError ) {
|
|
|
|
this.notAvailableOffline = true;
|
|
|
|
} else {
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load the columns
|
|
|
|
const columns = await this.api.getDatabaseColumns(
|
|
|
|
this.page.UUID, this.node.UUID, this.node.Value.Value, this.node.associatedTypeVersionNum);
|
|
|
|
this.setColumns(columns, false);
|
|
|
|
|
|
|
|
const rows = await this.api.getDatabaseEntries(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
|
|
|
this.rowData = rows.map(x => x.RowData);
|
|
|
|
this.agGridElement.api.setRowData(this.rowData);
|
|
|
|
|
|
|
|
this.pendingSetup = false;
|
|
|
|
this.dirty = false;
|
|
|
|
this.isInitialLoad = false;
|
|
|
|
|
|
|
|
if ( this.deferredUIActivation && this.gridReady ) {
|
|
|
|
await this.performUIActivation();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public async performDelete(): Promise<void> {
|
|
|
|
await this.api.deleteDatabase(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public getSaveColumns() {
|
|
|
|
return this.columnDefs.slice(1).map(x => {
|
|
|
|
if ( !x.additionalData ) {
|
|
|
|
x.additionalData = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( x.width ) {
|
|
|
|
x.additionalData.width = x.width;
|
|
|
|
}
|
|
|
|
|
|
|
|
return x;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public getRowNodeId(data: any) {
|
|
|
|
if ( !data.UUID ) {
|
|
|
|
data.UUID = uuid_v4();
|
|
|
|
}
|
|
|
|
|
|
|
|
return data.UUID;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected getAllRows() {
|
|
|
|
const rowData: any[] = [];
|
|
|
|
|
|
|
|
this.agGridElement.api.forEachNode(node => {
|
|
|
|
if ( !node.data.UUID ) {
|
|
|
|
node.data.UUID = uuid_v4();
|
|
|
|
}
|
|
|
|
|
|
|
|
rowData.push(node.data);
|
|
|
|
});
|
|
|
|
|
|
|
|
return rowData;
|
|
|
|
}
|
|
|
|
|
|
|
|
public async performSave(): Promise<void> {
|
|
|
|
// Save the columns first
|
|
|
|
await this.api.saveDatabaseColumns(this.page.UUID, this.node.UUID, this.node.Value.Value, this.getSaveColumns());
|
|
|
|
|
|
|
|
// Save the data
|
|
|
|
const allRows = this.getAllRows();
|
|
|
|
const rows = await this.api.saveDatabaseEntries(this.page.UUID, this.node.UUID, this.node.Value.Value, allRows);
|
|
|
|
// this.rowData = rows.map(x => x.RowData);
|
|
|
|
|
|
|
|
// Dynamically update the row data to avoid breaking open editors
|
|
|
|
const returnedUUIDs = rows.map(x => x.UUID);
|
|
|
|
const existingUUIDs = [];
|
|
|
|
|
|
|
|
const rowDataTransaction = {
|
|
|
|
add: [],
|
|
|
|
remove: [],
|
|
|
|
update: [],
|
|
|
|
};
|
|
|
|
|
|
|
|
this.agGridElement.api.forEachNode((rowNode, index) => {
|
|
|
|
const data = rowNode.data;
|
|
|
|
if ( !returnedUUIDs.includes(data.UUID) ) {
|
|
|
|
rowDataTransaction.remove.push(rowNode.id);
|
|
|
|
} else {
|
|
|
|
existingUUIDs.push(data.UUID);
|
|
|
|
const updatedRow = rows.find(x => x.UUID === data.UUID);
|
|
|
|
|
|
|
|
if ( updatedRow ) {
|
|
|
|
for ( const prop in updatedRow ) {
|
|
|
|
if ( !updatedRow.hasOwnProperty(prop) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
data[prop] = updatedRow[prop];
|
|
|
|
}
|
|
|
|
|
|
|
|
rowDataTransaction.update.push(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// for ( const row of rows ) {
|
|
|
|
// if ( !gridUUIDs.includes(row.UUID) ) {
|
|
|
|
// rowDataTransaction.add.push(row);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
this.agGridElement.api.applyTransaction(rowDataTransaction);
|
|
|
|
|
|
|
|
// this.agGridElement.api.setRowData(this.rowData);
|
|
|
|
|
|
|
|
// Save the name
|
|
|
|
await this.api.saveDatabaseName(this.page.UUID, this.node.UUID, this.node.Value.Value, this.dbName);
|
|
|
|
|
|
|
|
this.dirty = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
async openDatabase() {
|
|
|
|
const modal = await this.modals.create({
|
|
|
|
component: DatabasePageComponent,
|
|
|
|
componentProps: {
|
|
|
|
nodeId: this.nodeId,
|
|
|
|
pageId: this.editorService.currentPageId,
|
|
|
|
},
|
|
|
|
cssClass: 'modal-big',
|
|
|
|
});
|
|
|
|
|
|
|
|
modal.onDidDismiss().then(() => {
|
|
|
|
this.editorService.reload();
|
|
|
|
});
|
|
|
|
|
|
|
|
const modalState = {
|
|
|
|
modal : true,
|
|
|
|
desc : 'Open Database'
|
|
|
|
};
|
|
|
|
|
|
|
|
history.pushState(modalState, null);
|
|
|
|
|
|
|
|
await modal.present();
|
|
|
|
}
|
|
|
|
|
|
|
|
performUIActivation() {
|
|
|
|
if ( this.deferredUIActivation ) {
|
|
|
|
this.deferredUIActivation = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( this.gridReady && !this.pendingSetup ) {
|
|
|
|
return this.openDatabase();
|
|
|
|
} else {
|
|
|
|
this.deferredUIActivation = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
dismiss() {
|
|
|
|
this.modals.dismiss();
|
|
|
|
}
|
|
|
|
}
|