Create db_api service wrapper and OO classes
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
65de891fe8
commit
0378522e9a
@ -41,7 +41,6 @@
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
<ion-footer>
|
||||
<!-- <ion-searchbar placeholder="Filter pages..." (ionChange)="onFilterChange($event)"></ion-searchbar>-->
|
||||
<ion-item button lines="full" (click)="showOptions($event)">
|
||||
<ion-icon name="list" slot="start"></ion-icon>
|
||||
<ion-label>Menu</ion-label>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {Component, OnInit, ViewChild, HostListener, Host} from '@angular/core';
|
||||
import {Component, OnInit, ViewChild, HostListener} from '@angular/core';
|
||||
|
||||
import {
|
||||
AlertController,
|
||||
@ -144,21 +144,6 @@ export class AppComponent implements OnInit {
|
||||
}).then(popover => popover.present());
|
||||
}
|
||||
|
||||
onFilterChange($event) {
|
||||
const query = $event.detail.value.toLowerCase();
|
||||
this.menuTree.treeModel.clearFilter();
|
||||
if ( query ) {
|
||||
this.menuTree.treeModel.filterNodes(node => {
|
||||
if ( node.data.virtual ) {
|
||||
// "Virtual" tree nodes should always be shown
|
||||
return true;
|
||||
}
|
||||
|
||||
return node.data.name.toLowerCase().indexOf(query) >= 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.control./', ['$event'])
|
||||
async handleKeyboardEvent() {
|
||||
if ( this.hasSearchOpen ) {
|
||||
|
@ -285,12 +285,27 @@ export class ApiService {
|
||||
});
|
||||
}
|
||||
|
||||
public _build_url(endpoint) {
|
||||
public _build_url(endpoint, base = this.baseEndpoint) {
|
||||
if ( !endpoint.startsWith('/') ) {
|
||||
endpoint = `/${endpoint}`;
|
||||
}
|
||||
|
||||
return `${this.baseEndpoint.endsWith('/') ? this.baseEndpoint.slice(0, -1) : this.baseEndpoint}${endpoint}`;
|
||||
return `${base.endsWith('/') ? base.slice(0, -1) : base}${endpoint}`;
|
||||
}
|
||||
|
||||
public async getToken(): Promise<string> {
|
||||
return new Promise(async (res, rej) => {
|
||||
if ( this.isOffline ) {
|
||||
return rej(new ResourceNotAvailableOfflineError());
|
||||
}
|
||||
|
||||
this.get('token').subscribe({
|
||||
next: response => {
|
||||
return res(response.data);
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async syncOfflineData() {
|
||||
|
139
src/app/service/db-api.service.ts
Normal file
139
src/app/service/db-api.service.ts
Normal file
@ -0,0 +1,139 @@
|
||||
import {Injectable} from '@angular/core';
|
||||
import {ApiService} from './api.service';
|
||||
import {Observable} from 'rxjs';
|
||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
||||
import ApiResponse from '../structures/ApiResponse';
|
||||
import {environment} from '../../environments/environment';
|
||||
import {debug} from '../utility';
|
||||
import * as Structures from '../structures/db-api';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DbApiService {
|
||||
protected token?: string;
|
||||
protected tokenTime?: number;
|
||||
protected databaseBase: string = environment.databaseBase;
|
||||
|
||||
constructor(
|
||||
protected readonly api: ApiService,
|
||||
protected readonly http: HttpClient,
|
||||
) {
|
||||
Structures._setDbApi(this);
|
||||
}
|
||||
|
||||
public async getDatabase(databaseId: string): Promise<Structures.Database> {
|
||||
return new Promise(async (res, rej) => {
|
||||
|
||||
this._authRequest(`/${databaseId}`).subscribe({
|
||||
next: async response => {
|
||||
if ( response.status !== 200 ) {
|
||||
debug('Invalid get database response.', response);
|
||||
return rej(new Error('Invalid database ID.'));
|
||||
}
|
||||
|
||||
return res(new Structures.Database(response.data));
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async getDatabases(): Promise<Structures.Database[]> {
|
||||
return new Promise(async (res, rej) => {
|
||||
|
||||
this._authRequest('/').subscribe({
|
||||
next: async response => {
|
||||
return res(response.data.map(x => new Structures.Database(x)));
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async getColumns(databaseId: string): Promise<Structures.DatabaseColumn[]> {
|
||||
return new Promise(async (res, rej) => {
|
||||
|
||||
this._authRequest(`${databaseId}/columns`).subscribe({
|
||||
next: async response => {
|
||||
return res(response.data.map(x => new Structures.DatabaseColumn(x)));
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async getColumnOrder(databaseId: string): Promise<string[]> {
|
||||
return new Promise(async (res, rej) => {
|
||||
this._authRequest(`${databaseId}/columns/order`).subscribe({
|
||||
next: async response => {
|
||||
return res(response.data);
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async getData(databaseId: string): Promise<Structures.DatabaseRecord[]> {
|
||||
return new Promise(async (res, rej) => {
|
||||
this._authRequest(`${databaseId}/data`).subscribe({
|
||||
next: async response => {
|
||||
return res(response.data.map(x => new Structures.DatabaseRecord(x)));
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async getDataRecord(databaseId: string, recordId: string): Promise<Structures.DatabaseRecord> {
|
||||
return new Promise(async (res, rej) => {
|
||||
this._authRequest(`${databaseId}/record/${recordId}`).subscribe({
|
||||
next: async response => {
|
||||
return res(new Structures.DatabaseRecord(response.data));
|
||||
},
|
||||
error: rej,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
protected _authRequest(endpoint, params = {}, method: 'get' | 'post' = 'get') {
|
||||
return new Observable<ApiResponse>(sub => {
|
||||
this.getToken().then(token => {
|
||||
const headers = new HttpHeaders({
|
||||
authorization: `bearer ${token}`
|
||||
});
|
||||
|
||||
debug('Auth request headers', headers);
|
||||
|
||||
if ( method === 'get' ) {
|
||||
const data = {
|
||||
params,
|
||||
headers,
|
||||
};
|
||||
|
||||
this.http.get(this.api._build_url(endpoint, this.databaseBase), data).subscribe({
|
||||
next: (response: any) => {
|
||||
return sub.next(new ApiResponse(response));
|
||||
},
|
||||
error: e => {
|
||||
return sub.error(e);
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async getToken(): Promise<string> {
|
||||
const now = (new Date()).getTime();
|
||||
|
||||
// 1 hour
|
||||
if ( this.token && this.tokenTime && (now - this.tokenTime) < (60 * 60 * 1000) ) {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
this.token = await this.api.getToken();
|
||||
this.tokenTime = now;
|
||||
return this.token;
|
||||
}
|
||||
}
|
102
src/app/structures/db-api.ts
Normal file
102
src/app/structures/db-api.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import {DbApiService} from '../service/db-api.service';
|
||||
|
||||
let privDbApi!: DbApiService;
|
||||
export function _setDbApi(dbApi: DbApiService) {
|
||||
privDbApi = dbApi;
|
||||
}
|
||||
|
||||
export function _getDbApi(): DbApiService {
|
||||
return privDbApi;
|
||||
}
|
||||
|
||||
export class Database {
|
||||
public name!: string;
|
||||
public uuid!: string;
|
||||
public pageId!: string;
|
||||
public columnIds: string[] = [];
|
||||
public versionNum?: number;
|
||||
|
||||
static async all() {
|
||||
return _getDbApi().getDatabases();
|
||||
}
|
||||
|
||||
static async one(databaseId: string) {
|
||||
return _getDbApi().getDatabase(databaseId);
|
||||
}
|
||||
|
||||
constructor(record?: any) {
|
||||
if ( record ) {
|
||||
this.loadFrom(record);
|
||||
}
|
||||
}
|
||||
|
||||
loadFrom(record: any) {
|
||||
this.name = record.name;
|
||||
this.uuid = record.uuid;
|
||||
this.pageId = record.page_id;
|
||||
this.columnIds = record.column_ids;
|
||||
|
||||
if ( record.version_num ) {
|
||||
this.versionNum = record.version_num;
|
||||
}
|
||||
}
|
||||
|
||||
async columns() {
|
||||
const order = await this.columnOrder();
|
||||
const columns = await _getDbApi().getColumns(this.uuid);
|
||||
|
||||
return order.map(x => columns.find(col => col.uuid === x));
|
||||
}
|
||||
|
||||
async columnOrder() {
|
||||
return _getDbApi().getColumnOrder(this.uuid);
|
||||
}
|
||||
|
||||
async data() {
|
||||
return _getDbApi().getData(this.uuid);
|
||||
}
|
||||
|
||||
async record(id: string) {
|
||||
return _getDbApi().getDataRecord(this.uuid, id);
|
||||
}
|
||||
}
|
||||
|
||||
export class DatabaseColumn {
|
||||
public name!: string;
|
||||
public databaseId!: string;
|
||||
public uuid!: string;
|
||||
public type!: string;
|
||||
public metadata: any;
|
||||
|
||||
constructor(record?: any) {
|
||||
if ( record ) {
|
||||
this.loadFrom(record);
|
||||
}
|
||||
}
|
||||
|
||||
loadFrom(record: any) {
|
||||
this.name = record.name;
|
||||
this.databaseId = record.database_id;
|
||||
this.uuid = record.uuid;
|
||||
this.type = record.type;
|
||||
this.metadata = record.metadata;
|
||||
}
|
||||
}
|
||||
|
||||
export class DatabaseRecord {
|
||||
public data: any = {};
|
||||
public uuid!: string;
|
||||
public databaseId!: string;
|
||||
|
||||
constructor(record?: any) {
|
||||
if ( record ) {
|
||||
this.loadFrom(record);
|
||||
}
|
||||
}
|
||||
|
||||
loadFrom(record: any) {
|
||||
this.data = record.data;
|
||||
this.uuid = record.uuid;
|
||||
this.databaseId = record.database_id;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
export const environment = {
|
||||
production: true,
|
||||
backendBase: '/api/v1',
|
||||
databaseBase: '/db_api/v1',
|
||||
statUrl: '/stat?ngsw-bypass',
|
||||
versionUrl: '/i/version.html?ngsw-bypass',
|
||||
outputDebug: false,
|
||||
|
@ -5,6 +5,7 @@
|
||||
export const environment = {
|
||||
production: false,
|
||||
backendBase: '/link_api/api/v1',
|
||||
databaseBase: '/link_api/db_api/v1',
|
||||
statUrl: '/link_api/stat?ngsw-bypass',
|
||||
versionUrl: '/link_api/assets/version.html?ngsw-bypass',
|
||||
outputDebug: true,
|
||||
|
Loading…
Reference in New Issue
Block a user