Centralize opener logic to shared service
This commit is contained in:
parent
0fecb8a4ba
commit
72ab2064dd
@ -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 }]);
|
||||
});
|
||||
|
||||
|
@ -5,7 +5,12 @@ import {EditorService} from '../../../service/editor.service';
|
||||
selector: 'noded-file-box-page',
|
||||
template: `
|
||||
<div class="container" *ngIf="ready">
|
||||
<editor-file-box [nodeId]="nodeId" [editorUUID]="this.editorService.instanceUUID" [fullPage]="true" [boxId]="boxId"></editor-file-box>
|
||||
<editor-file-box
|
||||
[nodeId]="nodeId"
|
||||
[editorUUID]="this.editorService.instanceUUID"
|
||||
[fullPage]="true"
|
||||
[boxId]="boxId"
|
||||
></editor-file-box>
|
||||
</div>
|
||||
`,
|
||||
styles: [
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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<HostRecord[]> {
|
||||
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<void> {
|
||||
return new Promise(async (res, rej) => {
|
||||
const existingLocalCodiums = await this.db.codiums.where({ UUID: CodiumId }).toArray();
|
||||
|
@ -705,48 +705,7 @@ export class EditorService {
|
||||
}
|
||||
|
||||
async loadNodes(pageId: string, version?: number): Promise<HostRecord[]> {
|
||||
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<any> {
|
||||
|
@ -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<number> = new BehaviorSubject<number>(0);
|
||||
public readonly initialized$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
|
||||
constructor(
|
||||
protected readonly ionModalController: ModalController,
|
||||
protected readonly api: ApiService,
|
||||
) { }
|
||||
|
||||
requestSidebarRefresh({ quiet = false }) {
|
||||
this.refreshCount += 1;
|
||||
this.sidebarRefresh$.next([this.refreshCount, quiet]);
|
||||
|
81
src/app/service/opener.service.ts
Normal file
81
src/app/service/opener.service.ts
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user