├── .gitignore ├── src ├── open-browser.js ├── components │ ├── Wallet │ │ ├── QR │ │ │ ├── assets │ │ │ │ ├── qr-icon.gif │ │ │ │ └── cam-placeholder.png │ │ │ ├── Scan.button.vue │ │ │ └── Scan.modal.vue │ │ ├── Address │ │ │ ├── Modals │ │ │ │ ├── Main-Modal │ │ │ │ │ ├── parts │ │ │ │ │ │ ├── qrCode.part.vue │ │ │ │ │ │ ├── Transactions │ │ │ │ │ │ │ ├── Transaction-To.element.vue │ │ │ │ │ │ │ ├── Transaction-From.element.vue │ │ │ │ │ │ │ ├── Transaction.element.vue │ │ │ │ │ │ │ └── Transactions.part.vue │ │ │ │ │ │ └── Request.part.vue │ │ │ │ │ ├── Address-main.modal.offline.vue │ │ │ │ │ └── Address-main.modal.vue │ │ │ │ ├── Delete.modal.vue │ │ │ │ └── Lock.modal.vue │ │ │ ├── Balance │ │ │ │ ├── Balances │ │ │ │ │ └── Show-Sum-Balances.vue │ │ │ │ └── Show-Balance.vue │ │ │ └── Address.vue │ │ └── Wallet.vue │ ├── maps │ │ ├── Native-Map │ │ │ ├── helpers │ │ │ │ ├── Circles.js │ │ │ │ ├── Projection.js │ │ │ │ └── Circle-Map.js │ │ │ ├── res │ │ │ │ └── dialog │ │ │ │ │ ├── Network-Native-Map-Dialog-Element.vue │ │ │ │ │ └── Network-Native-Map-Dialog.vue │ │ │ └── Network-Native-Map.vue │ │ ├── Maps.tester.js │ │ └── Google-Maps │ │ │ ├── styles │ │ │ └── network-map-style-light.js │ │ │ └── Network-Google-Maps.js │ ├── UI │ │ ├── elements │ │ │ └── Loading-Spinner.vue │ │ ├── icons │ │ │ └── icon.vue │ │ └── modal │ │ │ └── Modal.vue │ ├── Mining │ │ └── slider.vue │ ├── Dashboard.vue │ └── alerts │ │ └── Notifications.vue ├── initialize-params │ ├── vue │ │ ├── Network-Native-Map-main-vue.js │ │ ├── Alerts-Sticky-Bar-main-vue.js │ │ └── Main-vue.js │ ├── global-initialize │ │ └── Global-Initialization.js │ └── Initialize-Params.js ├── helpers │ ├── File.helpers.js │ ├── Notification.helpers.js │ └── Browser.helpers.js └── main.js ├── README.md ├── dist_bundle └── index.html ├── .travis.yml └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | \.idea/ 2 | \node_modules/ 3 | package-lock\.json 4 | dist_bundle/* 5 | -------------------------------------------------------------------------------- /src/open-browser.js: -------------------------------------------------------------------------------- 1 | const opn = require('opn') 2 | 3 | opn('dist_bundle/index.html') // Opens the url in the default browser 4 | -------------------------------------------------------------------------------- /src/components/Wallet/QR/assets/qr-icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebDollar/User-Interface-WebDollar/HEAD/src/components/Wallet/QR/assets/qr-icon.gif -------------------------------------------------------------------------------- /src/components/Wallet/QR/assets/cam-placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WebDollar/User-Interface-WebDollar/HEAD/src/components/Wallet/QR/assets/cam-placeholder.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # User-Interface-WebDollar [![Build Status](https://travis-ci.org/WebDollar/User-Interface-WebDollar.svg)](https://travis-ci.org/WebDollar/User-Interface-WebDollar) 2 | 3 | The User Interface bundle "injects" in your web page three User Interface elements: 4 | 1. Map to show the Connections 5 | 2. Mining Bar 6 | 3. Wallet 7 | -------------------------------------------------------------------------------- /src/initialize-params/vue/Network-Native-Map-main-vue.js: -------------------------------------------------------------------------------- 1 | 2 | var Vue = require('vue/dist/vue.min.js'); 3 | 4 | import NetworkNativeMap from 'components/maps/Native-Map/Network-Native-Map.vue'; 5 | 6 | //for safari workaround 7 | export default (params)=> { 8 | 9 | if (document.getElementById('WebDollarMap') === null) 10 | return; 11 | 12 | new Vue({ 13 | el: '#WebDollarMap', 14 | render: h => h(NetworkNativeMap) 15 | }) 16 | } -------------------------------------------------------------------------------- /src/helpers/File.helpers.js: -------------------------------------------------------------------------------- 1 | const fs = require('browserify-fs'); 2 | 3 | class FileHelpers{ 4 | 5 | constructor(){ 6 | 7 | } 8 | 9 | readFileSync(fileName){ 10 | 11 | return new Promise((resolve)=>{ 12 | 13 | fs.readFile(fileName, function(err, data){ 14 | 15 | console.log(err, data); 16 | 17 | resolve(data.toString()); 18 | }); 19 | 20 | }) 21 | 22 | } 23 | 24 | } 25 | 26 | export default new FileHelpers(); -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | 2 | import BrowserHelpers from "helpers/Browser.helpers" 3 | import InitializeParams from "initialize-params/Initialize-Params" 4 | 5 | let exportObject = { 6 | 7 | helpers:{ 8 | browserHelpers: BrowserHelpers, 9 | }, 10 | initializeParams: InitializeParams, 11 | }; 12 | 13 | 14 | if (!process.env.BROWSER) 15 | module.exports = exportObject; 16 | 17 | //browser minimized script 18 | if ( typeof global.window !== 'undefined') 19 | global.window.WebDollarUserInterface = exportObject; 20 | 21 | if ( typeof window !== 'undefined') 22 | window.WebDollarUserInterface = exportObject; 23 | 24 | -------------------------------------------------------------------------------- /dist_bundle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 17 | 18 | 19 | 20 | 21 | 22 |

Hello WebDollar

23 |

User Interface

24 | 25 |
26 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /src/components/maps/Native-Map/helpers/Circles.js: -------------------------------------------------------------------------------- 1 | class Circles { 2 | 3 | constructor() { 4 | this.cells = {}; 5 | } 6 | 7 | inc(cell) { 8 | if (!this.cells[cell.cellId]) 9 | this.cells[cell.cellId] = 0; 10 | 11 | this.cells[cell.cellId]++; 12 | } 13 | 14 | del(cell) { 15 | 16 | if (!this.cells[cell.cellId]) this.cells[cell.cellId] = 0; 17 | 18 | if (this.cells[cell.cellId] > 0) return --this.cells[cell.cellId]; 19 | 20 | return 0; 21 | } 22 | 23 | get(cell) { 24 | return this.cells[cell.cellId] || 0; 25 | } 26 | 27 | } 28 | 29 | export default Circles; -------------------------------------------------------------------------------- /src/initialize-params/vue/Alerts-Sticky-Bar-main-vue.js: -------------------------------------------------------------------------------- 1 | var Vue = require('vue/dist/vue.min.js'); 2 | 3 | import AlertsStickyBar from 'components/alerts/Notifications.vue'; 4 | 5 | //for safari workaround 6 | export default (params)=> { 7 | 8 | if (document.getElementById("WebDollarAlertsStickyBarDiv") !== null && document.getElementById("WebDollarAlertsStickyBarDiv")){ 9 | return false; 10 | } 11 | 12 | if (document.getElementById('WebDollarAlertsStickyBar') === null) 13 | document.getElementsByTagName("body")[0].insertAdjacentHTML("afterbegin", `
`); 14 | 15 | new Vue({ 16 | el: '#WebDollarAlertsStickyBar', 17 | render: h => h(AlertsStickyBar) 18 | }) 19 | }; -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - stable 4 | notifications: 5 | slack: 6 | secure: SI4GUt2bPPf0GMYvpYF1I9hwMYuHryr6PuFrClNhWCgQEUNupOz1uxUgvmOSbXrHAnxOlTPiP/q4m1yzMggw1uXoS/Zh7an1YofPc4Mkg7MOaDZ/1lCQ5bjTY2eMWC3v9e6xtyeS81K/fXSranCazwRFXscBsFixL2d3YWc5xryceU077rnB1U7CI8OMaoiUtRfP81+tDmYv+6UVp8jg5IPD60C506Iv/ubZYk3HTtTf60nNs20w9+edwokCjQF3LZbCmI9n8U3kohpKd7eMagOwIhO97Ozws5rRXoztt6SUqh7ELB5y/hMXTXv1dj5RUJknMj8AZOQ8jcG5JBKKetdP53qpdiUijh2ikt9grpEzYuI2ErIiMthDbVn2Vojj8q5mdHmPMixnXZzh6CbJe1IraWUu5w6p/OMmCfl2d35ALyDgZRMC6x8Ko9VIHSJ5b7ryyTcmDOxxJQGe2D/fhWb2G7z3ZsBfdYW2DrsYfvUcU4pQHlaHfeeHKKtom/b9CZ7b3TaAqmzYS32J2aAvbeuVaKjXGH+WcsklnQI5rLn9WGH0lbXNSrNs6yHZosbmoQtv3UHU6cJp335PCzOJ95xLQnnw2mzB13tFfczrBBlheSGvoA68HwNMy9pJAQQXay6U9BPCd89cDG1Z8Fi2zzJqgusXcY8SmJY6uxDqG5k= 7 | email: false -------------------------------------------------------------------------------- /src/helpers/Notification.helpers.js: -------------------------------------------------------------------------------- 1 | let Vue = null; 2 | 3 | class Notification{ 4 | 5 | setVueInstance (instance) { Vue = instance } 6 | 7 | addAlert(statusId, statusType, title, statusMessage, timeoutDelete, href){ 8 | 9 | console.log("Vue.$notify", Vue.$notify) 10 | 11 | Vue.$notify({ 12 | group: (statusId === undefined) ? 'all' : statusId, 13 | title: title, 14 | text: statusMessage, 15 | type: statusType, 16 | duration: timeoutDelete, 17 | speed: 2000, 18 | data: {id:statusId} 19 | }) 20 | 21 | } 22 | 23 | deleteAlert(arrayStatusId){ 24 | 25 | Vue.$notify({ 26 | group: arrayStatusId, 27 | clean: true 28 | }) 29 | 30 | } 31 | 32 | } 33 | 34 | export default new Notification(); -------------------------------------------------------------------------------- /src/components/Wallet/QR/Scan.button.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 25 | 26 | 41 | -------------------------------------------------------------------------------- /src/initialize-params/vue/Main-vue.js: -------------------------------------------------------------------------------- 1 | var Vue = require('vue/dist/vue.min.js'); 2 | 3 | import Dashboard from 'components/Dashboard.vue'; 4 | import Notifications from 'vue-notification'; 5 | 6 | import VueQrcodeReader from "vue-qrcode-reader"; 7 | 8 | Vue.use(VueQrcodeReader); 9 | Vue.use(Notifications); 10 | 11 | //for safari workaround 12 | export default (params)=> { 13 | 14 | Dashboard.startAutomatically = params.startAutomatically; 15 | 16 | if (document.getElementById('WebDollar') === null) 17 | document.getElementsByTagName("body")[0].insertAdjacentHTML("beforeend", `
`); 18 | 19 | 20 | new Vue({ 21 | el: '#WebDollar', 22 | render: (createElement) => { 23 | let dashboard = createElement(Dashboard, { 24 | props: { 25 | startAutomatically: params.startAutomatically, 26 | } 27 | }) 28 | 29 | return dashboard; 30 | } 31 | }) 32 | } -------------------------------------------------------------------------------- /src/components/UI/elements/Loading-Spinner.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | -------------------------------------------------------------------------------- /src/initialize-params/global-initialize/Global-Initialization.js: -------------------------------------------------------------------------------- 1 | import BrowserHelpers from "helpers/Browser.helpers" 2 | 3 | class GlobalInitialization { 4 | 5 | constructor() { 6 | 7 | } 8 | 9 | initializeGlobalSettings() { 10 | 11 | //----------------------- 12 | // Int Script 13 | //----------------------- 14 | 15 | if (document.getElementById("WebdollarFont") === null) 16 | document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeend", ``); 17 | 18 | if (document.getElementById("WebdollarViewPort") === null) 19 | document.getElementsByTagName("head")[0].insertAdjacentHTML("beforeend", ``) 20 | 21 | window.screenHeight = window.innerHeight; 22 | window.screenWidth = window.innerWidth; 23 | 24 | BrowserHelpers.addEvent(window, "resize", (event) => { 25 | window.screenHeight = window.innerHeight; 26 | window.screenWidth = window.innerWidth; 27 | }); 28 | } 29 | 30 | 31 | } 32 | 33 | export default new GlobalInitialization() -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/parts/qrCode.part.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/parts/Transactions/Transaction-To.element.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 53 | 54 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/parts/Transactions/Transaction-From.element.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 52 | 53 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/parts/Transactions/Transaction.element.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 51 | 52 | -------------------------------------------------------------------------------- /src/helpers/Browser.helpers.js: -------------------------------------------------------------------------------- 1 | class BrowserHelpers{ 2 | 3 | static addEvent (object, type, callback) { 4 | if (object === null || typeof(object) === 'undefined') return; 5 | if (object.addEventListener) { 6 | object.addEventListener(type, callback, false); 7 | } else if (object.attachEvent) { 8 | object.attachEvent("on" + type, callback); 9 | } else { 10 | object["on"+type] = callback; 11 | } 12 | } 13 | 14 | static formatMoneyNumber(n, decimals=0) { 15 | 16 | n = parseInt(n); 17 | 18 | let number = parseInt(n/WebDollar.Applications.CoinsHelper.WEBD); 19 | let decimalNumber = BrowserHelpers._getNumberRest(n); 20 | 21 | if(number<100) decimals=4; 22 | if(number>99999) decimals=0; 23 | 24 | if(decimals===0) return BrowserHelpers._formatIntNumber(number); 25 | return BrowserHelpers._formatIntNumber(number)+'.'+BrowserHelpers._getFirstDigits(decimalNumber,decimals); 26 | } 27 | 28 | static _formatIntNumber(number){ 29 | 30 | return number.toString().replace(/./g, function(c, i, a) { 31 | return i && c !== "." && ((a.length - i) % 3 === 0) ? ',' + c : c; 32 | }); 33 | 34 | } 35 | 36 | static _getNumberRest(number){ 37 | 38 | return number % WebDollar.Applications.CoinsHelper.WEBD; 39 | 40 | } 41 | 42 | static _getFirstDigits(number,decimals){ 43 | 44 | let decimalsVerifier = Math.pow(10,decimals); 45 | let newNumber = ''; 46 | 47 | if(number<10){ 48 | 49 | newNumber='000'+number.toString(); 50 | 51 | }else if(number<100){ 52 | 53 | newNumber='00'+number.toString(); 54 | 55 | }else if(number<1000){ 56 | 57 | newNumber='0'+number.toString(); 58 | 59 | }else if(number<10000){ 60 | 61 | newNumber=''+number.toString(); 62 | 63 | } 64 | 65 | return newNumber.substring(0,decimals); 66 | 67 | } 68 | 69 | 70 | } 71 | 72 | export default BrowserHelpers; -------------------------------------------------------------------------------- /src/initialize-params/Initialize-Params.js: -------------------------------------------------------------------------------- 1 | import BrowserHelpers from "helpers/Browser.helpers" 2 | 3 | import GlobalInitialization from "./global-initialize/Global-Initialization" 4 | 5 | class InitializeParams{ 6 | 7 | constructor(){ 8 | 9 | this.maps = { 10 | activated: true, 11 | type: "NativeMap", 12 | style: "dark", 13 | id: "WebDollarMap", 14 | }; 15 | 16 | this.alertsStickyBar = { 17 | activated: true, 18 | id: "WebDollarAlertsStickyBar", 19 | }; 20 | 21 | this.mining = { 22 | activated: true, 23 | startAutomatically: true, 24 | style: "dark", 25 | id: "WebDollar", 26 | }; 27 | 28 | this.wallet = { 29 | activated: true, 30 | style: "dark", 31 | id: "WebDollar", 32 | }; 33 | 34 | 35 | /** 36 | * On Window Load 37 | */ 38 | document.addEventListener("DOMContentLoaded", (event) => { 39 | 40 | console.log("User-Interface-Loaded"); 41 | this.load(); 42 | 43 | }); 44 | 45 | } 46 | 47 | load(){ 48 | 49 | GlobalInitialization.initializeGlobalSettings(); 50 | 51 | if (process.env.DEV_SERVER){ 52 | this.mining.startAutomatically = false; 53 | } 54 | 55 | let mainVue = require('./vue/Main-vue').default; 56 | mainVue(this.mining, this.wallet); 57 | 58 | this.createElements(); 59 | 60 | } 61 | 62 | createElements(){ 63 | 64 | let networkNativeMapMainVue =require('./vue/Network-Native-Map-main-vue').default; 65 | if (this.maps.activated) 66 | networkNativeMapMainVue(this.maps); 67 | 68 | let alertsStickyBarMainVue = require('./vue/Alerts-Sticky-Bar-main-vue').default; 69 | if (this.alertsStickyBar.activated) 70 | alertsStickyBarMainVue(this.alertsStickyBar); 71 | 72 | } 73 | 74 | 75 | 76 | 77 | } 78 | 79 | export default new InitializeParams(); -------------------------------------------------------------------------------- /src/components/maps/Native-Map/helpers/Projection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * It's a Robison Projection 3 | * 4 | * https://en.wikipedia.org/wiki/Robinson_projection 5 | */ 6 | 7 | 8 | class Projection { 9 | 10 | constructor(width) { 11 | 12 | this.X = [594090, 593258.274, 591357.186, 588149.1, 583515.198, 578049.5700000001, 570326.4, 560048.643, 547513.3439999999, 532423.4580000001, 515610.71099999995, 496065.14999999997, 474440.274, 451330.173, 426913.07399999996, 399941.388, 369108.11699999997, 339938.298, 316174.698] 13 | 14 | this.Y = [0, 58689.82, 117379.64, 176069.46000000002, 234759.28, 293449.10000000003, 352138.92000000004, 410828.74000000005, 470275.848, 527356.431, 584626.336, 640760.3089999999, 695379.706, 748105.883, 798465.5349999999, 845890.696, 889245.434, 923986.021, 946610] 15 | 16 | this.EPS = 1e-8; 17 | this.INTERVAL = 5; 18 | 19 | this.radians = Math.PI / 180; 20 | this.degrees = 180 / Math.PI; 21 | 22 | this._width = width; 23 | this._r = this._width / 5.332539516; 24 | } 25 | 26 | _project(lat, lng) 27 | { 28 | // 5 degree intervals, so find right indices 29 | let lI = Math.floor((Math.abs(lat)-this.EPS)/this.INTERVAL); 30 | lI = Math.max(lI, 0); 31 | let hI = lI + 1; 32 | let ratio = (Math.abs(lat)-lI*this.INTERVAL) / this.INTERVAL; 33 | 34 | // interpolate x and y 35 | let xDist = this.X[hI]/700000-this.X[lI]/700000; 36 | let yDist = this.Y[hI]/700000-this.Y[lI]/700000; 37 | 38 | let x = ((xDist*ratio)+this.X[lI]/700000) * (Math.abs(lng) * this.radians); 39 | x = lng < 0 ? -x : x; 40 | let y = (yDist*ratio)+this.Y[lI]/700000; 41 | y = lat < 0 ? -y : y; 42 | 43 | return { 44 | x : x, 45 | y : y 46 | }; 47 | } 48 | 49 | project(lat, lng) { 50 | let p = this._project(lat, lng); 51 | return { 52 | x: p.x * this._r, 53 | y: p.y * this._r 54 | }; 55 | } 56 | } 57 | 58 | export default Projection; -------------------------------------------------------------------------------- /src/components/maps/Maps.tester.js: -------------------------------------------------------------------------------- 1 | class MapsTester{ 2 | 3 | constructor(parent){ 4 | 5 | this.parent = parent; 6 | } 7 | 8 | testConnections(){ 9 | 10 | this._createFakeMarker({country: 'USA', lat: 37.980388, lng:-92.539714 }, 2000); 11 | this._createFakeMarker({country: 'USA', lat: 36.828015, lng:-119.458796 }, 3100); 12 | this._createFakeMarker({country: 'Brazil', lat: -10.252334, lng:-55.143146}, 4200); 13 | this._createFakeMarker({country: 'Germany', lat: 51.809770, lng:8.688927}, 2000); 14 | this._createFakeMarker({country: 'France', lat: 44.745281, lng:2.080051}, 1500); 15 | this._createFakeMarker({country: 'Russia', lat: 56.875767, lng:41.410924}, 3500); 16 | this._createFakeMarker({country: 'India', lat: 17.001243, lng:78.807492}, 2500); 17 | this._createFakeMarker({country: 'UK', lat: 53.376271, lng:-0.660215}, 1500); 18 | this._createFakeMarker({country: 'China', lat: 29.832851, lng: 120.072671}, 5000); 19 | this._createFakeMarker({country: 'South Africa', lat: -29.256599, lng: 24.324561}, 5000); 20 | this._createFakeMarker({country: 'Portugal', lat: 38.989770, lng: -7.430283}, 5100); 21 | this._createFakeMarker({country: 'Australia', lat: -34.041968, lng: 150.994123}, 5200); 22 | this._createFakeMarker({country: 'Saint Petersburg', lat: 59.884495, lng: 30.434003}, 5100); 23 | this._createFakeMarker({country: 'Saudi', lat: 24.759399, lng: 46.640036}, 4800); 24 | this._createFakeMarker({country: 'Mexico', lat: 19.409722, lng: -98.991313}, 2200); 25 | this._createFakeMarker({country: 'USA', lat: 31.124374, lng: -97.531948}, 2200); 26 | this._createFakeMarker({country: 'South Korea', lat: 37.542154, lng: 126.988170}, 3400); 27 | this._createFakeMarker({country: 'Buenos Aires', lat: -34.534501, lng:-58.438049}, 3400); 28 | 29 | 30 | } 31 | 32 | _createFakeMarker( coordinates, timeOut){ 33 | 34 | setTimeout( ()=>{ 35 | 36 | //console.log("coordinates", coordinates); 37 | this.parent._addMarker(coordinates, "fake"); 38 | 39 | }, timeOut) 40 | 41 | } 42 | 43 | 44 | } 45 | 46 | export default MapsTester; -------------------------------------------------------------------------------- /src/components/maps/Native-Map/res/dialog/Network-Native-Map-Dialog-Element.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 53 | 54 | -------------------------------------------------------------------------------- /src/components/maps/Native-Map/res/dialog/Network-Native-Map-Dialog.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@webdollar/user-interface-webdollar", 3 | "version": "0.0.4", 4 | "description": "User Interface for WebDollar", 5 | "main": "index.js", 6 | "scripts": { 7 | "open_browser": "node src/open-browser", 8 | "build_browser": "cross-env NODE_ENV=production webpack --config build/webpack.browser-frontend.config.js && cp -r ./dist_bundle/assets ../vue-Frontend/public/WebDollar-dist/", 9 | "build_user_interface": "cross-env NODE_ENV=production && webpack --config build/webpack.browser.config.js --mode=production", 10 | "build": "npm run build_browser && npm run build_user_interface", 11 | "test": "npm run build_browser && npm run open_browser", 12 | "dev": "webpack-dev-server --config=./build/webpack.browser-hot-loader.config.js --content-base dist_bundle --hot --inline" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/WebDollar/User-Interface-WebDollar.git" 17 | }, 18 | "keywords": [ 19 | "WebDollar", 20 | "User Interface", 21 | "UI", 22 | "UX", 23 | "User Experience" 24 | ], 25 | "author": "WebDollar", 26 | "license": "ISC", 27 | "bugs": { 28 | "url": "https://github.com/WebDollar/User-Interface-WebDollar/issues" 29 | }, 30 | "homepage": "https://github.com/WebDollar/User-Interface-WebDollar#readme", 31 | "dependencies": { 32 | "caniuse-lite": "^1.0.30001717", 33 | "clipboard": "^1.7.1", 34 | "cross-env": "^7.0.3", 35 | "gsap": "^2.1.3", 36 | "nosleep.js": "^0.9.0", 37 | "uuid": "^3.2.1", 38 | "v-clipboard": "*", 39 | "vue": "^2.5.13", 40 | "vue-notification": "^1.3.12", 41 | "vue-qrcode-component": "^2.1.1", 42 | "vue-qrcode-reader": "^2.0.1", 43 | "vue-slider-component": "^2.8.16", 44 | "vue-style-loader": "^4.1.2" 45 | }, 46 | "devDependencies": { 47 | "@babel/cli": "^7.0.0", 48 | "@babel/core": "^7.4.5", 49 | "@babel/preset-env": "^7.4.5", 50 | "babel-loader": "^8.0.6", 51 | "babel-plugin-module-alias": "^1.6.0", 52 | "compression-webpack-plugin": "^1.1.3", 53 | "css-loader": "^0.28.9", 54 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 55 | "file-loader": "^3.0.1", 56 | "file-saver": "*", 57 | "friendly-errors-webpack-plugin": "^1.6.1", 58 | "install": "^0.12.2", 59 | "open-browser-webpack-plugin": "0.0.5", 60 | "opn": "^5.1.0", 61 | "source-map": "^0.7.0", 62 | "vue-loader": "^15.7.0", 63 | "vueify": "^9.4.1", 64 | "webpack": "^4.33.0", 65 | "webpack-bundle-analyzer": "^3.6.0", 66 | "webpack-cli": "^3.3.2", 67 | "webpack-dev-server": "^3.7.0", 68 | "webpack-hot-middleware": "^2.21.0", 69 | "webpack-merge": "^4.1.1" 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/components/Wallet/QR/Scan.modal.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 80 | 81 | 105 | 106 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Delete.modal.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 106 | 107 | 159 | 160 | -------------------------------------------------------------------------------- /src/components/maps/Google-Maps/styles/network-map-style-light.js: -------------------------------------------------------------------------------- 1 | exports.style = 2 | [ 3 | { 4 | "featureType": "administrative.land_parcel", 5 | "stylers": [ 6 | { 7 | "visibility": "off" 8 | } 9 | ] 10 | }, 11 | { 12 | "featureType": "administrative.neighborhood", 13 | "stylers": [ 14 | { 15 | "visibility": "off" 16 | } 17 | ] 18 | }, 19 | { 20 | "featureType": "landscape.natural", 21 | "elementType": "geometry.fill", 22 | "stylers": [ 23 | { 24 | "color": "#e0efef" 25 | }, 26 | { 27 | "visibility": "on" 28 | } 29 | ] 30 | }, 31 | { 32 | "featureType": "poi", 33 | "elementType": "geometry.fill", 34 | "stylers": [ 35 | { 36 | "color": "#c0e8e8" 37 | }, 38 | { 39 | "hue": "#1900ff" 40 | }, 41 | { 42 | "visibility": "on" 43 | } 44 | ] 45 | }, 46 | { 47 | "featureType": "poi", 48 | "elementType": "labels.text", 49 | "stylers": [ 50 | { 51 | "visibility": "off" 52 | } 53 | ] 54 | }, 55 | { 56 | "featureType": "poi.business", 57 | "stylers": [ 58 | { 59 | "visibility": "off" 60 | } 61 | ] 62 | }, 63 | { 64 | "featureType": "road", 65 | "elementType": "geometry", 66 | "stylers": [ 67 | { 68 | "lightness": 100 69 | }, 70 | { 71 | "visibility": "simplified" 72 | } 73 | ] 74 | }, 75 | { 76 | "featureType": "road", 77 | "elementType": "labels", 78 | "stylers": [ 79 | { 80 | "visibility": "off" 81 | } 82 | ] 83 | }, 84 | { 85 | "featureType": "road", 86 | "elementType": "labels.icon", 87 | "stylers": [ 88 | { 89 | "visibility": "off" 90 | } 91 | ] 92 | }, 93 | { 94 | "featureType": "road.arterial", 95 | "stylers": [ 96 | { 97 | "visibility": "off" 98 | } 99 | ] 100 | }, 101 | { 102 | "featureType": "road.highway", 103 | "elementType": "labels", 104 | "stylers": [ 105 | { 106 | "visibility": "off" 107 | } 108 | ] 109 | }, 110 | { 111 | "featureType": "road.local", 112 | "stylers": [ 113 | { 114 | "visibility": "off" 115 | } 116 | ] 117 | }, 118 | { 119 | "featureType": "transit", 120 | "stylers": [ 121 | { 122 | "visibility": "off" 123 | } 124 | ] 125 | }, 126 | { 127 | "featureType": "transit.line", 128 | "elementType": "geometry", 129 | "stylers": [ 130 | { 131 | "lightness": 700 132 | }, 133 | { 134 | "visibility": "on" 135 | } 136 | ] 137 | }, 138 | { 139 | "featureType": "water", 140 | "stylers": [ 141 | { 142 | "color": "#7dcdcd" 143 | } 144 | ] 145 | }, 146 | { 147 | "featureType": "water", 148 | "elementType": "labels.text", 149 | "stylers": [ 150 | { 151 | "visibility": "off" 152 | } 153 | ] 154 | } 155 | ]; 156 | -------------------------------------------------------------------------------- /src/components/Mining/slider.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 93 | 94 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/Address-main.modal.offline.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 102 | 103 | 170 | 171 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Balance/Balances/Show-Sum-Balances.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 137 | 138 | 191 | -------------------------------------------------------------------------------- /src/components/Dashboard.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 136 | 137 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/parts/Request.part.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Balance/Show-Balance.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 149 | 150 | -------------------------------------------------------------------------------- /src/components/maps/Native-Map/helpers/Circle-Map.js: -------------------------------------------------------------------------------- 1 | import Projection from "./Projection" 2 | 3 | class CircleMap { 4 | 5 | constructor(svgElement) { 6 | 7 | this._svg = svgElement; 8 | // temporarily unhide all the circlesto get the bounding rects 9 | 10 | svgElement.classList.remove('hide-circles'); 11 | 12 | let mapDimensions = this.getDimensions(); // also enforces a style update 13 | this._circleDiameter = 0; 14 | let circles = svgElement.querySelectorAll('circle'); 15 | 16 | for (let i = 0; i < circles.length; ++i) { 17 | circles[i].cellId = i; 18 | let boundingBox = circles[i].getBoundingClientRect(); 19 | // values relative to map width / height such that they work also when we resize the map 20 | circles[i].centerX = (boundingBox.left + boundingBox.width/2 - mapDimensions.left) / mapDimensions.width; 21 | circles[i].centerY = (boundingBox.top + boundingBox.height/2 - mapDimensions.top) / mapDimensions.height; 22 | // the circles differ very slightly in size, so we take the biggest 23 | this._circleDiameter = Math.max(this._circleDiameter, boundingBox.width / mapDimensions.width); 24 | } 25 | this._cells = circles; 26 | this._links = []; 27 | // after we got the circle bounding rects, we can hide them again 28 | svgElement.classList.add('hide-circles'); 29 | } 30 | 31 | getDimensions() { 32 | return this._svg.getBoundingClientRect(); 33 | } 34 | 35 | unhighlightCell(cell, index) { 36 | cell.setAttribute('class', ''); 37 | delete cell.data[index] 38 | if (cell.data === {}) 39 | cell.data = null; 40 | } 41 | 42 | putCellOnTop(cell){ 43 | // put my own cell on top of everything else. In svg the stacking is not affected by z-index, but 44 | // only by document order. So we make the cell the last child 45 | cell.parentElement.appendChild(cell); 46 | } 47 | 48 | highlightCell(cell, className, data, index) { 49 | 50 | if (cell.getAttribute('class') !== 'peer-own') 51 | if(cell.getAttribute('class') !== 'peer-connected-terminal') 52 | if(cell.getAttribute('class') !== 'peer-connected-browser') 53 | cell.setAttribute('class', className); 54 | 55 | // deleted 56 | 57 | // if (className === 'peer-own') 58 | // cell.parentElement.appendChild(cell); 59 | 60 | 61 | // XXX another hack 62 | if (data) { 63 | if (cell.data === undefined) cell.data = {}; 64 | cell.data[index] = data; 65 | } 66 | } 67 | 68 | _convertCoordinates(latitude, longitude) { 69 | let mapDimensions = this.getDimensions(); 70 | // the map that we have is cropped out from the full robinson projected map. We have to make 71 | // the computation on the full/original map, so we calculate the full size. 72 | let fullMapWidth = 1.0946808510638297 * mapDimensions.width; 73 | let fullMapHeight = fullMapWidth / 1.97165551906973; // RobinsonProjection maps have a fixed aspect ratio 74 | let projection = new Projection(fullMapWidth, fullMapHeight); 75 | let point = projection.project(latitude, longitude); 76 | // the origin is centered in the middle of the map, so we translate it 77 | // to the top left corner 78 | point.x = fullMapWidth/2 + point.x; 79 | point.y = fullMapHeight/2 - point.y; 80 | // the map that we have is robinson projected and then cropped out and scaled 81 | point.x = Math.max(0, point.x - 0.07045675413022352*fullMapWidth); 82 | point.y = Math.max(0, point.y - 0.012380952380952381*fullMapHeight); 83 | return point; 84 | } 85 | 86 | _testCoordinateConversion(latitude, longitude) { 87 | let testDot = window.testDot; 88 | if (!testDot) { 89 | testDot = document.createElement('div'); 90 | testDot.style.background = 'red'; 91 | testDot.style.width = '5px'; 92 | testDot.style.height = '5px'; 93 | testDot.style.position = 'absolute'; 94 | document.body.appendChild(testDot); 95 | window.testDot = testDot; 96 | } 97 | let convertedCoordinates = this._convertCoordinates(latitude, longitude); 98 | console.log(convertedCoordinates); 99 | testDot.style.left = convertedCoordinates.x-2+'px'; 100 | testDot.style.top = convertedCoordinates.y-2+'px'; 101 | } 102 | 103 | _getClosestCell(x, y) { 104 | let mapDimensions = this.getDimensions(); 105 | let bestDistance = 0; 106 | let bestCell = null; 107 | 108 | 109 | for (let i = 0; i < this._cells.length; ++i) { 110 | // Calculate position from bounding box. 111 | let cell = this._cells[i]; 112 | let centerX = cell.centerX * mapDimensions.width; 113 | let centerY = cell.centerY * mapDimensions.height; 114 | let xDist = centerX - x; 115 | let yDist = centerY - y; 116 | let distance = xDist*xDist + yDist*yDist; 117 | 118 | // Update best cell accordingly. 119 | if (!bestCell || distance < bestDistance) { 120 | bestDistance = distance; 121 | bestCell = cell; 122 | } 123 | } 124 | 125 | 126 | // Return best cell only if its distance in terms of cells is not too far. 127 | let circleDiameter = this._circleDiameter * mapDimensions.width; 128 | return bestDistance > CircleMap.MAX_CELL_DISTANCE * circleDiameter ? null : bestCell; 129 | } 130 | 131 | getCellByLocation(latitude, longitude) { 132 | let convertedCoordinates = this._convertCoordinates(latitude, longitude); 133 | let closestCell = this._getClosestCell(convertedCoordinates.x, convertedCoordinates.y); 134 | return closestCell; 135 | } 136 | 137 | addLink(startCell, endCell) { 138 | 139 | if (!startCell || !endCell) 140 | return; 141 | 142 | // search whether we already drew that link 143 | for (let i=0, link; link = this._links[i]; ++i) 144 | if (link.start === startCell && link.end === endCell || link.end === startCell && link.start === endCell) 145 | return; 146 | 147 | // draw the link 148 | let svgBoundingRect = this.getDimensions(); 149 | let viewBox = this._svg.viewBox; 150 | let viewBoxWidth = viewBox.baseVal.width; 151 | let viewBoxHeight = viewBox.baseVal.height; 152 | let pathEl = document.createElementNS(this._svg.namespaceURI, 'path'); 153 | 154 | let path = 'M'+(startCell.centerX*viewBoxWidth)+' '+(startCell.centerY*viewBoxHeight) +'L'+(endCell.centerX*viewBoxWidth)+' '+(endCell.centerY*viewBoxHeight); 155 | 156 | pathEl.setAttributeNS(null,'d', path); 157 | pathEl.classList.add('link'); 158 | 159 | this._links.push({ 160 | start: startCell, 161 | end: endCell, 162 | path: pathEl 163 | }); 164 | 165 | // insert the path before the startCell such that it will not be drawn over the startCell 166 | startCell.parentElement.append(pathEl); 167 | //startCell.parentElement.insertBefore(pathEl, startCell); 168 | } 169 | 170 | removeLink(startCell, endCell) { 171 | 172 | for (let i=0, link; link = this._links[i]; ++i) 173 | if (link.start === startCell && link.end === endCell || link.end === startCell && link.start === endCell) { 174 | // we found the link 175 | startCell.parentElement.removeChild(link.path); 176 | this._links.splice(i, 1); 177 | return; 178 | } 179 | 180 | } 181 | } 182 | 183 | CircleMap.MAX_CELL_DISTANCE = 12; // in terms of cells 184 | 185 | 186 | export default CircleMap; -------------------------------------------------------------------------------- /src/components/UI/icons/icon.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 31 | 32 | 33 | 54 | 55 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/Address-main.modal.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 184 | 185 | 252 | 253 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Main-Modal/parts/Transactions/Transactions.part.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Modals/Lock.modal.vue: -------------------------------------------------------------------------------- 1 | 41 | 42 | 215 | 216 | 293 | 294 | -------------------------------------------------------------------------------- /src/components/alerts/Notifications.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 175 | 176 | 235 | -------------------------------------------------------------------------------- /src/components/maps/Google-Maps/Network-Google-Maps.js: -------------------------------------------------------------------------------- 1 | import MapsTester from "../Maps.tester" 2 | 3 | import NetworkMapStyleLight from './styles/network-map-style-light'; 4 | 5 | class NetworkGoogleMaps { 6 | 7 | /* 8 | markers = [] 9 | */ 10 | 11 | constructor(){ 12 | 13 | console.log("NetworkMap constructor"); 14 | 15 | this._markers = []; 16 | 17 | let iconBase = 'https://maps.google.com/mapfiles/kml/shapes/'; 18 | this.icons = { 19 | 20 | general: { 21 | icon: 'https://maps.google.com/mapfiles/ms/micons/red.png', 22 | }, 23 | myself: { 24 | icon: 'https://pic2.iranshao.com/emoji/qq/4.gif', 25 | }, 26 | fullNodeServer: { 27 | icon: 'https://icons.iconarchive.com/icons/blackvariant/button-ui-system-apps/16/Terminal-icon.png', 28 | }, 29 | webPeer: { 30 | icon: 'https://icons.iconarchive.com/icons/dtafalonso/android-lollipop/16/Browser-icon.png', 31 | }, 32 | clientSocket: { 33 | icon: 'https://icons.iconarchive.com/icons/simplefly/simple-green/16/plug-electricity-icon.png', 34 | } 35 | }; 36 | 37 | } 38 | 39 | createMap(id, style){ 40 | 41 | if ( style === undefined) 42 | style = NetworkMapStyleLight.style; 43 | 44 | let map = new google.maps.Map(document.getElementById(id), { 45 | zoom: 2, 46 | center: {lat: 37.390487, lng: 29.308516}, 47 | mapTypeId: 'roadmap', 48 | styles: style, 49 | }); 50 | 51 | window.map = map; 52 | 53 | this._map = map 54 | 55 | return map; 56 | } 57 | 58 | createTestConnections(){ 59 | 60 | let mapsTester = new MapsTester(this); 61 | mapsTester.testConnections(); 62 | 63 | } 64 | 65 | 66 | async initialize(){ 67 | 68 | if ( google === undefined || google.maps === undefined){ 69 | alert('GOOGLE MAPS LIBRARY IS NOT REGISTERED'); 70 | return false; 71 | } 72 | 73 | WebDollar.Node.NodesList.emitter.on("nodes-list/connected", async (nodesListObject) => { 74 | 75 | let geoLocation = await nodesListObject.socket.node.sckAddress.geoLocation; 76 | 77 | //console.log("geoLocation",geoLocation); 78 | 79 | this._addMarker(geoLocation, nodesListObject.socket); 80 | 81 | } ); 82 | 83 | WebDollar.Node.NodesList.emitter.on("nodes-list/disconnected", async (nodesListObject) => { 84 | 85 | //deleting the marker 86 | 87 | let markerIndex = this._findMarkerIndexBySocket(nodesListObject.socket); 88 | 89 | if (markerIndex !== -1) { 90 | 91 | this._markers[markerIndex].setMap(null); 92 | 93 | if ( this._markers[markerIndex].curveMarker !== undefined) this._markers[markerIndex].curveMarker.setMap(null); 94 | if ( this._markers[markerIndex].linePoly !== undefined) this._markers[markerIndex].linePoly.setMap(null); 95 | if ( this._markers[markerIndex].infoWindow !== undefined) this._markers[markerIndex].infoWindow.setMap(null); 96 | 97 | this._markers.splice(markerIndex, 1); 98 | } 99 | 100 | }); 101 | 102 | await this._showMyself(); 103 | } 104 | 105 | _getInfoWindowContent(geoLocation, socket){ 106 | 107 | let address = ''; 108 | if (socket === 'myself') address = 'YOU'; 109 | else if (socket === 'fake') address = geoLocation.country; 110 | else address = socket.node.sckAddress.toString(); 111 | 112 | return ( 113 | '
'+ 114 | '
'+ 115 | '
'+ 116 | '

