fix widget

This commit is contained in:
peter
2019-08-12 18:00:42 +02:00
parent 71fa02d6db
commit b5d7042aa4
11 changed files with 397 additions and 37 deletions
+47
View File
@@ -20,6 +20,14 @@
"tslib": "^1.9.0" "tslib": "^1.9.0"
} }
}, },
"@angular/forms": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.2.1.tgz",
"integrity": "sha512-KcB652QBup+VWKDZICtpznr0a+v82oG0BowWetfkMgZAQj655uEMkkEtCTnfWnft4MLYlRr9ZoxQXc575TcZmA==",
"requires": {
"tslib": "^1.9.0"
}
},
"@angular/platform-browser": { "@angular/platform-browser": {
"version": "8.2.1", "version": "8.2.1",
"resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.2.1.tgz", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.2.1.tgz",
@@ -248,6 +256,14 @@
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
"@clr/angular": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@clr/angular/-/angular-2.1.1.tgz",
"integrity": "sha512-poC81C0xlv4zOr1dGYnpiF3sQKuxOH0a0KD9V9yizu7qQRfcbt6fM1S1RQKh2BPAlMY2xX1jsYOpJEPjZ6MG+g==",
"requires": {
"tslib": "^1.9.0"
}
},
"@cnakazawa/watch": { "@cnakazawa/watch": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.3.tgz",
@@ -3857,6 +3873,32 @@
} }
} }
}, },
"frontblock": {
"version": "0.9.9",
"resolved": "https://registry.npmjs.org/frontblock/-/frontblock-0.9.9.tgz",
"integrity": "sha512-bGRbyNcvUsyIXoZj4VxBFog98WFi2crhaNb5XYGZJekrRvXGr5moqQV5I/ySSHKsu2gdg2BhmNdqxa+DzERu+Q==",
"requires": {
"@angular/common": "^8.2.1",
"@angular/core": "^8.2.1",
"@angular/router": "^8.2.1",
"@types/node": "^11.13.10",
"angular": "^1.7.8",
"bip39": "^3.0.2",
"bitcoinjs-lib": "^5.0.4",
"bsock": "^0.1.9",
"express": "^4.16.4",
"frontblock-generic": "^0.22.0",
"hdkey": "^1.1.1",
"key-file-storage": "^2.2.1",
"log4js": "^4.3.1",
"minimist": "^1.2.0",
"node-fetch": "^2.5.0",
"rollup": "^0.55.1",
"rxjs": "^6.5.2",
"rxjs-compat": "^6.5.2",
"uuid": "^3.3.2"
}
},
"frontblock-generic": { "frontblock-generic": {
"version": "0.22.0", "version": "0.22.0",
"resolved": "https://registry.npmjs.org/frontblock-generic/-/frontblock-generic-0.22.0.tgz", "resolved": "https://registry.npmjs.org/frontblock-generic/-/frontblock-generic-0.22.0.tgz",
@@ -8983,6 +9025,11 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-0.55.5.tgz", "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.55.5.tgz",
"integrity": "sha512-2hke9NOy332kxvnmMQOgl7DHm94zihNyYJNd8ZLWo4U0EjFvjUkeWa0+ge+70bTg+mY0xJ7NUsf5kIhDtrGrtA==" "integrity": "sha512-2hke9NOy332kxvnmMQOgl7DHm94zihNyYJNd8ZLWo4U0EjFvjUkeWa0+ge+70bTg+mY0xJ7NUsf5kIhDtrGrtA=="
}, },
"rollup-plugin-node-externals": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-node-externals/-/rollup-plugin-node-externals-2.0.0.tgz",
"integrity": "sha512-LGaPL1j8TxxVk/uZRdJ/rB58RlN/2kz7CXDWoVQdaRbFtkaBx9OWEgMI+mMJy/mbfBtn7E6fdDGo3zj7nRtirg=="
},
"rollup-plugin-node-resolve": { "rollup-plugin-node-resolve": {
"version": "3.4.0", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz", "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz",
+4
View File
@@ -22,8 +22,10 @@
"dependencies": { "dependencies": {
"@angular/common": "^8.2.1", "@angular/common": "^8.2.1",
"@angular/core": "^8.2.1", "@angular/core": "^8.2.1",
"@angular/forms": "^8.2.1",
"@angular/platform-browser": "^8.2.1", "@angular/platform-browser": "^8.2.1",
"@angular/router": "^8.2.1", "@angular/router": "^8.2.1",
"@clr/angular": "^2.1.1",
"@uirouter/angularjs": "^1.0.5", "@uirouter/angularjs": "^1.0.5",
"adm-zip": "^0.4.13", "adm-zip": "^0.4.13",
"angular": "^1.7.8", "angular": "^1.7.8",
@@ -33,6 +35,7 @@
"bsock": "^0.1.9", "bsock": "^0.1.9",
"easy-unzip": "^1.1.0", "easy-unzip": "^1.1.0",
"express": "^4.16.4", "express": "^4.16.4",
"frontblock": "^0.9.9",
"frontblock-generic": "latest", "frontblock-generic": "latest",
"hdkey": "^1.1.1", "hdkey": "^1.1.1",
"http": "0.0.0", "http": "0.0.0",
@@ -42,6 +45,7 @@
"minimist": "^1.2.0", "minimist": "^1.2.0",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"rollup": "^0.55.1", "rollup": "^0.55.1",
"rollup-plugin-node-externals": "^2.0.0",
"rxjs": "^6.5.2", "rxjs": "^6.5.2",
"rxjs-compat": "^6.5.2", "rxjs-compat": "^6.5.2",
"socket.io": "^2.2.0", "socket.io": "^2.2.0",
@@ -13,7 +13,7 @@ declare const fb
<div class="card-header"> <div class="card-header">
Consumptions Consumptions
</div> </div>
<clr-alert *ngFor="let entry of alerts" [clrAlertType]="entry.severity" (clrAlertClosedChange)="onClose()"> <clr-alert *ngFor="let entry of alerts" [clrAlertType]="entry.severity">
<clr-alert-item> <clr-alert-item>
<span class="alert-text"> <span class="alert-text">
{{entry.message}} {{entry.message}}
@@ -73,6 +73,9 @@ export class ApiclientConsumptionComponent implements OnInit {
async load(){ async load(){
this.loading = true this.loading = true
this.entries = await fb.ApiClient.getConsumptions() this.entries = await fb.ApiClient.getConsumptions()
if(this.entries.length === 0){
this.alerts.push({ severity: "warning", message: "0 results were returned"})
}
this.loading = false this.loading = false
this.actionName = "refresh" this.actionName = "refresh"
} }
@@ -14,7 +14,7 @@ declare const fb
Subscriptions Subscriptions
</div> </div>
<clr-alert *ngFor="let entry of alerts" [clrAlertType]="entry.severity" (clrAlertClosedChange)="onClose()"> <clr-alert *ngFor="let entry of alerts" [clrAlertType]="entry.severity">
<clr-alert-item> <clr-alert-item>
<span class="alert-text"> <span class="alert-text">
{{entry.message}} {{entry.message}}
@@ -70,6 +70,9 @@ export class ApiclientSubscriptionComponent implements OnInit {
async load(){ async load(){
this.loading = true this.loading = true
this.entries = await fb.ApiClient.getSubscriptions() this.entries = await fb.ApiClient.getSubscriptions()
if(this.entries.length === 0){
this.alerts.push({ severity: "warning", message: "0 results were returned"})
}
this.loading = false this.loading = false
this.actionName = "refresh" this.actionName = "refresh"
} }
+3
View File
@@ -1,5 +1,6 @@
import resolve from 'rollup-plugin-node-resolve'; import resolve from 'rollup-plugin-node-resolve';
import typescript from 'rollup-plugin-typescript2'; import typescript from 'rollup-plugin-typescript2';
import externals from 'rollup-plugin-node-externals'
export default { export default {
input: 'src/frontend/widget/main.ts', input: 'src/frontend/widget/main.ts',
@@ -20,6 +21,8 @@ export default {
}) })
], ],
external: [ external: [
"frontblock",
"frontblock-generic",
'plugins-core', 'plugins-core',
'@angular/core', '@angular/core',
'@angular/common', '@angular/common',
@@ -12,4 +12,4 @@ export class ANestedComponent implements OnInit {
ngOnInit() { } ngOnInit() { }
} }
@@ -0,0 +1,89 @@
import { Component, OnInit } from '@angular/core';
declare const fb
@Component({
selector: 'consumptions',
template: `
<div class="card">
<div class="card-header">
Consumptions
</div>
<clr-alert *ngFor="let entry of alerts" [clrAlertType]="entry.severity">
<clr-alert-item>
<span class="alert-text">
{{entry.message}}
</span>
</clr-alert-item>
</clr-alert>
<div *ngIf="loading" class="card-block">
<span class="spinner spinner-inline"></span>
</div>
<div *ngIf="entries.length !== 0 && !loading" class="card-block">
<div class="card-text">
<table class="table table-noborder">
<thead>
<tr>
<th class="left">UUID</th>
<th>Expiry</th>
<th>Creation</th>
<th class="left"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let line of entries" >
<td class="left">{{line.uid}}</td>
<td>{{line.expiry}}</td>
<td>{{line.created}}</td>
<td class="left"><button class="btn btn-link btn-sm" (click)="quit(line.uid)">Quit</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card-footer">
<button *ngIf="!loading" class="btn btn-sm btn-link" (click)="load()">{{actionName}}</button>
</div>
</div>
`
})
export class ApiclientConsumptionComponent implements OnInit {
loading:boolean = false
actionName:string = "load"
entries:any[] = [{
uid: "1231",
message: "",
result: "Success"
}]
alerts: {
severity: "danger" | "warning" | "success"
message: string
}[] = []
constructor() { }
ngOnInit() { }
async load(){
this.loading = true
this.entries = await fb.ApiClient.getConsumptions()
if(this.entries.length === 0){
this.alerts.push({ severity: "warning", message: "0 results were returned"})
}
this.loading = false
this.actionName = "refresh"
}
async quit(uid:string){
const r = await fb.ApiClient.quit(uid)
if(r.uid != null){
this.alerts.push({ severity: "success", message: "Quit consuming "+uid})
this.load()
}else{
this.alerts.push({ severity: "danger", message: "Error "+r.message})
}
}
}
@@ -0,0 +1,129 @@
import { Component, OnInit } from '@angular/core';
declare const fb
@Component({
selector: 'settings',
template: `
<div class="card">
<div class="card-header">
Settings
</div>
<div class="card-block">
<div class="card-text">
<form clrForm clrLayout="vertical">
<clr-input-container>
<label>testnet</label>
<clr-control-error>We need your first name for legal compliance</clr-control-error>
</clr-input-container>
<input type="checkbox" [(ngModel)]="testnet" (change)="updateTestnet($event)" name="testnetToggle" clrToggle />
<clr-input-container *ngIf="!testnet">
<label>API key</label>
<input clrInput type="text" name="apiKey" required />
<clr-control-error>We need your first name for legal compliance</clr-control-error>
</clr-input-container>
<clr-input-container *ngIf="advanced">
<label>API address</label>
<input type="text" [(ngModel)]="data.apiHost" (change)="updatePort($event)" clrInput name="apiHost" required />
<clr-control-error>This field is required!</clr-control-error>
</clr-input-container>
<clr-checkbox-wrapper *ngIf="advanced" >
<input [(ngModel)]="data.tls" type="checkbox" clrCheckbox value="tls" name="options" />
<label>Use TLS</label>
</clr-checkbox-wrapper>
<clr-input-container *ngIf="advanced">
<label>Port</label>
<input [(ngModel)]="data.apiPort" clrInput type="number" name="lastName" required />
<clr-control-error>Valid range 1024 - 65536
</clr-control-error>
</clr-input-container>
</form>
</div>
</div>
<div class="card-footer">
<button *ngIf="!saving" class="btn btn-success" (click)="save()">
<span>Save</span>
</button>
<button *ngIf="saving" class="btn btn-disabled" (click)="save()" disabled>
<span class="spinner spinner-inline"></span>
</button>
<button *ngIf="!advanced" class="btn btn-sm btn-link" (click)="setAdvanced()">Advanced</button>
</div>
</div>
`
})
export class ApiclientFormComponent implements OnInit {
testnet:boolean = true
saving:boolean = false
advanced:boolean = false
data = {
apiHost: "api.testnet.frontblock.me",
apiPort: 10001,
tls: false,
apiKey: ""
}
constructor() { }
ngOnInit() { }
setAdvanced(){ this.advanced = true }
checkData():boolean{
return (
typeof this.data.apiPort === "number" &&
typeof this.data.apiHost === "string" &&
typeof this.data.tls === "boolean" &&
typeof this.data.apiKey === "string"
)
}
updateTestnet(){
if(this.testnet){
this.data.apiHost = "api.testnet.frontblock.me"
this.data.apiPort = 10001
}else{
this.data.apiHost = "api.frontblock.me"
this.data.apiPort = 10000
}
}
updatePort(obj){
switch (this.data.apiHost) {
case "api.testnet.frontblock.me":
this.data.apiPort = 10001
break;
case "api.frontblock.me":
this.data.apiPort = 10000
break;
default:
console.warn("A non-standard api host was chosen: "+this.data.apiPort)
break;
}
console.log(this.data)
}
async save(){
this.saving = true;
if(typeof this.data.apiPort === "string")
this.data.apiPort = parseInt(this.data.apiPort)
if(this.checkData()){
const conf = await fb.ApiClient.setConfig(this.data)
console.log(conf)
}else{
//show error in gui
console.error("bad data :(")
}
this.saving = false
}
}
@@ -0,0 +1,86 @@
import { Component, OnInit } from '@angular/core';
declare const fb
@Component({
selector: 'subscriptions',
template: `
<div class="card">
<div class="card-header">
Subscriptions
</div>
<clr-alert *ngFor="let entry of alerts" [clrAlertType]="entry.severity">
<clr-alert-item>
<span class="alert-text">
{{entry.message}}
</span>
</clr-alert-item>
</clr-alert>
<div *ngIf="loading" class="card-block">
<span class="spinner spinner-inline"></span>
</div>
<div *ngIf="entries.length !== 0 && !loading" class="card-block">
<div class="card-text">
<table class="table table-noborder">
<thead>
<tr>
<th class="left">UUID</th>
<th>Expiry</th>
<th>Creation</th>
<th class="left"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let line of entries" >
<td class="left">{{line.uid}}</td>
<td>{{line.expiry}}</td>
<td>{{line.created}}</td>
<td class="left"><button class="btn btn-link btn-sm" (click)="quit(line.uid)">Quit</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="card-footer">
<button *ngIf="!loading" class="btn btn-sm btn-link" (click)="load()">{{actionName}}</button>
</div>
</div>
`
})
export class ApiclientSubscriptionComponent implements OnInit {
loading:boolean = false
actionName:string = "load"
entries:any[] = []
alerts: {
severity: "danger" | "warning" | "success"
message: string
}[] = []
constructor() { }
ngOnInit() { }
async load(){
this.loading = true
this.entries = await fb.ApiClient.getSubscriptions()
if(this.entries.length === 0){
this.alerts.push({ severity: "warning", message: "0 results were returned"})
}
this.loading = false
this.actionName = "refresh"
}
async quit(uid:string){
const r = await fb.ApiClient.unsubscribe(uid)
if(r.uid != null){
this.alerts.push({ severity: "success", message: "Stopped subscription "+uid})
this.load()
}else{
this.alerts.push({ severity: "danger", message: "Error "+r.message})
}
}
}
+13 -22
View File
@@ -1,29 +1,20 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
declare const fb
@Component({ @Component({
selector: 'PLUGINMANAGER', //!!!! selector: 'apiclient', //!!!!
template: ` template: `
<div class="clr-row"> <div class="clr-row">
<div class="clr-col-lg-5 clr-col-md-8 clr-col-12"> <div class="clr-col-lg-auto">
<div class="card"> <settings></settings>
<div class="card-header"> </div>
Plugin manager </div>
</div> <div class="clr-row">
<div class="card-block"> <div class="clr-col">
<div class="card-title"> <consumptions></consumptions>
Block </div>
</div> </div>
<div class="card-text"> <div class="clr-row">
${Object.keys(fb.PluginManager).join("<br>")} <div class="clr-col">
<button class="btn btn-success">Success</button> <subscriptions></subscriptions>
</div>
</div>
<div class="card-footer">
<button class="btn btn-sm btn-link">Footer Action 1</button>
<button class="btn btn-sm btn-link">Footer Action 2</button>
</div>
</div>
</div> </div>
</div> </div>
` `
+17 -12
View File
@@ -1,16 +1,25 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { PluginComponent } from './component'; import { PluginComponent } from './component';
import { ANestedComponent } from './a-nested.component';
import { RouterModule } from '@angular/router'; import { RouterModule } from '@angular/router';
import { FrontendPlugin, SidebarEntries } from 'frontblock-generic/Plugin'; import { ApiclientFormComponent } from './apiclient-settings-form.component';
import { ApiclientConsumptionComponent } from './apiclient-consumptions.component';
import { ApiclientSubscriptionComponent } from './apiclient-subscriptions.component';
import { FrontendPlugin, SidebarEntry } from 'frontblock-generic/Plugin';
import { ANestedComponent } from './a-nested.component';
@NgModule({ @NgModule({
imports: [CommonModule, RouterModule.forChild([{path: "debug", component: PluginComponent}])], imports: [
CommonModule,
RouterModule.forChild([{path: "pluginmanager", component: PluginComponent}]),
],
exports: [RouterModule], exports: [RouterModule],
declarations: [ declarations: [
PluginComponent, PluginComponent,
ANestedComponent // ANestedComponent,
ApiclientFormComponent,
ApiclientConsumptionComponent,
ApiclientSubscriptionComponent
], ],
entryComponents: [PluginComponent], entryComponents: [PluginComponent],
providers: [{ providers: [{
@@ -19,15 +28,11 @@ import { FrontendPlugin, SidebarEntries } from 'frontblock-generic/Plugin';
}] }]
}) })
export class PluginModule implements FrontendPlugin{ export class PluginModule implements FrontendPlugin{
getSidebarEntry(): SidebarEntries { getSidebarEntry(): SidebarEntry {
return { return {
icon: 'cog', icon: "wrench",
text: 'Plugin Manager', route: "pluginmanager",
parentRoute: 'pluginmanager', text: "Plugin manager",
links: [{
route: 'debug',
text: 'DEBUG'
}]
} }
} }
} }