Show read-only editor in versions (not actually versioning yet)
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
26e8d6ecd6
commit
ab811bb54c
@ -17,7 +17,7 @@ const routes: Routes = [
|
||||
},
|
||||
{
|
||||
path: 'editor',
|
||||
loadChildren: () => import('./pages/editor/editor.module').then( m => m.EditorPageModule)
|
||||
loadChildren: () => import('./components/components.module').then( m => m.ComponentsModule)
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -31,6 +31,8 @@ import {MarkdownComponent as MarkdownEditorComponent} from './nodes/markdown/mar
|
||||
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 {EditorPage} from '../pages/editor/editor.page';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -58,6 +60,7 @@ import {VersionModalComponent} from './version-modal/version-modal.component';
|
||||
NormComponent,
|
||||
MarkdownEditorComponent,
|
||||
VersionModalComponent,
|
||||
EditorPage,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@ -69,6 +72,7 @@ import {VersionModalComponent} from './version-modal/version-modal.component';
|
||||
MonacoEditorModule,
|
||||
DirectivesModule,
|
||||
MarkdownModule,
|
||||
EditorPageRoutingModule,
|
||||
],
|
||||
entryComponents: [
|
||||
NodePickerComponent,
|
||||
@ -95,6 +99,7 @@ import {VersionModalComponent} from './version-modal/version-modal.component';
|
||||
NormComponent,
|
||||
MarkdownEditorComponent,
|
||||
VersionModalComponent,
|
||||
EditorPage,
|
||||
],
|
||||
exports: [
|
||||
NodePickerComponent,
|
||||
@ -121,6 +126,7 @@ import {VersionModalComponent} from './version-modal/version-modal.component';
|
||||
NormComponent,
|
||||
MarkdownEditorComponent,
|
||||
VersionModalComponent,
|
||||
EditorPage,
|
||||
]
|
||||
})
|
||||
export class ComponentsModule {}
|
||||
|
@ -19,7 +19,7 @@
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
<div class="preview">
|
||||
Page preview will be here.
|
||||
<app-editor [pageId]="pageId" *ngIf="selectedVersion" [hosted]="true" [readonly]="true" #editor></app-editor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -23,7 +23,7 @@
|
||||
|
||||
.contents {
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
overflow-y: hidden;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -35,6 +35,8 @@
|
||||
|
||||
.preview {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.version-date {
|
||||
|
@ -1,7 +1,8 @@
|
||||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {Component, Input, OnInit, ViewChild} from '@angular/core';
|
||||
import {AlertController, ModalController} from '@ionic/angular';
|
||||
import {EditorService} from '../../service/editor.service';
|
||||
import {PageVersionRecord} from '../../structures/PageRecord';
|
||||
import {EditorPage} from '../../pages/editor/editor.page';
|
||||
|
||||
@Component({
|
||||
selector: 'app-version-modal',
|
||||
@ -10,6 +11,8 @@ import {PageVersionRecord} from '../../structures/PageRecord';
|
||||
})
|
||||
export class VersionModalComponent implements OnInit {
|
||||
@Input() pageId: string;
|
||||
@ViewChild('editor') editor: EditorPage;
|
||||
|
||||
public pageVersions: PageVersionRecord[] = [];
|
||||
public selectedVersion?: PageVersionRecord;
|
||||
|
||||
@ -23,7 +26,10 @@ export class VersionModalComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
this.pageVersions = await this.editorService.loadPageVersions(this.pageId);
|
||||
await this.onVersionClick(this.pageVersions[0]);
|
||||
this.selectedVersion = this.pageVersions[0];
|
||||
setTimeout(() => {
|
||||
this.onVersionClick(this.pageVersions[0]);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
dismiss() {
|
||||
@ -32,5 +38,8 @@ export class VersionModalComponent implements OnInit {
|
||||
|
||||
async onVersionClick(version: PageVersionRecord) {
|
||||
this.selectedVersion = version;
|
||||
if ( this.editor ) {
|
||||
this.editor.ionViewDidEnter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { EditorPageRoutingModule } from './editor-routing.module';
|
||||
|
||||
import { EditorPage } from './editor.page';
|
||||
import {ComponentsModule} from '../../components/components.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
EditorPageRoutingModule,
|
||||
ComponentsModule
|
||||
],
|
||||
declarations: [EditorPage]
|
||||
})
|
||||
export class EditorPageModule {}
|
@ -7,6 +7,7 @@
|
||||
<ion-title #titleBar>
|
||||
<ion-input
|
||||
[(ngModel)]="editorService.mutablePageName"
|
||||
[readonly]="!editorService.canEdit()"
|
||||
placeholder="Click to edit page name..."
|
||||
class="title-input"
|
||||
></ion-input>
|
||||
@ -43,7 +44,7 @@
|
||||
>
|
||||
<div class="host-icons">
|
||||
<i class="type-icon fa" [ngClass]="typeIcons[(node.isNorm() ? 'node' : node.type)] + ' ' + (node.isNorm() ? 'node' : node.type)"></i>
|
||||
<button (click)="onOptionsClick($event, node)">
|
||||
<button (click)="onOptionsClick($event, node)" *ngIf="editorService.canEdit()">
|
||||
<i class="fa fa-ellipsis-v" title="Node options"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -63,7 +64,7 @@
|
||||
<editor-files style="flex: 1;" [nodeId]="node.UUID" [editorUUID]="editorService.instanceUUID"></editor-files>
|
||||
</ng-container>
|
||||
</div>
|
||||
<button class="host-add-button" (click)="onAddClick($event)">
|
||||
<button *ngIf="editorService.canEdit()" class="host-add-button" (click)="onAddClick($event)">
|
||||
<i class="fa fa-plus"></i> Add Node
|
||||
</button>
|
||||
</div>
|
||||
|
@ -17,6 +17,17 @@ import {VersionModalComponent} from '../../components/version-modal/version-moda
|
||||
export class EditorPage implements OnInit {
|
||||
public typeIcons = NodeTypeIcons;
|
||||
@Input() pageId: string;
|
||||
@Input() hosted = false;
|
||||
@Input() version?: number;
|
||||
|
||||
@Input()
|
||||
set readonly(val: boolean) {
|
||||
this.editorService.forceReadonly = val;
|
||||
}
|
||||
|
||||
get readonly() {
|
||||
return this.editorService.forceReadonly;
|
||||
}
|
||||
|
||||
constructor(
|
||||
protected route: ActivatedRoute,
|
||||
@ -39,7 +50,7 @@ export class EditorPage implements OnInit {
|
||||
ionViewDidEnter() {
|
||||
if ( this.pageId ) {
|
||||
this.editorService.startEditing(this.pageId);
|
||||
} else {
|
||||
} else if ( !this.hosted ) {
|
||||
this.router.navigate(['/home']);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +0,0 @@
|
||||
export interface RedirectAction {
|
||||
type: 'redirect';
|
||||
args: {
|
||||
destination: string
|
||||
blank?: boolean
|
||||
appUrl?: boolean
|
||||
};
|
||||
}
|
||||
|
||||
export type Action = RedirectAction;
|
@ -1,27 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Action } from './action.types';
|
||||
import {SessionService} from './session.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class ActionsService {
|
||||
constructor(
|
||||
protected readonly session: SessionService,
|
||||
) { }
|
||||
|
||||
async perform(action: Action) {
|
||||
if ( action.type === 'redirect' ) {
|
||||
let destination = action.args.destination;
|
||||
if ( action.args.appUrl ) {
|
||||
destination = this.session.buildAppUrl(destination);
|
||||
}
|
||||
|
||||
if ( action.args.blank ) {
|
||||
window.open(destination, '_blank');
|
||||
} else {
|
||||
window.location.href = destination;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ export class EditorService {
|
||||
protected ready$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
protected subs: Subscription[] = [];
|
||||
protected saving = false;
|
||||
public forceReadonly = false;
|
||||
protected saveTriggered = false;
|
||||
public notAvailable = false;
|
||||
public readonly instanceUUID: string;
|
||||
@ -139,7 +140,7 @@ export class EditorService {
|
||||
}
|
||||
|
||||
async save() {
|
||||
if ( !(await this.needsSave()) || this.saving ) {
|
||||
if ( !(await this.needsSave()) || this.saving || this.forceReadonly ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -170,6 +171,10 @@ export class EditorService {
|
||||
throw new NoPageLoadedError();
|
||||
}
|
||||
|
||||
if ( this.forceReadonly ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nodeIndex = this.currentNodes.findIndex(maybeNode => maybeNode.UUID === node.UUID);
|
||||
if ( nodeIndex < 0 ) {
|
||||
return;
|
||||
@ -417,6 +422,10 @@ export class EditorService {
|
||||
}
|
||||
|
||||
async needsSave() {
|
||||
if ( this.forceReadonly ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( this.dirtyOverride ) {
|
||||
return true;
|
||||
}
|
||||
@ -432,6 +441,10 @@ export class EditorService {
|
||||
throw new NoPageLoadedError();
|
||||
}
|
||||
|
||||
if ( this.forceReadonly ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const node = this.currentNodes.find(maybeNode => maybeNode.UUID === nodeId);
|
||||
if ( !node ) {
|
||||
throw new Error('Invalid node ID.');
|
||||
@ -463,6 +476,10 @@ export class EditorService {
|
||||
throw new NoPageLoadedError();
|
||||
}
|
||||
|
||||
if ( this.forceReadonly ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const baseHost = new HostRecord();
|
||||
baseHost.type = type;
|
||||
baseHost.PageId = this.currentPage.UUID;
|
||||
@ -495,11 +512,7 @@ export class EditorService {
|
||||
}
|
||||
|
||||
canEdit() {
|
||||
if ( !this.currentPage ) {
|
||||
throw new NoPageLoadedError();
|
||||
}
|
||||
|
||||
return !this.currentPage.isViewOnly();
|
||||
return this.currentPage && !this.currentPage.isViewOnly() && !this.forceReadonly;
|
||||
}
|
||||
|
||||
async registerNodeEditor(nodeId: string, editor: EditorNodeContract) {
|
||||
|
@ -1,74 +0,0 @@
|
||||
import {Host, Injectable} from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
import PageRecord from '../structures/PageRecord';
|
||||
import {ApiService} from './api.service';
|
||||
import HostRecord from '../structures/HostRecord';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PageService {
|
||||
|
||||
constructor(
|
||||
protected api: ApiService,
|
||||
) { }
|
||||
|
||||
load(id: string): Observable<PageRecord> {
|
||||
return new Observable<PageRecord>(sub => {
|
||||
this.api.get(`/page/${id}`).subscribe(response => {
|
||||
if ( response.status === 200 ) {
|
||||
sub.next(new PageRecord(response.data));
|
||||
sub.complete();
|
||||
} else {
|
||||
throw new Error(response.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
save(page: PageRecord): Observable<PageRecord> {
|
||||
return new Observable<PageRecord>(sub => {
|
||||
this.api.post(`/page/${page.UUID}/save`, page.toSave()).subscribe(res => {
|
||||
sub.next(new PageRecord(res.data));
|
||||
sub.complete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get_nodes(page: PageRecord): Observable<Array<HostRecord>> {
|
||||
return new Observable<Array<HostRecord>>(sub => {
|
||||
this.api.get(`/page/${page.UUID}/nodes`).subscribe(res => {
|
||||
const returns = [];
|
||||
res.data.forEach(rec => {
|
||||
const host = new HostRecord(rec.Value.Value);
|
||||
host.load(rec);
|
||||
returns.push(host);
|
||||
});
|
||||
|
||||
sub.next(returns);
|
||||
sub.complete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
save_nodes(page: PageRecord, nodes: Array<HostRecord>): Observable<Array<HostRecord>> {
|
||||
return new Observable<Array<HostRecord>>(sub => {
|
||||
nodes = nodes.map(x => {
|
||||
x.PageId = page.UUID;
|
||||
return x.toSave();
|
||||
});
|
||||
|
||||
this.api.post(`/page/${page.UUID}/nodes/save`, nodes).subscribe(res => {
|
||||
const returns = [];
|
||||
res.data.forEach(rec => {
|
||||
const host = new HostRecord(rec.Value.Value);
|
||||
host.load(rec);
|
||||
returns.push(host);
|
||||
});
|
||||
|
||||
sub.next(returns);
|
||||
sub.complete();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user