'+ address +'

'+ 117 | '

'+( (socket === 'myself' || socket === "fake" ) ? '' : socket.node.type + ' : '+socket.node.index)+'

'+ 118 | '
'+ 119 | '

Connected to '+ (geoLocation.city||'')+', '+geoLocation.country||''+'
'+ 120 | geoLocation.isp||'' + '

'+ 121 | (geoLocation.lat||'0') + ' '+ (geoLocation.lng||'0')+ '
'+ 122 | '

'+ 123 | '
'+ 124 | '
'); 125 | } 126 | 127 | _findMarkerIndexBySocket(socket){ 128 | 129 | for (let i=0; i< this._markers.length; i++ ) 130 | if (this._markers[i].socket === socket) 131 | return i; 132 | 133 | return -1; 134 | 135 | } 136 | 137 | _addMarker(geoLocation, socket){ 138 | 139 | if ( google === undefined || google.maps === undefined){ 140 | alert('GOOGLE MAPS LIBRARY IS NOT REGISTERED'); 141 | return false; 142 | } 143 | 144 | //console.log("marker ", google.maps.Marker, map) 145 | 146 | let position = {lat: geoLocation.lat||0, lng: geoLocation.lng||0}; 147 | 148 | let feature = ''; 149 | 150 | if (socket === 'myself') feature = 'myself'; 151 | else 152 | if (socket === 'fake') feature = 'webPeer'; 153 | else 154 | if (socket !== null) 155 | switch (socket.node.type){ 156 | case 'client': feature = 'fullNodeServer'; break; 157 | case 'server' : feature = 'clientSocket'; break; 158 | case 'webpeer' : feature = 'webPeer'; break; 159 | } 160 | 161 | let marker = new google.maps.Marker({ 162 | position: position, 163 | map: this._map, 164 | clickable: true, 165 | icon: (this.icons.hasOwnProperty(feature) ? this.icons[feature].icon : this.icons['general']), 166 | }); 167 | 168 | let infoWindow = new google.maps.InfoWindow({ 169 | content: this._getInfoWindowContent(geoLocation, socket) 170 | }); 171 | 172 | marker.addListener('click', function() { 173 | infoWindow.open(this._map, marker); 174 | }); 175 | 176 | marker.socket = socket; 177 | marker.infoWindow = infoWindow; 178 | 179 | this._markers.push(marker); 180 | 181 | this._createConnectionsArcs(false); 182 | 183 | } 184 | 185 | async _showMyself(){ 186 | let geoLocation = await WebDollar.Applications.GeoHelper.getLocationFromAddress('', true); 187 | 188 | this._addMarker( geoLocation, 'myself'); 189 | } 190 | 191 | 192 | initializePolylines(){ 193 | 194 | 195 | this._createConnectionsArcs(false); 196 | google.maps.event.addListener(this._map, 'projection_changed', () => {this._createConnectionsArcs(true) }); 197 | google.maps.event.addListener(this._map, 'zoom_changed', () => {this._createConnectionsArcs(true)}); 198 | 199 | // google.maps.event.addListener(markerP1, 'position_changed', updateCurveMarker); 200 | } 201 | 202 | _createConnectionsArcs(update, showOldArcs) { 203 | 204 | if ( showOldArcs === undefined) showOldArcs = false; 205 | 206 | /* 207 | TUTORIAL - BASED ON http://jsfiddle.net/medmunds/sd10up9t/ 208 | */ 209 | 210 | let markerMyself = null; 211 | for (let i=0; i 2 | 3 |
4 |
5 | 22 |
23 | 24 | 25 | 26 | 27 | 76 | 77 | 78 | 79 | 542 | -------------------------------------------------------------------------------- /src/components/Wallet/Address/Address.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 46 | 255 | 256 | 503 | -------------------------------------------------------------------------------- /src/components/maps/Native-Map/Network-Native-Map.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 492 | 493 | 494 | -------------------------------------------------------------------------------- /src/components/Wallet/Wallet.vue: -------------------------------------------------------------------------------- 1 | 82 | 83 | 84 | 85 | 306 | 307 | 549 | --------------------------------------------------------------------------------