Add offline caching for databases, database columns, and database entries
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
8de9db08a6
commit
02d8505b05
@ -38,7 +38,8 @@ export class ColumnsComponent implements OnInit {
|
|||||||
this.columnSets = this.columnSets.map(x => {
|
this.columnSets = this.columnSets.map(x => {
|
||||||
x.field = x.headerName;
|
x.field = x.headerName;
|
||||||
return x;
|
return x;
|
||||||
})
|
});
|
||||||
|
|
||||||
this.modals.dismiss(this.columnSets);
|
this.modals.dismiss(this.columnSets);
|
||||||
} else {
|
} else {
|
||||||
this.modals.dismiss();
|
this.modals.dismiss();
|
||||||
@ -46,10 +47,9 @@ export class ColumnsComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDeleteClick(i) {
|
onDeleteClick(i) {
|
||||||
const newSets = this.columnSets.filter((x, index) => {
|
this.columnSets = this.columnSets.filter((x, index) => {
|
||||||
return index !== i;
|
return index !== i;
|
||||||
});
|
});
|
||||||
this.columnSets = newSets;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpArrow(i) {
|
onUpArrow(i) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {Component, Input, OnInit, ViewChild} from '@angular/core';
|
import {Component, Input, OnInit, ViewChild} from '@angular/core';
|
||||||
import {ApiService} from '../../../service/api.service';
|
import {ApiService, ResourceNotAvailableOfflineError} from '../../../service/api.service';
|
||||||
import {AlertController, LoadingController, ModalController} from '@ionic/angular';
|
import {AlertController, LoadingController, ModalController} from '@ionic/angular';
|
||||||
import {ColumnsComponent} from './columns/columns.component';
|
import {ColumnsComponent} from './columns/columns.component';
|
||||||
import {AgGridAngular} from 'ag-grid-angular';
|
import {AgGridAngular} from 'ag-grid-angular';
|
||||||
@ -29,6 +29,7 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
|||||||
public dirty = false;
|
public dirty = false;
|
||||||
public lastClickRow = -1;
|
public lastClickRow = -1;
|
||||||
public dbName = '';
|
public dbName = '';
|
||||||
|
public notAvailableOffline = false;
|
||||||
protected dbId!: string;
|
protected dbId!: string;
|
||||||
|
|
||||||
public get readonly() {
|
public get readonly() {
|
||||||
@ -181,102 +182,52 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
|||||||
|
|
||||||
// Load the database record itself
|
// Load the database record itself
|
||||||
if ( !this.node.Value.Value && this.editorService.canEdit() ) {
|
if ( !this.node.Value.Value && this.editorService.canEdit() ) {
|
||||||
await new Promise((res, rej) => {
|
this.dbRecord = await this.api.createDatabase(this.page.UUID, this.node.UUID);
|
||||||
this.api.post(`/db/${this.page.UUID}/${this.node.UUID}/create`).subscribe({
|
this.dbName = this.dbRecord.Name;
|
||||||
next: result => {
|
|
||||||
this.dbRecord = result.data;
|
|
||||||
this.dbName = result.data.Name;
|
|
||||||
this.node.Value.Mode = 'database';
|
this.node.Value.Mode = 'database';
|
||||||
this.node.Value.Value = result.data.UUID;
|
this.node.Value.Value = this.dbRecord.UUID;
|
||||||
this.node.value = result.data.UUID;
|
this.node.value = this.dbRecord.UUID;
|
||||||
res();
|
|
||||||
},
|
|
||||||
error: rej,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
await new Promise((res, rej) => {
|
try {
|
||||||
this.api.get(`/db/${this.page.UUID}/${this.node.UUID}/get/${this.node.Value.Value}`).subscribe({
|
this.dbRecord = await this.api.getDatabase(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
||||||
next: result => {
|
this.dbName = this.dbRecord.Name;
|
||||||
this.dbRecord = result.data;
|
this.notAvailableOffline = false;
|
||||||
this.dbName = result.data.Name;
|
} catch (e: unknown) {
|
||||||
res();
|
if ( e instanceof ResourceNotAvailableOfflineError ) {
|
||||||
},
|
this.notAvailableOffline = true;
|
||||||
error: rej,
|
} else {
|
||||||
});
|
throw e;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the columns
|
// Load the columns
|
||||||
await new Promise((res, rej) => {
|
const columns = await this.api.getDatabaseColumns(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
||||||
this.api.get(`/db/${this.page.UUID}/${this.node.UUID}/get/${this.node.Value.Value}/columns`).subscribe({
|
this.setColumns(columns);
|
||||||
next: result => {
|
|
||||||
this.setColumns(result.data);
|
|
||||||
res();
|
|
||||||
},
|
|
||||||
error: rej,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load the data
|
const rows = await this.api.getDatabaseEntries(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
||||||
await new Promise((res, rej) => {
|
this.rowData = rows.map(x => x.RowData);
|
||||||
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);
|
this.agGridElement.api.setRowData(this.rowData);
|
||||||
res();
|
|
||||||
},
|
|
||||||
error: rej,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
this.pendingSetup = false;
|
this.pendingSetup = false;
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public performDelete(): void | Promise<void> {
|
public async performDelete(): Promise<void> {
|
||||||
return new Promise((res, rej) => {
|
await this.api.deleteDatabase(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
||||||
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<void> {
|
public async performSave(): Promise<void> {
|
||||||
// Save the columns first
|
// Save the columns first
|
||||||
await new Promise((res, rej) => {
|
await this.api.saveDatabaseColumns(this.page.UUID, this.node.UUID, this.node.Value.Value, this.columnDefs);
|
||||||
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
|
// Save the data
|
||||||
await new Promise((res, rej) => {
|
const rows = await this.api.saveDatabaseEntries(this.page.UUID, this.node.UUID, this.node.Value.Value, this.rowData);
|
||||||
this.api.post(`/db/${this.page.UUID}/${this.node.UUID}/set/${this.node.Value.Value}/data`, this.rowData).subscribe({
|
this.rowData = rows.map(x => x.RowData);
|
||||||
next: result => {
|
|
||||||
this.rowData = result.data.map(x => x.RowData);
|
|
||||||
this.agGridElement.api.setRowData(this.rowData);
|
this.agGridElement.api.setRowData(this.rowData);
|
||||||
res();
|
|
||||||
},
|
|
||||||
error: rej,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Save the name
|
// Save the name
|
||||||
await new Promise((res, rej) => {
|
await this.api.saveDatabaseName(this.page.UUID, this.node.UUID, this.node.Value.Value, this.dbName);
|
||||||
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;
|
this.dirty = false;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ import {MenuItem} from './db/MenuItem';
|
|||||||
import {DatabaseService} from './db/database.service';
|
import {DatabaseService} from './db/database.service';
|
||||||
import {ConnectionService} from 'ng-connection-service';
|
import {ConnectionService} from 'ng-connection-service';
|
||||||
import {Codium} from './db/Codium';
|
import {Codium} from './db/Codium';
|
||||||
|
import {Database} from './db/Database';
|
||||||
|
import {DatabaseColumn} from './db/DatabaseColumn';
|
||||||
|
import {DatabaseEntry} from './db/DatabaseEntry';
|
||||||
|
|
||||||
export class ResourceNotAvailableOfflineError extends Error {
|
export class ResourceNotAvailableOfflineError extends Error {
|
||||||
constructor(msg = 'This resource is not yet available offline on this device.') {
|
constructor(msg = 'This resource is not yet available offline on this device.') {
|
||||||
@ -122,7 +125,7 @@ export class ApiService {
|
|||||||
|
|
||||||
protected _request(endpoint, params = {}, method: 'get'|'post' = 'get'): Observable<ApiResponse> {
|
protected _request(endpoint, params = {}, method: 'get'|'post' = 'get'): Observable<ApiResponse> {
|
||||||
return new Observable<ApiResponse>(sub => {
|
return new Observable<ApiResponse>(sub => {
|
||||||
let data: any = {}
|
let data: any = {};
|
||||||
if ( method === 'get' ) {
|
if ( method === 'get' ) {
|
||||||
data.params = params;
|
data.params = params;
|
||||||
} else {
|
} else {
|
||||||
@ -387,4 +390,317 @@ export class ApiService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public deleteDatabase(PageId: string, NodeId: string, DatabaseId: string): Promise<void> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
const existingLocalDatabase = await this.db.databases.where({ UUID: DatabaseId }).first() as Database;
|
||||||
|
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
if ( existingLocalDatabase ) {
|
||||||
|
existingLocalDatabase.needsServerUpdate = true;
|
||||||
|
existingLocalDatabase.deleted = true;
|
||||||
|
await existingLocalDatabase.save();
|
||||||
|
return res();
|
||||||
|
} else {
|
||||||
|
return rej(new ResourceNotAvailableOfflineError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.post(`/db/${PageId}/${NodeId}/drop/${DatabaseId}`).subscribe({
|
||||||
|
next: async result => {
|
||||||
|
if ( existingLocalDatabase ) {
|
||||||
|
await this.db.databases.delete(existingLocalDatabase.id);
|
||||||
|
res();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatabaseEntries(PageId: string, NodeId: string, DatabaseId: string): Promise<any[]> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
const rows = (await this.db.databaseEntries.where({ DatabaseId }).toArray()) as DatabaseEntry[];
|
||||||
|
return res(rows.filter(x => !x.deleted).map(x => x.inflateToRecord()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get(`/db/${PageId}/${NodeId}/get/${DatabaseId}/data`).subscribe({
|
||||||
|
next: async result => {
|
||||||
|
for ( const row of result.data ) {
|
||||||
|
const existingDatabaseEntry = await this.db.databaseEntries.where({
|
||||||
|
DatabaseId, UUID: row.UUID,
|
||||||
|
}).first() as DatabaseEntry;
|
||||||
|
|
||||||
|
if ( existingDatabaseEntry ) {
|
||||||
|
existingDatabaseEntry.fillFromRecord(row);
|
||||||
|
await existingDatabaseEntry.save();
|
||||||
|
} else {
|
||||||
|
const newDatabaseEntry = new DatabaseEntry(
|
||||||
|
row.DatabaseId,
|
||||||
|
JSON.stringify(row.RowData),
|
||||||
|
row.UUID
|
||||||
|
);
|
||||||
|
|
||||||
|
await newDatabaseEntry.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res(result.data);
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatabaseColumns(PageId: string, NodeId: string, DatabaseId: string): Promise<any[]> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
// If offline, fetch the columns from the local database
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
const columns = (await this.db.databaseColumns.where({ DatabaseId }).toArray()) as DatabaseColumn[];
|
||||||
|
return res(columns.filter(x => !x.deleted).map(x => x.getSaveRecord()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If online, fetch the columns and sync the local database
|
||||||
|
this.get(`/db/${PageId}/${NodeId}/get/${DatabaseId}/columns`).subscribe({
|
||||||
|
next: async results => {
|
||||||
|
for ( const def of results.data ) {
|
||||||
|
const existingColumnDef = await this.db.databaseColumns.where({
|
||||||
|
DatabaseId, UUID: def.UUID,
|
||||||
|
}).first() as DatabaseColumn;
|
||||||
|
|
||||||
|
if ( existingColumnDef ) {
|
||||||
|
existingColumnDef.fillFromRecord(def);
|
||||||
|
await existingColumnDef.save();
|
||||||
|
} else {
|
||||||
|
const newColumnDef = new DatabaseColumn(
|
||||||
|
def.headerName,
|
||||||
|
def.field,
|
||||||
|
def.DatabaseId,
|
||||||
|
def.UUID,
|
||||||
|
def.Type,
|
||||||
|
def.additionalData,
|
||||||
|
);
|
||||||
|
|
||||||
|
await newColumnDef.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res(results.data);
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public createDatabase(PageId: string, NodeId: string): Promise<any> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
const newLocalDatabase = new Database(
|
||||||
|
'New Database',
|
||||||
|
NodeId,
|
||||||
|
PageId,
|
||||||
|
[],
|
||||||
|
Database.getUUID(),
|
||||||
|
true,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
await newLocalDatabase.save();
|
||||||
|
return res(newLocalDatabase.getSaveRecord());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.post(`/db/${PageId}/${NodeId}/create`).subscribe({
|
||||||
|
next: async result => {
|
||||||
|
const newLocalDatabase = new Database(
|
||||||
|
result.data.Name,
|
||||||
|
result.data.NodeId,
|
||||||
|
result.data.PageId,
|
||||||
|
result.data.ColumnIds,
|
||||||
|
result.data.UUID,
|
||||||
|
result.data.Active
|
||||||
|
);
|
||||||
|
|
||||||
|
await newLocalDatabase.save();
|
||||||
|
return res(result.data);
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatabase(PageId: string, NodeId: string, DatabaseId: string): Promise<any> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
const existingLocalDatabases = await this.db.databases.where({ UUID: DatabaseId }).toArray();
|
||||||
|
const existingLocalDatabase = existingLocalDatabases.length > 0 ? existingLocalDatabases[0] as Database : undefined;
|
||||||
|
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
if ( existingLocalDatabase ) {
|
||||||
|
return res(existingLocalDatabase.getSaveRecord());
|
||||||
|
} else {
|
||||||
|
return rej(new ResourceNotAvailableOfflineError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get(`/db/${PageId}/${NodeId}/get/${DatabaseId}`).subscribe({
|
||||||
|
next: async result => {
|
||||||
|
if ( existingLocalDatabase ) {
|
||||||
|
existingLocalDatabase.fillFromRecord(result.data);
|
||||||
|
|
||||||
|
await existingLocalDatabase.save();
|
||||||
|
return res(result.data);
|
||||||
|
} else {
|
||||||
|
const newLocalDatabase = new Database(
|
||||||
|
result.data.Name,
|
||||||
|
result.data.NodeId,
|
||||||
|
result.data.PageId,
|
||||||
|
result.data.ColumnIds,
|
||||||
|
result.data.UUID,
|
||||||
|
result.data.Active
|
||||||
|
);
|
||||||
|
|
||||||
|
await newLocalDatabase.save();
|
||||||
|
return res(result.data);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveDatabaseEntries(PageId: string, NodeId: string, DatabaseId: string, rowData: any[]): Promise<any[]> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
const existingDatabaseEntries = await this.db.databaseEntries.where({ DatabaseId }).toArray() as DatabaseEntry[];
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
const returnData = [];
|
||||||
|
|
||||||
|
for ( const entry of existingDatabaseEntries ) {
|
||||||
|
entry.deleted = true;
|
||||||
|
entry.needsServerUpdate = true;
|
||||||
|
await entry.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( const row of rowData ) {
|
||||||
|
const newDatabaseEntry = new DatabaseEntry(
|
||||||
|
row.DatabaseId,
|
||||||
|
JSON.stringify(row.RowData),
|
||||||
|
row.UUID || DatabaseEntry.getUUID()
|
||||||
|
);
|
||||||
|
|
||||||
|
await newDatabaseEntry.save();
|
||||||
|
returnData.push(newDatabaseEntry.inflateToRecord());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res(returnData);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.post(`/db/${PageId}/${NodeId}/set/${DatabaseId}/data`, rowData).subscribe({
|
||||||
|
next: async result => {
|
||||||
|
await this.db.databaseEntries.bulkDelete(existingDatabaseEntries.map(x => x.id));
|
||||||
|
|
||||||
|
for ( const row of result.data ) {
|
||||||
|
const newDatabaseEntry = new DatabaseEntry(
|
||||||
|
row.DatabaseId,
|
||||||
|
JSON.stringify(row.RowData),
|
||||||
|
row.UUID
|
||||||
|
);
|
||||||
|
|
||||||
|
await newDatabaseEntry.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res(result.data);
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveDatabaseColumns(PageId: string, NodeId: string, DatabaseId: string, columns: any[]): Promise<void> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
for ( const def of columns ) {
|
||||||
|
const existingColumnDef = await this.db.databaseColumns.where({
|
||||||
|
DatabaseId, ...(def.UUID ? { UUID: def.UUID } : { headerName: def.headerName }),
|
||||||
|
}).first() as DatabaseColumn;
|
||||||
|
|
||||||
|
if ( existingColumnDef ) {
|
||||||
|
existingColumnDef.fillFromRecord(def);
|
||||||
|
existingColumnDef.needsServerUpdate = true;
|
||||||
|
await existingColumnDef.save();
|
||||||
|
} else {
|
||||||
|
const newColumnDef = new DatabaseColumn(
|
||||||
|
def.headerName,
|
||||||
|
def.field,
|
||||||
|
def.DatabaseId,
|
||||||
|
def.UUID || DatabaseColumn.getUUID(),
|
||||||
|
def.Type,
|
||||||
|
def.additionalData,
|
||||||
|
);
|
||||||
|
|
||||||
|
await newColumnDef.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.post(`/db/${PageId}/${NodeId}/set/${DatabaseId}/columns`, { columns }).subscribe({
|
||||||
|
next: async results => {
|
||||||
|
for ( const def of results.data ) {
|
||||||
|
const existingColumnDef = await this.db.databaseColumns.where({
|
||||||
|
DatabaseId, UUID: def.UUID,
|
||||||
|
}).first() as DatabaseColumn;
|
||||||
|
|
||||||
|
if ( existingColumnDef ) {
|
||||||
|
existingColumnDef.fillFromRecord(def);
|
||||||
|
existingColumnDef.needsServerUpdate = false;
|
||||||
|
await existingColumnDef.save();
|
||||||
|
} else {
|
||||||
|
const newColumnDef = new DatabaseColumn(
|
||||||
|
def.headerName,
|
||||||
|
def.field,
|
||||||
|
def.DatabaseId,
|
||||||
|
def.UUID,
|
||||||
|
def.Type,
|
||||||
|
def.additionalData,
|
||||||
|
);
|
||||||
|
|
||||||
|
await newColumnDef.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res();
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public saveDatabaseName(PageId: string, NodeId: string, DatabaseId: string, name: string): Promise<void> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
const existingDatabase = await this.db.databases.where({ UUID: DatabaseId }).first() as Database;
|
||||||
|
|
||||||
|
if ( this.isOffline ) {
|
||||||
|
if ( existingDatabase ) {
|
||||||
|
existingDatabase.Name = name;
|
||||||
|
existingDatabase.needsServerUpdate = true;
|
||||||
|
await existingDatabase.save();
|
||||||
|
return res();
|
||||||
|
} else {
|
||||||
|
return rej(new ResourceNotAvailableOfflineError());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.post(`/db/${PageId}/${NodeId}/set/${DatabaseId}/name`, { Name: name }).subscribe({
|
||||||
|
next: async result => {
|
||||||
|
if ( existingDatabase ) {
|
||||||
|
existingDatabase.Name = name;
|
||||||
|
await existingDatabase.save();
|
||||||
|
res();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
93
src/app/service/db/Database.ts
Normal file
93
src/app/service/db/Database.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import {Model} from './Model';
|
||||||
|
|
||||||
|
export interface IDatabase {
|
||||||
|
id?: number;
|
||||||
|
Name: string;
|
||||||
|
NodeId: string;
|
||||||
|
PageId: string;
|
||||||
|
ColumnIds: string[];
|
||||||
|
UUID: string;
|
||||||
|
Active: boolean;
|
||||||
|
needsServerUpdate?: boolean;
|
||||||
|
deleted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Database extends Model<IDatabase> implements IDatabase {
|
||||||
|
id?: number;
|
||||||
|
Name: string;
|
||||||
|
NodeId: string;
|
||||||
|
PageId: string;
|
||||||
|
ColumnIds: string[];
|
||||||
|
UUID: string;
|
||||||
|
Active: boolean;
|
||||||
|
needsServerUpdate?: boolean;
|
||||||
|
deleted?: boolean;
|
||||||
|
|
||||||
|
public static getTableName() {
|
||||||
|
return 'databases';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getSchema() {
|
||||||
|
return '++id, Name, NodeId, PageId, ColumnIds, UUID, Active, needsServerUpdate, deleted';
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
Name: string,
|
||||||
|
NodeId: string,
|
||||||
|
PageId: string,
|
||||||
|
ColumnIds: string[],
|
||||||
|
UUID: string,
|
||||||
|
Active: boolean,
|
||||||
|
needsServerUpdate?: boolean,
|
||||||
|
deleted?: boolean,
|
||||||
|
id?: number
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.Name = Name;
|
||||||
|
this.NodeId = NodeId;
|
||||||
|
this.PageId = PageId;
|
||||||
|
this.ColumnIds = ColumnIds;
|
||||||
|
this.UUID = UUID;
|
||||||
|
this.Active = Active;
|
||||||
|
|
||||||
|
if ( typeof needsServerUpdate !== 'undefined' ) {
|
||||||
|
this.needsServerUpdate = needsServerUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( typeof deleted !== 'undefined' ) {
|
||||||
|
this.deleted = deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( id ) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fillFromRecord(record: any) {
|
||||||
|
this.Name = record.Name;
|
||||||
|
this.NodeId = record.NodeId;
|
||||||
|
this.PageId = record.PageId;
|
||||||
|
this.ColumnIds = record.ColumnIds;
|
||||||
|
this.UUID = record.UUID;
|
||||||
|
this.Active = record.Active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSaveRecord(): any {
|
||||||
|
return {
|
||||||
|
...(this.id ? { id: this.id } : {}),
|
||||||
|
Name: this.Name,
|
||||||
|
NodeId: this.NodeId,
|
||||||
|
PageId: this.PageId,
|
||||||
|
ColumnIds: this.ColumnIds,
|
||||||
|
UUID: this.UUID,
|
||||||
|
Active: this.Active,
|
||||||
|
...(typeof this.needsServerUpdate === 'undefined' ? {} : { needsServerUpdate: this.needsServerUpdate }),
|
||||||
|
...(typeof this.deleted === 'undefined' ? {} : { deleted: this.deleted }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatabase(): Dexie.Table<IDatabase, number> {
|
||||||
|
return this.staticClass().dbService.table('databases') as Dexie.Table<IDatabase, number>;
|
||||||
|
}
|
||||||
|
}
|
93
src/app/service/db/DatabaseColumn.ts
Normal file
93
src/app/service/db/DatabaseColumn.ts
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
import {Model} from './Model';
|
||||||
|
|
||||||
|
export interface IDatabaseColumn {
|
||||||
|
id?: number;
|
||||||
|
headerName: string;
|
||||||
|
field: string;
|
||||||
|
DatabaseId: string;
|
||||||
|
UUID: string;
|
||||||
|
Type: string;
|
||||||
|
additionalData: string;
|
||||||
|
needsServerUpdate?: boolean;
|
||||||
|
deleted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DatabaseColumn extends Model<IDatabaseColumn> implements IDatabaseColumn {
|
||||||
|
id?: number;
|
||||||
|
headerName: string;
|
||||||
|
field: string;
|
||||||
|
DatabaseId: string;
|
||||||
|
UUID: string;
|
||||||
|
Type: string;
|
||||||
|
additionalData: string;
|
||||||
|
needsServerUpdate?: boolean;
|
||||||
|
deleted?: boolean;
|
||||||
|
|
||||||
|
public static getTableName() {
|
||||||
|
return 'databaseColumns';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getSchema() {
|
||||||
|
return '++id, headerName, field, DatabaseId, UUID, Type, additionalData, needsServerUpdate, deleted';
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
headerName: string,
|
||||||
|
field: string,
|
||||||
|
DatabaseId: string,
|
||||||
|
UUID: string,
|
||||||
|
Type: string,
|
||||||
|
additionalData: string,
|
||||||
|
needsServerUpdate?: boolean,
|
||||||
|
deleted?: boolean,
|
||||||
|
id?: number
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.headerName = headerName;
|
||||||
|
this.field = field;
|
||||||
|
this.DatabaseId = DatabaseId;
|
||||||
|
this.UUID = UUID;
|
||||||
|
this.Type = Type;
|
||||||
|
this.additionalData = additionalData;
|
||||||
|
|
||||||
|
if ( typeof needsServerUpdate !== 'undefined' ) {
|
||||||
|
this.needsServerUpdate = needsServerUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( typeof deleted !== 'undefined' ) {
|
||||||
|
this.deleted = deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( id ) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fillFromRecord(record: any) {
|
||||||
|
this.headerName = record.headerName;
|
||||||
|
this.field = record.field;
|
||||||
|
this.DatabaseId = record.DatabaseId;
|
||||||
|
this.UUID = record.UUID;
|
||||||
|
this.Type = record.Type;
|
||||||
|
this.additionalData = record.additionalData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSaveRecord(): any {
|
||||||
|
return {
|
||||||
|
...(this.id ? { id: this.id } : {}),
|
||||||
|
headerName: this.headerName,
|
||||||
|
field: this.field,
|
||||||
|
DatabaseId: this.DatabaseId,
|
||||||
|
UUID: this.UUID,
|
||||||
|
Type: this.Type,
|
||||||
|
additionalData: this.additionalData,
|
||||||
|
...(typeof this.needsServerUpdate === 'undefined' ? {} : { needsServerUpdate: this.needsServerUpdate }),
|
||||||
|
...(typeof this.deleted === 'undefined' ? {} : { deleted: this.deleted }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatabase(): Dexie.Table<IDatabaseColumn, number> {
|
||||||
|
return this.staticClass().dbService.table('databaseColumns') as Dexie.Table<IDatabaseColumn, number>;
|
||||||
|
}
|
||||||
|
}
|
82
src/app/service/db/DatabaseEntry.ts
Normal file
82
src/app/service/db/DatabaseEntry.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import {Model} from './Model';
|
||||||
|
|
||||||
|
export interface IDatabaseEntry {
|
||||||
|
id?: number;
|
||||||
|
DatabaseId: string;
|
||||||
|
RowDataJSON: string;
|
||||||
|
UUID: string;
|
||||||
|
needsServerUpdate?: boolean;
|
||||||
|
deleted?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DatabaseEntry extends Model<IDatabaseEntry> implements IDatabaseEntry {
|
||||||
|
id?: number;
|
||||||
|
DatabaseId: string;
|
||||||
|
RowDataJSON: string;
|
||||||
|
UUID: string;
|
||||||
|
needsServerUpdate?: boolean;
|
||||||
|
deleted?: boolean;
|
||||||
|
|
||||||
|
public static getTableName() {
|
||||||
|
return 'databaseEntries';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getSchema() {
|
||||||
|
return '++id, DatabaseId, RowDataJSON, UUID, needsServerUpdate, deleted';
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
DatabaseId: string,
|
||||||
|
RowDataJSON: string,
|
||||||
|
UUID: string,
|
||||||
|
needsServerUpdate?: boolean,
|
||||||
|
deleted?: boolean,
|
||||||
|
id?: number
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.DatabaseId = DatabaseId;
|
||||||
|
this.RowDataJSON = RowDataJSON;
|
||||||
|
this.UUID = UUID;
|
||||||
|
|
||||||
|
if ( typeof needsServerUpdate !== 'undefined' ) {
|
||||||
|
this.needsServerUpdate = needsServerUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( typeof deleted !== 'undefined' ) {
|
||||||
|
this.deleted = deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( id ) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fillFromRecord(record: any) {
|
||||||
|
this.DatabaseId = record.DatabaseId;
|
||||||
|
this.RowDataJSON = JSON.stringify(record.RowData);
|
||||||
|
this.UUID = record.UUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public inflateToRecord() {
|
||||||
|
const record = this.getSaveRecord();
|
||||||
|
record.RowData = JSON.parse(record.RowDataJSON);
|
||||||
|
delete record.RowDataJSON;
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getSaveRecord(): any {
|
||||||
|
return {
|
||||||
|
...(this.id ? { id: this.id } : {}),
|
||||||
|
DatabaseId: this.DatabaseId,
|
||||||
|
RowDataJSON: this.RowDataJSON,
|
||||||
|
UUID: this.UUID,
|
||||||
|
...(typeof this.needsServerUpdate === 'undefined' ? {} : { needsServerUpdate: this.needsServerUpdate }),
|
||||||
|
...(typeof this.deleted === 'undefined' ? {} : { deleted: this.deleted }),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public getDatabase(): Dexie.Table<IDatabaseEntry, number> {
|
||||||
|
return this.staticClass().dbService.table('databaseEntries') as Dexie.Table<IDatabaseEntry, number>;
|
||||||
|
}
|
||||||
|
}
|
@ -4,18 +4,24 @@ import {IMigration, Migration} from './Migration';
|
|||||||
import {IMenuItem, MenuItem} from './MenuItem';
|
import {IMenuItem, MenuItem} from './MenuItem';
|
||||||
import {KeyValue, IKeyValue} from './KeyValue';
|
import {KeyValue, IKeyValue} from './KeyValue';
|
||||||
import {Codium, ICodium} from './Codium';
|
import {Codium, ICodium} from './Codium';
|
||||||
|
import {Database, IDatabase} from './Database';
|
||||||
|
import {DatabaseColumn, IDatabaseColumn} from './DatabaseColumn';
|
||||||
|
import {DatabaseEntry, IDatabaseEntry} from './DatabaseEntry';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class DatabaseService extends Dexie {
|
export class DatabaseService extends Dexie {
|
||||||
protected static registeredModels = [Migration, MenuItem, KeyValue, Codium];
|
protected static registeredModels = [Migration, MenuItem, KeyValue, Codium, Database, DatabaseColumn, DatabaseEntry];
|
||||||
protected initialized = false;
|
protected initialized = false;
|
||||||
|
|
||||||
migrations!: Dexie.Table<IMigration, number>;
|
migrations!: Dexie.Table<IMigration, number>;
|
||||||
menuItems!: Dexie.Table<IMenuItem, number>;
|
menuItems!: Dexie.Table<IMenuItem, number>;
|
||||||
keyValues!: Dexie.Table<IKeyValue, number>;
|
keyValues!: Dexie.Table<IKeyValue, number>;
|
||||||
codiums!: Dexie.Table<ICodium, number>;
|
codiums!: Dexie.Table<ICodium, number>;
|
||||||
|
databases!: Dexie.Table<IDatabase, number>;
|
||||||
|
databaseColumns!: Dexie.Table<IDatabaseColumn, number>;
|
||||||
|
databaseEntries!: Dexie.Table<IDatabaseEntry, number>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
) {
|
) {
|
||||||
@ -48,7 +54,7 @@ export class DatabaseService extends Dexie {
|
|||||||
schema[ModelClass.getTableName()] = ModelClass.getSchema();
|
schema[ModelClass.getTableName()] = ModelClass.getSchema();
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.version(5).stores(schema);
|
await this.version(9).stores(schema);
|
||||||
await this.open();
|
await this.open();
|
||||||
|
|
||||||
this.migrations = this.table('migrations');
|
this.migrations = this.table('migrations');
|
||||||
@ -62,5 +68,14 @@ export class DatabaseService extends Dexie {
|
|||||||
|
|
||||||
this.codiums = this.table('codiums');
|
this.codiums = this.table('codiums');
|
||||||
this.codiums.mapToClass(Codium);
|
this.codiums.mapToClass(Codium);
|
||||||
|
|
||||||
|
this.databases = this.table('databases');
|
||||||
|
this.databases.mapToClass(Database);
|
||||||
|
|
||||||
|
this.databaseColumns = this.table('databaseColumns');
|
||||||
|
this.databaseColumns.mapToClass(DatabaseColumn);
|
||||||
|
|
||||||
|
this.databaseEntries = this.table('databaseEntries');
|
||||||
|
this.databaseEntries.mapToClass(DatabaseEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user