diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 1aad1e8..c53f12d 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -25,6 +25,7 @@ import {DatabaseService} from './service/db/database.service';
import {EditorService} from './service/editor.service';
import {debug} from './utility';
import {AuthService} from './service/auth.service';
+import {OpenerService} from './service/opener.service';
@Component({
selector: 'app-root',
@@ -115,6 +116,7 @@ export class AppComponent implements OnInit {
protected db: DatabaseService,
protected editor: EditorService,
protected auth: AuthService,
+ protected opener: OpenerService,
) { }
async checkNewVersion() {
@@ -205,8 +207,8 @@ export class AppComponent implements OnInit {
if ( !node.data.virtual ) {
debug('Navigating editor to node:', {id, nodeId});
- this.currentPageId = id;
- this.router.navigate(['/editor', { id, ...(nodeId ? { node_id: nodeId } : {}) }]);
+ this.opener.currentPageId = id;
+ this.opener.openTarget(id, nodeId);
}
}
@@ -438,7 +440,7 @@ export class AppComponent implements OnInit {
this.api
.post(`/page/delete/${this.deleteTarget.data.id}`)
.subscribe(res => {
- if ( this.currentPageId === this.deleteTarget.data.id ) {
+ if ( this.opener.currentPageId === this.deleteTarget.data.id ) {
this.router.navigate(['/home']);
}
@@ -630,7 +632,7 @@ export class AppComponent implements OnInit {
return;
}
- this.currentPageId = pageId;
+ this.opener.currentPageId = pageId;
this.router.navigate(['/editor', { id: pageId }]);
});
diff --git a/src/app/components/nodes/file-box/file-box-page.component.ts b/src/app/components/nodes/file-box/file-box-page.component.ts
index 4edc8e4..acedb63 100644
--- a/src/app/components/nodes/file-box/file-box-page.component.ts
+++ b/src/app/components/nodes/file-box/file-box-page.component.ts
@@ -5,7 +5,12 @@ import {EditorService} from '../../../service/editor.service';
selector: 'noded-file-box-page',
template: `
-
+
`,
styles: [
diff --git a/src/app/components/nodes/file-box/file-box.component.scss b/src/app/components/nodes/file-box/file-box.component.scss
index ef4723b..3b99ed8 100644
--- a/src/app/components/nodes/file-box/file-box.component.scss
+++ b/src/app/components/nodes/file-box/file-box.component.scss
@@ -101,6 +101,10 @@ div.file-box-wrapper {
}
}
+.close {
+ padding: 0 20px;
+}
+
.file-box-wrapper.dark {
color: white;
display: flex;
@@ -115,10 +119,6 @@ div.file-box-wrapper {
}
}
- .close {
- padding: 0 20px;
- }
-
.item {
background: #393939;
diff --git a/src/app/components/search/Search.component.ts b/src/app/components/search/Search.component.ts
index f41f4f3..e1745eb 100644
--- a/src/app/components/search/Search.component.ts
+++ b/src/app/components/search/Search.component.ts
@@ -5,8 +5,7 @@ import {BehaviorSubject} from 'rxjs';
import {Router} from '@angular/router';
import {NodeTypeIcons} from '../../structures/node-types';
import {debounce} from '../../utility';
-import {DatabasePageComponent} from '../editor/database/database-page.component';
-import {FileBoxPageComponent} from '../nodes/file-box/file-box-page.component';
+import {OpenerService} from '../../service/opener.service';
export interface SearchResult {
title: string;
@@ -44,6 +43,7 @@ export class SearchComponent implements OnInit {
protected ionModalController: ModalController,
protected api: ApiService,
protected router: Router,
+ protected opener: OpenerService,
) { }
async dismiss() {
@@ -75,15 +75,15 @@ export class SearchComponent implements OnInit {
];
if ( result.type === 'page' ) {
- await this.router.navigate(['/editor', { id: result.id }]);
+ await this.opener.openTarget(result.id);
await this.dismiss();
} else if ( nodeTypes.includes(result.type) ) {
- await this.router.navigate(['/editor', { id: result.associated.id, node_id: result.id }]);
+ await this.opener.openTarget(result.associated.id, result.id);
await this.dismiss();
} else if ( result.type === 'db' ) {
- await this.openDatabase(result.associated.id, result.id);
+ await this.opener.openDatabase(result.associated.id, result.id);
} else if ( result.type.startsWith('file_box') ) {
- await this.openFileBox(result.associated.id, result.id, result.boxId);
+ await this.opener.openFileBox(result.associated.id, result.id, result.boxId);
}
}
@@ -93,50 +93,9 @@ export class SearchComponent implements OnInit {
if ( result.associated ) {
if ( result.associated.type === 'page' ) {
- await this.router.navigate(['/editor', { id: result.associated.id }]);
+ await this.opener.openTarget(result.associated.id);
await this.dismiss();
}
}
}
-
- async openDatabase(pageId: string, nodeId: string) {
- const modal = await this.ionModalController.create({
- component: DatabasePageComponent,
- componentProps: {
- nodeId,
- pageId,
- },
- cssClass: 'modal-big',
- });
-
- const modalState = {
- modal : true,
- desc : 'Open Database'
- };
-
- history.pushState(modalState, null);
-
- await modal.present();
- }
-
- async openFileBox(pageId: string, nodeId: string, boxId?: string) {
- const modal = await this.ionModalController.create({
- component: FileBoxPageComponent,
- componentProps: {
- nodeId,
- pageId,
- boxId,
- },
- cssClass: 'modal-big',
- });
-
- const modalState = {
- modal : true,
- desc : 'Open File Box'
- };
-
- history.pushState(modalState, null);
-
- await modal.present();
- }
}
diff --git a/src/app/service/api.service.ts b/src/app/service/api.service.ts
index 27c9d81..cfae368 100644
--- a/src/app/service/api.service.ts
+++ b/src/app/service/api.service.ts
@@ -14,6 +14,7 @@ import {FileGroup} from './db/FileGroup';
import {Page} from './db/Page';
import {PageNode} from './db/PageNode';
import {debug} from '../utility';
+import HostRecord from '../structures/HostRecord';
export class ResourceNotAvailableOfflineError extends Error {
constructor(msg = 'This resource is not yet available offline on this device.') {
@@ -647,6 +648,51 @@ export class ApiService {
});
}
+ public async loadNodes(pageId: string, version?: number): Promise {
+ return new Promise(async (res, rej) => {
+ const existingNodes = await this.db.pageNodes.where({ PageId: pageId }).toArray() as PageNode[];
+
+ const inflateRecords = (records) => {
+ return records.map(rec => {
+ const host = new HostRecord(rec.Value.Value);
+ host.load(rec);
+ return host;
+ });
+ };
+
+ // If we're offline, just resolve the offline nodes
+ if ( this.isOffline ) {
+ const parsedRecords = existingNodes.map(x => x.inflateToRecord());
+ return res(inflateRecords(parsedRecords));
+ }
+
+ this.get(`/page/${pageId}/nodes${version ? '?version=' + version : ''}`).subscribe({
+ next: async result => {
+ // If we got resolved records, delete the local ones to replace them
+ await this.db.pageNodes.where({ PageId: pageId }).delete();
+
+ for ( const rawRec of result.data ) {
+ const newLocalNode = new PageNode(
+ rawRec.UUID,
+ rawRec.Type,
+ JSON.stringify(rawRec.Value),
+ rawRec.PageId,
+ rawRec.CreatedAt,
+ rawRec.UpdatedAt,
+ rawRec.CreatedUserId,
+ rawRec.UpdateUserId,
+ );
+
+ await newLocalNode.save();
+ }
+
+ res(inflateRecords(result.data));
+ },
+ error: rej,
+ });
+ });
+ }
+
public deleteCodium(PageId: string, NodeId: string, CodiumId: string): Promise {
return new Promise(async (res, rej) => {
const existingLocalCodiums = await this.db.codiums.where({ UUID: CodiumId }).toArray();
diff --git a/src/app/service/editor.service.ts b/src/app/service/editor.service.ts
index a83d87e..52acf06 100644
--- a/src/app/service/editor.service.ts
+++ b/src/app/service/editor.service.ts
@@ -705,48 +705,7 @@ export class EditorService {
}
async loadNodes(pageId: string, version?: number): Promise {
- return new Promise(async (res, rej) => {
- const existingNodes = await this.db.pageNodes.where({ PageId: pageId }).toArray() as PageNode[];
-
- const inflateRecords = (records) => {
- return records.map(rec => {
- const host = new HostRecord(rec.Value.Value);
- host.load(rec);
- return host;
- });
- };
-
- // If we're offline, just resolve the offline nodes
- if ( this.api.isOffline ) {
- const parsedRecords = existingNodes.map(x => x.inflateToRecord());
- return res(inflateRecords(parsedRecords));
- }
-
- this.api.get(`/page/${pageId}/nodes${version ? '?version=' + version : ''}`).subscribe({
- next: async result => {
- // If we got resolved records, delete the local ones to replace them
- await this.db.pageNodes.where({ PageId: pageId }).delete();
-
- for ( const rawRec of result.data ) {
- const newLocalNode = new PageNode(
- rawRec.UUID,
- rawRec.Type,
- JSON.stringify(rawRec.Value),
- rawRec.PageId,
- rawRec.CreatedAt,
- rawRec.UpdatedAt,
- rawRec.CreatedUserId,
- rawRec.UpdateUserId,
- );
-
- await newLocalNode.save();
- }
-
- res(inflateRecords(result.data));
- },
- error: rej,
- });
- });
+ return this.api.loadNodes(pageId, version);
}
public createPage(name: string): Promise {
diff --git a/src/app/service/navigation.service.ts b/src/app/service/navigation.service.ts
index ce968ef..9619f4d 100644
--- a/src/app/service/navigation.service.ts
+++ b/src/app/service/navigation.service.ts
@@ -1,6 +1,10 @@
import { Injectable } from '@angular/core';
import {BehaviorSubject} from 'rxjs';
import {debug} from '../utility';
+import {DatabasePageComponent} from '../components/editor/database/database-page.component';
+import {FileBoxPageComponent} from '../components/nodes/file-box/file-box-page.component';
+import {ModalController} from '@ionic/angular';
+import {ApiService} from './api.service';
@Injectable({
providedIn: 'root'
@@ -12,6 +16,11 @@ export class NavigationService {
public readonly initializationRequest$: BehaviorSubject = new BehaviorSubject(0);
public readonly initialized$: BehaviorSubject = new BehaviorSubject(false);
+ constructor(
+ protected readonly ionModalController: ModalController,
+ protected readonly api: ApiService,
+ ) { }
+
requestSidebarRefresh({ quiet = false }) {
this.refreshCount += 1;
this.sidebarRefresh$.next([this.refreshCount, quiet]);
diff --git a/src/app/service/opener.service.ts b/src/app/service/opener.service.ts
new file mode 100644
index 0000000..712ed85
--- /dev/null
+++ b/src/app/service/opener.service.ts
@@ -0,0 +1,81 @@
+import {Injectable} from '@angular/core';
+import {DatabasePageComponent} from '../components/editor/database/database-page.component';
+import {FileBoxPageComponent} from '../components/nodes/file-box/file-box-page.component';
+import {NavigationService} from './navigation.service';
+import {EditorService} from './editor.service';
+import {ModalController} from '@ionic/angular';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class OpenerService {
+ public currentPageId = '';
+
+ constructor(
+ protected readonly nav: NavigationService,
+ protected readonly editor: EditorService,
+ protected readonly ionModalController: ModalController,
+ ) { }
+
+ async openTarget(pageId: string, nodeId?: string) {
+ if ( !nodeId ) {
+ this.currentPageId = pageId;
+ return this.nav.requestNavigation(pageId);
+ }
+
+ const node = (await this.editor.loadNodes(pageId)).find(rec => rec.UUID === nodeId);
+ if ( !node ) {
+ this.currentPageId = pageId;
+ return this.nav.requestNavigation(pageId);
+ }
+
+ if ( node.type === 'database_ref' ) {
+ return this.openDatabase(pageId, nodeId);
+ }
+
+ if ( node.type === 'file_box' ) {
+ return this.openFileBox(pageId, nodeId);
+ }
+ }
+
+ async openDatabase(pageId: string, nodeId: string) {
+ const modal = await this.ionModalController.create({
+ component: DatabasePageComponent,
+ componentProps: {
+ nodeId,
+ pageId,
+ },
+ cssClass: 'modal-big',
+ });
+
+ const modalState = {
+ modal : true,
+ desc : 'Open Database'
+ };
+
+ history.pushState(modalState, null);
+
+ await modal.present();
+ }
+
+ async openFileBox(pageId: string, nodeId: string, boxId?: string) {
+ const modal = await this.ionModalController.create({
+ component: FileBoxPageComponent,
+ componentProps: {
+ nodeId,
+ pageId,
+ boxId,
+ },
+ cssClass: 'modal-big',
+ });
+
+ const modalState = {
+ modal : true,
+ desc : 'Open File Box'
+ };
+
+ history.pushState(modalState, null);
+
+ await modal.present();
+ }
+}
diff --git a/src/app/structures/HostRecord.ts b/src/app/structures/HostRecord.ts
index 291a00e..c6a1877 100644
--- a/src/app/structures/HostRecord.ts
+++ b/src/app/structures/HostRecord.ts
@@ -1,7 +1,7 @@
export default class HostRecord {
public value = '';
// tslint:disable-next-line:max-line-length
- public type: 'paragraph'|'database_ref'|'code_ref'|'file_ref'|'markdown'|'form_input_text'|'form_input_number'|'form_input_password'|'form_input_email'|'form_input_select'|'form_input_multiselect'|'form_input_textarea' = 'paragraph';
+ public type: 'paragraph'|'database_ref'|'code_ref'|'file_ref'|'markdown'|'form_input_text'|'form_input_number'|'form_input_password'|'form_input_email'|'form_input_select'|'form_input_multiselect'|'form_input_textarea'|'file_box' = 'paragraph';
public CreatedAt: string;
public PageId: string;