diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index e26a037..1b91b6a 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -3,7 +3,6 @@ import { PreloadAllModules, RouterModule, Routes } from '@angular/router'; import {LoginPage} from './pages/login/login.page'; import {AuthService} from './service/auth.service'; import {GuestOnlyGuard} from './service/guard/GuestOnly.guard'; -import {EditorGuard} from './service/guard/Editor.guard'; const routes: Routes = [ { @@ -18,7 +17,6 @@ const routes: Routes = [ }, { path: 'editor', - canActivate: [EditorGuard], loadChildren: () => import('./components/components.module').then( m => m.ComponentsModule) }, { diff --git a/src/app/app.component.html b/src/app/app.component.html index 5f804db..a45ec3e 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,6 +1,6 @@ - + {{ appName }} diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts index 36babea..755a8e4 100644 --- a/src/app/components/components.module.ts +++ b/src/app/components/components.module.ts @@ -33,7 +33,9 @@ import {DirectivesModule} from '../directives/directives.module'; import {MarkdownModule} from 'ngx-markdown'; import {VersionModalComponent} from './version-modal/version-modal.component'; import {EditorPageRoutingModule} from '../pages/editor/editor-routing.module'; +import {ViewerPageRoutingModule} from '../pages/viewer/viewer-routing.module'; import {EditorPage} from '../pages/editor/editor.page'; +import {ViewerPage} from '../pages/viewer/viewer.page'; import {LoginPage} from '../pages/login/login.page'; import {WysiwygComponent} from './wysiwyg/wysiwyg.component'; import {WysiwygEditorComponent} from './editor/database/editors/wysiwyg/wysiwyg-editor.component'; @@ -77,6 +79,7 @@ import {FileBoxPageComponent} from './nodes/file-box/file-box-page.component'; MarkdownEditorComponent, VersionModalComponent, EditorPage, + ViewerPage, LoginPage, WysiwygComponent, WysiwygEditorComponent, @@ -103,6 +106,7 @@ import {FileBoxPageComponent} from './nodes/file-box/file-box-page.component'; DirectivesModule, MarkdownModule, EditorPageRoutingModule, + ViewerPageRoutingModule, AngularResizedEventModule, IonicSelectableModule, ], @@ -132,6 +136,7 @@ import {FileBoxPageComponent} from './nodes/file-box/file-box-page.component'; MarkdownEditorComponent, VersionModalComponent, EditorPage, + ViewerPage, LoginPage, WysiwygComponent, WysiwygEditorComponent, @@ -173,6 +178,7 @@ import {FileBoxPageComponent} from './nodes/file-box/file-box-page.component'; MarkdownEditorComponent, VersionModalComponent, EditorPage, + ViewerPage, LoginPage, WysiwygComponent, WysiwygEditorComponent, diff --git a/src/app/components/nodes/richtext/RichTextNode.component.ts b/src/app/components/nodes/richtext/RichTextNode.component.ts new file mode 100644 index 0000000..bbc19cc --- /dev/null +++ b/src/app/components/nodes/richtext/RichTextNode.component.ts @@ -0,0 +1,41 @@ +import {EditorNodeContract} from '../EditorNode.contract'; +import {Component, Input, OnInit} from '@angular/core'; +import {EditorService} from '../../../service/editor.service'; + +@Component({ + selector: 'editor-richtext', + template: ` + + + + `, +}) +export class RichTextNodeComponent extends EditorNodeContract implements OnInit { + @Input() nodeId: string; + @Input() editorUUID?: string; + + constructor( + public editorService: EditorService, + ) { super(); } + + isDirty(): boolean | Promise { + return false; + } + + writeChangesToNode(): void | Promise { + return undefined; + } + + ngOnInit(): void { + this.editorService = this.editorService.getEditor(this.editorUUID); + this.editorService.registerNodeEditor(this.nodeId, this).then(() => { + if ( !this.node.Value ) { + this.node.Value = {}; + } + + if ( this.node.Value.Value ) { + this.initialValue = this.node.Value.Value; + } + }); + } +} diff --git a/src/app/pages/editor/editor-routing.module.ts b/src/app/pages/editor/editor-routing.module.ts index 46c1429..59c08f0 100644 --- a/src/app/pages/editor/editor-routing.module.ts +++ b/src/app/pages/editor/editor-routing.module.ts @@ -2,10 +2,12 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { EditorPage } from './editor.page'; +import {EditorGuard} from '../../service/guard/Editor.guard'; const routes: Routes = [ { path: '', + canActivate: [EditorGuard], component: EditorPage } ]; diff --git a/src/app/pages/editor/editor.page.ts b/src/app/pages/editor/editor.page.ts index 11d3e7c..1c9e0ad 100644 --- a/src/app/pages/editor/editor.page.ts +++ b/src/app/pages/editor/editor.page.ts @@ -19,6 +19,7 @@ import {DatabaseLinkComponent} from '../../components/editor/forms/database-link export class EditorPage implements OnInit { public typeIcons = NodeTypeIcons; @Input() pageId: string; + @Input() baseId: string; @Input() isFilloutMode = false; @Input() hosted = false; @Input() version?: number; @@ -40,18 +41,20 @@ export class EditorPage implements OnInit { } constructor( - protected route: ActivatedRoute, - protected router: Router, - protected loader: LoadingController, - protected popover: PopoverController, - protected alerts: AlertController, - protected modals: ModalController, - public readonly editorService: EditorService, + public readonly route: ActivatedRoute, + public readonly router: Router, + public readonly loader: LoadingController, + public readonly popover: PopoverController, + public readonly alerts: AlertController, + public readonly modals: ModalController, + public editorService: EditorService, ) { debug('Constructed editor page.'); + this.editorService = editorService.getEditor(); this.route.params.subscribe(params => { - this.pageId = params.id; + this.baseId = params.id; + this.pageId = params.page || params.id; debug('Got page ID from route:', this.pageId, params); if ( params.node_id ) { @@ -59,8 +62,6 @@ export class EditorPage implements OnInit { this.scrollToNodeId = params.node_id; } }); - - this.editorService = editorService.getEditor(); } ngOnInit() {} diff --git a/src/app/pages/viewer/viewer-routing.module.ts b/src/app/pages/viewer/viewer-routing.module.ts new file mode 100644 index 0000000..4f8b499 --- /dev/null +++ b/src/app/pages/viewer/viewer-routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +import {ViewerPage} from './viewer.page'; +import {EditorGuard} from '../../service/guard/Editor.guard'; + +const routes: Routes = [ + { + path: 'site', + canActivate: [EditorGuard], + component: ViewerPage + } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], +}) +export class ViewerPageRoutingModule {} diff --git a/src/app/pages/viewer/viewer.page.html b/src/app/pages/viewer/viewer.page.html new file mode 100644 index 0000000..780763e --- /dev/null +++ b/src/app/pages/viewer/viewer.page.html @@ -0,0 +1,125 @@ + + + + + + + +
+ + +
+
+ + {{ editorService.mutablePageName }} +
+
+ + + + +
+
+ + + +
+ Sorry, this page is not available offline yet. +
+
+ + + + {{ rootPageName }} + + + + + + + + + +
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
+
+ + + + {{ baseItem.name }} + + + + + + + diff --git a/src/app/pages/viewer/viewer.page.scss b/src/app/pages/viewer/viewer.page.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/pages/viewer/viewer.page.ts b/src/app/pages/viewer/viewer.page.ts new file mode 100644 index 0000000..b6464e2 --- /dev/null +++ b/src/app/pages/viewer/viewer.page.ts @@ -0,0 +1,98 @@ +import {EditorPage} from '../editor/editor.page'; +import {Component} from '@angular/core'; +import {ActivatedRoute, Router} from '@angular/router'; +import {Location} from '@angular/common'; +import {AlertController, LoadingController, MenuController, ModalController, PopoverController} from '@ionic/angular'; +import {EditorService} from '../../service/editor.service'; +import {ApiService} from '../../service/api.service'; +import {debug} from '../../utility'; + +@Component({ + selector: 'app-viewer', + templateUrl: './viewer.page.html', + styleUrls: ['../editor/editor.page.scss', './viewer.page.scss'], +}) +export class ViewerPage extends EditorPage { + public rootPageId?: string; + protected cachedRootPageName?: string; + public menuTree: any[] = []; + private lookingUpRootPageName = false; + + public get rootPageName(): string { + if ( !this.cachedRootPageName ) { + if ( this.pageId === this.rootPageId ) { + this.cachedRootPageName = this.editorService.mutablePageName; + } else { + if ( !this.lookingUpRootPageName ) { + this.cachedRootPageName = ''; + this.lookingUpRootPageName = true; + this.lookupRootPageName(); + } + } + } + + return this.cachedRootPageName; + } + + constructor( + public readonly route: ActivatedRoute, + public readonly router: Router, + public readonly loader: LoadingController, + public readonly popover: PopoverController, + public readonly alerts: AlertController, + public readonly modals: ModalController, + public editorService: EditorService, + public readonly api: ApiService, + public readonly menu: MenuController, + public readonly activatedRoute: ActivatedRoute, + public readonly location: Location, + ) { + super(route, router, loader, popover, alerts, modals, editorService); + this.editorService = this.editorService.getEditor(); + debug('Viewer page component', this); + } + + async ionViewDidEnter() { + this.rootPageId = this.baseId; + this.menuTree = await this.api.getMenuItems(true, this.rootPageId); + if ( this.menuTree.length === 1 && this.menuTree[0].virtual ) { + this.menuTree = this.menuTree[0].children; + } + + return await super.ionViewDidEnter(); + } + + async openNav() { + if ( await this.menu.isOpen(`site-${this.rootPageId}`) ) { + await this.menu.close(`site-${this.rootPageId}`); + } else { + await this.menu.enable(true, `site-${this.rootPageId}`); + await this.menu.open(`site-${this.rootPageId}`); + } + } + + async navigate(id: string) { + await this.editorService.stopEditing(); + await this.editorService.startEditing(id); + + let newLocation: string = window.location.pathname; + newLocation = newLocation.split(';').filter(x => !x.startsWith('page=')).join(';'); + if ( id !== this.rootPageId ) { + newLocation += `;page=${id}`; + } + + this.location.replaceState(newLocation); + } + + async lookupRootPageName() { + if ( !this.rootPageId ) { + this.lookingUpRootPageName = false; + return; + } + + const page = await this.editorService.loadPage(this.rootPageId); + console.log('loaded root page', page); + this.cachedRootPageName = page.Name; + this.lookingUpRootPageName = false; + } +} diff --git a/src/app/service/guard/Editor.guard.ts b/src/app/service/guard/Editor.guard.ts index 47f699c..91a5126 100644 --- a/src/app/service/guard/Editor.guard.ts +++ b/src/app/service/guard/Editor.guard.ts @@ -16,6 +16,7 @@ export class EditorGuard implements CanActivate { async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise { const checkCanActivate = async () => { const PageId = route.paramMap.get('id'); + console.log('editor guard check can navigate', PageId, route, state); const canView = await this.api.checkPagePermission(String(PageId)); diff --git a/src/global.scss b/src/global.scss index 81fe750..05715d6 100644 --- a/src/global.scss +++ b/src/global.scss @@ -215,3 +215,11 @@ body.dark { color: white; } } + +.custom-menu-item { + pointer-events: auto !important; + + .item { + pointer-events: auto !important; + } +}