Cache pages and page nodes offline
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
8f5ad697b3
commit
6bcb4bf455
@ -22,6 +22,7 @@ import {SearchComponent} from './components/search/Search.component';
|
|||||||
import {NodeTypeIcons} from './structures/node-types';
|
import {NodeTypeIcons} from './structures/node-types';
|
||||||
import {NavigationService} from './service/navigation.service';
|
import {NavigationService} from './service/navigation.service';
|
||||||
import {DatabaseService} from './service/db/database.service';
|
import {DatabaseService} from './service/db/database.service';
|
||||||
|
import {EditorService} from './service/editor.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@ -97,6 +98,7 @@ export class AppComponent implements OnInit {
|
|||||||
protected navService: NavigationService,
|
protected navService: NavigationService,
|
||||||
protected toasts: ToastController,
|
protected toasts: ToastController,
|
||||||
protected db: DatabaseService,
|
protected db: DatabaseService,
|
||||||
|
protected editor: EditorService,
|
||||||
) {
|
) {
|
||||||
this.initializeApp();
|
this.initializeApp();
|
||||||
}
|
}
|
||||||
@ -303,7 +305,7 @@ export class AppComponent implements OnInit {
|
|||||||
{
|
{
|
||||||
text: 'Create',
|
text: 'Create',
|
||||||
handler: async args => {
|
handler: async args => {
|
||||||
const page = await this.api.createPage(args.name);
|
const page = await this.editor.createPage(args.name);
|
||||||
this.reloadMenuItems().subscribe();
|
this.reloadMenuItems().subscribe();
|
||||||
await this.router.navigate(['/editor', { id: page.UUID }]);
|
await this.router.navigate(['/editor', { id: page.UUID }]);
|
||||||
}
|
}
|
||||||
|
@ -870,101 +870,4 @@ export class ApiService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public createPage(name: string): Promise<any> {
|
|
||||||
return new Promise(async (res, rej) => {
|
|
||||||
// If we're offline, create a stub page to be saved later
|
|
||||||
if ( this.isOffline ) {
|
|
||||||
const page = new Page(
|
|
||||||
Page.getUUID(),
|
|
||||||
'New Page',
|
|
||||||
'OrgUserId',
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
'0',
|
|
||||||
[],
|
|
||||||
String(new Date()),
|
|
||||||
String(new Date()),
|
|
||||||
true,
|
|
||||||
'create user id',
|
|
||||||
'update user id',
|
|
||||||
[],
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
const firstNode = new PageNode(
|
|
||||||
PageNode.getUUID(),
|
|
||||||
'paragraph',
|
|
||||||
JSON.stringify({ Value: 'Click to edit...' }),
|
|
||||||
page.UUID,
|
|
||||||
String(new Date()),
|
|
||||||
String(new Date()),
|
|
||||||
'create user id',
|
|
||||||
'update user id',
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
await firstNode.save();
|
|
||||||
|
|
||||||
page.NodeIds.push(firstNode.UUID);
|
|
||||||
await page.save();
|
|
||||||
|
|
||||||
// Because we're offline, we need to manually create the menu item node
|
|
||||||
const topLevelItem = await this.db.menuItems.where({
|
|
||||||
serverId: 0,
|
|
||||||
name: 'My Info Tree',
|
|
||||||
}).first() as MenuItem;
|
|
||||||
|
|
||||||
if ( topLevelItem ) {
|
|
||||||
const newItem = new MenuItem(
|
|
||||||
page.Name,
|
|
||||||
MenuItem.getUUID(),
|
|
||||||
[],
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
'page',
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
await newItem.save();
|
|
||||||
|
|
||||||
topLevelItem.childIds.push(newItem.serverId);
|
|
||||||
await topLevelItem.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return res(page.getSaveRecord());
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're online, the server will handle all of that mess...
|
|
||||||
this.post('/page/create', { name }).subscribe({
|
|
||||||
next: async result => {
|
|
||||||
const page = new Page(
|
|
||||||
result.data.UUID,
|
|
||||||
result.data.Name,
|
|
||||||
result.data.OrgUserId,
|
|
||||||
result.data.IsPublic,
|
|
||||||
result.data.IsVisibleInMenu,
|
|
||||||
result.data.ParentId,
|
|
||||||
result.data.NodeIds,
|
|
||||||
result.data.CreatedAt,
|
|
||||||
result.data.UpdatedAt,
|
|
||||||
true,
|
|
||||||
result.data.CreatedUserId,
|
|
||||||
result.data.UpdateUserId,
|
|
||||||
result.data.ChildPageIds,
|
|
||||||
result.data.noDelete,
|
|
||||||
result.data.virtual
|
|
||||||
);
|
|
||||||
|
|
||||||
await page.save();
|
|
||||||
return res(result.data);
|
|
||||||
},
|
|
||||||
error: rej,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,9 @@ import {NavigationService} from './navigation.service';
|
|||||||
import {DatabaseService} from './db/database.service';
|
import {DatabaseService} from './db/database.service';
|
||||||
import {Page} from './db/Page';
|
import {Page} from './db/Page';
|
||||||
import {PageNode} from './db/PageNode';
|
import {PageNode} from './db/PageNode';
|
||||||
|
import {MenuItem} from './db/MenuItem';
|
||||||
|
import {SessionService} from './session.service';
|
||||||
|
import {debounce} from '../utility';
|
||||||
|
|
||||||
export class NoPageLoadedError extends Error {
|
export class NoPageLoadedError extends Error {
|
||||||
constructor(msg = 'There is no page open for editing.') {
|
constructor(msg = 'There is no page open for editing.') {
|
||||||
@ -15,17 +18,6 @@ export class NoPageLoadedError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function debounce(func: (...args: any[]) => any, timeout?: number) {
|
|
||||||
let timer: number | undefined;
|
|
||||||
return (...args: any[]) => {
|
|
||||||
const next = () => func(...args);
|
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
}
|
|
||||||
timer = setTimeout(next, timeout > 0 ? timeout : 300);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
@ -90,6 +82,7 @@ export class EditorService {
|
|||||||
protected api: ApiService,
|
protected api: ApiService,
|
||||||
protected nav: NavigationService,
|
protected nav: NavigationService,
|
||||||
protected db: DatabaseService,
|
protected db: DatabaseService,
|
||||||
|
protected session: SessionService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async startEditing(pageId: string) {
|
async startEditing(pageId: string) {
|
||||||
@ -175,6 +168,7 @@ export class EditorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async savePage(page: PageRecord): Promise<void> {
|
async savePage(page: PageRecord): Promise<void> {
|
||||||
|
console.log('saving page', page);
|
||||||
await new Promise(async (res, rej) => {
|
await new Promise(async (res, rej) => {
|
||||||
const existingLocalPage = await this.db.pages.where({ UUID: page.UUID }).first() as Page;
|
const existingLocalPage = await this.db.pages.where({ UUID: page.UUID }).first() as Page;
|
||||||
const saveData = page.toSave();
|
const saveData = page.toSave();
|
||||||
@ -343,8 +337,12 @@ export class EditorService {
|
|||||||
return rej(new ResourceNotAvailableOfflineError());
|
return rej(new ResourceNotAvailableOfflineError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( !nodeData.UUID ) {
|
||||||
|
nodeData.UUID = PageNode.getUUID();
|
||||||
|
}
|
||||||
|
|
||||||
const newLocalNode = new PageNode(
|
const newLocalNode = new PageNode(
|
||||||
nodeData.UUID || PageNode.getUUID(),
|
nodeData.UUID,
|
||||||
nodeData.Type,
|
nodeData.Type,
|
||||||
JSON.stringify(nodeData.Value),
|
JSON.stringify(nodeData.Value),
|
||||||
nodeData.PageId,
|
nodeData.PageId,
|
||||||
@ -448,6 +446,7 @@ export class EditorService {
|
|||||||
baseHost.PageId = this.currentPage.UUID;
|
baseHost.PageId = this.currentPage.UUID;
|
||||||
|
|
||||||
const host = await this.saveNodeToPage(this.currentPage, baseHost);
|
const host = await this.saveNodeToPage(this.currentPage, baseHost);
|
||||||
|
console.log('added node to page', host)
|
||||||
|
|
||||||
let placed = false;
|
let placed = false;
|
||||||
if ( position === 'before' && positionNodeId ) {
|
if ( position === 'before' && positionNodeId ) {
|
||||||
@ -530,7 +529,7 @@ export class EditorService {
|
|||||||
// If we're offline, return the local record, or throw an error.
|
// If we're offline, return the local record, or throw an error.
|
||||||
if ( this.api.isOffline ) {
|
if ( this.api.isOffline ) {
|
||||||
if ( existingLocalPage ) {
|
if ( existingLocalPage ) {
|
||||||
return res(existingLocalPage.getSaveRecord());
|
return res(new PageRecord(existingLocalPage.getSaveRecord()));
|
||||||
} else {
|
} else {
|
||||||
return rej(new ResourceNotAvailableOfflineError());
|
return rej(new ResourceNotAvailableOfflineError());
|
||||||
}
|
}
|
||||||
@ -618,4 +617,106 @@ export class EditorService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public createPage(name: string): Promise<any> {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
const userId = this.session.get('user.id');
|
||||||
|
if ( !userId ) {
|
||||||
|
throw new ResourceNotAvailableOfflineError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're offline, create a stub page to be saved later
|
||||||
|
if ( this.api.isOffline ) {
|
||||||
|
const page = new Page(
|
||||||
|
Page.getUUID(),
|
||||||
|
name,
|
||||||
|
userId,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
'0',
|
||||||
|
[],
|
||||||
|
String(new Date()),
|
||||||
|
String(new Date()),
|
||||||
|
true,
|
||||||
|
userId,
|
||||||
|
userId,
|
||||||
|
[],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
const firstNode = new PageNode(
|
||||||
|
PageNode.getUUID(),
|
||||||
|
'paragraph',
|
||||||
|
JSON.stringify({ Value: 'Click to edit...' }),
|
||||||
|
page.UUID,
|
||||||
|
String(new Date()),
|
||||||
|
String(new Date()),
|
||||||
|
userId,
|
||||||
|
userId,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
await firstNode.save();
|
||||||
|
|
||||||
|
page.NodeIds.push(firstNode.UUID);
|
||||||
|
await page.save();
|
||||||
|
|
||||||
|
// Because we're offline, we need to manually create the menu item node
|
||||||
|
const topLevelItem = await this.db.menuItems.where({
|
||||||
|
serverId: 0,
|
||||||
|
name: 'My Info Tree',
|
||||||
|
}).first() as MenuItem;
|
||||||
|
|
||||||
|
if ( topLevelItem ) {
|
||||||
|
const newItem = new MenuItem(
|
||||||
|
page.Name,
|
||||||
|
page.UUID,
|
||||||
|
[],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
'page',
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
await newItem.save();
|
||||||
|
|
||||||
|
topLevelItem.childIds.push(newItem.serverId);
|
||||||
|
await topLevelItem.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res(page.getSaveRecord());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're online, the server will handle all of that mess...
|
||||||
|
this.api.post('/page/create', { name }).subscribe({
|
||||||
|
next: async result => {
|
||||||
|
const page = new Page(
|
||||||
|
result.data.UUID,
|
||||||
|
result.data.Name,
|
||||||
|
result.data.OrgUserId,
|
||||||
|
result.data.IsPublic,
|
||||||
|
result.data.IsVisibleInMenu,
|
||||||
|
result.data.ParentId,
|
||||||
|
result.data.NodeIds,
|
||||||
|
result.data.CreatedAt,
|
||||||
|
result.data.UpdatedAt,
|
||||||
|
true,
|
||||||
|
result.data.CreatedUserId,
|
||||||
|
result.data.UpdateUserId,
|
||||||
|
result.data.ChildPageIds,
|
||||||
|
result.data.noDelete,
|
||||||
|
result.data.virtual
|
||||||
|
);
|
||||||
|
|
||||||
|
await page.save();
|
||||||
|
return res(result.data);
|
||||||
|
},
|
||||||
|
error: rej,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import {ApiService} from './api.service';
|
import {ApiService} from './api.service';
|
||||||
import {debounce} from './editor.service';
|
import {debounce} from '../utility';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
|
@ -6,3 +6,14 @@ export function uuid_v4() {
|
|||||||
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function debounce(func: (...args: any[]) => any, timeout?: number) {
|
||||||
|
let timer: number | undefined;
|
||||||
|
return (...args: any[]) => {
|
||||||
|
const next = () => func(...args);
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
}
|
||||||
|
timer = setTimeout(next, timeout > 0 ? timeout : 300);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user