Adjust visuals for small screens

This commit is contained in:
Rene Vergara 2021-11-11 09:18:38 -06:00
parent b66650d34d
commit 7145a437b4
20 changed files with 258 additions and 144 deletions

View file

@ -2,6 +2,7 @@ const express = require('express');
const app = express(); const app = express();
const bodyparser = require('body-parser'); const bodyparser = require('body-parser');
const cors = require('cors'); const cors = require('cors');
const crypto = require('crypto');
const postmodel = require('./models/post'); const postmodel = require('./models/post');
const usermodel = require('./models/user'); const usermodel = require('./models/user');
const ownermodel = require('./models/owner'); const ownermodel = require('./models/owner');
@ -12,6 +13,8 @@ const txmodel = require('./models/tx');
const mongoose = require('mongoose'); const mongoose = require('mongoose');
const stdrpc = require('stdrpc'); const stdrpc = require('stdrpc');
const CoinGecko = require('coingecko-api'); const CoinGecko = require('coingecko-api');
var URLSafeBase64 = require('urlsafe-base64');
var Buffer = require('buffer/').Buffer;
var db = require('./config/db'); var db = require('./config/db');
mongoose.connect('mongodb://'+db.user+':'+db.password+'@'+db.server+'/'+db.database).then(() => { mongoose.connect('mongodb://'+db.user+':'+db.password+'@'+db.server+'/'+db.database).then(() => {
@ -74,16 +77,24 @@ function hexToString(hexString) {
return str; return str;
} }
function sendPin(pin, address) {
//var memo = URLSafeBase64.encode(Buffer.from('ZGO pin: '.concat(pin)));
var memo = Buffer.from('ZGO pin: '.concat(pin)).toString('hex');
//console.log(typeof(memo));
var amounts = [
{
address: address,
amount: 0.00000001,
memo: memo
}
];
rpc.z_sendmany(fullnode.addr, amounts).catch((err) => {
console.log('Sendmany', err);
});
}
var blockInterval = setInterval( function() { var blockInterval = setInterval( function() {
console.log('Node periodic Zcash scan'); console.log('Node periodic Zcash scan');
//usermodel.find({}, function (err, docs) {
//if (err) {
//console.log(err);
//} else {
//console.log(session, blocktime);
//console.log(docs);
//}
//});
rpc.z_listreceivedbyaddress(fullnode.addr, 1).then(txs => { rpc.z_listreceivedbyaddress(fullnode.addr, 1).then(txs => {
var re = /.*ZGO::(.*)\sReply-To:\s(z\w+)/; var re = /.*ZGO::(.*)\sReply-To:\s(z\w+)/;
async.each (txs, function(txData, callback) { async.each (txs, function(txData, callback) {
@ -95,17 +106,31 @@ var blockInterval = setInterval( function() {
var address = match[2]; var address = match[2];
var session = match[1]; var session = match[1];
var blocktime = txData.blocktime; var blocktime = txData.blocktime;
var amount = txData.amount;
var expiration = blocktime;
//console.log(' ', session, blocktime); //console.log(' ', session, blocktime);
if (txData.confirmations >= 10 ) { if (txData.confirmations >= 10 ) {
usermodel.findOne({address: address, session: session, blocktime: blocktime}).then(function(doc){ usermodel.findOne({address: address, session: session, blocktime: blocktime}).then(function(doc){
if (doc != null) { if (doc != null) {
console.log('Found user'); console.log('Found user');
} else { } else {
console.log('User not found', session, blocktime); console.log('User not found', session, blocktime, amount);
if (amount >= 0.001 && amount < 0.005){
expiration = blocktime + 3600;
} else if (amount >= 0.005){
expiration = blocktime + 24*3600;
}
console.log('exp', expiration);
const n = crypto.randomInt(0, 10000000);
const pin = n.toString().padStart(6, '0');
sendPin(pin, address);
var user = new usermodel({ var user = new usermodel({
address: address, address: address,
session: session, session: session,
blocktime: blocktime blocktime: blocktime,
expiration: expiration,
pin: pin,
validated: false
}); });
user.save(function(error) { user.save(function(error) {
if (error) { if (error) {
@ -181,6 +206,10 @@ app.use((req, res, next) => {
}); });
app.get('/api/test', (req, res, next) => {
sendPin('12345678', 'zs1w6nkameazc5gujm69350syl5w8tgvyaphums3pw8eytzy5ym08x7dvskmykkatmwrucmgv3er8e');
res.status(200).send('Endpoint triggered');
});
app.get('/api/users', (req, res, next) => { app.get('/api/users', (req, res, next) => {
console.log('Get: /api/users'); console.log('Get: /api/users');
@ -223,8 +252,7 @@ app.get('/api/pending', (req, res, next) => {
app.get('/api/getuser', (req, res, next) => { app.get('/api/getuser', (req, res, next) => {
console.log('Get: /api/getuser/', req.query.session); console.log('Get: /api/getuser/', req.query.session);
var today = new Date().getTime() / 1000; var today = new Date().getTime() / 1000;
var expiration = today - (24*3600); usermodel.find({'session': req.query.session, 'expiration': { $gt: today }}).
usermodel.find({'session': req.query.session, 'blocktime': { $gt: expiration }}).
then((documents) => { then((documents) => {
if(documents.length > 0){ if(documents.length > 0){
//console.log(documents); //console.log(documents);
@ -253,8 +281,6 @@ app.get('/api/blockheight', (req, res, next) => {
}); });
}); });
app.get('/api/txs', (req, res, next) => { app.get('/api/txs', (req, res, next) => {
console.log('Get: /api/txs'); console.log('Get: /api/txs');
rpc.z_listreceivedbyaddress(fullnode.addr, 10).then(txs => { rpc.z_listreceivedbyaddress(fullnode.addr, 10).then(txs => {
@ -301,6 +327,21 @@ app.post('/api/addowner', (req, res, next) => {
}); });
}); });
app.post('/api/validateuser', (req, res, next) => {
console.log('Post: /api/validateuser');
usermodel.findByIdAndUpdate(req.body.user._id, req.body.user,
function(err, docs) {
if (err) {
console.log(err);
} else {
res.status(201).json({
message: 'User Validated',
user: docs
});
}
});
});
app.post('/api/updateowner', (req, res, next) => { app.post('/api/updateowner', (req, res, next) => {
console.log('Post: /api/updateowner'); console.log('Post: /api/updateowner');
ownermodel.findByIdAndUpdate(req.body.owner._id, req.body.owner, ownermodel.findByIdAndUpdate(req.body.owner._id, req.body.owner,

View file

@ -3,7 +3,10 @@ const mongoose = require('mongoose');
const userSchema = mongoose.Schema({ const userSchema = mongoose.Schema({
address: {type: String, required:true}, address: {type: String, required:true},
session: {type: String, required:true}, session: {type: String, required:true},
blocktime: {type: Number, required:true} blocktime: {type: Number, required:true},
expiration: {type: Number, required:true, default:0},
pin: {type: String, required:true},
validated: {type: Boolean, required:true}
}); });
module.exports = mongoose.model('User', userSchema); module.exports = mongoose.model('User', userSchema);

View file

@ -11,7 +11,7 @@ const routes: Routes = [
//{ path: 'create', component: PostCreateComponent, canActivate: [AuthGuardService]}, //{ path: 'create', component: PostCreateComponent, canActivate: [AuthGuardService]},
{ path: 'shop', component: ViewerComponent, canActivate: [AuthGuardService]}, { path: 'shop', component: ViewerComponent, canActivate: [AuthGuardService]},
{ path: 'orders', component: ListOrdersComponent, canActivate: [AuthGuardService]}, { path: 'orders', component: ListOrdersComponent, canActivate: [AuthGuardService]},
{ path: 'login', component: LoginComponent} { path: 'login', component: LoginComponent, resolve: { response: NodeResolverService}}
]; ];
@NgModule({ @NgModule({

View file

@ -1,5 +1,3 @@
main{ main{
margin-top: 16px;
width: 80%;
margin: auto; margin: auto;
} }

View file

@ -1,5 +1,5 @@
<div align="center" mat-dialog-title> <div align="center" mat-dialog-title>
<h2 class="text">Scan to make payment</h2> <h4 class="text">Scan to make payment</h4>
</div> </div>
<mat-dialog-content> <mat-dialog-content>

View file

@ -1,14 +1,10 @@
<mat-toolbar color="primary"> <mat-toolbar color="primary">
<span align="center"> <span align="center">
<a routerLink = "/" class="text"> <img src="/assets/logo.png" height="45px" />
Z Go!
</a>
<p class="mini text">Last block seen: {{heightUpdate | async}}</p>
</span> </span>
<span class="spacer"></span> <span class="spacer"></span>
<span align="center"> <span align="center">
<button mat-raised-button class="text" (click)="openSettings()"> <p class="mini text">Last block:</p>
{{ shortenZaddr((ownerUpdate | async)!.address) }} <mat-icon class="icon">manage_accounts</mat-icon> <p class="mini text">{{heightUpdate | async}}</p>
</button>
</span> </span>
</mat-toolbar> </mat-toolbar>

View file

@ -3,7 +3,6 @@ import { MatDialog, MatDialogConfig} from '@angular/material/dialog';
import {FullnodeService} from '../fullnode.service'; import {FullnodeService} from '../fullnode.service';
import { UserService } from '../user.service'; import { UserService } from '../user.service';
import {Subscription, Observable} from 'rxjs'; import {Subscription, Observable} from 'rxjs';
import { SettingsComponent } from '../settings/settings.component';
import {Owner} from '../owner.model'; import {Owner} from '../owner.model';
@ -42,28 +41,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
ngOnDestroy(){ ngOnDestroy(){
} }
shortenZaddr(address:string) {
var addr = address;
var end = addr.length;
var last = end - 5;
return addr.substring(0,5).concat('...').concat(addr.substring(last, end));
}
openSettings() {
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = this.owner;
const dialogRef = this.dialog.open(SettingsComponent, dialogConfig);
dialogRef.afterClosed().subscribe((val) => {
if (val != null) {
console.log('Saving settings');
this.userService.updateOwner(val);
}
});
}
} }

View file

@ -20,3 +20,6 @@ img.icon{
.total{ .total{
font-size: large; font-size: large;
} }
img.total{
margin-bottom:-2px;
}

View file

@ -1,6 +1,6 @@
<app-header></app-header> <app-header></app-header>
<div align="center"> <div align="center">
<h1 class="text">{{(ownerUpdate | async)!.name}}</h1> <h3 class="text">{{(ownerUpdate | async)!.name}}</h3>
<button class="text" mat-raised-button [routerLink]="['/shop']" color="primary"> <button class="text" mat-raised-button [routerLink]="['/shop']" color="primary">
Back to Shop Back to Shop
</button> </button>
@ -11,11 +11,11 @@
<tr> <tr>
<td width="50%" align="center"> <td width="50%" align="center">
<h3>Today's Total:</h3> <h3>Today's Total:</h3>
<p class="total"><img src="/assets/zec-roboto.png" height="14px" />{{todayTotal}}</p> <p class="total"><img class="total" src="/assets/zec-roboto.png" height="18px" />{{todayTotal | number: '1.0-6'}}</p>
</td> </td>
<td width="50%" align="center"> <td width="50%" align="center">
<h3>Overall Total:</h3> <h3>Overall Total:</h3>
<p class="total"><img src="/assets/zec-roboto.png" height="14px" />{{total}}</p> <p class="total"><img class="total" src="/assets/zec-roboto.png" height="18px" />{{total | number: '1.0-6'}}</p>
</td> </td>
</tr> </tr>
</table> </table>
@ -25,13 +25,14 @@
<mat-expansion-panel class="text" *ngFor = "let order of orders"> <mat-expansion-panel class="text" *ngFor = "let order of orders">
<mat-expansion-panel-header class="text" > <mat-expansion-panel-header class="text" >
<mat-panel-title> <mat-panel-title>
<span class="price"><img src="/assets/zec-roboto.png" height="50%" />{{order.totalZec}}</span> <span class="mini"> (@{{order.price | currency: 'USD'}})</span> <span class="price"><img src="/assets/zec-roboto.png" height="50%" />{{order.totalZec}}</span>
</mat-panel-title> </mat-panel-title>
<mat-panel-description> <mat-panel-description>
{{order.timestamp | date: 'medium'}} {{order.timestamp | date: 'short'}}
</mat-panel-description> </mat-panel-description>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<p class="text">Order: {{order._id}}</p> <p class="text">Order: {{order._id}}</p>
<p class="text">Zcash price: {{order.price | currency: 'USD'}}</p>
<mat-list> <mat-list>
<mat-list-item class="text small" *ngFor="let item of order.lines">{{item.qty}} x {{item.name}}</mat-list-item> <mat-list-item class="text small" *ngFor="let item of order.lines">{{item.qty}} x {{item.name}}</mat-list-item>
</mat-list> </mat-list>

View file

@ -4,6 +4,7 @@
mat-card.coolcard{ mat-card.coolcard{
background-color: #FF5722; background-color: #FF5722;
color: #FFFFFF; color: #FFFFFF;
margin: 5px;
} }
.icon{ .icon{
font-family: 'Material Icons'; font-family: 'Material Icons';
@ -14,3 +15,7 @@ mat-card.coolcard{
font-size: 120%; font-size: 120%;
padding: 3px; padding: 3px;
} }
.alert-success{
margin: 5px;
background-color: #BBFFBB
}

View file

@ -1,44 +1,48 @@
<br> <br>
<div align="center" class="text"> <div align="center" class="text">
<mat-card class="coolcard"> <mat-card class="coolcard">
<h3> <img src="/assets/logo.png" />
<pre> <!--<h3>-->
__||__ _____ _ <!--<pre>-->
|___ / / ____| | | <!--__||__ _____ _ -->
/ / | | __ ___ | | <!--|___ / / ____| | |-->
/ / | | |_ |/ _ \| | <!--/ / | | __ ___ | |-->
/ /__ | |__| | (_) |_| <!--/ / | | |_ |/ _ \| |-->
/__ _| \_____|\___/(_) <!--/ /__ | |__| | (_) |_|-->
|| <!--/__ _| \_____|\___/(_)-->
</pre> <!--|| -->
</h3> <!--</pre>-->
<!--</h3>-->
<p class="text">Last block seen: {{ heightUpdate | async }}</p> <p class="text">Last block seen: {{ heightUpdate | async }}</p>
</mat-card> </mat-card>
</div> </div>
<div align="center"> <div align="center">
<table width="80%">
<colgroup>
<col span="1" style="width: 60%;">
<col span="1" style="width: 40%;">
</colgroup>
<tr>
<td>
<mat-card> <mat-card>
<p>A non-custodial point-of-sale application, powered by Zcash!</p> <p>A non-custodial point-of-sale application, powered by Zcash!</p>
<ul> <p>Your Zcash shielded address is your login.</p>
<li>Your Zcash shielded address is your login.</li> <p>Your customer pays directly to your wallet.</p>
<li>Your customer pays directly to your wallet.</li>
</ul>
</mat-card> </mat-card>
</td> <mat-card [formGroup]="pinForm" *ngIf="prompt">
<td align="center"> <h4>
<mat-card *ngIf = "txs.length > 0"> Check your wallet
</h4>
<mat-form-field appearance="outline">
<mat-label>PIN</mat-label>
<input matInput formControlName="pinValue">
</mat-form-field>
<mat-card-actions>
<button mat-raised-button color="primary" [disabled]="!pinForm.valid" (click)="confirmPin()">
Confirm
</button>
</mat-card-actions>
</mat-card>
<mat-card class="alert-success" *ngIf = "txs.length > 0">
<h4>Login received!</h4> <h4>Login received!</h4>
<mat-list> <mat-list>
<mat-list-item *ngFor="let tx of txsUpdate | async">It has {{tx.confirmations}} confirmations, needs 10.</mat-list-item> <mat-list-item *ngFor="let tx of txsUpdate | async">It needs {{10 - tx.confirmations}} more confirmations.</mat-list-item>
</mat-list> </mat-list>
</mat-card> </mat-card>
<mat-card [formGroup]="entryForm"> <mat-card [formGroup]="entryForm" *ngIf="!prompt">
<div align="center" id="info"> <div align="center" id="info">
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Session length</mat-label> <mat-label>Session length</mat-label>
@ -55,7 +59,4 @@
</mat-card-actions> </mat-card-actions>
</div> </div>
</mat-card> </mat-card>
</td>
</tr>
</table>
</div> </div>

View file

@ -6,6 +6,7 @@ import { UserService } from '../user.service';
import { FullnodeService } from '../fullnode.service'; import { FullnodeService } from '../fullnode.service';
import { ScanComponent} from '../scan/scan.component'; import { ScanComponent} from '../scan/scan.component';
import { Tx } from '../tx.model'; import { Tx } from '../tx.model';
import {User} from '../user.model';
import { Subscription, Observable } from 'rxjs'; import { Subscription, Observable } from 'rxjs';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
var QRCode = require('easyqrcodejs'); var QRCode = require('easyqrcodejs');
@ -25,10 +26,19 @@ export class LoginComponent implements OnInit {
nodeAddress: string = ''; nodeAddress: string = '';
localToken: string | null = ''; localToken: string | null = '';
selectedValue: number = 0.001; selectedValue: number = 0.001;
public user:User = {
address: '',
session: '',
blocktime: 0,
expiration: 0,
pin: '',
validated: false
};
private FullnodeSub: Subscription = new Subscription(); private FullnodeSub: Subscription = new Subscription();
private UserSub: Subscription = new Subscription(); private UserSub: Subscription = new Subscription();
public heightUpdate: Observable<number>; public heightUpdate: Observable<number>;
public uZaddrUpdate: Observable<string>; public uZaddrUpdate: Observable<string>;
public userUpdate:Observable<User>;
public txsUpdate: Observable<Tx[]>; public txsUpdate: Observable<Tx[]>;
tickets = [ tickets = [
{ {
@ -39,8 +49,10 @@ export class LoginComponent implements OnInit {
viewValue: 'One day' viewValue: 'One day'
} }
]; ];
prompt: boolean = false;
entryForm: FormGroup; entryForm: FormGroup;
pinForm: FormGroup;
constructor( constructor(
private fb: FormBuilder, private fb: FormBuilder,
@ -55,8 +67,15 @@ export class LoginComponent implements OnInit {
this.entryForm = fb.group({ this.entryForm = fb.group({
selectedSession: [0.001, Validators.required] selectedSession: [0.001, Validators.required]
}); });
this.pinForm = fb.group({
pinValue: [null, Validators.required]
});
this.heightUpdate = fullnodeService.heightUpdate; this.heightUpdate = fullnodeService.heightUpdate;
this.uZaddrUpdate = userService.uZaddrUpdate; this.uZaddrUpdate = userService.uZaddrUpdate;
this.userUpdate = userService.userUpdate;
this.userUpdate.subscribe((user) => {
this.user = user;
});
this.txsUpdate = userService.txUpdate; this.txsUpdate = userService.txUpdate;
this.txsUpdate.subscribe((txs) => { this.txsUpdate.subscribe((txs) => {
this.txs = txs; this.txs = txs;
@ -76,26 +95,7 @@ export class LoginComponent implements OnInit {
localStorage.setItem('s4z_token', token); localStorage.setItem('s4z_token', token);
this.localToken = token; this.localToken = token;
} }
this.userService.findUser(); this.loginCheck();
this.userService.uZaddrUpdate.
subscribe((userAddr: string) => {
if (userAddr.length != 0) {
console.log('Log in found!');
this.router.navigate(['/shop']);
} else {
console.log('No login for existing token found');
//console.log('Showing QR code for login');
////console.log(URLSafeBase64.encode(Buffer.from('S4ZEC::'.concat(localToken))));
//var codeString = `zcash:${this.nodeAddress}?amount=0.005&memo=${URLSafeBase64.encode(Buffer.from('ZGO::'.concat(this.localToken!)))}`;
//console.log(codeString);
//var qrcode = new QRCode(document.getElementById("qrcode"), {
//text: codeString,
//logo: "/assets/zcash.png",
//logoWidth: 80,
//logoHeight: 80
//});
}
});
}); });
this.intervalHolder = setInterval(() => { this.intervalHolder = setInterval(() => {
this.fullnodeService.getHeight(); this.fullnodeService.getHeight();
@ -106,21 +106,25 @@ export class LoginComponent implements OnInit {
} }
loginCheck(){ loginCheck(){
var today = new Date().getTime() / 1000;
this.userService.findUser(); this.userService.findUser();
this.userService.findPending(); this.userService.findPending();
this.txsUpdate.subscribe((txs) => { this.txsUpdate.subscribe((txs) => {
this.txs = txs; this.txs = txs;
}); });
this.uZaddrUpdate.subscribe((userAddr: string) => { this.userUpdate.subscribe((user) => {
if (userAddr.length != 0) { if (user.expiration > today) {
this.prompt = true;
console.log('Log in found in blockchain!'); console.log('Log in found in blockchain!');
if (user.validated) {
this.router.navigate(['/shop']); this.router.navigate(['/shop']);
} }
}
}); });
} }
login() { login() {
console.log('Dropdown:', this.entryForm.value.selectedSession); //console.log('Dropdown:', this.entryForm.value.selectedSession);
const dialogConfig = new MatDialogConfig(); const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true; dialogConfig.disableClose = true;
@ -137,6 +141,13 @@ export class LoginComponent implements OnInit {
}); });
} }
confirmPin(){
if (this.user.pin === this.pinForm.value.pinValue) {
this.userService.validateUser();
this.router.navigate(['/shop']);
}
}
ngOnDestroy(){ ngOnDestroy(){
this.FullnodeSub.unsubscribe(); this.FullnodeSub.unsubscribe();
this.UserSub.unsubscribe(); this.UserSub.unsubscribe();

View file

@ -16,7 +16,10 @@ export class OrderService {
user:{ user:{
address: '', address: '',
session: '', session: '',
blocktime: 0 blocktime: 0,
expiration: 0,
pin: '',
validated: false
}, },
order: { order: {
address: '', address: '',

View file

@ -3,4 +3,5 @@ export interface Tx {
address: string; address: string;
session: string; session: string;
confirmations: number; confirmations: number;
amount: number;
} }

View file

@ -3,4 +3,7 @@ export interface User {
address: string; address: string;
session: string; session: string;
blocktime: number; blocktime: number;
expiration: number;
pin: string;
validated: boolean;
} }

View file

@ -13,7 +13,10 @@ export class UserService{
user: { user: {
address: '', address: '',
session: '', session: '',
blocktime: 0 blocktime: 0,
expiration: 0,
pin: '',
validated: false
}, },
owner: { owner: {
address: '', address: '',
@ -99,6 +102,15 @@ export class UserService{
} }
} }
validateUser(){
var validatedUser: User = this.dataStore.user;
validatedUser.validated = true;
this.http.post<{message: string, user: User}>(this.beUrl+'api/validateuser', {user: validatedUser}, {headers: this.reqHeaders}).
subscribe((responseData) => {
console.log(responseData.message);
});
}
addOwner(address: string) { addOwner(address: string) {
const owner: Owner={_id: '', address: address, name: 'Zgo-'.concat(address.substring(0,5))}; const owner: Owner={_id: '', address: address, name: 'Zgo-'.concat(address.substring(0,5))};
let obs = this.http.post<{message: string}>(this.beUrl+'api/addowner', {address: owner.address, name: owner.name}, {headers: this.reqHeaders}); let obs = this.http.post<{message: string}>(this.beUrl+'api/addowner', {address: owner.address, name: owner.name}, {headers: this.reqHeaders});

View file

@ -1,3 +1,9 @@
* { * {
font-family: 'Roboto Mono', monospace; font-family: 'Roboto Mono', monospace;
} }
.icon{
font-family: 'Material Icons';
}
.small{
font-size: x-small;
}

View file

@ -1,15 +1,13 @@
<app-header></app-header> <app-header></app-header>
<div align="center"> <div align="center">
<h1>{{(ownerUpdate | async)!.name}}</h1> <h3>{{(ownerUpdate | async)!.name}}</h3>
<p class="small">{{ shortenZaddr((ownerUpdate | async)!.address) }}</p>
<span align="center">
<button mat-raised-button class="text" (click)="openSettings()">
<mat-icon class="icon">manage_accounts</mat-icon>
</button>
</span>
<button mat-raised-button [routerLink]="['/orders']">View Orders</button> <button mat-raised-button [routerLink]="['/orders']">View Orders</button>
</div> </div>
<table cellspacing="0" width="100%"> <app-order></app-order>
<tr> <app-item-list></app-item-list>
<td>
<app-item-list></app-item-list>
</td>
<td>
<app-order></app-order>
</td>
</tr>
</table>

View file

@ -5,8 +5,10 @@ import { UserService } from '../user.service';
import { FullnodeService } from '../fullnode.service'; import { FullnodeService } from '../fullnode.service';
import { ItemService } from '../items/items.service'; import { ItemService } from '../items/items.service';
import { Subscription, Observable } from 'rxjs'; import { Subscription, Observable } from 'rxjs';
import { SettingsComponent } from '../settings/settings.component';
import {Owner} from '../owner.model'; import {Owner} from '../owner.model';
import {User} from '../user.model';
@Component({ @Component({
@ -16,9 +18,20 @@ import {Owner} from '../owner.model';
}) })
export class ViewerComponent implements OnInit { export class ViewerComponent implements OnInit {
intervalHolder: any;
public message: string = "Welcome to the inside!"; public message: string = "Welcome to the inside!";
public user: User = {
address: '',
session: '',
blocktime: 0,
expiration: 0,
pin: '',
validated: false
};
private owner: Owner= {_id:'', address: 'none', name:''};
public addrUpdate: Observable<string>; public addrUpdate: Observable<string>;
public ownerUpdate: Observable<Owner>; public ownerUpdate: Observable<Owner>;
public userUpdate: Observable<User>;
constructor( constructor(
public fullnodeService: FullnodeService, public fullnodeService: FullnodeService,
@ -28,15 +41,57 @@ export class ViewerComponent implements OnInit {
){ ){
this.addrUpdate = fullnodeService.addrUpdate; this.addrUpdate = fullnodeService.addrUpdate;
this.ownerUpdate = userService.ownerUpdate; this.ownerUpdate = userService.ownerUpdate;
this.ownerUpdate.subscribe((owner) => {
this.owner = owner;
});
this.userUpdate = userService.userUpdate;
this.userUpdate.subscribe((user) => {
this.user = user;
});
} }
ngOnInit(){ ngOnInit(){
this.ownerUpdate.subscribe((owner) => { this.ownerUpdate.subscribe((owner) => {
this.message = owner.name; this.message = owner.name;
}); });
this.loginCheck();
this.intervalHolder = setInterval(() => {
this.loginCheck();
}, 60000);
} }
ngOnDestroy(){ ngOnDestroy(){
} }
shortenZaddr(address:string) {
var addr = address;
var end = addr.length;
var last = end - 5;
return addr.substring(0,5).concat('...').concat(addr.substring(last, end));
}
openSettings() {
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.data = this.owner;
const dialogRef = this.dialog.open(SettingsComponent, dialogConfig);
dialogRef.afterClosed().subscribe((val) => {
if (val != null) {
console.log('Saving settings');
this.userService.updateOwner(val);
}
});
}
loginCheck(){
var today = new Date().getTime() / 1000;
console.log('User check', this.user.validated);
if (this.user.expiration < today || !this.user.validated) {
console.log('Log in expired!');
this.router.navigate(['/login']);
}
}
} }

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB