Menu enhancements

This commit is contained in:
garrettmills 2020-02-11 00:39:47 -06:00
parent 6a7618f971
commit fd76f43c7e
4 changed files with 61 additions and 26 deletions

View File

@ -26,24 +26,14 @@
</ion-buttons> </ion-buttons>
</ion-list-header> </ion-list-header>
<tree-root [nodes]="nodes" [options]="options"></tree-root> <tree-root style="font-size: 15px;" #menuTree [nodes]="nodes" [options]="options"></tree-root>
</ion-list> </ion-list>
</ion-content> </ion-content>
<ion-footer> <ion-footer>
<ion-item slot="end" lines="full"> <ion-searchbar placeholder="Filter pages..." (ionChange)="onFilterChange($event)"></ion-searchbar>
<ion-icon slot="start" name="moon"></ion-icon>
<ion-label>
Dark mode
</ion-label>
<ion-toggle (ionChange)="toggleDark()" id="themeToggle" slot="end"></ion-toggle>
</ion-item>
<ion-item button slot="end" lines="full" (click)="logOut()">
<ion-icon name="exit" slot="start"></ion-icon>
<ion-label>Log out</ion-label>
</ion-item>
<ion-item button slot="end" lines="full" (click)="showOptions()"> <ion-item button slot="end" lines="full" (click)="showOptions()">
<ion-icon name="list" slot="start"></ion-icon> <ion-icon name="list" slot="start"></ion-icon>
<ion-label>Options</ion-label> <ion-label>Menu</ion-label>
</ion-item> </ion-item>
</ion-footer> </ion-footer>
</ion-menu> </ion-menu>

View File

