Add session service and startup logic to check for authed user (#15)
This commit is contained in:
parent
d3af6611c6
commit
3e9a0a03f8
@ -1,9 +1,9 @@
|
|||||||
<ion-app class="dark">
|
<ion-app class="dark">
|
||||||
<ion-split-pane contentId="main-content">
|
<ion-split-pane contentId="main-content" *ngIf="ready$ | async">
|
||||||
<ion-menu class="sidebar" contentId="main-content" content="content" type="push" side="start">
|
<ion-menu class="sidebar" contentId="main-content" content="content" type="push" side="start">
|
||||||
<ion-header>
|
<ion-header>
|
||||||
<ion-toolbar color="primary">
|
<ion-toolbar color="primary">
|
||||||
<ion-title>Noded
|
<ion-title>{{ appName }}
|
||||||
<ion-menu-toggle menu="first" autoHide="false"></ion-menu-toggle>
|
<ion-menu-toggle menu="first" autoHide="false"></ion-menu-toggle>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
|
import {AfterViewInit, Component, ElementRef, OnInit, ViewChild} from '@angular/core';
|
||||||
|
|
||||||
import {AlertController, ModalController, Platform, PopoverController} from '@ionic/angular';
|
import {AlertController, ModalController, Platform, PopoverController, LoadingController} 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, TreeComponent} from '@circlon/angular-tree-component';
|
import {TREE_ACTIONS, TreeComponent} from '@circlon/angular-tree-component';
|
||||||
import { Observable } from 'rxjs';
|
import {BehaviorSubject, Observable} from 'rxjs';
|
||||||
import {OptionPickerComponent} from './components/option-picker/option-picker.component';
|
import {OptionPickerComponent} from './components/option-picker/option-picker.component';
|
||||||
import {OptionMenuComponent} from './components/option-menu/option-menu.component';
|
import {OptionMenuComponent} from './components/option-menu/option-menu.component';
|
||||||
import {SelectorComponent} from './components/sharing/selector/selector.component';
|
import {SelectorComponent} from './components/sharing/selector/selector.component';
|
||||||
|
import {SessionService} from './service/session.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@ -18,6 +19,7 @@ import {SelectorComponent} from './components/sharing/selector/selector.componen
|
|||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
@ViewChild('menuTree') menuTree: TreeComponent;
|
@ViewChild('menuTree') menuTree: TreeComponent;
|
||||||
|
public readonly ready$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||||
public addChildTarget: any = false;
|
public addChildTarget: any = false;
|
||||||
public deleteTarget: any = false;
|
public deleteTarget: any = false;
|
||||||
public menuTarget: any = false;
|
public menuTarget: any = false;
|
||||||
@ -59,8 +61,14 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
public get appName(): string {
|
||||||
|
return this.session.appName || 'Noded';
|
||||||
|
}
|
||||||
|
|
||||||
public darkMode = false;
|
public darkMode = false;
|
||||||
|
protected loader?: any;
|
||||||
|
|
||||||
|
protected initialized$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private platform: Platform,
|
private platform: Platform,
|
||||||
@ -71,16 +79,35 @@ export class AppComponent implements OnInit {
|
|||||||
protected alerts: AlertController,
|
protected alerts: AlertController,
|
||||||
protected popover: PopoverController,
|
protected popover: PopoverController,
|
||||||
protected modal: ModalController,
|
protected modal: ModalController,
|
||||||
|
protected session: SessionService,
|
||||||
|
protected loading: LoadingController,
|
||||||
) {
|
) {
|
||||||
this.initializeApp();
|
this.initializeApp();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
_doInit() {
|
||||||
this.reloadMenuItems().subscribe(() => {
|
this.reloadMenuItems().subscribe(() => {
|
||||||
|
this.ready$.next(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.loader.dismiss();
|
||||||
this.menuTree.treeModel.expandAll();
|
this.menuTree.treeModel.expandAll();
|
||||||
|
}, 10);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
if ( !this.initialized$.getValue() ) {
|
||||||
|
const sub = this.initialized$.subscribe((didInit) => {
|
||||||
|
if (didInit) {
|
||||||
|
this._doInit();
|
||||||
|
sub.unsubscribe();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._doInit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
showOptions($event) {
|
showOptions($event) {
|
||||||
this.popover.create({
|
this.popover.create({
|
||||||
event: $event,
|
event: $event,
|
||||||
@ -108,7 +135,6 @@ export class AppComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onNodeMenuClick($event) {
|
async onNodeMenuClick($event) {
|
||||||
console.log(this.menuTarget)
|
|
||||||
let canManage = this.menuTarget.data.level === 'manage';
|
let canManage = this.menuTarget.data.level === 'manage';
|
||||||
if ( !canManage ) {
|
if ( !canManage ) {
|
||||||
if ( !this.menuTarget.data.level ) {
|
if ( !this.menuTarget.data.level ) {
|
||||||
@ -270,11 +296,30 @@ export class AppComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeApp() {
|
async initializeApp() {
|
||||||
this.platform.ready().then(() => {
|
this.loader = await this.loading.create({
|
||||||
this.statusBar.styleDefault();
|
message: 'Starting up...',
|
||||||
this.splashScreen.hide();
|
cssClass: 'noded-loading-mask',
|
||||||
|
showBackdrop: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await this.loader.present();
|
||||||
|
|
||||||
|
await this.platform.ready();
|
||||||
|
const stat: any = await this.session.stat();
|
||||||
|
|
||||||
|
if ( !stat.authenticated_user ) {
|
||||||
|
window.location.href = `${stat.system_base}start`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.session.appName = stat.app_name;
|
||||||
|
this.session.systemBase = stat.system_base;
|
||||||
|
|
||||||
|
await this.session.initialize();
|
||||||
|
await this.statusBar.styleDefault();
|
||||||
|
await this.splashScreen.hide();
|
||||||
|
this.initialized$.next(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleDark() {
|
toggleDark() {
|
||||||
|
10
src/app/service/action.types.ts
Normal file
10
src/app/service/action.types.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface RedirectAction {
|
||||||
|
type: 'redirect';
|
||||||
|
args: {
|
||||||
|
destination: string
|
||||||
|
blank?: boolean
|
||||||
|
appUrl?: boolean
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Action = RedirectAction;
|
27
src/app/service/actions.service.ts
Normal file
27
src/app/service/actions.service.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import ApiResponse from '../structures/ApiResponse';
|
|||||||
})
|
})
|
||||||
export class ApiService {
|
export class ApiService {
|
||||||
protected baseEndpoint: string = environment.backendBase;
|
protected baseEndpoint: string = environment.backendBase;
|
||||||
|
protected statUrl: string = environment.statUrl;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected http: HttpClient,
|
protected http: HttpClient,
|
||||||
@ -23,6 +24,14 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public request(endpoint, params = {}, method: 'get'|'post' = 'get'): Observable<ApiResponse> {
|
public request(endpoint, params = {}, method: 'get'|'post' = 'get'): Observable<ApiResponse> {
|
||||||
|
return this._request(this._build_url(endpoint), params, method);
|
||||||
|
}
|
||||||
|
|
||||||
|
public stat(): Observable<ApiResponse> {
|
||||||
|
return this._request(this.statUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _request(endpoint, params = {}, method: 'get'|'post' = 'get'): Observable<ApiResponse> {
|
||||||
return new Observable<ApiResponse>(sub => {
|
return new Observable<ApiResponse>(sub => {
|
||||||
let data: any = {}
|
let data: any = {}
|
||||||
if ( method === 'get' ) {
|
if ( method === 'get' ) {
|
||||||
@ -31,7 +40,7 @@ export class ApiService {
|
|||||||
data = params;
|
data = params;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.http[method](this._build_url(endpoint), data).subscribe({
|
this.http[method](endpoint, data).subscribe({
|
||||||
next: (response: any) => {
|
next: (response: any) => {
|
||||||
sub.next(new ApiResponse(response));
|
sub.next(new ApiResponse(response));
|
||||||
},
|
},
|
||||||
|
48
src/app/service/session.service.ts
Normal file
48
src/app/service/session.service.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import {ApiService} from './api.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class SessionService {
|
||||||
|
public appName!: string;
|
||||||
|
public systemBase!: string;
|
||||||
|
protected data: any = {};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected readonly api: ApiService,
|
||||||
|
) { }
|
||||||
|
|
||||||
|
async stat() {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
this.api.stat().subscribe(response => {
|
||||||
|
res(response.data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
this.api.get('/session').subscribe(response => {
|
||||||
|
this.data = response.data;
|
||||||
|
res();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAppUrl(...parts: string[]): string {
|
||||||
|
parts = parts.map(x => {
|
||||||
|
if ( x.startsWith('/') ) {
|
||||||
|
x = x.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( x.endsWith('/') ) {
|
||||||
|
x = x.slice(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
|
||||||
|
return `${this.systemBase}${this.systemBase.endsWith('/') ? '' : '/'}${parts.join('/')}`;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
production: true,
|
production: true,
|
||||||
backendBase: '/api/v1',
|
backendBase: '/api/v1',
|
||||||
|
statUrl: '/stat',
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
production: false,
|
production: false,
|
||||||
backendBase: '/link_api/api/v1',
|
backendBase: '/link_api/api/v1',
|
||||||
|
statUrl: '/link_api/stat',
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -33,3 +33,15 @@ div.picker-wrapper {
|
|||||||
border: 2px solid lightgrey !important;
|
border: 2px solid lightgrey !important;
|
||||||
border-radius: 7px !important;
|
border-radius: 7px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.noded-loading-mask {
|
||||||
|
//--background: #222;
|
||||||
|
//--spinner-color: #fff;
|
||||||
|
--backdrop-opacity: 0.7;
|
||||||
|
|
||||||
|
ion-backdrop {
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
//color: #fff;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user