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 => {
|
||||
x.field = x.headerName;
|
||||
return x;
|
||||
})
|
||||
});
|
||||
|
||||
this.modals.dismiss(this.columnSets);
|
||||
} else {
|
||||
this.modals.dismiss();
|
||||
@ -46,10 +47,9 @@ export class ColumnsComponent implements OnInit {
|
||||
}
|
||||
|
||||
onDeleteClick(i) {
|
||||
const newSets = this.columnSets.filter((x, index) => {
|
||||
this.columnSets = this.columnSets.filter((x, index) => {
|
||||
return index !== i;
|
||||
});
|
||||
this.columnSets = newSets;
|
||||
}
|
||||
|
||||
onUpArrow(i) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
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 {ColumnsComponent} from './columns/columns.component';
|
||||
import {AgGridAngular} from 'ag-grid-angular';
|
||||
@ -29,6 +29,7 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
||||
public dirty = false;
|
||||
public lastClickRow = -1;
|
||||
public dbName = '';
|
||||
public notAvailableOffline = false;
|
||||
protected dbId!: string;
|
||||
|
||||
public get readonly() {
|
||||
@ -181,102 +182,52 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
||||
|
||||
// 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.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 = result.data.UUID;
|
||||
this.node.value = result.data.UUID;
|
||||
res();
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
this.node.Value.Value = this.dbRecord.UUID;
|
||||
this.node.value = this.dbRecord.UUID;
|
||||
} 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,
|
||||
});
|
||||
});
|
||||
try {
|
||||
this.dbRecord = await this.api.getDatabase(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
||||
this.dbName = this.dbRecord.Name;
|
||||
this.notAvailableOffline = false;
|
||||
} catch (e: unknown) {
|
||||
if ( e instanceof ResourceNotAvailableOfflineError ) {
|
||||
this.notAvailableOffline = true;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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,
|
||||
});
|
||||
});
|
||||
const columns = await this.api.getDatabaseColumns(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
||||
this.setColumns(columns);
|
||||
|
||||
// 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);
|
||||
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);
|
||||
res();
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
|
||||
this.pendingSetup = false;
|
||||
this.dirty = false;
|
||||
}
|
||||
|
||||
public performDelete(): void | Promise<void> {
|
||||
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 performDelete(): Promise<void> {
|
||||
await this.api.deleteDatabase(this.page.UUID, this.node.UUID, this.node.Value.Value);
|
||||
}
|
||||
|
||||
public async performSave(): Promise<void> {
|
||||
// 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,
|
||||
});
|
||||
});
|
||||
await this.api.saveDatabaseColumns(this.page.UUID, this.node.UUID, this.node.Value.Value, this.columnDefs);
|
||||
|
||||
// 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);
|
||||
const rows = await this.api.saveDatabaseEntries(this.page.UUID, this.node.UUID, this.node.Value.Value, this.rowData);
|
||||
this.rowData = rows.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,
|
||||
});
|
||||
});
|
||||
await this.api.saveDatabaseName(this.page.UUID, this.node.UUID, this.node.Value.Value, this.dbName);
|
||||
|
||||
this.dirty = false;
|
||||
}
|
||||
|
@ -7,6 +7,9 @@ import {MenuItem} from './db/MenuItem';
|
||||
import {DatabaseService} from './db/database.service';
|
||||
import {ConnectionService} from 'ng-connection-service';
|
||||
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 {
|
||||
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> {
|
||||
return new Observable<ApiResponse>(sub => {
|
||||
let data: any = {}
|
||||
let data: any = {};
|
||||
if ( method === 'get' ) {
|
||||
data.params = params;
|
||||
} 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 {KeyValue, IKeyValue} from './KeyValue';
|
||||
import {Codium, ICodium} from './Codium';
|
||||
import {Database, IDatabase} from './Database';
|
||||
import {DatabaseColumn, IDatabaseColumn} from './DatabaseColumn';
|
||||
import {DatabaseEntry, IDatabaseEntry} from './DatabaseEntry';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
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;
|
||||
|
||||
migrations!: Dexie.Table<IMigration, number>;
|
||||
menuItems!: Dexie.Table<IMenuItem, number>;
|
||||
keyValues!: Dexie.Table<IKeyValue, number>;
|
||||
codiums!: Dexie.Table<ICodium, number>;
|
||||
databases!: Dexie.Table<IDatabase, number>;
|
||||
databaseColumns!: Dexie.Table<IDatabaseColumn, number>;
|
||||
databaseEntries!: Dexie.Table<IDatabaseEntry, number>;
|
||||
|
||||
constructor(
|
||||
) {
|
||||
@ -48,7 +54,7 @@ export class DatabaseService extends Dexie {
|
||||
schema[ModelClass.getTableName()] = ModelClass.getSchema();
|
||||
}
|
||||
|
||||
await this.version(5).stores(schema);
|
||||
await this.version(9).stores(schema);
|
||||
await this.open();
|
||||
|
||||
this.migrations = this.table('migrations');
|
||||
@ -62,5 +68,14 @@ export class DatabaseService extends Dexie {
|
||||
|
||||
this.codiums = this.table('codiums');
|
||||
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