Commit 6f5dee1d authored by Juan Nogueira's avatar Juan Nogueira
Browse files

Squashed 'web-blockchain-client/' changes from 8c8e88d..e11b133

e11b133 Web interface
f918e38 Web interface WIP
6e9f5a1 Web interface WIP
41c6372 Web interface WIP
5b38fe1 WIP
c5a68d2 WIP

git-subtree-dir: web-blockchain-client
git-subtree-split: e11b1335303dc1e75e1da2559c5cd001cbd01e26
parent 0b6b494f
......@@ -8,7 +8,7 @@
/bazel-out
# dependencies
/node_modules
node_modules
# profiling files
chrome-profiler-events*.json
......
......@@ -66,7 +66,8 @@
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "blockchain-client:build"
"browserTarget": "blockchain-client:build",
"proxyConfig": "proxy.conf.json"
},
"configurations": {
"production": {
......
{
"/api": {
"target": "http://localhost:3010",
"secure": false,
"pathRewrite": {
"^/api": ""
}
}
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { RequestsListComponent } from './components/requests-list/requests-list.component';
import { NewRequestComponent } from './components/new-request/new-request.component';
import { RequestResponseComponent } from './components/request-response/request-response.component';
const routes: Routes = [{
path: 'lista-pedidos',
......@@ -9,6 +10,12 @@ const routes: Routes = [{
}, {
path: 'nuevo-pedido',
component: NewRequestComponent
}, {
path: 'respuesta-pedido',
component: RequestResponseComponent
}, {
path: 'respuesta-pedido/:requestID',
component: RequestResponseComponent
}, {
path: '',
redirectTo: '/lista-pedidos',
......
......@@ -2,6 +2,8 @@
<a class="header-link" routerLink="lista-pedidos">LISTA DE PEDIDOS</a>
<div class="header-separator">|</div>
<a class="header-link" routerLink="nuevo-pedido">REGISTRAR NUEVO PEDIDO</a>
<div class="header-separator">|</div>
<a class="header-link" routerLink="respuesta-pedido">REGISTRAR RESPUESTA DE PEDIDO</a>
</header>
<div class="centered-container">
......
......@@ -15,11 +15,11 @@ header {
@at-root
.header-separator {
margin: 0 20px;
margin: 0 25px;
}
}
.centered-container {
max-width: 1000px;
margin: 0 auto;
max-width: 800px;
margin: 45px auto 0;
}
\ No newline at end of file
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { CommonModule } from "@angular/common"
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { RequestsListComponent } from './components/requests-list/requests-list.component';
import { NewRequestComponent } from './components/new-request/new-request.component';
import { RequestComponent } from './components/requests-list/request/request.component';
import { RequestResponseComponent } from './components/request-response/request-response.component';
@NgModule({
declarations: [
AppComponent,
RequestsListComponent,
NewRequestComponent
NewRequestComponent,
RequestComponent,
RequestResponseComponent
],
imports: [
BrowserModule,
AppRoutingModule
AppRoutingModule,
CommonModule,
FormsModule
],
providers: [],
bootstrap: [AppComponent]
......
<p>new-request works!</p>
<h1>Registrar pedido</h1>
<div class="dv-field">
<label>Request ID</label>
<input [(ngModel)]="requestID" />
</div>
<div class="dv-field">
<label>Sender institution</label>
<input [(ngModel)]="senderInstitution" />
</div>
<div class="dv-field">
<label>Receiver institution</label>
<input [(ngModel)]="receiverInstitution" />
</div>
<div class="dv-field">
<label>Request type</label>
<input [(ngModel)]="type" />
</div>
<div class="dv-field">
<label>Expected reply date</label>
<input [(ngModel)]="date" />
</div>
<div class="dv-field">
<label>Package hash</label>
<input [(ngModel)]="hash" />
</div>
<button [hidden]="confirmando" (click)="registerBtnClick()">Registrar pedido</button>
<div [hidden]="!confirmando" class="dv-loader">
<div class="loader"></div>
Confirmando transaccion...
</div>
\ No newline at end of file
@keyframes spin {
from {
transform: rotate(0deg);
} to {
transform: rotate(360deg);
}
}
h1 {
margin-bottom: 27px;
}
.dv-field {
margin: 15px 0;
label {
display: inline-block;
width: 150px;
font-size: 14px;
}
input {
width: 220px;
padding: 5px;
font-size: 14px;
}
}
button {
margin-top: 15px;
padding: 7px 20px;
}
.dv-loader {
display: flex;
align-items: center;
&[hidden] {
display: none;
}
.loader {
animation: spin .8s infinite linear;
width: 20px;
height: 20px;
margin-right: 10px;
border: 7px solid transparent;
border-top: 7px solid #1976d2;
border-radius: 50%;
}
}
\ No newline at end of file
import { Component, OnInit } from '@angular/core';
const axios = require('axios');
@Component({
selector: 'app-new-request',
......@@ -6,10 +7,43 @@ import { Component, OnInit } from '@angular/core';
styleUrls: ['./new-request.component.scss']
})
export class NewRequestComponent implements OnInit {
confirmando = false;
requestID;
senderInstitution;
receiverInstitution;
type;
date;
hash;
constructor() { }
ngOnInit(): void {
}
ngOnInit(): void { }
registerBtnClick() {
const data = {
requestID: this.requestID,
senderInstitution: this.senderInstitution,
receiverInstitution: this.receiverInstitution,
type: this.type,
date: this.date,
hash: this.hash
};
this.confirmando = true;
axios.post('/api/new-request', data)
.then(resp => {
this.confirmando = false;
if (resp.data.success) {
alert('El pedido se registro correctamente');
} else {
alert('Ocurrio un error al intentar registrar el pedido');
}
})
.catch(() => {
this.confirmando = false;
alert('Ocurrio un error al conectar con el servidor');
});
}
}
<h1>Registrar respuesta de pedido</h1>
<div class="dv-field">
<label>Request ID</label>
<input [(ngModel)]="requestID" />
</div>
<div class="dv-field">
<label>Hash paquete</label>
<input [(ngModel)]="responsePackageHash" />
</div>
<button [hidden]="confirmando" (click)="registerBtnClick()">Registrar respuesta</button>
<div [hidden]="!confirmando" class="dv-loader">
<div class="loader"></div>
Confirmando transaccion...
</div>
\ No newline at end of file
@keyframes spin {
from {
transform: rotate(0deg);
} to {
transform: rotate(360deg);
}
}
h1 {
margin-bottom: 27px;
}
.dv-field {
margin: 15px 0;
label {
display: inline-block;
width: 150px;
font-size: 14px;
}
input {
width: 220px;
padding: 5px;
font-size: 14px;
}
}
button {
margin-top: 15px;
padding: 7px 20px;
}
.dv-loader {
display: flex;
align-items: center;
&[hidden] {
display: none;
}
.loader {
animation: spin .8s infinite linear;
width: 20px;
height: 20px;
margin-right: 10px;
border: 7px solid transparent;
border-top: 7px solid #1976d2;
border-radius: 50%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RequestResponseComponent } from './request-response.component';
describe('RequestResponseComponent', () => {
let component: RequestResponseComponent;
let fixture: ComponentFixture<RequestResponseComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RequestResponseComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RequestResponseComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
const axios = require('axios');
@Component({
selector: 'app-request-response',
templateUrl: './request-response.component.html',
styleUrls: ['./request-response.component.scss']
})
export class RequestResponseComponent implements OnInit {
confirmando = false;
requestID = '';
responsePackageHash: string;
constructor(private route: ActivatedRoute) { }
ngOnInit(): void {
const routeParams = this.route.snapshot.paramMap;
this.requestID = routeParams.get('requestID');
}
registerBtnClick() {
this.confirmando = true;
axios.post('/api/request-response', {
requestID: this.requestID,
responsePackageHash: this.responsePackageHash
})
.then(resp => {
this.confirmando = false;
if (resp.data.success) {
alert('La respuesta del pedido se registro correctamente');
} else {
alert('Ocurrio un error al intentar registrar la respuesta del pedido');
}
})
.catch(() => {
this.confirmando = false;
alert('Ocurrio un error al conectar con el servidor');
});
}
}
[{
"id": "j23NNs959APSdf",
"senderInstitution": "UY",
"receiverInstitution": "BR",
"requestDate": "21/02/2021 08:22",
"expectedReplyDate": "21/03/2021",
"responseDate": null,
"type": "WorkedPeriods",
"requestPackageHash": "feNSR4823sdl",
"responsePackageHash": null,
"replied": false
}, {
"id": "FEdsam32Ksffw9",
"senderInstitution": "CO",
"receiverInstitution": "MX",
"requestDate": "07/12/2020 18:52",
"expectedReplyDate": "15/01/2021",
"responseDate": "22/12/2020 15:36",
"type": "WorkedPeriods",
"requestPackageHash": "feNSR4823sdl",
"responsePackageHash": "k49daNE2219fj",
"replied": true
}, {
"id": "d933KKaado0",
"senderInstitution": "AR",
"receiverInstitution": "CL",
"requestDate": "01/02/2021 12:04",
"expectedReplyDate": "01/03/2021",
"responseDate": null,
"type": "LifeStatus",
"requestPackageHash": "ne22ndwNSSks",
"responsePackageHash": null,
"replied": false
}]
\ No newline at end of file
<div class="wrapper" [ngClass]="{'replied': request.status=='replied', 'pending': request.status=='pending'}">
<div class="header">
<div class="sender-receiver">
<div class="role">DE</div>
<div class="country">{{request.senderInstitution}}</div>
</div>
<div class="arrow">></div>
<div class="sender-receiver">
<div class="role">A</div>
<div class="country">{{request.receiverInstitution}}</div>
</div>
</div>
<div class="body">
<div class="col">
<div class="col-header">PEDIDO</div>
<div class="fila"><b>ID:</b> {{request.requestID}}</div>
<div class="fila"><b>Fecha:</b> {{request.requestDate}}</div>
<div class="fila"><b>Tipo:</b> {{request.requestType}}</div>
<div class="fila"><b>Fecha esperada de respuesta:</b> {{request.expectedReplyDate}}</div>
<div class="fila"><b>Hash del paquete:</b> {{request.requestPackageHash}}</div>
</div>
<div class="col">
<div class="col-header">RESPUESTA</div>
<div *ngIf="request.status=='replied'">
<div class="fila"><b>Fecha:</b> {{request.responseDate}}</div>
<div class="fila"><b>Hash del paquete:</b> {{request.responsePackageHash}}</div>
</div>
<div class="btn-wrapper" *ngIf="request.status=='pending'">
<a class="registrar-resp" [routerLink]="['/respuesta-pedido/', request.requestID]">REGISTRAR RESPUESTA</a>
</div>
</div>
</div>
</div>
\ No newline at end of file
.wrapper {
position: relative;
display: block;
padding: 17px;
margin-top: 20px;
background: #FFF;
border: 2px solid #888;
border-radius: 2px;
&::before {
content: '';
display: block;
position: absolute;
top: -1px;
right: 0;
padding: 6px 12px;
color: #FFF;
font-weight: bold;
}
&.replied {
border-color: #3aff3a;
&::before {
content: 'RESPONDIDO';
background: #329932;
}
}
&.pending {
border-color: #F00;
&::before {
content: 'PENDIENTE';
background: #F00;
}
}
}
.header {
display: flex;
align-items: center;
justify-content: center;
.sender-receiver {
text-align: center;
.role {
height: 15px;
font-size: 11px;
}
.country {
font-size: 29px;
}
}
.arrow {
margin: 15px 12px 0;
font-size: 23px;
}
}
.body {
display: flex;
justify-content: space-between;
margin-top: 25px;
.col {
flex: 0 0 48%;
.col-header {
display: block;
margin-bottom: 18px;
text-align: center;
text-decoration: underline;
font-size: 14px;
}
.fila {
padding: 7px;
font-size: 13px;
&:nth-child(2n) {
background: #F4F4F4;
}
}
.btn-wrapper {
text-align: center;
}
.registrar-resp {
color: #1976d2;
}
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RequestComponent } from './request.component';
describe('RequestComponent', () => {
let component: RequestComponent;
let fixture: ComponentFixture<RequestComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RequestComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(RequestComponent);
component = fixture.componentInstance;