@ -1,11 +1,11 @@
import { Component, OnInit } from '@angular/core'; import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
import {AlertController, Platform, PopoverController} from '@ionic/angular'; import {AlertController, Platform, PopoverController} from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx'; import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx'; import { StatusBar } from '@ionic-native/status-bar/ngx';
import { ApiService } from './service/api.service'; import { ApiService } from './service/api.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { TREE_ACTIONS } from 'angular-tree-component'; import {TREE_ACTIONS, TreeComponent} from 'angular-tree-component';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import {OptionPickerComponent} from './components/option-picker/option-picker.component'; import {OptionPickerComponent} from './components/option-picker/option-picker.component';
@ -15,22 +15,35 @@ import {OptionPickerComponent} from './components/option-picker/option-picker.co
styleUrls: ['app.component.scss'] styleUrls: ['app.component.scss']
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
@ViewChild('menuTree', {static: false}) menuTree: TreeComponent;
public addChildTarget: any = false; public addChildTarget: any = false;
public deleteTarget: any = false; public deleteTarget: any = false;
public refreshingMenu = false; public refreshingMenu = false;
public lastClickEvent: Array<any> = []; public lastClickEvent: Array<any> = [];
public nodes = []; public nodes = [];
public currentPageId: string;
public options = { public options = {
isExpandedField: 'expanded',
animateExpand: true,
actionMapping: { actionMapping: {
mouse: { mouse: {
dblClick: (tree, node, $event) => { dblClick: (tree, node, $event) => {
const id = node.data.id; const id = node.data.id;
this.router.navigate(['/editor', { id }]); if ( !node.data.virtual ) {
this.currentPageId = id;
this.router.navigate(['/editor', { id }]);
}
}, },
click: (tree, node, $event) => { click: (tree, node, $event) => {
TREE_ACTIONS.FOCUS(tree, node, $event); TREE_ACTIONS.FOCUS(tree, node, $event);
this.addChildTarget = node; TREE_ACTIONS.EXPAND(tree, node, $event);
this.deleteTarget = node; if ( !node.data.noChildren ) {
this.addChildTarget = node;
}
if ( !node.data.noDelete ) {
this.deleteTarget = node;
}
this.lastClickEvent = [tree, node, $event]; this.lastClickEvent = [tree, node, $event];
} }
} }
@ -52,15 +65,26 @@ export class AppComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.reloadMenuItems().subscribe(); this.reloadMenuItems().subscribe(() => {
this.menuTree.treeModel.expandAll();
});
} }
showOptions() { showOptions() {
this.popover.create({ this.popover.create({
component: OptionPickerComponent, component: OptionPickerComponent,
componentProps: {
toggleDark: () => this.toggleDark(),
isDark: () => this.isDark(),
}
}).then(popover => popover.present()); }).then(popover => popover.present());
} }
onFilterChange($event) {
const value = $event.detail.value;
this.menuTree.treeModel.filterNodes(value, true);
}
async onTopLevelCreate() { async onTopLevelCreate() {
const alert = await this.alerts.create({ const alert = await this.alerts.create({
header: 'Create Page', header: 'Create Page',
@ -153,6 +177,10 @@ export class AppComponent implements OnInit {
this.api this.api
.post(`/page/delete/${this.deleteTarget.data.id}`) .post(`/page/delete/${this.deleteTarget.data.id}`)
.subscribe(res => { .subscribe(res => {
if ( this.currentPageId === this.deleteTarget.data.id ) {
this.router.navigate(['/home']);
}
this.reloadMenuItems().subscribe(); this.reloadMenuItems().subscribe();
this.deleteTarget = false; this.deleteTarget = false;
this.addChildTarget = false; this.addChildTarget = false;
@ -177,8 +205,10 @@ export class AppComponent implements OnInit {
return new Observable(sub => { return new Observable(sub => {
this.api.get('/menu/items').subscribe(result => { this.api.get('/menu/items').subscribe(result => {
this.nodes = result.data; this.nodes = result.data;
sub.next(); setTimeout(() => {
sub.complete(); sub.next();
sub.complete();
}, 0);
}); });
}); });
} }
@ -191,12 +221,12 @@ export class AppComponent implements OnInit {
} }
toggleDark() { toggleDark() {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)'); // const prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
this.darkMode = !this.darkMode; this.darkMode = !this.darkMode;
document.body.classList.toggle('dark', this.darkMode); document.body.classList.toggle('dark', this.darkMode);
} }
logOut() { isDark() {
window.open('/auth/logout'); return !!this.darkMode;
} }
} }

View File

@ -3,4 +3,12 @@
<ion-icon slot="start" name="menu"></ion-icon> <ion-icon slot="start" name="menu"></ion-icon>
<ion-label>Export to HTML Site</ion-label> <ion-label>Export to HTML Site</ion-label>
</ion-item> </ion-item>
<ion-item button (click)="onSelect('toggle_darkmode')">
<ion-icon slot="start" [name]="isDark() ? 'sun' : 'moon'"></ion-icon>
<ion-label>{{ isDark() ? 'To The Light!' : 'Go Dark...' }}</ion-label>
</ion-item>
<ion-item button (click)="onSelect('logout')">
<ion-icon slot="start" name="exit"></ion-icon>
<ion-label>Logout</ion-label>
</ion-item>
</ion-list> </ion-list>

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {ApiService} from '../../service/api.service'; import {ApiService} from '../../service/api.service';
@ -8,9 +8,12 @@ import {ApiService} from '../../service/api.service';
styleUrls: ['./option-picker.component.scss'], styleUrls: ['./option-picker.component.scss'],
}) })
export class OptionPickerComponent implements OnInit { export class OptionPickerComponent implements OnInit {
@Input() toggleDark: () => void;
@Input() isDark: () => boolean;
constructor( constructor(
protected api: ApiService protected api: ApiService,
protected router: Router,
) { } ) { }
ngOnInit() {} ngOnInit() {}
@ -18,6 +21,10 @@ export class OptionPickerComponent implements OnInit {
onSelect(key) { onSelect(key) {
if ( key === 'html_export' ) { if ( key === 'html_export' ) {
window.open(this.api._build_url('/data/export/html'), '_blank'); window.open(this.api._build_url('/data/export/html'), '_blank');
} else if ( key === 'logout' ) {
window.location.href = '/auth/logout';
} else if ( key === 'toggle_darkmode' ) {
this.toggleDark();
} }
} }
} }