You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
frontend/src/app/app.component.ts

280 lines
7.5 KiB

import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {AlertController, ModalController, Platform, PopoverController} from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { ApiService } from './service/api.service';
import { Router } from '@angular/router';
import {TREE_ACTIONS, TreeComponent} from 'angular-tree-component';
import { Observable } from 'rxjs';
import {OptionPickerComponent} from './components/option-picker/option-picker.component';
import {OptionMenuComponent} from './components/option-menu/option-menu.component';
import {SelectorComponent} from './components/sharing/selector/selector.component';
@Component({
selector: 'app-root',
templateUrl: 'app.component.html',
styleUrls: ['app.component.scss']
})
export class AppComponent implements OnInit {
@ViewChild('menuTree', {static: false}) menuTree: TreeComponent;
public addChildTarget: any = false;
public deleteTarget: any = false;
public menuTarget: any = false;
public refreshingMenu = false;
public lastClickEvent: Array<any> = [];
public nodes = [];
public currentPageId: string;
public options = {
isExpandedField: 'expanded',
animateExpand: true,
actionMapping: {
mouse: {
dblClick: (tree, node, $event) => {
const id = node.data.id;
if ( !node.data.virtual ) {
this.currentPageId = id;
this.router.navigate(['/editor', { id }]);
}
},
click: (tree, node, $event) => {
TREE_ACTIONS.FOCUS(tree, node, $event);
TREE_ACTIONS.EXPAND(tree, node, $event);
this.addChildTarget = false;
this.deleteTarget = false;
this.menuTarget = false;
if ( !node.data.noChildren && (!node.data.level || node.data.level === 'manage') ) {
this.addChildTarget = node;
}
if ( !node.data.noDelete && (!node.data.level || node.data.level === 'manage') ) {
this.deleteTarget = node;
}
this.menuTarget = node;
this.lastClickEvent = [tree, node, $event];
}
}
}
};
public darkMode = false;
constructor(
private platform: Platform,
private splashScreen: SplashScreen,
private statusBar: StatusBar,
private api: ApiService,
protected router: Router,
protected alerts: AlertController,
protected popover: PopoverController,
protected modal: ModalController,
) {
this.initializeApp();
}
ngOnInit() {
this.reloadMenuItems().subscribe(() => {
this.menuTree.treeModel.expandAll();
});
}
showOptions($event) {
this.popover.create({
event: $event,
component: OptionPickerComponent,
componentProps: {
toggleDark: () => this.toggleDark(),
isDark: () => this.isDark(),
}
}).then(popover => popover.present());
}
onFilterChange($event) {
const value = $event.detail.value;
this.menuTree.treeModel.filterNodes(value, true);
}
async onNodeMenuClick($event) {
console.log(this.menuTarget)
let canManage = this.menuTarget.data.level === 'manage';
if ( !canManage ) {
if ( !this.menuTarget.data.level ) {
canManage = true;
}
}
const popover = await this.popover.create({
component: OptionMenuComponent,
componentProps: {
menuItems: [
...(!canManage ? [] : [{name: 'Share Sub-Tree', icon: 'person-add', value: 'share'}]),
],
},
event: $event,
});
popover.onDidDismiss().then((result) => {
if ( result.data === 'share' ) {
this.modal.create({
component: SelectorComponent,
componentProps: {
node: this.menuTarget.data,
}
}).then(modal => {
modal.present();
});
}
});
await popover.present();
}
async onTopLevelCreate() {
const alert = await this.alerts.create({
header: 'Create Page',
message: 'Please enter a new name for the page:',
cssClass: 'page-prompt',
inputs: [
{
name: 'name',
type: 'text',
placeholder: 'My Awesome Page'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary'
},
{
text: 'Create',
handler: async args => {
this.api.post('/page/create', args).subscribe(res => {
this.router.navigate(['/editor', { id: res.data.UUID }]);
this.reloadMenuItems().subscribe();
});
}
}
]
});
await alert.present();
}
async onChildCreate() {
const alert = await this.alerts.create({
header: 'Create Sub-Page',
message: 'Please enter a new name for the page:',
cssClass: 'page-prompt',
inputs: [
{
name: 'name',
type: 'text',
placeholder: 'My Awesome Page'
}
],
buttons: [
{
text: 'Cancel',
role: 'cancel',
cssClass: 'secondary'
},
{
text: 'Create',
handler: async args => {
args = {
name: args.name,
parentId: this.addChildTarget.data.id
};
this.api.post('/page/create-child', args).subscribe(res => {
this.reloadMenuItems().subscribe(() => {
TREE_ACTIONS.EXPAND(
this.lastClickEvent[0],
this.lastClickEvent[1],
this.lastClickEvent[2]
);
this.router.navigate(['/editor', { id: res.data.UUID }]);
});
});
}
}
]
});
await alert.present();
}
async onDeleteClick() {
const alert = await this.alerts.create({
header: 'Delete page?',
message:
'Deleting this page will make its contents and all of its children inaccessible. Are you sure you want to continue?',
buttons: [
{
text: 'Keep It',
role: 'cancel'
},
{
text: 'Delete It',
handler: async () => {
this.api
.post(`/page/delete/${this.deleteTarget.data.id}`)
.subscribe(res => {
if ( this.currentPageId === this.deleteTarget.data.id ) {
this.router.navigate(['/home']);
}
this.reloadMenuItems().subscribe();
this.deleteTarget = false;
this.addChildTarget = false;
this.menuTarget = false;
});
}
}
]
});
await alert.present();
}
onMenuRefresh() {
this.refreshingMenu = true;
this.reloadMenuItems().subscribe();
setTimeout(() => {
this.refreshingMenu = false;
}, 2000);
}
reloadMenuItems() {
return new Observable(sub => {
this.api.get('/menu/items').subscribe(result => {
this.nodes = result.data;
setTimeout(() => {
sub.next();
sub.complete();
}, 0);
});
});
}
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
toggleDark() {
// const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
this.darkMode = !this.darkMode;
document.body.classList.toggle('dark', this.darkMode);
}
isDark() {
return !!this.darkMode;
}
}