diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts index 49632ed..ed5df46 100644 --- a/src/app/components/components.module.ts +++ b/src/app/components/components.module.ts @@ -29,7 +29,8 @@ import {SearchComponent} from './search/Search.component'; import {NormComponent} from './nodes/norm/norm.component'; import {MarkdownComponent as MarkdownEditorComponent} from './nodes/markdown/markdown.component'; import {DirectivesModule} from '../directives/directives.module'; -import {MarkdownModule} from "ngx-markdown"; +import {MarkdownModule} from 'ngx-markdown'; +import {VersionModalComponent} from './version-modal/version-modal.component'; @NgModule({ declarations: [ @@ -56,18 +57,19 @@ import {MarkdownModule} from "ngx-markdown"; NormComponent, MarkdownEditorComponent, + VersionModalComponent, + ], + imports: [ + CommonModule, + IonicModule, + AgGridModule, + FormsModule, + ReactiveFormsModule, + ContenteditableModule, + MonacoEditorModule, + DirectivesModule, + MarkdownModule, ], - imports: [ - CommonModule, - IonicModule, - AgGridModule, - FormsModule, - ReactiveFormsModule, - ContenteditableModule, - MonacoEditorModule, - DirectivesModule, - MarkdownModule, - ], entryComponents: [ NodePickerComponent, DatabaseComponent, @@ -92,6 +94,7 @@ import {MarkdownModule} from "ngx-markdown"; NormComponent, MarkdownEditorComponent, + VersionModalComponent, ], exports: [ NodePickerComponent, @@ -117,6 +120,7 @@ import {MarkdownModule} from "ngx-markdown"; NormComponent, MarkdownEditorComponent, + VersionModalComponent, ] }) export class ComponentsModule {} diff --git a/src/app/components/option-menu/option-menu.component.html b/src/app/components/option-menu/option-menu.component.html index 1dee87c..eab4628 100644 --- a/src/app/components/option-menu/option-menu.component.html +++ b/src/app/components/option-menu/option-menu.component.html @@ -1,5 +1,5 @@ - + {{ menuItems[i].name }} diff --git a/src/app/components/option-menu/option-menu.component.ts b/src/app/components/option-menu/option-menu.component.ts index 2a30469..711b179 100644 --- a/src/app/components/option-menu/option-menu.component.ts +++ b/src/app/components/option-menu/option-menu.component.ts @@ -7,7 +7,7 @@ import {PopoverController} from '@ionic/angular'; styleUrls: ['./option-menu.component.scss'], }) export class OptionMenuComponent implements OnInit { - @Input() menuItems: Array<{name: string, icon: string, value: string, type?: string}> = []; + @Input() menuItems: Array<{name: string, icon: string, value: string, type?: string, title?: string}> = []; constructor( protected popover: PopoverController, @@ -18,5 +18,4 @@ export class OptionMenuComponent implements OnInit { async onSelect(value) { await this.popover.dismiss(value); } - } diff --git a/src/app/components/version-modal/version-modal.component.html b/src/app/components/version-modal/version-modal.component.html new file mode 100644 index 0000000..f36646a --- /dev/null +++ b/src/app/components/version-modal/version-modal.component.html @@ -0,0 +1,25 @@ +
+
+
Page Versions
+ +
+
+ + + +

+ #{{ version.versionNum }} + ({{ version.versionCreateDate.toLocaleString() }}) + +

+
{{ version.versionMessage }} by {{ version.userDisplay }}
+
+
+
+
+ Page preview will be here. +
+
+
\ No newline at end of file diff --git a/src/app/components/version-modal/version-modal.component.scss b/src/app/components/version-modal/version-modal.component.scss new file mode 100644 index 0000000..b87676d --- /dev/null +++ b/src/app/components/version-modal/version-modal.component.scss @@ -0,0 +1,49 @@ +.container { + display: flex; + flex-direction: column; + height: 100%; + + .header { + background: lightgrey; + display: flex; + flex-direction: row; + + .title { + flex: 1; + padding: 10px; + font-size: 1.2em; + } + + .close { + padding: 10px 15px; + background: #ff6666; + color: white; + } + } + + .contents { + height: 100%; + overflow-y: scroll; + display: flex; + flex-direction: row; + + ion-list { + height: 100%; + overflow-y: scroll; + max-width: 325px; + } + + .preview { + flex: 1; + } + + .version-date { + font-weight: normal; + } + + .current-version { + color: darkgreen; + margin-left: 10px; + } + } +} \ No newline at end of file diff --git a/src/app/components/version-modal/version-modal.component.ts b/src/app/components/version-modal/version-modal.component.ts new file mode 100644 index 0000000..42a0232 --- /dev/null +++ b/src/app/components/version-modal/version-modal.component.ts @@ -0,0 +1,36 @@ +import {Component, Input, OnInit} from '@angular/core'; +import {AlertController, ModalController} from '@ionic/angular'; +import {EditorService} from '../../service/editor.service'; +import {PageVersionRecord} from '../../structures/PageRecord'; + +@Component({ + selector: 'app-version-modal', + templateUrl: './version-modal.component.html', + styleUrls: ['./version-modal.component.scss'], +}) +export class VersionModalComponent implements OnInit { + @Input() pageId: string; + public pageVersions: PageVersionRecord[] = []; + public selectedVersion?: PageVersionRecord; + + constructor( + protected alerts: AlertController, + protected modals: ModalController, + protected editorService: EditorService, + ) { + console.log('version modal', this); + } + + async ngOnInit() { + this.pageVersions = await this.editorService.loadPageVersions(this.pageId); + await this.onVersionClick(this.pageVersions[0]); + } + + dismiss() { + this.modals.dismiss(); + } + + async onVersionClick(version: PageVersionRecord) { + this.selectedVersion = version; + } +} diff --git a/src/app/pages/editor/editor.page.html b/src/app/pages/editor/editor.page.html index 2fda9ad..933d86f 100644 --- a/src/app/pages/editor/editor.page.html +++ b/src/app/pages/editor/editor.page.html @@ -12,10 +12,18 @@ > - + + + diff --git a/src/app/pages/editor/editor.page.ts b/src/app/pages/editor/editor.page.ts index 00139f6..8876a28 100644 --- a/src/app/pages/editor/editor.page.ts +++ b/src/app/pages/editor/editor.page.ts @@ -1,11 +1,13 @@ import {Component, HostListener, Input, OnInit} from '@angular/core'; import HostRecord from '../../structures/HostRecord'; import {ActivatedRoute, Router} from '@angular/router'; -import {AlertController, LoadingController, PopoverController} from '@ionic/angular'; +import {AlertController, LoadingController, ModalController, PopoverController} from '@ionic/angular'; import {NodePickerComponent} from '../../components/editor/node-picker/node-picker.component'; import {HostOptionsComponent} from '../../components/editor/host-options/host-options.component'; import {EditorService} from '../../service/editor.service'; import {NodeTypeIcons} from '../../structures/node-types'; +import {OptionMenuComponent} from '../../components/option-menu/option-menu.component'; +import {VersionModalComponent} from "../../components/version-modal/version-modal.component"; @Component({ selector: 'app-editor', @@ -22,6 +24,7 @@ export class EditorPage implements OnInit { protected loader: LoadingController, protected popover: PopoverController, protected alerts: AlertController, + protected modals: ModalController, public readonly editorService: EditorService, ) { this.route.params.subscribe(params => { @@ -86,9 +89,9 @@ export class EditorPage implements OnInit { } else if ( value === 'move_down' ) { this.editorService.moveNode(node, 'down'); } else if ( value === 'add_before' ) { - this.onAddClick(dismissEvent, 'before', node.UUID); + this.onAddClick(event, 'before', node.UUID); } else if ( value === 'add_after' ) { - this.onAddClick(dismissEvent, 'after', node.UUID); + this.onAddClick(event, 'after', node.UUID); } }); @@ -115,4 +118,43 @@ export class EditorPage implements OnInit { await popover.present(); } + + async onPageMenuClick(event: MouseEvent) { + const popover = await this.popover.create({ + event, + component: OptionMenuComponent, + componentProps: { + menuItems: [ + { + name: 'Versions', + icon: 'fa fa-history', + value: 'view-versions', + title: 'View other versions of this page', + }, + ], + }, + }); + + popover.onDidDismiss().then(async value => { + const { data } = value; + + if ( data === 'view-versions' ) { + await this.showVersionModal(); + } + }); + + await popover.present(); + } + + async showVersionModal() { + const modal = await this.modals.create({ + component: VersionModalComponent, + componentProps: { + pageId: this.pageId, + }, + cssClass: 'modal-big', + }); + + await modal.present(); + } } diff --git a/src/app/service/editor.service.ts b/src/app/service/editor.service.ts index 97aec64..758db19 100644 --- a/src/app/service/editor.service.ts +++ b/src/app/service/editor.service.ts @@ -1,6 +1,6 @@ import {Injectable} from '@angular/core'; import {ApiService, ResourceNotAvailableOfflineError} from './api.service'; -import PageRecord from '../structures/PageRecord'; +import PageRecord, {PageVersionRecord} from '../structures/PageRecord'; import HostRecord from '../structures/HostRecord'; import {EditorNodeContract} from '../components/nodes/EditorNode.contract'; import {BehaviorSubject, Subscription} from 'rxjs'; @@ -55,6 +55,10 @@ export class EditorService { return this.saveTriggered; } + public get isEditing() { + return !!this.currentPage; + } + public get immutableNodes(): HostRecord[] { return [...this.currentNodes]; } @@ -570,6 +574,31 @@ export class EditorService { }); } + async loadPageVersions(pageId: string): Promise { + return new Promise(async (res, rej) => { + if ( this.api.isOffline ) { + return rej(new ResourceNotAvailableOfflineError()); + } + + this.api.get(`/page/${pageId}/versions`).subscribe({ + next: results => { + return res(results.data.map(data => { + return { + currentVersion: Boolean(data.current_version), + versionNum: Number(data.version_num), + versionUserId: data.version_user_id, + versionMessage: data.version_message, + versionUUID: data.version_UUID, + versionCreateDate: new Date(data.version_create_date), + userDisplay: data.user_display, + }; + })); + }, + error: rej, + }); + }); + } + async loadNodes(pageId: string): Promise { return new Promise(async (res, rej) => { const existingNodes = await this.db.pageNodes.where({ PageId: pageId }).toArray() as PageNode[]; diff --git a/src/app/structures/PageRecord.ts b/src/app/structures/PageRecord.ts index f42bc06..0ea0bf8 100644 --- a/src/app/structures/PageRecord.ts +++ b/src/app/structures/PageRecord.ts @@ -1,3 +1,13 @@ +export class PageVersionRecord { + currentVersion: boolean; + versionNum: number; + versionUserId: string; + versionMessage: string; + versionUUID: string; + versionCreateDate: Date; + userDisplay: string; +} + export default class PageRecord { public UUID: string; public Name: string; diff --git a/src/global.scss b/src/global.scss index 64ccf5d..805026f 100644 --- a/src/global.scss +++ b/src/global.scss @@ -123,3 +123,10 @@ hr { padding: 10px; } } + +.modal-big { + .modal-wrapper { + height: calc(100vh - 30px); + width: calc(100vw - 30px); + } +}