Currency Unit Convesion

Currency Unit Convesion
pull/260/head
Shahana Farooqui 5 years ago
parent d11ae4f916
commit 3d19c493fb

@ -154,6 +154,8 @@ THE SOFTWARE.
@angular/material/table
@angular/material/tabs
@angular/material/toolbar
@angular/material/tooltip

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -9,8 +9,8 @@
<link rel="icon" type="image/png" sizes="32x32" href="assets/images/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="assets/images/favicon/favicon-16x16.png">
<link rel="manifest" href="assets/images/favicon/site.webmanifest">
<link rel="stylesheet" href="styles.5f4e054d3598702b6fb0.css"></head>
<link rel="stylesheet" href="styles.283353200dc668e12877.css"></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.9b2fce285f8c03dde3ad.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.a8d7c33cc661c997a839.js"></script></body>
<script src="runtime.508868925a77d5fc90cc.js"></script><script src="polyfills-es5.92f4069201c83f4833ef.js" nomodule></script><script src="polyfills.5ddcccdb990eb395f306.js"></script><script src="main.b901a7c6a0dab32c8849.js"></script></body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +1 @@
!function(e){function r(r){for(var n,i,a=r[0],c=r[1],f=r[2],d=0,p=[];d<a.length;d++)o[i=a[d]]&&p.push(o[i][0]),o[i]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);p.length;)p.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++)0!==o[t[a]]&&(n=!1);n&&(u.splice(r--,1),e=i(i.s=t[0]))}return e}var n={},o={0:0},u=[];function i(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,i),t.l=!0,t.exports}i.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,a=document.createElement("script");a.charset="utf-8",a.timeout=120,i.nc&&a.setAttribute("nonce",i.nc),a.src=function(e){return i.p+""+({}[e]||e)+"."+{1:"286c4dfbd0213d219ea9",6:"625d19f75fd9dd782c69",7:"e69b47865bc33dd41c29"}[e]+".js"}(e);var c=new Error;u=function(r){a.onerror=a.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:a})}),12e4);a.onerror=a.onload=u,document.head.appendChild(a)}return Promise.all(r)},i.m=e,i.c=n,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,(function(r){return e[r]}).bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="",i.oe=function(e){throw console.error(e),e};var a=window.webpackJsonp=window.webpackJsonp||[],c=a.push.bind(a);a.push=r,a=a.slice();for(var f=0;f<a.length;f++)r(a[f]);var l=c;t()}([]);
!function(e){function r(r){for(var n,i,a=r[0],c=r[1],f=r[2],p=0,s=[];p<a.length;p++)o[i=a[p]]&&s.push(o[i][0]),o[i]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(e[n]=c[n]);for(l&&l(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,a=1;a<t.length;a++)0!==o[t[a]]&&(n=!1);n&&(u.splice(r--,1),e=i(i.s=t[0]))}return e}var n={},o={0:0},u=[];function i(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,i),t.l=!0,t.exports}i.e=function(e){var r=[],t=o[e];if(0!==t)if(t)r.push(t[2]);else{var n=new Promise((function(r,n){t=o[e]=[r,n]}));r.push(t[2]=n);var u,a=document.createElement("script");a.charset="utf-8",a.timeout=120,i.nc&&a.setAttribute("nonce",i.nc),a.src=function(e){return i.p+""+({}[e]||e)+"."+{1:"df9093d1e13d9e6f0394",6:"c84a7e3b20b9550b6e5e",7:"97b98af961941a6521c7"}[e]+".js"}(e);var c=new Error;u=function(r){a.onerror=a.onload=null,clearTimeout(f);var t=o[e];if(0!==t){if(t){var n=r&&("load"===r.type?"missing":r.type),u=r&&r.target&&r.target.src;c.message="Loading chunk "+e+" failed.\n("+n+": "+u+")",c.name="ChunkLoadError",c.type=n,c.request=u,t[1](c)}o[e]=void 0}};var f=setTimeout((function(){u({type:"timeout",target:a})}),12e4);a.onerror=a.onload=u,document.head.appendChild(a)}return Promise.all(r)},i.m=e,i.c=n,i.d=function(e,r,t){i.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,r){if(1&r&&(e=i(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(i.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)i.d(t,n,(function(r){return e[r]}).bind(null,n));return t},i.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(r,"a",r),r},i.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},i.p="",i.oe=function(e){throw console.error(e),e};var a=window.webpackJsonp=window.webpackJsonp||[],c=a.push.bind(a);a.push=r,a=a.slice();for(var f=0;f<a.length;f++)r(a[f]);var l=c;t()}([]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -9,6 +9,7 @@ common.node_auth_type = 'DEFAULT';
common.rtl_pass = '';
common.rtl_sso = 0;
common.port = 3000;
common.currency_unit = 'USD';
common.rtl_cookie_path = '';
common.logout_redirect_link = '/login';
common.cookie = '';

@ -22,46 +22,58 @@ connect.setDefaultConfig = () => {
case 'win32':
macaroonPath = homeDir + '\\AppData\\Local\\Lnd\\data\\chain\\bitcoin\\mainnet';
configPath = homeDir + '\\AppData\\Local\\Lnd\\lnd.conf';
channelBackupPath = homeDir + '\\backup\\node-1';
break;
case 'darwin':
macaroonPath = homeDir + '/Library/Application Support/Lnd/data/chain/bitcoin/mainnet';
configPath = homeDir + '/Library/Application Support/Lnd/lnd.conf';
channelBackupPath = homeDir + '/backup/node-1';
break;
case 'linux':
macaroonPath = homeDir + '/.lnd/data/chain/bitcoin/mainnet';
configPath = homeDir + '/.lnd/lnd.conf';
channelBackupPath = homeDir + '/backup/node-1';
break;
default:
macaroonPath = '';
configPath = '';
channelBackupPath = '';
break;
}
return {
Authentication: {
macaroonPath: macaroonPath,
nodeAuthType: 'DEFAULT',
configPath: configPath,
rtlPass: ''
},
Settings: {
flgSidenavOpened: true,
flgSidenavPinned: true,
menu: 'vertical',
menuType: 'regular',
fontSize: 'regular-font',
themeMode: 'night',
themeColor: 'blue',
satsToBTC: false,
channelBackupPath: homeDir + common.path_separator + 'backup' + common.path_separator + 'node-0',
lnServerUrl: 'https://localhost:8080/v1',
enableLogging: false,
port: 3000
},
port: "3000",
defaultNodeIndex: 1,
multiPass: "password",
SSO: {
rtlSSO: 0,
rtlCookiePath: '',
logoutRedirectLink: '/login'
}
rtlCookiePath: "",
logoutRedirectLink: ""
},
nodes: [
{
index: 1,
lnNode: "LND Testnet",
lnImplementation: "LND",
Authentication: {
macaroonPath: macaroonPath,
configPath: configPath,
},
Settings: {
flgSidenavOpened: true,
flgSidenavPinned: true,
menu: "vertical",
menuType: "regular",
fontSize: "regular-font",
themeMode: "day",
themeColor: "purple-white",
satsToBTC: false,
channelBackupPath: channelBackupPath,
enableLogging: "true",
lndServerUrl: "https://localhost:8080/v1",
currencyUnit: "USD"
}
}
]
};
}
@ -259,6 +271,14 @@ connect.validateSingleNodeConfig = (config) => {
}
}
if (undefined !== process.env.CURRENCY_UNIT) {
common.nodes[0].currency_unit = process.env.CURRENCY_UNIT;
} else if (undefined !== config.Settings.currencyUnit) {
common.nodes[0].currency_unit = config.Settings.currencyUnit;
} else {
common.nodes[0].currency_unit = 'USD';
}
if (undefined !== process.env.PORT) {
common.port = connect.normalizePort(process.env.PORT);
} else if (undefined !== config.Settings.port) {
@ -307,6 +327,8 @@ connect.validateMultiNodeConfig = (config) => {
common.nodes[idx].index = node.index;
common.nodes[idx].ln_node = node.lnNode;
common.nodes[idx].ln_implementation = node.lnImplementation;
common.nodes[idx].currency_unit = node.Settings.currencyUnit ? node.Settings.currencyUnit : 'USD';
if (undefined !== node.Authentication && undefined !== node.Authentication.lndConfigPath) {
common.nodes[idx].config_path = node.Authentication.lndConfigPath;
} else if (undefined !== node.Authentication && undefined !== node.Authentication.configPath) {
@ -453,6 +475,7 @@ connect.logEnvVariables = () => {
logger.info({fileName: 'Config Setup Variable', msg: 'LN NODE: ' + node.ln_node, node});
logger.info({fileName: 'Config Setup Variable', msg: 'LN IMPLEMENTATION: ' + node.ln_implementation, node});
logger.info({fileName: 'Config Setup Variable', msg: 'PORT: ' + common.port, node});
logger.info({fileName: 'Config Setup Variable', msg: 'CURRENCY_UNIT: ' + common.currency_unit, node});
logger.info({fileName: 'Config Setup Variable', msg: 'MACAROON_PATH: ' + node.macaroon_path, node});
logger.info({fileName: 'Config Setup Variable', msg: 'LND_SERVER_URL: ' + node.ln_server_url, node});
logger.info({fileName: 'Config Setup Variable', msg: 'RTL_CONFIG_PATH: ' + node.rtl_conf_file_path, node});
@ -464,6 +487,7 @@ connect.logEnvVariables = () => {
if (!common.nodes[0].enable_logging) { return; }
logger.info({fileName: 'Config Setup Variable', msg: 'NODE_SETUP: SINGLE'});
logger.info({fileName: 'Config Setup Variable', msg: 'PORT: ' + common.port});
logger.info({fileName: 'Config Setup Variable', msg: 'CURRENCY_UNIT: ' + common.currency_unit});
logger.info({fileName: 'Config Setup Variable', msg: 'LND_SERVER_URL: ' + common.nodes[0].ln_server_url});
logger.info({fileName: 'Config Setup Variable', msg: 'MACAROON_PATH: ' + common.nodes[0].macaroon_path});
logger.info({fileName: 'Config Setup Variable', msg: 'NODE_AUTH_TYPE: ' + common.node_auth_type});

@ -103,6 +103,7 @@ exports.updateUISettings = (req, res, next) => {
node.Settings.themeMode = req.body.updatedSettings.themeMode;
node.Settings.themeColor = req.body.updatedSettings.themeColor;
node.Settings.satsToBTC = req.body.updatedSettings.satsToBTC;
node.Settings.currencyUnit = req.body.updatedSettings.currencyUnit;
}
});
try {
@ -129,6 +130,7 @@ exports.updateUISettings = (req, res, next) => {
settingsTemp.themeMode = req.body.updatedSettings.themeMode;
settingsTemp.themeColor = req.body.updatedSettings.themeColor;
settingsTemp.satsToBTC = req.body.updatedSettings.satsToBTC;
settingsTemp.currencyUnit = req.body.updatedSettings.currencyUnit;
delete config.Settings;
fs.writeFileSync(RTLConfFile, ini.stringify(config));
fs.appendFile(RTLConfFile, ini.stringify(settingsTemp, { section: 'Settings' }), function(err) {

@ -18,6 +18,7 @@ bitcoindConfigPath=
enableLogging=true
port=3000
lndServerUrl=https://localhost:8080/v1
currencyUnit=USD
[SSO]
rtlSSO=0

@ -24,7 +24,7 @@ export interface CLState {
export const initCLState: CLState = {
effectErrorsCl: [],
nodeSettings: { channelBackupPath: '', satsToBTC: false },
nodeSettings: { channelBackupPath: '', satsToBTC: false, currencyUnits: [] },
information: {},
fees: {},
feeRatesPerKB: {},

@ -14,6 +14,7 @@ import { PaymentsComponent } from './payments/send-receive/payments.component';
import { ChannelManageComponent } from './channels/channel-manage/channel-manage.component';
import { ChannelPendingComponent } from './channels/channel-pending/channel-pending.component';
import { ChannelClosedComponent } from './channels/channel-closed/channel-closed.component';
import { TransactionsComponent } from './transactions/transactions.component';
import { ListTransactionsComponent } from './transactions/list-transactions/list-transactions.component';
import { LookupsComponent } from './lookups/lookups.component';
import { ForwardingHistoryComponent } from './switch/forwarding-history.component';
@ -44,6 +45,7 @@ import { LNDUnlockedGuard } from '../shared/services/auth.guard';
ChannelManageComponent,
ChannelPendingComponent,
ChannelClosedComponent,
TransactionsComponent,
ListTransactionsComponent,
LookupsComponent,
ForwardingHistoryComponent,

@ -8,6 +8,7 @@ import { ChannelClosedComponent } from './channels/channel-closed/channel-closed
import { ChannelManageComponent } from './channels/channel-manage/channel-manage.component';
import { ChannelPendingComponent } from './channels/channel-pending/channel-pending.component';
import { PeersComponent } from './peers/peers.component';
import { TransactionsComponent } from './transactions/transactions.component';
import { SendReceiveTransComponent } from './transactions/send-receive/send-receive-trans.component';
import { ListTransactionsComponent } from './transactions/list-transactions/list-transactions.component';
import { PaymentsComponent } from './payments/send-receive/payments.component';
@ -33,6 +34,7 @@ export const LndRoutes: Routes = [
{ path: 'chnlpending', component: ChannelPendingComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlbackup', component: ChannelBackupComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'chnlrestore', component: ChannelRestoreComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transactions', component: TransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'transsendreceive', component: SendReceiveTransComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'translist', component: ListTransactionsComponent, canActivate: [LNDUnlockedGuard] },
{ path: 'paymentsend', component: PaymentsComponent, canActivate: [LNDUnlockedGuard] },

@ -32,7 +32,7 @@ export interface LNDState {
export const initLNDState: LNDState = {
effectErrorsLnd: [],
nodeSettings: { channelBackupPath: '', satsToBTC: false },
nodeSettings: { channelBackupPath: '', satsToBTC: false, currencyUnits: [] },
information: {},
peers: [],
fees: {},

@ -0,0 +1,26 @@
<div fxLayout="row" class="padding-gap-x page-title-container">
<fa-icon [icon]="faChartPie" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Lightning Balance</span>
</div>
<div fxLayout="column" class="padding-gap-x mb-4">
<mat-card>
<mat-card-content fxLayout="column">
<rtl-currency-unit-converter [values]="balances"></rtl-currency-unit-converter>
</mat-card-content>
</mat-card>
</div>
<div fxLayout="row" class="padding-gap-x page-title-container">
<fa-icon [icon]="faExchangeAlt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Lightning Transactions</span>
</div>
<div fxLayout="column" class="padding-gap-x">
<mat-card>
<mat-card-content fxLayout="column">
<mat-tab-group>
<mat-tab label="Payments">Payments</mat-tab>
<mat-tab label="Invoices">Invoices</mat-tab>
</mat-tab-group>
</mat-card-content>
</mat-card>
</div>

@ -0,0 +1,14 @@
.tree-invisible {
display: none;
}
.lookup-tree ul,
.lookup-tree li {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
}
.pl-3 {
padding-left: 3rem;
}

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TransactionsComponent } from './transactions.component';
describe('TransactionsComponent', () => {
let component: TransactionsComponent;
let fixture: ComponentFixture<TransactionsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TransactionsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TransactionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,41 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { faExchangeAlt, faChartPie } from '@fortawesome/free-solid-svg-icons';
import { LoggerService } from '../../shared/services/logger.service';
import * as fromRTLReducer from '../../store/rtl.reducers';
@Component({
selector: 'rtl-transactions',
templateUrl: './transactions.component.html',
styleUrls: ['./transactions.component.scss']
})
export class TransactionsComponent implements OnInit, OnDestroy {
faExchangeAlt = faExchangeAlt;
faChartPie = faChartPie;
currencyUnits = [];
balances = [{title: 'Local Capacity', dataValue: -1, tooltip: 'Amount you can send'}, {title: 'Remote Capacity', dataValue: -1, tooltip: 'Amount you can receive'}];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>) {}
ngOnInit() {
this.store.select('lnd')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((rtlStore) => {
this.currencyUnits = rtlStore.nodeSettings.currencyUnits;
this.balances = [{title: 'Local Capacity', dataValue: rtlStore.totalLocalBalance, tooltip: 'Amount you can send'}, {title: 'Remote Capacity', dataValue: rtlStore.totalRemoteBalance, tooltip: 'Amount you can receive'}];
this.logger.info(rtlStore);
});
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -1,19 +1,32 @@
<div fxLayout="row" class="padding-gap page-title-container">
<div fxLayout="row" class="padding-gap-x page-title-container">
<fa-icon [icon]="faTools" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Application Settings</span>
</div>
<div fxLayout="column" class="padding-gap-x settings-container">
<mat-card>
<mat-card-content fxLayout="column">
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="space-between center"
fxLayoutAlign="center space-between">
<div fxFlex="30" *ngIf="selNode.lnImplementation !== 'CLT'">
<h4>Currency Unit</h4>
<div fxLayoutAlign="start center">
<span class="slider-text">{{smallerCurrencyUnit}}</span>
<mat-slide-toggle color="primary" [checked]="selNode?.settings?.satsToBTC"
(change)="toggleSettings('satsToBTC')" labelPosition="before"></mat-slide-toggle>
<span class="slider-text">{{currencyUnit}}</span>
<mat-card-content fxLayout="column" class="card-content-gap">
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign.gt-sm="space-between center" fxLayoutAlign="center space-between">
<div fxLayout="row" fxFlex="100" fxLayoutAlign="space-between center">
<div fxFlex="50">
<div fxFlex="60">
<h4>Currency Unit{{selNode.settings.currencyUnit}}</h4>
<mat-select [(ngModel)]="selNode.settings.currencyUnit" placeholder="Currency Unit" (selectionChange)="onCurrencyChange($event)" tabindex="1" required name="currencyUnit">
<mat-option *ngFor="let currencyUnit of currencyUnits" [value]="currencyUnit.id">
{{currencyUnit.name}}
</mat-option>
</mat-select>
</div>
</div>
<div fxFlex="50" *ngIf="selNode.lnImplementation !== 'CLT'">
<div fxFlex="60">
<h4>BTC</h4>
<div fxLayoutAlign="start center">
<span class="slider-text">{{smallerCurrencyUnit}}</span>
<mat-slide-toggle color="primary" [checked]="selNode?.settings?.satsToBTC"
(change)="toggleSettings('satsToBTC')" labelPosition="before"></mat-slide-toggle>
<span class="slider-text">{{currencyUnit}}</span>
</div>
</div>
</div>
</div>
</div>

@ -5,6 +5,7 @@ import { Store } from '@ngrx/store';
import { faTools } from '@fortawesome/free-solid-svg-icons';
import { CURRENCY_UNITS } from '../../../../environments/environment';
import { LightningNode, Settings, RTLConfiguration, GetInfoRoot } from '../../models/RTLconfig';
import { LoggerService } from '../../services/logger.service';
import { CommonService } from '../../services/common.service';
@ -21,6 +22,7 @@ export class AppSettingsComponent implements OnInit, OnDestroy {
public faTools = faTools;
public selNode: LightningNode;
public information: GetInfoRoot = {};
public currencyUnits = [{id: 'USD', name: 'United States Dollar'}, {id: 'GBP', name: 'Pound'}, {id: 'INR', name: 'Indian Rupee'}];
public menus = [{id: 'vertical', name: 'Vertical'}, {id: 'horizontal', name: 'Horizontal'}];
public menuTypes = [{id: 'regular', name: 'Regular'}, {id: 'compact', name: 'Compact'}, {id: 'mini', name: 'Mini'}];
public themeModes = [{id: 'day', name: 'Day'}, {id: 'night', name: 'Night'}];
@ -67,19 +69,24 @@ export class AppSettingsComponent implements OnInit, OnDestroy {
});
}
public chooseMenuType() {
onCurrencyChange(event: any) {
console.warn(event);
this.selNode.settings.currencyUnit = event.value;
}
chooseMenuType() {
this.selNode.settings.menuType = this.selectedMenuType.id;
this.commonService.changeContainerWidth('menuType');
}
public chooseFontSize() {
chooseFontSize() {
this.selNode.settings.fontSize = (this.fontSizes.filter(fontSize => fontSize.id === this.selectedFontSize.id)[0]).class;
}
toggleSettings(toggleField: string, event?: any) {
if (toggleField === 'satsToBTC') {
this.store.dispatch(new RTLActions.SetChildNodeSettings({channelBackupPath: this.selNode.settings.channelBackupPath, satsToBTC: this.selNode.settings.satsToBTC}));
this.store.dispatch(new RTLActions.SetChildNodeSettingsCL({channelBackupPath: this.selNode.settings.channelBackupPath, satsToBTC: this.selNode.settings.satsToBTC}));
this.store.dispatch(new RTLActions.SetChildNodeSettings({channelBackupPath: this.selNode.settings.channelBackupPath, satsToBTC: this.selNode.settings.satsToBTC, currencyUnits: [...CURRENCY_UNITS, this.selNode.settings.currencyUnit]}));
this.store.dispatch(new RTLActions.SetChildNodeSettingsCL({channelBackupPath: this.selNode.settings.channelBackupPath, satsToBTC: this.selNode.settings.satsToBTC, currencyUnits: [...CURRENCY_UNITS, this.selNode.settings.currencyUnit]}));
}
if(toggleField === 'menu') {
this.selNode.settings.flgSidenavOpened = (!event.checked) ? false : true;

@ -0,0 +1,12 @@
<mat-tab-group>
<mat-tab *ngFor="let currencyUnit of currencyUnits" [label]="currencyUnit">
<div fxLayout="row" fxFlex="100">
<div fxLayout="column" *ngFor="let value of values" [matTooltip]="value.tooltip" [matTooltipPosition]="'below'" class="cc-data-block">
<div class="cc-data-title">{{value.title}}</div>
<span class="cc-data-value" *ngIf="currencyUnit === CurrencyUnitEnum.SATS">{{value.dataValue | number}}</span>
<span class="cc-data-value" *ngIf="currencyUnit === CurrencyUnitEnum.BTC">{{value.dataValue | unitconvert:0.00000001 | number:'1.6-6'}}</span>
<span class="cc-data-value" *ngIf="currencyUnit !== CurrencyUnitEnum.SATS && currencyUnit !== CurrencyUnitEnum.BTC">{{value.dataValue | unitconvert:(unitConversionValue * 0.00000001) | number:'1.2-2'}}</span>
</div>
</div>
</mat-tab>
</mat-tab-group>

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CurrencyUnitConverterComponent } from './currency-unit-converter.component';
describe('CurrencyUnitConverterComponent', () => {
let component: CurrencyUnitConverterComponent;
let fixture: ComponentFixture<CurrencyUnitConverterComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CurrencyUnitConverterComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CurrencyUnitConverterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

@ -0,0 +1,49 @@
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { takeUntil, take } from 'rxjs/operators';
import { Store } from '@ngrx/store';
import { LoggerService } from '../../services/logger.service';
import { CurrencyUnit } from '../../models/enums';
import * as fromRTLReducer from '../../../store/rtl.reducers';
@Component({
selector: 'rtl-currency-unit-converter',
templateUrl: './currency-unit-converter.component.html',
styleUrls: ['./currency-unit-converter.component.scss']
})
export class CurrencyUnitConverterComponent implements OnInit, OnDestroy {
@Input() values = [];
currencyUnits = [];
CurrencyUnitEnum = CurrencyUnit;
unitConversionValue = 0;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<fromRTLReducer.RTLState>, private httpClient: HttpClient) {}
ngOnInit() {
this.store.select('lnd')
.pipe(take(2))
.subscribe((rtlStore) => {
this.currencyUnits = rtlStore.nodeSettings.currencyUnits;
this.logger.info(rtlStore);
if(this.currencyUnits[2]) {
this.httpClient.get('https://blockchain.info/ticker')
.pipe(takeUntil(this.unSubs[0]))
.subscribe((data: any) => {
this.unitConversionValue = data[this.currencyUnits[2]].last;
});
}
});
}
ngOnDestroy() {
this.unSubs.forEach(completeSub => {
completeSub.next();
completeSub.complete();
});
}
}

@ -1,11 +1,11 @@
<div fxLayout="row" class="padding-gap page-title">
<fa-icon [icon]="faUnlockAlt" class="mr-1"></fa-icon>
<span>Signin to RTL</span>
<div fxLayout="row" class="padding-gap-x page-title-container">
<fa-icon [icon]="faUnlockAlt" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Signin to RTL</span>
</div>
<div fxLayout="column">
<div class="padding-gap">
<mat-card>
<mat-card-content>
<mat-card-content class="card-content-gap">
<form (ngSubmit)="onSignin()" #signinForm="ngForm" fxLayoutAlign="start center">
<mat-form-field fxFlex="50" fxLayoutAlign="start">
<input matInput placeholder="Password" type="password" id="password" name="password" [(ngModel)]="password"

@ -1,10 +1,5 @@
import { GetInfoChain } from './lndModels';
export enum AuthenticateWith {
TOKEN = 'TOKEN',
PASSWORD = 'PASSWORD'
}
export class SSO {
constructor(
public rtlSSO: number,
@ -25,7 +20,8 @@ export class Settings {
public bitcoindConfigPath?: string,
public enableLogging?: boolean,
public lnServerUrl?: string,
public channelBackupPath?: string
public channelBackupPath?: string,
public currencyUnit?: string
) { }
}
@ -69,4 +65,5 @@ export interface GetInfoRoot {
export interface SelNodeChild {
channelBackupPath?: string;
satsToBTC?: boolean;
currencyUnits?: string[];
}

@ -0,0 +1,9 @@
export enum AuthenticateWith {
TOKEN = 'TOKEN',
PASSWORD = 'PASSWORD'
}
export enum CurrencyUnit {
SATS = 'SATS',
BTC = 'BTC'
}

@ -6,7 +6,7 @@ export const MENU_DATA: MenuRootNode = {
{id: 2, parentId: 0, name: 'On-chain', iconType: 'FA', icon: faLink, link: '/lnd/transsendreceive'},
{id: 3, parentId: 0, name: 'Lightning', iconType: 'FA', icon: faBolt, link: '/lnd/chnlmanage', children: [
{id: 31, parentId: 3, name: 'Peers/Channels', iconType: 'FA', icon: faUsers, link: '/lnd/chnlpending'},
{id: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/lnd/chnlmanage'},
{id: 32, parentId: 3, name: 'Transactions', iconType: 'FA', icon: faExchangeAlt, link: '/lnd/transactions'},
{id: 33, parentId: 3, name: 'Lookup', iconType: 'FA', icon: faSearch, link: '/lnd/chnlclosed'},
{id: 34, parentId: 3, name: 'Routing', iconType: 'FA', icon: faProjectDiagram, link: '/lnd/chnlbackup'}
]},

@ -10,3 +10,12 @@ export class RemoveLeadingZerosPipe implements PipeTransform {
}
}
@Pipe({ name: 'unitconvert' })
export class CurrencyUnitConvertPipe implements PipeTransform {
transform(value: string, multiplier?: number): string {
return (+value * multiplier).toString();
}
}

@ -6,10 +6,10 @@ import { HttpClientModule } from '@angular/common/http';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { FlexLayoutModule } from '@angular/flex-layout';
import {
MatButtonModule, MatButtonToggleModule, MatCardModule, MatCheckboxModule, MatDialogModule, MatExpansionModule, MatGridListModule, MatDatepickerModule,
MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatProgressBarModule, MatProgressSpinnerModule, MatRadioModule, MatTreeModule, MatNativeDateModule,
MatSelectModule, MatSidenavModule, MatSlideToggleModule, MatSortModule, MatTableModule, MatToolbarModule, MatTooltipModule, MAT_DIALOG_DEFAULT_OPTIONS, MatBadgeModule,
MatPaginatorModule, MatStepperModule, MatSliderModule
MatButtonModule, MatButtonToggleModule, MatCardModule, MatCheckboxModule, MatDialogModule, MatExpansionModule, MatGridListModule, MatDatepickerModule,
MatIconModule, MatInputModule, MatListModule, MatMenuModule, MatProgressBarModule, MatProgressSpinnerModule, MatRadioModule, MatTreeModule, MatNativeDateModule,
MatSelectModule, MatSidenavModule, MatSlideToggleModule, MatSortModule, MatTableModule, MatToolbarModule, MatTooltipModule, MAT_DIALOG_DEFAULT_OPTIONS, MatBadgeModule,
MatPaginatorModule, MatStepperModule, MatSliderModule, MatTabsModule
} from '@angular/material';
import { QRCodeModule } from 'angularx-qrcode';
@ -27,123 +27,130 @@ import { TopMenuComponent } from './components/navigation/top-menu/top-menu.comp
import { HorizontalNavigationComponent } from './components/navigation/horizontal-navigation/horizontal-navigation.component';
import { ServerConfigComponent } from './components/server-config/server-config.component';
import { ErrorComponent } from './components/error/error.component';
import { CurrencyUnitConverterComponent } from './components/currency-unit-converter/currency-unit-converter.component';
import { ClipboardDirective } from './directive/clipboard.directive';
import { RemoveLeadingZerosPipe } from './pipes/remove-leading-zero.pipe';
import { RemoveLeadingZerosPipe, CurrencyUnitConvertPipe } from './pipes/app.pipe';
import { CommonService } from './services/common.service';
@NgModule({
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
FontAwesomeModule,
FlexLayoutModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatDialogModule,
MatExpansionModule,
MatGridListModule,
MatDatepickerModule,
MatNativeDateModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatTreeModule,
MatSelectModule,
MatSidenavModule,
MatSlideToggleModule,
MatSortModule,
MatTableModule,
MatToolbarModule,
MatTooltipModule,
MatBadgeModule,
MatPaginatorModule,
MatStepperModule,
MatSliderModule,
QRCodeModule,
NgxChartsModule,
RouterModule,
HttpClientModule
],
exports: [
FormsModule,
ReactiveFormsModule,
FontAwesomeModule,
FlexLayoutModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatDialogModule,
MatExpansionModule,
MatGridListModule,
MatDatepickerModule,
MatNativeDateModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatTreeModule,
MatSelectModule,
MatSidenavModule,
MatSlideToggleModule,
MatSortModule,
MatTableModule,
MatToolbarModule,
MatTooltipModule,
MatBadgeModule,
MatPaginatorModule,
MatStepperModule,
MatSliderModule,
AppSettingsComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
SpinnerDialogComponent,
NotFoundComponent,
SideNavigationComponent,
TopMenuComponent,
HorizontalNavigationComponent,
SigninComponent,
HelpComponent,
ServerConfigComponent,
ClipboardDirective,
QRCodeModule,
NgxChartsModule,
RemoveLeadingZerosPipe
],
declarations: [
AppSettingsComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
SpinnerDialogComponent,
NotFoundComponent,
SideNavigationComponent,
TopMenuComponent,
HorizontalNavigationComponent,
SigninComponent,
HelpComponent,
ServerConfigComponent,
ClipboardDirective,
ErrorComponent,
RemoveLeadingZerosPipe
],
entryComponents: [
AlertMessageComponent,
SpinnerDialogComponent,
ConfirmationMessageComponent
],
providers: [
{ provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: true, autoFocus: true, disableClose: true, role: 'dialog', width: '700px' } },
CommonService
]
imports: [
CommonModule,
FormsModule,
ReactiveFormsModule,
FontAwesomeModule,
FlexLayoutModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatDialogModule,
MatExpansionModule,
MatGridListModule,
MatDatepickerModule,
MatNativeDateModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatTreeModule,
MatSelectModule,
MatSidenavModule,
MatSlideToggleModule,
MatSortModule,
MatTableModule,
MatToolbarModule,
MatTooltipModule,
MatBadgeModule,
MatPaginatorModule,
MatStepperModule,
MatSliderModule,
MatTabsModule,
QRCodeModule,
NgxChartsModule,
RouterModule,
HttpClientModule
],
exports: [
FormsModule,
ReactiveFormsModule,
FontAwesomeModule,
FlexLayoutModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatDialogModule,
MatExpansionModule,
MatGridListModule,
MatDatepickerModule,
MatNativeDateModule,
MatIconModule,
MatInputModule,
MatListModule,
MatMenuModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatTreeModule,
MatSelectModule,
MatSidenavModule,
MatSlideToggleModule,
MatSortModule,
MatTableModule,
MatToolbarModule,
MatTooltipModule,
MatBadgeModule,
MatPaginatorModule,
MatStepperModule,
MatSliderModule,
MatTabsModule,
AppSettingsComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
SpinnerDialogComponent,
NotFoundComponent,
SideNavigationComponent,
TopMenuComponent,
HorizontalNavigationComponent,
SigninComponent,
HelpComponent,
ServerConfigComponent,
CurrencyUnitConverterComponent,
ClipboardDirective,
QRCodeModule,
NgxChartsModule,
RemoveLeadingZerosPipe,
CurrencyUnitConvertPipe
],
declarations: [
AppSettingsComponent,
AlertMessageComponent,
ConfirmationMessageComponent,
SpinnerDialogComponent,
NotFoundComponent,
SideNavigationComponent,
TopMenuComponent,
HorizontalNavigationComponent,
SigninComponent,
HelpComponent,
ServerConfigComponent,
CurrencyUnitConverterComponent,
ErrorComponent,
ClipboardDirective,
RemoveLeadingZerosPipe,
CurrencyUnitConvertPipe
],
entryComponents: [
AlertMessageComponent,
SpinnerDialogComponent,
ConfirmationMessageComponent
],
providers: [
{ provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { hasBackdrop: true, autoFocus: true, disableClose: true, role: 'dialog', width: '700px' } },
CommonService
]
})
export class SharedModule { }

@ -2,14 +2,16 @@
@mixin change-theme($theme, $alternate-theme) {
$primary: map-get($theme, primary);
$primary-lighter: mat-color(mat-palette($primary, lighter));
$primary-darker: mat-color(mat-palette($primary, darker));
$primary-node-toolbar : mat-color(mat-palette($primary, A700));
$primary-color: mat-color($primary);
$primary-lighter: mat-color($primary, lighter);
$primary-darker: mat-color($primary, darker);
$accent: map-get($theme, accent);
$accent-color: mat-color(mat-palette($accent));
$accent-color: mat-color($accent);
$warn: map-get($theme, warn);
$foreground: map-get($theme, foreground);
$foreground-color: mat-color($foreground, text);
$foreground-color: mat-color($foreground);
$foreground-text: mat-color($foreground, text);
$foreground-divider: mat-color($foreground, divider);
$background: map-get($theme, background);
$alternate-primary: map-get($alternate-theme, primary);
@ -199,7 +201,7 @@
}
.foreground.mat-progress-spinner circle, .foreground.mat-spinner circle {
stroke: mat-color($foreground, text);
stroke: $foreground-text;
}
.mat-toolbar-row, .mat-toolbar-single-row {
@ -207,45 +209,45 @@
}
.lnd-info{
border-bottom: 1px solid mat-color($foreground, divider);
border-bottom: 1px solid $foreground-divider;
}
a {
color: mat-color($primary);
a, .cc-data-block .cc-data-title {
color: $primary-color;
}
.active-link, .active-link .fa-icon-small {
color: mat-color($primary);
color: $primary-color;
font-weight: 500;
cursor: pointer;
fill: mat-color($primary);
fill: $primary-color;
}
.mat-tree-node:hover, .mat-nested-tree-node-parent:hover {
color: mat-color($primary);
color: $primary-color;
cursor: pointer;
background: rgba(0, 0, 0, 0.04);
& .ng-fa-icon, & .mat-icon {
color: mat-color($primary);
color: $primary-color;
}
& .sidenav-img svg {
fill: mat-color($primary);
fill: $primary-color;
}
}
.mat-tree-node .sidenav-img, .mat-nested-tree-node .sidenav-img, .mat-nested-tree-node-parent .sidenav-img,
.page-title-container .page-title-img, .horizontal-button .sidenav-img svg, svg.top-icon-small {
fill: $foreground-color;
fill: $foreground-text;
}
.h-active-link {
border-bottom: 2px solid mat-color($accent);
border-bottom: 2px solid $accent-color;
}
.ngx-charts {
fill: mat-color($foreground, text);
fill: $foreground-text;
.bar {
fill: mat-color($primary) !important;
fill: $primary-color !important;
cursor: default;
}
}
@ -264,27 +266,27 @@
.genseed-message {
width:10%;
color: mat-color($accent);
color: $accent-color;
}
.insecure-message {
width:100%;
color: mat-color($accent);
color: $accent-color;
}
.page-title-container {
color: mat-color($foreground);
color: $foreground-color;
}
.material-icons.primary { color: mat-color($primary); }
.material-icons.primary { color: $primary-color; }
.material-icons.accent { color: mat-color($accent); }
.material-icons.accent { color: $accent-color; }
.validation-error-message {
position: relative;
margin-top: 0.5rem;
width:100%;
color: mat-color($accent);
color: $accent-color;
}
.mat-vertical-content {
@ -306,19 +308,22 @@
height: $toolbar-height;
border-radius: 0;
&:hover {
background: mat-color($primary, darker);
color: mat-color($accent);
background: $primary-darker;
color: $accent-color;
}
}
.horizontal-button-show {
color: mat-color($accent);
background: mat-color($primary, lighter);
color: $accent-color;
background: $primary-lighter;
border-radius: 12rem;
&:hover {
background: mat-color($accent);
color: mat-color($primary, darker);
background: $accent-color;
color: $primary-darker;
}
}
.mat-tab-label.mat-tab-label-active {
color: $primary-darker;
}
}

@ -269,11 +269,15 @@ body {
}
.mat-card {
padding: 1.2rem 2.4rem !important;
padding: 0 !important;
overflow: hidden;
border-radius: 2px !important;
}
.mat-tab-body-wrapper, .card-content-gap {
padding: 1.2rem 2.4rem !important;
}
.mat-card-actions{
display: block;
margin-bottom: 1.6rem;
@ -376,6 +380,10 @@ body {
margin-bottom: 1.6rem !important;
}
.mb-4 {
margin-bottom: 3.2rem !important;
}
.ml-2 {
margin-left: 1.6rem !important;
}
@ -812,4 +820,20 @@ tr.mat-row:hover {
.mat-select.multi-node-select {
width: 87%;
}
.page-title-container {
margin-bottom: 1.2rem;
}
.cc-data-block {
margin-right: 3.2rem;
& .cc-data-title {
font-size: 80%;
font-weight: 500;
}
& .cc-data-value {
font-size: 120%;
color: rgba(0, 0, 0, 0.6);
}
}

@ -8,10 +8,11 @@ import { map, mergeMap, catchError, take, withLatestFrom } from 'rxjs/operators'
import { MatDialog } from '@angular/material';
import { environment, API_URL } from '../../environments/environment';
import { environment, API_URL, CURRENCY_UNITS } from '../../environments/environment';
import { LoggerService } from '../shared/services/logger.service';
import { SessionService } from '../shared/services/session.service';
import { Settings, RTLConfiguration, AuthenticateWith } from '../shared/models/RTLconfig';
import { Settings, RTLConfiguration } from '../shared/models/RTLconfig';
import { AuthenticateWith } from '../shared/models/enums';
import { SpinnerDialogComponent } from '../shared/components/spinner-dialog/spinner-dialog.component';
import { AlertMessageComponent } from '../shared/components/alert-message/alert-message.component';
@ -270,7 +271,7 @@ export class RTLEffects implements OnDestroy {
initializeNode(node: any, isInitialSetup: boolean) {
const landingPage = isInitialSetup ? '' : 'HOME';
let selNode = { channelBackupPath: node.settings.channelBackupPath, satsToBTC: node.settings.satsToBTC };
let selNode = { channelBackupPath: node.settings.channelBackupPath, satsToBTC: node.settings.satsToBTC, currencyUnits: [...CURRENCY_UNITS, node.settings.currencyUnit] };
this.store.dispatch(new RTLActions.ResetRootStore(node));
this.store.dispatch(new RTLActions.ResetLNDStore(selNode));
this.store.dispatch(new RTLActions.ResetCLStore(selNode));

@ -10,10 +10,10 @@ export interface RootState {
effectErrorsRoot: ErrorPayload[];
selNode: LightningNode;
appConfig: RTLConfiguration;
nodeData: GetInfoRoot
nodeData: GetInfoRoot;
}
const initNodeSettings = { flgSidenavOpened: true, flgSidenavPinned: true, menu: 'vertical', menuType: 'regular', fontSize: 'regular-font', themeMode: 'night', themeColor: 'blue', satsToBTC: false, channelBackupPath: '' };
const initNodeSettings = { flgSidenavOpened: true, flgSidenavPinned: true, menu: 'vertical', menuType: 'regular', fontSize: 'regular-font', themeMode: 'night', themeColor: 'blue', satsToBTC: false, channelBackupPath: '', currencyUnit: 'USD' };
const initNodeAuthentication = { nodeAuthType: 'CUSTOM', configPath: '', bitcoindConfigPath: '' };
const initRootState: RootState = {

@ -1,5 +1,6 @@
import { VERSION } from './version';
export const CURRENCY_UNITS = [ 'SATS', 'BTC' ];
export const API_URL = './api';
export const environment = {

@ -1,5 +1,7 @@
import { VERSION } from './version';
export const CURRENCY_UNITS = [ 'SATS', 'BTC' ];
export const API_URL = 'http://localhost:3000/rtl/api';
export const environment = {

Loading…
Cancel
Save