Adjust visuals for small screens
This commit is contained in:
parent
b66650d34d
commit
7145a437b4
20 changed files with 258 additions and 144 deletions
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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({
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
main{
|
main{
|
||||||
margin-top: 16px;
|
|
||||||
width: 80%;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,3 +20,6 @@ img.icon{
|
||||||
.total{
|
.total{
|
||||||
font-size: large;
|
font-size: large;
|
||||||
}
|
}
|
||||||
|
img.total{
|
||||||
|
margin-bottom:-2px;
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -1,61 +1,62 @@
|
||||||
<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%">
|
<mat-card>
|
||||||
<colgroup>
|
<p>A non-custodial point-of-sale application, powered by Zcash!</p>
|
||||||
<col span="1" style="width: 60%;">
|
<p>Your Zcash shielded address is your login.</p>
|
||||||
<col span="1" style="width: 40%;">
|
<p>Your customer pays directly to your wallet.</p>
|
||||||
</colgroup>
|
</mat-card>
|
||||||
<tr>
|
<mat-card [formGroup]="pinForm" *ngIf="prompt">
|
||||||
<td>
|
<h4>
|
||||||
<mat-card>
|
Check your wallet
|
||||||
<p>A non-custodial point-of-sale application, powered by Zcash!</p>
|
</h4>
|
||||||
<ul>
|
<mat-form-field appearance="outline">
|
||||||
<li>Your Zcash shielded address is your login.</li>
|
<mat-label>PIN</mat-label>
|
||||||
<li>Your customer pays directly to your wallet.</li>
|
<input matInput formControlName="pinValue">
|
||||||
</ul>
|
</mat-form-field>
|
||||||
</mat-card>
|
<mat-card-actions>
|
||||||
</td>
|
<button mat-raised-button color="primary" [disabled]="!pinForm.valid" (click)="confirmPin()">
|
||||||
<td align="center">
|
Confirm
|
||||||
<mat-card *ngIf = "txs.length > 0">
|
</button>
|
||||||
<h4>Login received!</h4>
|
</mat-card-actions>
|
||||||
<mat-list>
|
</mat-card>
|
||||||
<mat-list-item *ngFor="let tx of txsUpdate | async">It has {{tx.confirmations}} confirmations, needs 10.</mat-list-item>
|
<mat-card class="alert-success" *ngIf = "txs.length > 0">
|
||||||
</mat-list>
|
<h4>Login received!</h4>
|
||||||
</mat-card>
|
<mat-list>
|
||||||
<mat-card [formGroup]="entryForm">
|
<mat-list-item *ngFor="let tx of txsUpdate | async">It needs {{10 - tx.confirmations}} more confirmations.</mat-list-item>
|
||||||
<div align="center" id="info">
|
</mat-list>
|
||||||
<mat-form-field appearance="outline">
|
</mat-card>
|
||||||
<mat-label>Session length</mat-label>
|
<mat-card [formGroup]="entryForm" *ngIf="!prompt">
|
||||||
<mat-select formControlName="selectedSession">
|
<div align="center" id="info">
|
||||||
<mat-option *ngFor="let ticket of tickets" [value]="ticket.value">
|
<mat-form-field appearance="outline">
|
||||||
{{ticket.viewValue}}
|
<mat-label>Session length</mat-label>
|
||||||
</mat-option>
|
<mat-select formControlName="selectedSession">
|
||||||
</mat-select>
|
<mat-option *ngFor="let ticket of tickets" [value]="ticket.value">
|
||||||
</mat-form-field>
|
{{ticket.viewValue}}
|
||||||
<mat-card-actions>
|
</mat-option>
|
||||||
<button mat-raised-button color="primary" [disabled]="!entryForm.valid" (click)="login()">
|
</mat-select>
|
||||||
<mat-icon class="icon">login</mat-icon><span class="bigbutton">Log in</span>
|
</mat-form-field>
|
||||||
</button>
|
<mat-card-actions>
|
||||||
</mat-card-actions>
|
<button mat-raised-button color="primary" [disabled]="!entryForm.valid" (click)="login()">
|
||||||
</div>
|
<mat-icon class="icon">login</mat-icon><span class="bigbutton">Log in</span>
|
||||||
</mat-card>
|
</button>
|
||||||
</td>
|
</mat-card-actions>
|
||||||
</tr>
|
</div>
|
||||||
</table>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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!');
|
||||||
this.router.navigate(['/shop']);
|
if (user.validated) {
|
||||||
|
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();
|
||||||
|
|
|
@ -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: '',
|
||||||
|
|
|
@ -3,4 +3,5 @@ export interface Tx {
|
||||||
address: string;
|
address: string;
|
||||||
session: string;
|
session: string;
|
||||||
confirmations: number;
|
confirmations: number;
|
||||||
|
amount: number;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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});
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
* {
|
* {
|
||||||
font-family: 'Roboto Mono', monospace;
|
font-family: 'Roboto Mono', monospace;
|
||||||
}
|
}
|
||||||
|
.icon{
|
||||||
|
font-family: 'Material Icons';
|
||||||
|
}
|
||||||
|
.small{
|
||||||
|
font-size: x-small;
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
|
||||||
|
|
|
@ -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
BIN
src/assets/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Loading…
Reference in a new issue