parent
0948ea139c
commit
75a50e83d5
File diff suppressed because it is too large
Load Diff
@ -1,4 +0,0 @@
|
||||
.inline-spinner {
|
||||
display: inline-flex !important;
|
||||
top: 0px !important;
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil, filter } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Actions } from '@ngrx/effects';
|
||||
|
||||
import * as CLActions from './store/cl.actions';
|
||||
import * as RTLActions from '../store/rtl.actions';
|
||||
import * as fromApp from '../store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-cl-root-app',
|
||||
templateUrl: './cl-root.component.html',
|
||||
styleUrls: ['./cl-root.component.scss']
|
||||
})
|
||||
export class ClRootComponent implements OnInit, OnDestroy {
|
||||
unsubs: Array<Subject<void>> = [new Subject(), new Subject()];
|
||||
|
||||
constructor(private store: Store<fromApp.AppState>, private actions$: Actions, private router: Router, private activatedRoute: ActivatedRoute) {}
|
||||
|
||||
ngOnInit() {
|
||||
console.warn('CL ROOT');
|
||||
// this.store.dispatch(new CLActions.FetchCLInfo());
|
||||
this.router.navigate(['./home'], {relativeTo: this.activatedRoute});
|
||||
// this.store.select('cl')
|
||||
// .pipe(takeUntil(this.unsubs[0]))
|
||||
// .subscribe(clStore => {
|
||||
// console.warn(clStore);
|
||||
// if (undefined !== clStore.information.identity_pubkey) {
|
||||
// this.initializeRemainingData();
|
||||
// }
|
||||
// });
|
||||
// this.actions$
|
||||
// .pipe(
|
||||
// takeUntil(this.unSubs[3]),
|
||||
// filter(action => action.type === RTLActions.INIT_APP_DATA || action.type === LNDActions.SET_INFO || action.type === CLActions.SET_CL_INFO)
|
||||
// ).subscribe((actionPayload: RTLActions.InitAppData | LNDActions.SetInfo | CLActions.SetCLInfo) => {
|
||||
// // if (actionPayload.type === RTLActions.INIT_APP_DATA) {
|
||||
// if(this.information.identity_pubkey) {
|
||||
// this.initializeRemainingData();
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
initializeRemainingData() {
|
||||
console.warn('SOMETHING IS WRONG HERE');
|
||||
// this.store.dispatch(new CLActions.FetchCLFees());
|
||||
|
||||
// this.store.dispatch(new CLActions.FetchPeers());
|
||||
// this.store.dispatch(new CLActions.FetchBalance('channels'));
|
||||
// this.store.dispatch(new CLActions.FetchFees());
|
||||
// this.store.dispatch(new CLActions.FetchNetwork());
|
||||
// this.store.dispatch(new CLActions.FetchChannels({routeParam: 'all'}));
|
||||
// this.store.dispatch(new CLActions.FetchChannels({routeParam: 'pending'}));
|
||||
// this.store.dispatch(new CLActions.FetchInvoices({num_max_invoices: 25, reversed: true}));
|
||||
// this.store.dispatch(new CLActions.FetchPayments());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsubs.forEach(unsub => {
|
||||
unsub.next();
|
||||
unsub.complete();
|
||||
});
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgxChartsModule } from '@swimlane/ngx-charts';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
|
||||
import { environment } from '../../environments/environment';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
import { clRouting } from './cl.routing';
|
||||
import { ClRootComponent } from './cl-root.component';
|
||||
import { HomeComponent } from './home/home.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
clRouting,
|
||||
NgxChartsModule,
|
||||
!environment.production ? StoreDevtoolsModule.instrument() : []
|
||||
],
|
||||
declarations: [
|
||||
ClRootComponent,
|
||||
HomeComponent
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [ClRootComponent]
|
||||
})
|
||||
export class ClModule {}
|
@ -1,19 +0,0 @@
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
|
||||
import { AuthGuard } from '../shared/services/auth.guard';
|
||||
import { NotFoundComponent } from '../shared/components/not-found/not-found.component';
|
||||
|
||||
import { ClRootComponent } from './cl-root.component';
|
||||
import { HomeComponent } from './home/home.component';
|
||||
|
||||
export const clRoutes: Routes = [
|
||||
{ path: '', component: ClRootComponent,
|
||||
children: [
|
||||
{ path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
|
||||
{ path: '**', component: NotFoundComponent }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export const clRouting: ModuleWithProviders = RouterModule.forChild(clRoutes);
|
@ -1,2 +0,0 @@
|
||||
<h4>CL Home</h4>
|
||||
<p>{{information | json}}</p>
|
@ -1,56 +0,0 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import { LoggerService } from '../../shared/services/logger.service';
|
||||
import { GetInfo } from '../../shared/models/clModels';
|
||||
|
||||
import * as fromApp from '../../store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['./home.component.scss']
|
||||
})
|
||||
export class HomeComponent implements OnInit, OnDestroy {
|
||||
public information: GetInfo = {};
|
||||
private unsubs: Array<Subject<void>> = [new Subject(), new Subject()];
|
||||
|
||||
constructor(private logger: LoggerService, private store: Store<fromApp.AppState>) {}
|
||||
|
||||
ngOnInit() {
|
||||
console.warn('CL HOME');
|
||||
this.store.select('cl')
|
||||
.pipe(takeUntil(this.unsubs[1]))
|
||||
.subscribe(clStore => {
|
||||
this.information = clStore.information;
|
||||
if (undefined !== this.information.identity_pubkey) {
|
||||
this.initializeRemainingData();
|
||||
}
|
||||
this.logger.info(clStore);
|
||||
});
|
||||
}
|
||||
|
||||
initializeRemainingData() {
|
||||
console.warn('SOMETHING IS WRONG HERE');
|
||||
// this.store.dispatch(new CLActions.FetchCLFees());
|
||||
|
||||
// this.store.dispatch(new CLActions.FetchPeers());
|
||||
// this.store.dispatch(new CLActions.FetchBalance('channels'));
|
||||
// this.store.dispatch(new CLActions.FetchFees());
|
||||
// this.store.dispatch(new CLActions.FetchNetwork());
|
||||
// this.store.dispatch(new CLActions.FetchChannels({routeParam: 'all'}));
|
||||
// this.store.dispatch(new CLActions.FetchChannels({routeParam: 'pending'}));
|
||||
// this.store.dispatch(new CLActions.FetchInvoices({num_max_invoices: 25, reversed: true}));
|
||||
// this.store.dispatch(new CLActions.FetchPayments());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsubs.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { GetInfo } from '../../shared/models/clModels';
|
||||
|
||||
export const RESET_CL_STORE = 'RESET_CL_STORE';
|
||||
export const FETCH_CL_INFO = 'FETCH_CL_INFO';
|
||||
export const SET_CL_INFO = 'SET_CL_INFO';
|
||||
export const FETCH_CL_FEES = 'FETCH_CL_FEES';
|
||||
export const SET_CL_FEES = 'SET_CL_FEES';
|
||||
|
||||
export class ResetCLStore implements Action {
|
||||
readonly type = RESET_CL_STORE;
|
||||
}
|
||||
|
||||
export class FetchCLInfo implements Action {
|
||||
readonly type = FETCH_CL_INFO;
|
||||
}
|
||||
|
||||
export class SetCLInfo implements Action {
|
||||
readonly type = SET_CL_INFO;
|
||||
constructor(public payload: GetInfo) {}
|
||||
}
|
||||
|
||||
export class FetchCLFees implements Action {
|
||||
readonly type = FETCH_CL_FEES;
|
||||
}
|
||||
|
||||
export class SetCLFees implements Action {
|
||||
readonly type = SET_CL_FEES;
|
||||
constructor(public payload: {}) {}
|
||||
}
|
||||
|
||||
export type CLActions =
|
||||
ResetCLStore | FetchCLInfo | SetCLInfo | FetchCLFees | SetCLFees;
|
@ -1,102 +0,0 @@
|
||||
import { Injectable, OnDestroy } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import { of, Subject } from 'rxjs';
|
||||
import { map, mergeMap, catchError, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
import { MatDialog } from '@angular/material';
|
||||
|
||||
import { environment } from '../../../environments/environment';
|
||||
import { LoggerService } from '../../shared/services/logger.service';
|
||||
import { GetInfo } from '../../shared/models/clModels';
|
||||
|
||||
import * as RTLActions from '../../store/rtl.actions';
|
||||
import * as CLActions from './cl.actions';
|
||||
import * as fromApp from '../../store/rtl.reducers';
|
||||
|
||||
@Injectable()
|
||||
export class CLEffects implements OnDestroy {
|
||||
dialogRef: any;
|
||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
|
||||
|
||||
constructor(
|
||||
private actions$: Actions,
|
||||
private httpClient: HttpClient,
|
||||
private store: Store<fromApp.AppState>,
|
||||
private logger: LoggerService,
|
||||
public dialog: MatDialog,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute) { }
|
||||
|
||||
@Effect()
|
||||
infoFetch = this.actions$.pipe(
|
||||
ofType(CLActions.FETCH_CL_INFO),
|
||||
withLatestFrom(this.store.select('rtlRoot')),
|
||||
mergeMap(([action, store]: [CLActions.FetchCLInfo, fromApp.RootState]) => {
|
||||
this.store.dispatch(new RTLActions.ClearEffectError('FetchInfo'));
|
||||
return this.httpClient.get<GetInfo>(environment.GETINFO_API)
|
||||
.pipe(
|
||||
map((info) => {
|
||||
this.logger.info(info);
|
||||
if (undefined === info.identity_pubkey) {
|
||||
sessionStorage.removeItem('clUnlocked');
|
||||
return {
|
||||
type: CLActions.SET_CL_INFO,
|
||||
payload: {}
|
||||
};
|
||||
} else {
|
||||
sessionStorage.setItem('clUnlocked', 'true');
|
||||
return {
|
||||
type: CLActions.SET_CL_INFO,
|
||||
payload: (undefined !== info) ? info : {}
|
||||
};
|
||||
}
|
||||
}),
|
||||
catchError((err) => {
|
||||
this.logger.error(err);
|
||||
this.store.dispatch(new RTLActions.EffectError({ action: 'FetchInfo', code: err.status, message: err.error.error }));
|
||||
if (+store.appConfig.sso.rtlSSO) {
|
||||
this.router.navigate(['../ssoerror'], {relativeTo: this.activatedRoute});
|
||||
} else {
|
||||
if (err.status === 401) {
|
||||
this.logger.info('Redirecting to Signin');
|
||||
this.router.navigate([store.appConfig.sso.logoutRedirectLink], {relativeTo: this.activatedRoute});
|
||||
return of();
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
));
|
||||
|
||||
@Effect()
|
||||
fetchFees = this.actions$.pipe(
|
||||
ofType(CLActions.FETCH_CL_FEES),
|
||||
mergeMap((action: CLActions.FetchCLFees) => {
|
||||
this.store.dispatch(new RTLActions.ClearEffectError('FetchCLFees'));
|
||||
return this.httpClient.get(environment.FEES_API);
|
||||
}),
|
||||
map((fees) => {
|
||||
this.logger.info(fees);
|
||||
return {
|
||||
type: CLActions.SET_CL_FEES,
|
||||
payload: (undefined !== fees) ? fees : {}
|
||||
};
|
||||
}),
|
||||
catchError((err: any) => {
|
||||
this.logger.error(err);
|
||||
this.store.dispatch(new RTLActions.EffectError({ action: 'FetchCLFees', code: err.status, message: err.error.error }));
|
||||
return of();
|
||||
}
|
||||
));
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unSubs.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
import * as CLActions from './cl.actions';
|
||||
import { GetInfo, GetInfoChain } from '../../shared/models/clModels';
|
||||
|
||||
export interface CLState {
|
||||
information: GetInfo;
|
||||
fees: {};
|
||||
}
|
||||
|
||||
export const CLInitialState: CLState = {
|
||||
information: {},
|
||||
fees: {}
|
||||
};
|
||||
|
||||
export function CLReducer(state = CLInitialState, action: CLActions.CLActions) {
|
||||
switch (action.type) {
|
||||
case CLActions.RESET_CL_STORE:
|
||||
return {
|
||||
...CLInitialState
|
||||
};
|
||||
case CLActions.SET_CL_INFO:
|
||||
if (undefined !== action.payload.chains) {
|
||||
if (typeof action.payload.chains[0] === 'string') {
|
||||
action.payload.smaller_currency_unit = (action.payload.chains[0].toString().toLowerCase().indexOf('bitcoin') < 0) ? 'Litoshis' : 'Sats';
|
||||
action.payload.currency_unit = (action.payload.chains[0].toString().toLowerCase().indexOf('bitcoin') < 0) ? 'LTC' : 'BTC';
|
||||
} else if (typeof action.payload.chains[0] === 'object' && action.payload.chains[0].hasOwnProperty('chain')) {
|
||||
const getInfoChain = <GetInfoChain>action.payload.chains[0];
|
||||
action.payload.smaller_currency_unit = (getInfoChain.chain.toLowerCase().indexOf('bitcoin') < 0) ? 'Litoshis' : 'Sats';
|
||||
action.payload.currency_unit = (getInfoChain.chain.toLowerCase().indexOf('bitcoin') < 0) ? 'LTC' : 'BTC';
|
||||
}
|
||||
action.payload.version = (undefined === action.payload.version) ? '' : action.payload.version.split(' ')[0];
|
||||
} else {
|
||||
action.payload.smaller_currency_unit = 'Sats';
|
||||
action.payload.currency_unit = 'BTC';
|
||||
action.payload.version = (undefined === action.payload.version) ? '' : action.payload.version.split(' ')[0];
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
information: action.payload
|
||||
};
|
||||
case CLActions.SET_CL_FEES:
|
||||
return {
|
||||
...state,
|
||||
fees: action.payload
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-cl-root',
|
||||
templateUrl: './cl-root.component.html',
|
||||
styleUrls: ['./cl-root.component.scss']
|
||||
})
|
||||
export class CLRootComponent implements OnInit {
|
||||
|
||||
constructor(private router: Router, private activatedRoute: ActivatedRoute) {}
|
||||
|
||||
ngOnInit() {
|
||||
console.warn('CL ROOT');
|
||||
this.router.navigate(['./home'], {relativeTo: this.activatedRoute});
|
||||
}
|
||||
|
||||
// @ViewChild('sideNavigation', { static: false }) sideNavigation: any;
|
||||
// @ViewChild('settingSidenav', { static: true }) settingSidenav: any;
|
||||
// public selNode: Node;
|
||||
// public settings: Settings;
|
||||
// public information: GetInfo = {};
|
||||
// public flgLoading: Array<Boolean | 'error'> = [true]; // 0: Info
|
||||
// public flgCopied = false;
|
||||
// public appConfig: RTLConfiguration;
|
||||
// public accessKey = '';
|
||||
// public smallScreen = false;
|
||||
// unsubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
|
||||
|
||||
// constructor(private logger: LoggerService, private store: Store<fromRTLReducer.State>, private actions$: Actions,
|
||||
// private userIdle: UserIdleService, private router: Router) {}
|
||||
|
||||
// ngOnInit() {
|
||||
// this.store.dispatch(new RTLActions.FetchRTLConfig());
|
||||
// this.accessKey = this.readAccessKey();
|
||||
// this.store.select('rtlRoot')
|
||||
// .pipe(takeUntil(this.unsubs[0]))
|
||||
// .subscribe(rtlStore => {
|
||||
// this.selNode = rtlStore.selNode;
|
||||
// this.settings = this.selNode.settings;
|
||||
// this.appConfig = rtlStore.appConfig;
|
||||
// this.information = rtlStore.information;
|
||||
// this.flgLoading[0] = (undefined !== this.information.identity_pubkey) ? false : true;
|
||||
// if (window.innerWidth <= 768) {
|
||||
// this.settings.menu = 'Vertical';
|
||||
// this.settings.flgSidenavOpened = false;
|
||||
// this.settings.flgSidenavPinned = false;
|
||||
// }
|
||||
// if (window.innerWidth <= 414) {
|
||||
// this.smallScreen = true;
|
||||
// }
|
||||
// this.logger.info(this.settings);
|
||||
// if (!sessionStorage.getItem('token')) {
|
||||
// this.flgLoading[0] = false;
|
||||
// }
|
||||
// });
|
||||
// if (sessionStorage.getItem('token')) {
|
||||
// this.store.dispatch(new RTLActions.FetchInfo());
|
||||
// }
|
||||
// this.actions$
|
||||
// .pipe(
|
||||
// takeUntil(this.unsubs[1]),
|
||||
// filter((action) => action.type === RTLActions.INIT_APP_DATA || action.type === RTLActions.SET_RTL_CONFIG)
|
||||
// ).subscribe((actionPayload: (RTLActions.InitAppData | RTLActions.SetRTLConfig)) => {
|
||||
// if (actionPayload.type === RTLActions.SET_RTL_CONFIG) {
|
||||
// if (!sessionStorage.getItem('token')) {
|
||||
// if (+actionPayload.payload.sso.rtlSSO) {
|
||||
// this.store.dispatch(new RTLActions.Signin(sha256(this.accessKey)));
|
||||
// } else {
|
||||
// this.router.navigate([this.appConfig.sso.logoutRedirectLink]);
|
||||
// }
|
||||
// }
|
||||
// if (
|
||||
// this.settings.menu === 'Horizontal' ||
|
||||
// this.settings.menuType === 'Compact' ||
|
||||
// this.settings.menuType === 'Mini') {
|
||||
// this.settingSidenav.toggle(); // To dynamically update the width to 100% after side nav is closed
|
||||
// setTimeout(() => { this.settingSidenav.toggle(); }, 100);
|
||||
// }
|
||||
// } else if (actionPayload.type === RTLActions.INIT_APP_DATA) {
|
||||
// this.store.dispatch(new RTLActions.FetchInfo());
|
||||
// }
|
||||
// });
|
||||
// this.actions$
|
||||
// .pipe(
|
||||
// takeUntil(this.unsubs[1]),
|
||||
// filter((action) => action.type === RTLActions.SET_INFO)
|
||||
// ).subscribe((infoData: RTLActions.SetInfo) => {
|
||||
// if (undefined !== infoData.payload.identity_pubkey) {
|
||||
// this.initializeRemainingData();
|
||||
// }
|
||||
// });
|
||||
// this.userIdle.startWatching();
|
||||
// this.userIdle.onTimerStart().subscribe(count => {});
|
||||
// this.userIdle.onTimeout().subscribe(() => {
|
||||
// if (sessionStorage.getItem('token')) {
|
||||
// this.logger.warn('Time limit exceeded for session inactivity! Logging out!');
|
||||
// this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
|
||||
// type: 'WARN',
|
||||
// titleMessage: 'Time limit exceeded for session inactivity! Logging out!'
|
||||
// }}));
|
||||
// this.store.dispatch(new RTLActions.Signout());
|
||||
// this.userIdle.resetTimer();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// private readAccessKey() {
|
||||
// const url = window.location.href;
|
||||
// return url.substring(url.lastIndexOf('access-key=') + 11).trim();
|
||||
// }
|
||||
|
||||
// initializeRemainingData() {
|
||||
// this.store.dispatch(new RTLActions.FetchPeers());
|
||||
// this.store.dispatch(new RTLActions.FetchBalance('channels'));
|
||||
// this.store.dispatch(new RTLActions.FetchFees());
|
||||
// this.store.dispatch(new RTLActions.FetchNetwork());
|
||||
// this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'all'}));
|
||||
// this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'pending'}));
|
||||
// this.store.dispatch(new RTLActions.FetchInvoices({num_max_invoices: 25, reversed: true}));
|
||||
// this.store.dispatch(new RTLActions.FetchPayments());
|
||||
// }
|
||||
|
||||
// ngAfterViewInit() {
|
||||
// if (!this.settings.flgSidenavPinned) {
|
||||
// this.sideNavigation.close();
|
||||
// this.settingSidenav.toggle();
|
||||
// }
|
||||
// if (window.innerWidth <= 768) {
|
||||
// this.sideNavigation.close();
|
||||
// this.settingSidenav.toggle();
|
||||
// }
|
||||
// }
|
||||
|
||||
// @HostListener('window:resize')
|
||||
// public onWindowResize(): void {
|
||||
// if (window.innerWidth <= 768) {
|
||||
// this.settings.menu = 'Vertical';
|
||||
// this.settings.flgSidenavOpened = false;
|
||||
// this.settings.flgSidenavPinned = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// sideNavToggle() {
|
||||
// this.sideNavigation.toggle();
|
||||
// }
|
||||
|
||||
// onNavigationClicked(event: any) {
|
||||
// if (window.innerWidth <= 414) {
|
||||
// this.sideNavigation.close();
|
||||
// }
|
||||
// }
|
||||
|
||||
// copiedText(payload) {
|
||||
// this.flgCopied = true;
|
||||
// setTimeout(() => {this.flgCopied = false; }, 5000);
|
||||
// this.logger.info('Copied Text: ' + payload);
|
||||
// }
|
||||
|
||||
// ngOnDestroy() {
|
||||
// this.unsubs.forEach(unsub => {
|
||||
// unsub.next();
|
||||
// unsub.complete();
|
||||
// });
|
||||
// }
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { CLRouting } from './cl.routing';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
import { CLRootComponent } from './cl-root.component';
|
||||
import { CLHomeComponent } from './home/home.component';
|
||||
|
||||
import { CommonService } from '../shared/services/common.service';
|
||||
import { LoggerService, ConsoleLoggerService } from '../shared/services/logger.service';
|
||||
import { CLUnlockedGuard } from '../shared/services/auth.guard';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
CLRouting
|
||||
],
|
||||
declarations: [
|
||||
CLRootComponent,
|
||||
CLHomeComponent
|
||||
],
|
||||
providers: [
|
||||
{ provide: LoggerService, useClass: ConsoleLoggerService },
|
||||
CLUnlockedGuard,
|
||||
CommonService
|
||||
],
|
||||
bootstrap: [CLRootComponent]
|
||||
})
|
||||
export class CLModule {}
|
@ -0,0 +1,18 @@
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { ModuleWithProviders } from '@angular/core';
|
||||
|
||||
import { CLRootComponent } from './cl-root.component';
|
||||
import { CLHomeComponent } from './home/home.component';
|
||||
|
||||
import { CLUnlockedGuard } from '../shared/services/auth.guard';
|
||||
import { NotFoundComponent } from '../shared/components/not-found/not-found.component';
|
||||
|
||||
export const ClRoutes: Routes = [
|
||||
{ path: '', component: CLRootComponent,
|
||||
children: [
|
||||
{ path: 'home', component: CLHomeComponent, canActivate: [CLUnlockedGuard] },
|
||||
{ path: '**', component: NotFoundComponent }
|
||||
]}
|
||||
];
|
||||
|
||||
export const CLRouting: ModuleWithProviders = RouterModule.forChild(ClRoutes);
|
@ -0,0 +1,237 @@
|
||||
<div fxLayout="column" fxLayout.gt-sm="row wrap">
|
||||
<div fxFlex="25" class="padding-gap">
|
||||
<mat-card [ngClass]="{'custom-card error-border': flgLoading[2]==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center end">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Wallet Balance</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content fxLayout="column" fxLayoutAlign="center center">
|
||||
<mat-card-content class="mt-1">
|
||||
<mat-icon class="icon-large">account_balance_wallet</mat-icon>
|
||||
</mat-card-content>
|
||||
<span *ngIf="information?.currency_unit; else withoutData">
|
||||
<h3 *ngIf="selNode?.settings?.satsToBTC; else smallerUnit1">{{BTCtotalBalance | number}} {{information?.currency_unit}}</h3>
|
||||
<ng-template #smallerUnit1><h3>{{totalBalance | number}} {{information?.smaller_currency_unit}}</h3></ng-template>
|
||||
</span>
|
||||
</mat-card-content>
|
||||
<mat-progress-bar class="mt-minus-5" *ngIf="flgLoading[2]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div fxFlex="25" class="padding-gap">
|
||||
<mat-card [ngClass]="{'custom-card error-border': flgLoading[0]==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Peers</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content fxLayout="column" fxLayoutAlign="center center">
|
||||
<mat-card-content class="mt-1">
|
||||
<mat-icon class="icon-large">group</mat-icon>
|
||||
</mat-card-content>
|
||||
<h3 *ngIf="information.num_peers; else zeroPeers">{{totalPeers | number}}</h3>
|
||||
<ng-template #zeroPeers>
|
||||
<h3>0</h3>
|
||||
</ng-template>
|
||||
</mat-card-content>
|
||||
<mat-progress-bar class="mt-minus-5" *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div fxFlex="25" class="padding-gap">
|
||||
<mat-card [ngClass]="{'custom-card error-border': flgLoading[3]==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Channel Balance</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content fxLayout="column" fxLayoutAlign="center center">
|
||||
<mat-card-content class="mt-1">
|
||||
<mat-icon class="icon-large">linear_scale</mat-icon>
|
||||
</mat-card-content>
|
||||
<span *ngIf="information?.currency_unit; else withoutData">
|
||||
<h3 *ngIf="selNode?.settings?.satsToBTC; else smallerUnit2">{{BTCchannelBalance | number}} {{information?.currency_unit}}</h3>
|
||||
<ng-template #smallerUnit2><h3>{{channelBalance | number}} {{information?.smaller_currency_unit}}</h3></ng-template>
|
||||
</span>
|
||||
</mat-card-content>
|
||||
<mat-progress-bar class="mt-minus-5" *ngIf="flgLoading[3]===true || flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div fxFlex="25" class="padding-gap">
|
||||
<mat-card [ngClass]="{'custom-card error-border': flgLoading[0]==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Chain Sync Status</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content fxLayout="column" fxLayoutAlign="center center">
|
||||
<mat-card-content class="mt-1">
|
||||
<mat-icon class="icon-large">sync</mat-icon>
|
||||
</mat-card-content>
|
||||
<mat-icon *ngIf="information?.synced_to_chain; else notSynced" class="size-30 green sync-to-chain">check_circle</mat-icon>
|
||||
<ng-template #notSynced>
|
||||
<mat-icon class="size-30 red">cancel</mat-icon>
|
||||
</ng-template>
|
||||
</mat-card-content>
|
||||
<mat-progress-bar class="mt-minus-5" *ngIf="flgLoading[0]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<div fxLayout="column" fxLayout.gt-sm="row wrap">
|
||||
<div fxFlex="25" class="padding-gap">
|
||||
<div fxLayout="column">
|
||||
<mat-card fxFlex="100" [ngClass]="{'custom-card error-border': flgLoading[1]==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Fee Report</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div fxLayout="column" class="pl-4">
|
||||
<mat-list fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Daily ({{information?.smaller_currency_unit}})</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start">{{fees?.day_fee_sum}}</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Weekly ({{information?.smaller_currency_unit}})</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start">{{fees?.week_fee_sum}}</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Monthly ({{information?.smaller_currency_unit}})</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start">{{fees?.month_fee_sum}}</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="flgLoading[1]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<mat-card fxFlex="100" [ngClass]="{'mt-2 custom-card error-border': flgLoading[5]==='error','mt-2 custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Channel Status</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div fxLayout="column" class="pl-4">
|
||||
<mat-list fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Active</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start"><p class="mat-button-text pt-2">{{activeChannels}}</p></mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Inactive</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start"><p class="mat-button-text pt-2">{{inactiveChannels}}</p></mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxFlex="100" fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Pending</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start"><p class="mat-button-text pt-2">{{pendingChannels}}</p></mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="flgLoading[6]===true" mode="indeterminate" class="mt-minus-5"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<div fxFlex="40" class="padding-gap">
|
||||
<mat-card [ngClass]="{'custom-card error-border': flgLoading[5]==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Local-Remote Channel Capacity</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div fxLayout="row" class="card-chnl-balances">
|
||||
<div fxFlex="100" fxLayoutAlign="center center" *ngIf="flgTotalCalculated">
|
||||
<ngx-charts-bar-vertical
|
||||
[view]="view"
|
||||
[scheme]="colorScheme"
|
||||
[results]="totalBalances"
|
||||
[yAxisLabel]="yAxisLabel"
|
||||
[yScaleMax]="maxBalanceValue"
|
||||
xAxis="false"
|
||||
yAxis="true"
|
||||
showYAxis="true"
|
||||
showDataLabel="true"
|
||||
tooltipDisabled="true">
|
||||
</ngx-charts-bar-vertical>
|
||||
</div>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="flgLoading[5]===true" mode="indeterminate" class="mt-minus-5"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div fxFlex="35" class="padding-gap">
|
||||
<mat-card [ngClass]="{'custom-card error-border': flgLoading[5]==='error','custom-card': true}">
|
||||
<mat-card-header class="bg-primary" fxLayoutAlign="center center">
|
||||
<mat-card-title class="m-0 pt-2">
|
||||
<h5>Network Information</h5>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div fxLayout="column" class="pl-4 network-info-list">
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start" *ngIf="selNode?.settings?.satsToBTC; else smallerUnit6">Network Capacity ({{information?.currency_unit}})</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start" *ngIf="selNode?.settings?.satsToBTC; else smallerData6">{{networkInfo?.btc_total_network_capacity | number}}</mat-list-item>
|
||||
<ng-template #smallerUnit6><mat-list-item fxFlex="65" fxLayoutAlign="start start">Network Capacity ({{information?.smaller_currency_unit}})</mat-list-item></ng-template>
|
||||
<ng-template #smallerData6><mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.total_network_capacity | number}}</mat-list-item></ng-template>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Number of Nodes</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.num_nodes | number}}</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Number of Channels</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.num_channels | number}}</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Max Out Degree</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.max_out_degree | number}}</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start">Avg Out Degree</mat-list-item>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.avg_out_degree | number:'1.0-2'}}</mat-list-item>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start" *ngIf="selNode?.settings?.satsToBTC; else smallerUnit7">Max Channel Size ({{information?.currency_unit}})</mat-list-item>
|
||||
<ng-template #smallerUnit7><mat-list-item fxFlex="65" fxLayoutAlign="start start">Max Channel Size ({{information?.smaller_currency_unit}})</mat-list-item></ng-template>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start" *ngIf="selNode?.settings?.satsToBTC; else smallerData7">{{networkInfo?.btc_max_channel_size | number}}</mat-list-item>
|
||||
<ng-template #smallerData7><mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.max_channel_size | number}}</mat-list-item></ng-template>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start" *ngIf="selNode?.settings?.satsToBTC; else smallerUnit8">Avg Channel Size ({{information?.currency_unit}})</mat-list-item>
|
||||
<ng-template #smallerUnit8><mat-list-item fxFlex="65" fxLayoutAlign="start start">Avg Channel Size ({{information?.smaller_currency_unit}})</mat-list-item></ng-template>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start" *ngIf="selNode?.settings?.satsToBTC; else smallerData8">{{networkInfo?.btc_avg_channel_size | number}}</mat-list-item>
|
||||
<ng-template #smallerData8><mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.avg_channel_size | number:'1.0-2'}}</mat-list-item></ng-template>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
<mat-list fxLayoutAlign="start start">
|
||||
<mat-list-item fxFlex="65" fxLayoutAlign="start start" *ngIf="selNode?.settings?.satsToBTC; else smallerUnit9">Min Channel Size ({{information?.currency_unit}})</mat-list-item>
|
||||
<ng-template #smallerUnit9><mat-list-item fxFlex="65" fxLayoutAlign="start start">Min Channel Size ({{information?.smaller_currency_unit}})</mat-list-item></ng-template>
|
||||
<mat-list-item fxFlex="25" fxLayoutAlign="end start" *ngIf="selNode?.settings?.satsToBTC; else smallerData9">{{networkInfo?.btc_min_channel_size | number}}</mat-list-item>
|
||||
<ng-template #smallerData9><mat-list-item fxFlex="25" fxLayoutAlign="end start">{{networkInfo?.min_channel_size | number}}</mat-list-item></ng-template>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-list>
|
||||
</div>
|
||||
<mat-progress-bar *ngIf="flgLoading[4]===true" mode="indeterminate"></mat-progress-bar>
|
||||
<mat-divider></mat-divider>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #withoutData><h3>Sats</h3></ng-template>
|
@ -0,0 +1,12 @@
|
||||
.network-info-list .mat-list-item {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
.mat-column-bytes_sent, .mat-column-bytes_recv, .mat-column-sat_sent, .mat-column-sat_recv, .mat-column-inbound, .mat-column-ping_time {
|
||||
flex: 0 0 8%;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.card-chnl-balances {
|
||||
min-height: 354px;
|
||||
}
|
@ -0,0 +1,148 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import { LoggerService } from '../../shared/services/logger.service';
|
||||
import { GetInfo, NetworkInfo, Fees, Peer } from '../../shared/models/lndModels';
|
||||
import { Node } from '../../shared/models/RTLconfig';
|
||||
|
||||
import * as fromRTLReducer from '../../shared/store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-cl-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['./home.component.scss']
|
||||
})
|
||||
export class CLHomeComponent implements OnInit, OnDestroy {
|
||||
public selNode: Node;
|
||||
public fees: Fees;
|
||||
public information: GetInfo = {};
|
||||
public remainder = 0;
|
||||
public totalPeers = -1;
|
||||
public totalBalance = '';
|
||||
public channelBalance = '';
|
||||
public BTCtotalBalance = '';
|
||||
public BTCchannelBalance = '';
|
||||
public networkInfo: NetworkInfo = {};
|
||||
public flgLoading: Array<Boolean | 'error'> = [true, true, true, true, true, true, true, true]; // 0: Info, 1: Fee, 2: Wallet, 3: Channel, 4: Network
|
||||
private unsub: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
|
||||
public channels: any;
|
||||
public position = 'below';
|
||||
public activeChannels = 0;
|
||||
public inactiveChannels = 0;
|
||||
public pendingChannels = 0;
|
||||
public peers: Peer[] = [];
|
||||
barPadding = 0;
|
||||
maxBalanceValue = 0;
|
||||
totalBalances = [...[{'name': 'Local Balance', 'value': 0}, {'name': 'Remote Balance', 'value': 0}]];
|
||||
flgTotalCalculated = false;
|
||||
view = [];
|
||||
yAxisLabel = 'Balance';
|
||||
colorScheme = {domain: ['#FFFFFF']};
|
||||
|
||||
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.State>) {
|
||||
switch (true) {
|
||||
case (window.innerWidth <= 730):
|
||||
this.view = [250, 352];
|
||||
break;
|
||||
case (window.innerWidth > 415 && window.innerWidth <= 730):
|
||||
this.view = [280, 352];
|
||||
break;
|
||||
case (window.innerWidth > 730 && window.innerWidth <= 1024):
|
||||
this.view = [300, 352];
|
||||
break;
|
||||
case (window.innerWidth > 1024 && window.innerWidth <= 1280):
|
||||
this.view = [350, 352];
|
||||
break;
|
||||
default:
|
||||
this.view = [300, 352];
|
||||
break;
|
||||
}
|
||||
Object.assign(this, this.totalBalances);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.flgTotalCalculated = false;
|
||||
this.store.select('rtlRoot')
|
||||
.pipe(takeUntil(this.unsub[0]))
|
||||
.subscribe((rtlStore: fromRTLReducer.State) => {
|
||||
rtlStore.effectErrors.forEach(effectsErr => {
|
||||
if (effectsErr.action === 'FetchInfo') {
|
||||
this.flgLoading[0] = 'error';
|
||||
}
|
||||
if (effectsErr.action === 'FetchFees') {
|
||||
this.flgLoading[1] = 'error';
|
||||
}
|
||||
if (effectsErr.action === 'FetchBalance/blockchain') {
|
||||
this.flgLoading[2] = 'error';
|
||||
}
|
||||
if (effectsErr.action === 'FetchBalance/channels') {
|
||||
this.flgLoading[3] = 'error';
|
||||
}
|
||||
if (effectsErr.action === 'FetchNetwork') {
|
||||
this.flgLoading[4] = 'error';
|
||||
}
|
||||
if (effectsErr.action === 'FetchChannels/all') {
|
||||
this.flgLoading[5] = 'error';
|
||||
this.flgLoading[6] = 'error';
|
||||
}
|
||||
});
|
||||
this.selNode = rtlStore.selNode;
|
||||
this.information = rtlStore.information;
|
||||
if (this.flgLoading[0] !== 'error') {
|
||||
this.flgLoading[0] = (undefined !== this.information.identity_pubkey) ? false : true;
|
||||
}
|
||||
|
||||
this.fees = rtlStore.fees;
|
||||
if (this.flgLoading[1] !== 'error') {
|
||||
this.flgLoading[1] = (undefined !== this.fees.day_fee_sum) ? false : true;
|
||||
}
|
||||
|
||||
this.totalBalance = rtlStore.blockchainBalance.total_balance;
|
||||
this.BTCtotalBalance = rtlStore.blockchainBalance.btc_total_balance;
|
||||
if (this.flgLoading[2] !== 'error') {
|
||||
this.flgLoading[2] = ('' !== this.totalBalance) ? false : true;
|
||||
}
|
||||
|
||||
this.channelBalance = rtlStore.channelBalance.balance;
|
||||
this.BTCchannelBalance = rtlStore.channelBalance.btc_balance;
|
||||
if (this.flgLoading[3] !== 'error') {
|
||||
this.flgLoading[3] = ('' !== this.channelBalance) ? false : true;
|
||||
}
|
||||
|
||||
this.networkInfo = rtlStore.networkInfo;
|
||||
if (this.flgLoading[4] !== 'error') {
|
||||
this.flgLoading[4] = (undefined !== this.networkInfo.num_nodes) ? false : true;
|
||||
}
|
||||
|
||||
this.totalBalances = [...[{'name': 'Local Balance', 'value': +rtlStore.totalLocalBalance}, {'name': 'Remote Balance', 'value': +rtlStore.totalRemoteBalance}]];
|
||||
this.maxBalanceValue = (rtlStore.totalLocalBalance > rtlStore.totalRemoteBalance) ? rtlStore.totalLocalBalance : rtlStore.totalRemoteBalance;
|
||||
if (rtlStore.totalLocalBalance >= 0 && rtlStore.totalRemoteBalance >= 0) {
|
||||
this.flgTotalCalculated = true;
|
||||
if (this.flgLoading[5] !== 'error') {
|
||||
this.flgLoading[5] = false;
|
||||
}
|
||||
}
|
||||
|
||||
this.activeChannels = rtlStore.numberOfActiveChannels;
|
||||
this.inactiveChannels = rtlStore.numberOfInactiveChannels;
|
||||
this.pendingChannels = (undefined !== rtlStore.pendingChannels.pending_open_channels) ? rtlStore.pendingChannels.pending_open_channels.length : 0;
|
||||
if (rtlStore.totalLocalBalance >= 0 && rtlStore.totalRemoteBalance >= 0 && this.flgLoading[6] !== 'error') {
|
||||
this.flgLoading[6] = false;
|
||||
}
|
||||
|
||||
this.totalPeers = (rtlStore.peers !== null) ? rtlStore.peers.length : 0;
|
||||
|
||||
this.logger.info(rtlStore);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsub.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
.inline-spinner {
|
||||
display: inline-flex !important;
|
||||
top: 0px !important;
|
||||
}
|
@ -1,71 +1,166 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil, filter } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Actions } from '@ngrx/effects';
|
||||
|
||||
import * as LNDActions from './store/lnd.actions';
|
||||
import * as fromApp from '../store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-lnd-root-app',
|
||||
selector: 'rtl-lnd-root',
|
||||
templateUrl: './lnd-root.component.html',
|
||||
styleUrls: ['./lnd-root.component.scss']
|
||||
})
|
||||
export class LndRootComponent implements OnInit, OnDestroy {
|
||||
unsubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
|
||||
|
||||
constructor(private store: Store<fromApp.AppState>, private router: Router, private activatedRoute: ActivatedRoute, private actions$: Actions) {}
|
||||
export class LNDRootComponent implements OnInit {
|
||||
|
||||
constructor(private router: Router, private activatedRoute: ActivatedRoute) {}
|
||||
|
||||
ngOnInit() {
|
||||
console.warn('LND ROOT');
|
||||
// this.store.dispatch(new LNDActions.FetchInfo());
|
||||
console.warn('LND ROOT')
|
||||
this.router.navigate(['./home'], {relativeTo: this.activatedRoute});
|
||||
this.store.select('lnd')
|
||||
.pipe(takeUntil(this.unsubs[0]))
|
||||
.subscribe(lndStore => {
|
||||
console.warn(lndStore);
|
||||
if (undefined !== lndStore.information.identity_pubkey) {
|
||||
this.initializeRemainingData();
|
||||
}
|
||||
});
|
||||
this.actions$.pipe(takeUntil(this.unsubs[2]), filter((action) => action.type === LNDActions.SET_INFO))
|
||||
.subscribe((infoData: LNDActions.SetInfo) => {
|
||||
console.warn(infoData);
|
||||
if (undefined !== infoData.payload.identity_pubkey) {
|
||||
this.initializeRemainingData();
|
||||
}
|
||||
});
|
||||
// this.actions$
|
||||
// .pipe(
|
||||
// takeUntil(this.unSubs[3]),
|
||||
// filter(action => action.type === RTLActions.INIT_APP_DATA || action.type === LNDActions.SET_INFO || action.type === CLActions.SET_CL_INFO)
|
||||
// ).subscribe((actionPayload: RTLActions.InitAppData | LNDActions.SetInfo | CLActions.SetCLInfo) => {
|
||||
// // if (actionPayload.type === RTLActions.INIT_APP_DATA) {
|
||||
// if(this.information.identity_pubkey) {
|
||||
// this.initializeRemainingData();
|
||||
// }
|
||||
// });
|
||||
|
||||
}
|
||||
|
||||
initializeRemainingData() {
|
||||
console.warn('SOMETHING IS WRONG HERE');
|
||||
// this.store.dispatch(new LNDActions.FetchPeers());
|
||||
// this.store.dispatch(new LNDActions.FetchBalance('channels'));
|
||||
// this.store.dispatch(new LNDActions.FetchFees());
|
||||
// this.store.dispatch(new LNDActions.FetchNetwork());
|
||||
// this.store.dispatch(new LNDActions.FetchChannels({routeParam: 'all'}));
|
||||
// this.store.dispatch(new LNDActions.FetchChannels({routeParam: 'pending'}));
|
||||
// this.store.dispatch(new LNDActions.FetchInvoices({num_max_invoices: 25, reversed: true}));
|
||||
// this.store.dispatch(new LNDActions.FetchPayments());
|
||||
}
|
||||
// @ViewChild('sideNavigation', { static: false }) sideNavigation: any;
|
||||
// @ViewChild('settingSidenav', { static: true }) settingSidenav: any;
|
||||
// public selNode: Node;
|
||||
// public settings: Settings;
|
||||
// public information: GetInfo = {};
|
||||
// public flgLoading: Array<Boolean | 'error'> = [true]; // 0: Info
|
||||
// public flgCopied = false;
|
||||
// public appConfig: RTLConfiguration;
|
||||
// public accessKey = '';
|
||||
// public smallScreen = false;
|
||||
// unsubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject()];
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsubs.forEach(unsub => {
|
||||
unsub.next();
|
||||
unsub.complete();
|
||||
});
|
||||
}
|
||||
// constructor(private logger: LoggerService, private store: Store<fromRTLReducer.State>, private actions$: Actions,
|
||||
// private userIdle: UserIdleService, private router: Router) {}
|
||||
|
||||
// ngOnInit() {
|
||||
// this.store.dispatch(new RTLActions.FetchRTLConfig());
|
||||
// this.accessKey = this.readAccessKey();
|
||||
// this.store.select('rtlRoot')
|
||||
// .pipe(takeUntil(this.unsubs[0]))
|
||||
// .subscribe(rtlStore => {
|
||||
// this.selNode = rtlStore.selNode;
|
||||
// this.settings = this.selNode.settings;
|
||||
// this.appConfig = rtlStore.appConfig;
|
||||
// this.information = rtlStore.information;
|
||||
// this.flgLoading[0] = (undefined !== this.information.identity_pubkey) ? false : true;
|
||||
// if (window.innerWidth <= 768) {
|
||||
// this.settings.menu = 'Vertical';
|
||||
// this.settings.flgSidenavOpened = false;
|
||||
// this.settings.flgSidenavPinned = false;
|
||||
// }
|
||||
// if (window.innerWidth <= 414) {
|
||||
// this.smallScreen = true;
|
||||
// }
|
||||
// this.logger.info(this.settings);
|
||||
// if (!sessionStorage.getItem('token')) {
|
||||
// this.flgLoading[0] = false;
|
||||
// }
|
||||
// });
|
||||
// if (sessionStorage.getItem('token')) {
|
||||
// this.store.dispatch(new RTLActions.FetchInfo());
|
||||
// }
|
||||
// this.actions$
|
||||
// .pipe(
|
||||
// takeUntil(this.unsubs[1]),
|
||||
// filter((action) => action.type === RTLActions.INIT_APP_DATA || action.type === RTLActions.SET_RTL_CONFIG)
|
||||
// ).subscribe((actionPayload: (RTLActions.InitAppData | RTLActions.SetRTLConfig)) => {
|
||||
// if (actionPayload.type === RTLActions.SET_RTL_CONFIG) {
|
||||
// if (!sessionStorage.getItem('token')) {
|
||||
// if (+actionPayload.payload.sso.rtlSSO) {
|
||||
// this.store.dispatch(new RTLActions.Signin(sha256(this.accessKey)));
|
||||
// } else {
|
||||
// this.router.navigate([this.appConfig.sso.logoutRedirectLink]);
|
||||
// }
|
||||
// }
|
||||
// if (
|
||||
// this.settings.menu === 'Horizontal' ||
|
||||
// this.settings.menuType === 'Compact' ||
|
||||
// this.settings.menuType === 'Mini') {
|
||||
// this.settingSidenav.toggle(); // To dynamically update the width to 100% after side nav is closed
|
||||
// setTimeout(() => { this.settingSidenav.toggle(); }, 100);
|
||||
// }
|
||||
// } else if (actionPayload.type === RTLActions.INIT_APP_DATA) {
|
||||
// this.store.dispatch(new RTLActions.FetchInfo());
|
||||
// }
|
||||
// });
|
||||
// this.actions$
|
||||
// .pipe(
|
||||
// takeUntil(this.unsubs[1]),
|
||||
// filter((action) => action.type === RTLActions.SET_INFO)
|
||||
// ).subscribe((infoData: RTLActions.SetInfo) => {
|
||||
// if (undefined !== infoData.payload.identity_pubkey) {
|
||||
// this.initializeRemainingData();
|
||||
// }
|
||||
// });
|
||||
// this.userIdle.startWatching();
|
||||
// this.userIdle.onTimerStart().subscribe(count => {});
|
||||
// this.userIdle.onTimeout().subscribe(() => {
|
||||
// if (sessionStorage.getItem('token')) {
|
||||
// this.logger.warn('Time limit exceeded for session inactivity! Logging out!');
|
||||
// this.store.dispatch(new RTLActions.OpenAlert({ width: '75%', data: {
|
||||
// type: 'WARN',
|
||||
// titleMessage: 'Time limit exceeded for session inactivity! Logging out!'
|
||||
// }}));
|
||||
// this.store.dispatch(new RTLActions.Signout());
|
||||
// this.userIdle.resetTimer();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// private readAccessKey() {
|
||||
// const url = window.location.href;
|
||||
// return url.substring(url.lastIndexOf('access-key=') + 11).trim();
|
||||
// }
|
||||
|
||||
// initializeRemainingData() {
|
||||
// this.store.dispatch(new RTLActions.FetchPeers());
|
||||
// this.store.dispatch(new RTLActions.FetchBalance('channels'));
|
||||
// this.store.dispatch(new RTLActions.FetchFees());
|
||||
// this.store.dispatch(new RTLActions.FetchNetwork());
|
||||
// this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'all'}));
|
||||
// this.store.dispatch(new RTLActions.FetchChannels({routeParam: 'pending'}));
|
||||
// this.store.dispatch(new RTLActions.FetchInvoices({num_max_invoices: 25, reversed: true}));
|
||||
// this.store.dispatch(new RTLActions.FetchPayments());
|
||||
// }
|
||||
|
||||
// ngAfterViewInit() {
|
||||
// if (!this.settings.flgSidenavPinned) {
|
||||
// this.sideNavigation.close();
|
||||
// this.settingSidenav.toggle();
|
||||
// }
|
||||
// if (window.innerWidth <= 768) {
|
||||
// this.sideNavigation.close();
|
||||
// this.settingSidenav.toggle();
|
||||
// }
|
||||
// }
|
||||
|
||||
// @HostListener('window:resize')
|
||||
// public onWindowResize(): void {
|
||||
// if (window.innerWidth <= 768) {
|
||||
// this.settings.menu = 'Vertical';
|
||||
// this.settings.flgSidenavOpened = false;
|
||||
// this.settings.flgSidenavPinned = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
// sideNavToggle() {
|
||||
// this.sideNavigation.toggle();
|
||||
// }
|
||||
|
||||
// onNavigationClicked(event: any) {
|
||||
// if (window.innerWidth <= 414) {
|
||||
// this.sideNavigation.close();
|
||||
// }
|
||||
// }
|
||||
|
||||
// copiedText(payload) {
|
||||
// this.flgCopied = true;
|
||||
// setTimeout(() => {this.flgCopied = false; }, 5000);
|
||||
// this.logger.info('Copied Text: ' + payload);
|
||||
// }
|
||||
|
||||
// ngOnDestroy() {
|
||||
// this.unsubs.forEach(unsub => {
|
||||
// unsub.next();
|
||||
// unsub.complete();
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
@ -1,47 +1,40 @@
|
||||
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { formatDate } from '@angular/common';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
|
||||
import { ChannelEdge } from '../../../shared/models/lndModels';
|
||||
import * as fromLNDReducer from '../../store/lnd.reducers';
|
||||
import * as fromRTLReducer from '../../../shared/store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-channel-lookup',
|
||||
templateUrl: './channel-lookup.component.html',
|
||||
styleUrls: ['./channel-lookup.component.css']
|
||||
})
|
||||
export class ChannelLookupComponent implements OnInit, OnDestroy {
|
||||
export class ChannelLookupComponent implements OnInit {
|
||||
@Input() lookupResult: ChannelEdge;
|
||||
public node1_match = false;
|
||||
public node2_match = false;
|
||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
|
||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
|
||||
|
||||
constructor(private lndStore: Store<fromLNDReducer.LNDState>) { }
|
||||
constructor(private store: Store<fromRTLReducer.State>) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (undefined !== this.lookupResult && undefined !== this.lookupResult.last_update_str) {
|
||||
this.lookupResult.last_update_str = (this.lookupResult.last_update_str === '') ?
|
||||
'' : formatDate(this.lookupResult.last_update_str, 'MMM/dd/yy HH:mm:ss', 'en-US');
|
||||
}
|
||||
this.lndStore.select('lnd')
|
||||
.pipe(takeUntil(this.unSubs[1]))
|
||||
.subscribe(lndStore => {
|
||||
if (this.lookupResult.node1_pub === lndStore.information.identity_pubkey) {
|
||||
this.store.select('rtlRoot')
|
||||
.pipe(takeUntil(this.unSubs[0]))
|
||||
.subscribe((rtlStore: fromRTLReducer.State) => {
|
||||
if (this.lookupResult.node1_pub === rtlStore.information.identity_pubkey) {
|
||||
this.node1_match = true;
|
||||
}
|
||||
if (this.lookupResult.node2_pub === lndStore.information.identity_pubkey) {
|
||||
if (this.lookupResult.node2_pub === rtlStore.information.identity_pubkey) {
|
||||
this.node2_match = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unSubs.forEach(unsub => {
|
||||
unsub.next();
|
||||
unsub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-not-found',
|
||||
templateUrl: './not-found.component.html'
|
||||
})
|
||||
export class NotFoundComponent {}
|
||||
export class NotFoundComponent {
|
||||
|
||||
constructor(public router: Router) {}
|
||||
|
||||
goToHelp(): void {
|
||||
this.router.navigate(['/help']);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,43 +0,0 @@
|
||||
// export interface GetInfoAddress {
|
||||
// type?: string;
|
||||
// address?: string;
|
||||
// port?: number;
|
||||
// }
|
||||
|
||||
// export interface GetInfo {
|
||||
// id?: string;
|
||||
// alias?: string;
|
||||
// color?: string;
|
||||
// num_peers?: number;
|
||||
// num_pending_channels?: number;
|
||||
// num_active_channels?: number;
|
||||
// num_inactive_channels?: number;
|
||||
// address?: GetInfoAddress[];
|
||||
// binding?: GetInfoAddress[];
|
||||
// version?: string;
|
||||
// blockheight?: number;
|
||||
// network?: string;
|
||||
// msatoshi_fees_collected?: number;
|
||||
// fees_collected_msat?: string;
|
||||
// }
|
||||
|
||||
export interface GetInfoChain {
|
||||
chain?: string;
|
||||
network?: string;
|
||||
}
|
||||
|
||||
export interface GetInfo {
|
||||
identity_pubkey?: string;
|
||||
alias?: string;
|
||||
num_pending_channels?: number;
|
||||
num_active_channels?: number;
|
||||
num_inactive_channels?: number;
|
||||
num_peers?: number;
|
||||
block_height?: number;
|
||||
synced_to_chain?: boolean;
|
||||
testnet?: boolean;
|
||||
chains?: GetInfoChain[];
|
||||
version?: string;
|
||||
currency_unit?: string;
|
||||
smaller_currency_unit?: string;
|
||||
}
|
@ -1,118 +0,0 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { RTLConfiguration, Settings, Node } from '../shared/models/RTLconfig';
|
||||
import { ErrorPayload } from '../shared/models/errorPayload';
|
||||
import { MatDialogConfig } from '@angular/material';
|
||||
|
||||
export const RESET_STORE = 'RESET_STORE';
|
||||
export const CLEAR_EFFECT_ERROR = 'CLEAR_EFFECT_ERROR';
|
||||
export const EFFECT_ERROR = 'EFFECT_ERROR';
|
||||
export const OPEN_SPINNER = 'OPEN_SPINNER';
|
||||
export const CLOSE_SPINNER = 'CLOSE_SPINNER';
|
||||
export const OPEN_ALERT = 'OPEN_ALERT';
|
||||
export const CLOSE_ALERT = 'CLOSE_ALERT';
|
||||
export const OPEN_CONFIRMATION = 'OPEN_CONFIRMATION';
|
||||
export const CLOSE_CONFIRMATION = 'CLOSE_CONFIRMATION';
|
||||
export const FETCH_STORE = 'FETCH_STORE';
|
||||
export const SET_STORE = 'SET_STORE';
|
||||
export const FETCH_RTL_CONFIG = 'FETCH_RTL_CONFIG';
|
||||
export const SET_RTL_CONFIG = 'SET_RTL_CONFIG';
|
||||
export const SAVE_SETTINGS = 'SAVE_SETTINGS';
|
||||
export const SET_SELECTED_NODE = 'SET_SELECTED_NODE';
|
||||
export const IS_AUTHORIZED = 'IS_AUTHORIZED';
|
||||
export const IS_AUTHORIZED_RES = 'IS_AUTHORIZED_RES';
|
||||
export const SIGNIN = 'SIGNIN';
|
||||
export const SIGNOUT = 'SIGNOUT';
|
||||
export const INIT_APP_DATA = 'INIT_APP_DATA';
|
||||
|
||||
export class ClearEffectError implements Action {
|
||||
readonly type = CLEAR_EFFECT_ERROR;
|
||||
constructor(public payload: string) {} // payload = errorAction
|
||||
}
|
||||
|
||||
export class EffectError implements Action {
|
||||
readonly type = EFFECT_ERROR;
|
||||
constructor(public payload: ErrorPayload) {}
|
||||
}
|
||||
|
||||
export class OpenSpinner implements Action {
|
||||
readonly type = OPEN_SPINNER;
|
||||
constructor(public payload: string) {} // payload = titleMessage
|
||||
}
|
||||
|
||||
export class CloseSpinner implements Action {
|
||||
readonly type = CLOSE_SPINNER;
|
||||
}
|
||||
|
||||
export class OpenAlert implements Action {
|
||||
readonly type = OPEN_ALERT;
|
||||
constructor(public payload: MatDialogConfig) {}
|
||||
}
|
||||
|
||||
export class CloseAlert implements Action {
|
||||
readonly type = CLOSE_ALERT;
|
||||
}
|
||||
|
||||
export class OpenConfirmation implements Action {
|
||||
readonly type = OPEN_CONFIRMATION;
|
||||
constructor(public payload: MatDialogConfig) {}
|
||||
}
|
||||
|
||||
export class CloseConfirmation implements Action {
|
||||
readonly type = CLOSE_CONFIRMATION;
|
||||
constructor(public payload: boolean) {}
|
||||
}
|
||||
|
||||
export class ResetStore implements Action {
|
||||
readonly type = RESET_STORE;
|
||||
constructor(public payload: Node) {}
|
||||
}
|
||||
|
||||
export class FetchRTLConfig implements Action {
|
||||
readonly type = FETCH_RTL_CONFIG;
|
||||
}
|
||||
|
||||
export class SetRTLConfig implements Action {
|
||||
readonly type = SET_RTL_CONFIG;
|
||||
constructor(public payload: RTLConfiguration) {}
|
||||
}
|
||||
|
||||
export class SaveSettings implements Action {
|
||||
readonly type = SAVE_SETTINGS;
|
||||
constructor(public payload: Settings) {}
|
||||
}
|
||||
|
||||
export class SetSelelectedNode implements Action {
|
||||
readonly type = SET_SELECTED_NODE;
|
||||
constructor(public payload: Node) {}
|
||||
}
|
||||
|
||||
export class IsAuthorized implements Action {
|
||||
readonly type = IS_AUTHORIZED;
|
||||
constructor(public payload: string) {} // payload = password
|
||||
}
|
||||
|
||||
export class IsAuthorizedRes implements Action {
|
||||
readonly type = IS_AUTHORIZED_RES;
|
||||
constructor(public payload: any) {} // payload = token/error
|
||||
}
|
||||
|
||||
export class Signin implements Action {
|
||||
readonly type = SIGNIN;
|
||||
constructor(public payload: string) {} // payload = password
|
||||
}
|
||||
|
||||
export class Signout implements Action {
|
||||
readonly type = SIGNOUT;
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
export class InitAppData implements Action {
|
||||
readonly type = INIT_APP_DATA;
|
||||
}
|
||||
|
||||
export type RTLActions =
|
||||
ClearEffectError | EffectError | OpenSpinner | CloseSpinner |
|
||||
FetchRTLConfig | SetRTLConfig | SaveSettings |
|
||||
OpenAlert | CloseAlert | OpenConfirmation | CloseConfirmation |
|
||||
ResetStore | SetSelelectedNode |
|
||||
IsAuthorized | IsAuthorizedRes | Signin | Signout | InitAppData;
|
@ -1,261 +0,0 @@
|
||||
import { Injectable, OnDestroy } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Actions, Effect, ofType } from '@ngrx/effects';
|
||||
import { of, Subject } from 'rxjs';
|
||||
import { map, mergeMap, catchError, take, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
import { MatDialog } from '@angular/material';
|
||||
import { environment } from '../../environments/environment';
|
||||
import { LoggerService } from '../shared/services/logger.service';
|
||||
import { Settings } from '../shared/models/RTLconfig';
|
||||
|
||||
import { SpinnerDialogComponent } from '../shared/components/spinner-dialog/spinner-dialog.component';
|
||||
import { AlertMessageComponent } from '../shared/components/alert-message/alert-message.component';
|
||||
import { ConfirmationMessageComponent } from '../shared/components/confirmation-message/confirmation-message.component';
|
||||
|
||||
import * as CLActions from '../c-lightning/store/cl.actions';
|
||||
import * as LNDActions from '../lnd/store/lnd.actions';
|
||||
import * as RTLActions from './rtl.actions';
|
||||
import * as fromApp from './rtl.reducers';
|
||||
|
||||
@Injectable()
|
||||
export class RTLEffects implements OnDestroy {
|
||||
dialogRef: any;
|
||||
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
|
||||
|
||||
constructor(
|
||||
private actions$: Actions,
|
||||
private httpClient: HttpClient,
|
||||
private store: Store<fromApp.AppState>,
|
||||
private logger: LoggerService,
|
||||
public dialog: MatDialog,
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute) { }
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
openSpinner = this.actions$.pipe(
|
||||
ofType(RTLActions.OPEN_SPINNER),
|
||||
map((action: RTLActions.OpenSpinner) => {
|
||||
this.dialogRef = this.dialog.open(SpinnerDialogComponent, { data: { titleMessage: action.payload}});
|
||||
}
|
||||
));
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
closeSpinner = this.actions$.pipe(
|
||||
ofType(RTLActions.CLOSE_SPINNER),
|
||||
map((action: RTLActions.CloseSpinner) => {
|
||||
if (this.dialogRef) { this.dialogRef.close(); }
|
||||
}
|
||||
));
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
openAlert = this.actions$.pipe(
|
||||
ofType(RTLActions.OPEN_ALERT),
|
||||
map((action: RTLActions.OpenAlert) => {
|
||||
this.dialogRef = this.dialog.open(AlertMessageComponent, action.payload);
|
||||
}
|
||||
));
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
closeAlert = this.actions$.pipe(
|
||||
ofType(RTLActions.CLOSE_ALERT),
|
||||
map((action: RTLActions.CloseAlert) => {
|
||||
if (this.dialogRef) { this.dialogRef.close(); }
|
||||
}
|
||||
));
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
openConfirm = this.actions$.pipe(
|
||||
ofType(RTLActions.OPEN_CONFIRMATION),
|
||||
map((action: RTLActions.OpenConfirmation) => {
|
||||
this.dialogRef = this.dialog.open(ConfirmationMessageComponent, action.payload);
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
closeConfirm = this.actions$.pipe(
|
||||
ofType(RTLActions.CLOSE_CONFIRMATION),
|
||||
take(1),
|
||||
map((action: RTLActions.CloseConfirmation) => {
|
||||
this.dialogRef.close();
|
||||
this.logger.info(action.payload);
|
||||
return action.payload;
|
||||
}
|
||||
));
|
||||
|
||||
@Effect()
|
||||
appConfigFetch = this.actions$.pipe(
|
||||
ofType(RTLActions.FETCH_RTL_CONFIG),
|
||||
mergeMap((action: RTLActions.FetchRTLConfig) => {
|
||||
this.store.dispatch(new RTLActions.ClearEffectError('FetchRTLConfig'));
|
||||
return this.httpClient.get(environment.CONF_API + '/rtlconf');
|
||||
}),
|
||||
map((rtlConfig: any) => {
|
||||
this.logger.info(rtlConfig);
|
||||
if (+rtlConfig.sso.rtlSSO) { this.store.dispatch(new RTLActions.Signout()); }
|
||||
return {
|
||||
type: RTLActions.SET_RTL_CONFIG,
|
||||
payload: rtlConfig
|
||||
};
|
||||
},
|
||||
catchError((err) => {
|
||||
this.logger.error(err);
|
||||
this.store.dispatch(new RTLActions.EffectError({ action: 'FetchRTLConfig', code: err.status, message: err.error.error }));
|
||||
return of();
|
||||
})
|
||||
));
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
settingSave = this.actions$.pipe(
|
||||
ofType(RTLActions.SAVE_SETTINGS),
|
||||
mergeMap((action: RTLActions.SaveSettings) => {
|
||||
return this.httpClient.post<Settings>(environment.CONF_API, { updatedSettings: action.payload });
|
||||
}
|
||||
));
|
||||
|
||||
@Effect()
|
||||
isAuthorized = this.actions$.pipe(
|
||||
ofType(RTLActions.IS_AUTHORIZED),
|
||||
withLatestFrom(this.store.select('rtlRoot')),
|
||||
mergeMap(([action, store]: [RTLActions.IsAuthorized, fromApp.RootState]) => {
|
||||
this.store.dispatch(new RTLActions.ClearEffectError('IsAuthorized'));
|
||||
return this.httpClient.post(environment.AUTHENTICATE_API, { password: action.payload })
|
||||
.pipe(
|
||||
map((postRes: any) => {
|
||||
this.logger.info(postRes);
|
||||
this.logger.info('Successfully Authorized!');
|
||||
return {
|
||||
type: RTLActions.IS_AUTHORIZED_RES,
|
||||
payload: postRes
|
||||
};
|
||||
}),
|
||||
catchError((err) => {
|
||||
this.store.dispatch(new RTLActions.OpenAlert({ width: '70%', data: {type: 'ERROR', titleMessage: 'Authorization Failed',
|
||||
message: JSON.stringify({Code: err.status, Message: err.error.error})}}));
|
||||
this.store.dispatch(new RTLActions.EffectError({ action: 'IsAuthorized', code: err.status, message: err.error.message }));
|
||||
this.logger.error(err.error);
|
||||
return of({
|
||||
type: RTLActions.IS_AUTHORIZED_RES,
|
||||
payload: 'ERROR'
|
||||
});
|
||||
})
|
||||
);
|
||||
}));
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
isAuthorizedRes = this.actions$.pipe(
|
||||
ofType(RTLActions.IS_AUTHORIZED_RES),
|
||||
map((action: RTLActions.IsAuthorizedRes) => {
|
||||
return action.payload;
|
||||
})
|
||||
);
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
authSignin = this.actions$.pipe(
|
||||
ofType(RTLActions.SIGNIN),
|
||||
withLatestFrom(this.store.select('rtlRoot')),
|
||||
mergeMap(([action, store]: [RTLActions.Signin, fromApp.RootState]) => {
|
||||
this.store.dispatch(new RTLActions.ClearEffectError('Signin'));
|
||||
return this.httpClient.post(environment.AUTHENTICATE_API, { password: action.payload })
|
||||
.pipe(
|
||||
map((postRes: any) => {
|
||||
this.logger.info(postRes);
|
||||
this.logger.info('Successfully Authorized!');
|
||||
this.SetToken(postRes.token);
|
||||
this.router.navigate(['/'], { relativeTo: this.activatedRoute });
|
||||
}),
|
||||
catchError((err) => {
|
||||
this.store.dispatch(new RTLActions.OpenAlert({ width: '70%', data: {type: 'ERROR', message: JSON.stringify(err.error)}}));
|
||||
this.store.dispatch(new RTLActions.EffectError({ action: 'Signin', code: err.status, message: err.error.message }));
|
||||
this.logger.error(err.error);
|
||||
this.logger.info('Redirecting to Signin Error Page');
|
||||
if (+store.appConfig.sso.rtlSSO) {
|
||||
this.router.navigate(['/ssoerror'], { relativeTo: this.activatedRoute });
|
||||
} else {
|
||||
this.router.navigate([store.appConfig.sso.logoutRedirectLink], { relativeTo: this.activatedRoute });
|
||||
}
|
||||
return of();
|
||||
})
|
||||
);
|
||||
}));
|
||||
|
||||
@Effect({ dispatch: false })
|
||||
signOut = this.actions$.pipe(
|
||||
ofType(RTLActions.SIGNOUT),
|
||||
withLatestFrom(this.store.select('rtlRoot')),
|
||||
mergeMap(([action, store]: [RTLActions.Signout, fromApp.RootState]) => {
|
||||
if (+store.appConfig.sso.rtlSSO) {
|
||||
window.location.href = store.appConfig.sso.logoutRedirectLink;
|
||||
} else {
|
||||
this.router.navigate([store.appConfig.sso.logoutRedirectLink], { relativeTo: this.activatedRoute });
|
||||
}
|
||||
sessionStorage.removeItem('lndUnlocked');
|
||||
sessionStorage.removeItem('token');
|
||||
this.logger.warn('LOGGED OUT');
|
||||
return of();
|
||||
}));
|
||||
|
||||
@Effect()
|
||||
setSelectedNode = this.actions$.pipe(
|
||||
ofType(RTLActions.SET_SELECTED_NODE),
|
||||
mergeMap((action: RTLActions.SetSelelectedNode) => {
|
||||
this.store.dispatch(new RTLActions.ClearEffectError('UpdateSelNode'));
|
||||
return this.httpClient.post(environment.CONF_API + '/updateSelNode', { selNodeIndex: action.payload.index })
|
||||
.pipe(
|
||||
map((postRes: any) => {
|
||||
this.logger.info(postRes);
|
||||
this.store.dispatch(new RTLActions.CloseSpinner());
|
||||
if (sessionStorage.getItem('token')) {
|
||||
this.store.dispatch(new RTLActions.ResetStore(action.payload));
|
||||
if (action.payload.lnImplementation.toLowerCase() === 'clightning') {
|
||||
this.router.navigate(['./cl'], { relativeTo: this.activatedRoute });
|
||||
return { type: CLActions.FETCH_CL_INFO };
|
||||
} else {
|
||||
this.router.navigate(['./lnd'], { relativeTo: this.activatedRoute });
|
||||
return { type: LNDActions.FETCH_INFO };
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
type: RTLActions.OPEN_ALERT,
|
||||
payload: { width: '70%', data: {type: 'WARN', titleMessage: 'Authorization required to get the data from the node!' }}
|
||||
};
|
||||
}
|
||||
}),
|
||||
catchError((err: any) => {
|
||||
this.store.dispatch(new RTLActions.CloseSpinner());
|
||||
this.store.dispatch(new RTLActions.EffectError({ action: 'UpdateSelNode', code: err.status, message: err.error.message }));
|
||||
this.logger.error(err);
|
||||
return of(
|
||||
{
|
||||
type: RTLActions.OPEN_ALERT,
|
||||
payload: { width: '70%', data: {type: 'ERROR', titleMessage: 'Update Selected Node Failed!',
|
||||
message: JSON.stringify({code: err.status, Message: err.error.error})
|
||||
}}
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
));
|
||||
|
||||
SetToken(token: string) {
|
||||
if (token) {
|
||||
sessionStorage.setItem('lndUnlocked', 'true');
|
||||
sessionStorage.setItem('token', token);
|
||||
this.store.dispatch(new RTLActions.InitAppData());
|
||||
} else {
|
||||
sessionStorage.removeItem('lndUnlocked');
|
||||
sessionStorage.removeItem('token');
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unSubs.forEach(completeSub => {
|
||||
completeSub.next();
|
||||
completeSub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
import * as RTLActions from './rtl.actions';
|
||||
import { ErrorPayload } from '../shared/models/errorPayload';
|
||||
import { RTLConfiguration, Node } from '../shared/models/RTLconfig';
|
||||
|
||||
import { ActionReducerMap } from '@ngrx/store';
|
||||
|
||||
import * as fromLND from '../lnd/store/lnd.reducers';
|
||||
import * as fromCL from '../c-lightning/store/cl.reducers';
|
||||
|
||||
export interface AppState {
|
||||
rtlRoot: RootState;
|
||||
lnd: fromLND.LNDState;
|
||||
cl: fromCL.CLState;
|
||||
}
|
||||
|
||||
export interface RootState {
|
||||
effectErrors: ErrorPayload[];
|
||||
selNode: Node;
|
||||
appConfig: RTLConfiguration;
|
||||
}
|
||||
|
||||
const initNodeSettings = { flgSidenavOpened: true, flgSidenavPinned: true, menu: 'Vertical', menuType: 'Regular', theme: 'dark-blue', satsToBTC: false };
|
||||
const initNodeAuthentication = { nodeAuthType: 'CUSTOM', lndConfigPath: '', bitcoindConfigPath: '' };
|
||||
|
||||
const initialState: RootState = {
|
||||
effectErrors: [],
|
||||
selNode: {settings: initNodeSettings, authentication: initNodeAuthentication},
|
||||
appConfig: {
|
||||
selectedNodeIndex: -1,
|
||||
sso: { rtlSSO: 0, logoutRedirectLink: '/login' },
|
||||
nodes: [{ settings: initNodeSettings, authentication: initNodeAuthentication}]
|
||||
}
|
||||
};
|
||||
|
||||
export function RTLRootReducer(state = initialState, action: RTLActions.RTLActions) {
|
||||
switch (action.type) {
|
||||
case RTLActions.CLEAR_EFFECT_ERROR:
|
||||
const clearedEffectErrors = [...state.effectErrors];
|
||||
const removeEffectIdx = state.effectErrors.findIndex(err => {
|
||||
return err.action === action.payload;
|
||||
});
|
||||
if (removeEffectIdx > -1) {
|
||||
clearedEffectErrors.splice(removeEffectIdx, 1);
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
effectErrors: clearedEffectErrors
|
||||
};
|
||||
case RTLActions.EFFECT_ERROR:
|
||||
return {
|
||||
...state,
|
||||
effectErrors: [...state.effectErrors, action.payload]
|
||||
};
|
||||
case RTLActions.RESET_STORE:
|
||||
return {
|
||||
...initialState,
|
||||
appConfig: state.appConfig,
|
||||
selNode: action.payload
|
||||
};
|
||||
case RTLActions.SET_SELECTED_NODE:
|
||||
return {
|
||||
...state,
|
||||
selNode: action.payload
|
||||
};
|
||||
case RTLActions.SET_RTL_CONFIG:
|
||||
return {
|
||||
...state,
|
||||
selNode: action.payload.nodes.find(node => +node.index === action.payload.selectedNodeIndex),
|
||||
appConfig: action.payload
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const appReducer: ActionReducerMap<AppState> = {
|
||||
rtlRoot: RTLRootReducer,
|
||||
lnd: fromLND.LNDReducer,
|
||||
cl: fromCL.CLReducer
|
||||
};
|
||||
|
@ -1,2 +0,0 @@
|
||||
<router-outlet></router-outlet>
|
||||
|
@ -1,25 +0,0 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SuperUserDashboardComponent } from './super-user-dashboard.component';
|
||||
|
||||
describe('SuperUserDashboardComponent', () => {
|
||||
let component: SuperUserDashboardComponent;
|
||||
let fixture: ComponentFixture<SuperUserDashboardComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SuperUserDashboardComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SuperUserDashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -1,70 +0,0 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil, filter } from 'rxjs/operators';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { Actions } from '@ngrx/effects';
|
||||
import { UserIdleService } from 'angular-user-idle';
|
||||
|
||||
import { LoggerService } from '../shared/services/logger.service';
|
||||
import { RTLConfiguration, Settings, Node } from '../shared/models/RTLconfig';
|
||||
import { GetInfo } from '../shared/models/lndModels';
|
||||
|
||||
import * as LNDActions from '../lnd/store/lnd.actions';
|
||||
import * as CLActions from '../c-lightning/store/cl.actions';
|
||||
import * as RTLActions from '../store/rtl.actions';
|
||||
import * as fromApp from '../store/rtl.reducers';
|
||||
|
||||
@Component({
|
||||
selector: 'rtl-super-user-dashboard',
|
||||
templateUrl: './super-user-dashboard.component.html',
|
||||
styleUrls: ['./super-user-dashboard.component.scss']
|
||||
})
|
||||
export class SuperUserDashboardComponent implements OnInit, OnDestroy {
|
||||
public selNode: Node;
|
||||
public settings: Settings;
|
||||
public information: GetInfo = {};
|
||||
public flgLoading: Array<Boolean | 'error'> = [true];
|
||||
public flgCopied = false;
|
||||
public appConfig: RTLConfiguration;
|
||||
public accessKey = '';
|
||||
public smallScreen = false;
|
||||
unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
|
||||
|
||||
constructor(private logger: LoggerService, private store: Store<fromApp.AppState>, private actions$: Actions, private userIdle: UserIdleService, private router: Router, private activatedRoute: ActivatedRoute) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.actions$.pipe(takeUntil(this.unSubs[3]), filter(action => action.type === RTLActions.SET_RTL_CONFIG))
|
||||
.subscribe((setConfigAction: RTLActions.SetRTLConfig) => {
|
||||
console.warn(setConfigAction);
|
||||
this.selNode = setConfigAction.payload.nodes.find(node => +node.index === setConfigAction.payload.selectedNodeIndex)
|
||||
if (this.selNode.lnImplementation.toLowerCase() === 'clightning') {
|
||||
this.store.dispatch(new CLActions.FetchCLInfo());
|
||||
this.router.navigate(['../cl'], { relativeTo: this.activatedRoute });
|
||||
} else {
|
||||
this.store.dispatch(new LNDActions.FetchInfo());
|
||||
this.router.navigate(['../lnd'], { relativeTo: this.activatedRoute });
|
||||
}
|
||||
});
|
||||
// this.store.select('rtlRoot')
|
||||
// .pipe(takeUntil(this.unSubs[0]))
|
||||
// .subscribe(rtlStore => {
|
||||
// this.selNode = rtlStore.selNode;
|
||||
// if (this.selNode.lnImplementation.toLowerCase() === 'clightning') {
|
||||
// this.store.dispatch(new CLActions.FetchCLInfo());
|
||||
// this.router.navigate(['./cl'], { relativeTo: this.activatedRoute });
|
||||
// } else {
|
||||
// this.store.dispatch(new LNDActions.FetchInfo());
|
||||
// this.router.navigate(['./lnd'], { relativeTo: this.activatedRoute });
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unSubs.forEach(unsub => {
|
||||
unsub.next();
|
||||
unsub.complete();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1 +1 @@
|
||||
export const VERSION = '0.4.7-beta';
|
||||
export const VERSION = '0.4.8-beta';
|
Loading…
Reference in New Issue