From ff68252e6285986bbc87faedb8bb046e13815c9a Mon Sep 17 00:00:00 2001 From: Taegus Date: Tue, 25 Dec 2018 15:27:02 +0100 Subject: [PATCH] + block sorting even for unconfirmed empty blocks * code for transactions table moved to separate unit --- assets/scripts/datatables-absolute.js | 184 ++++++++++++++++++++++++++ assets/templates/transactions.html | 1 + index.html | 2 + modules/database.js | 16 ++- package.json | 1 + renderer/send.js | 13 +- renderer/tableTransactions.js | 73 ++++++++++ renderer/transactions.js | 62 +-------- 8 files changed, 288 insertions(+), 64 deletions(-) create mode 100644 assets/scripts/datatables-absolute.js create mode 100644 renderer/tableTransactions.js diff --git a/assets/scripts/datatables-absolute.js b/assets/scripts/datatables-absolute.js new file mode 100644 index 0000000..35587b3 --- /dev/null +++ b/assets/scripts/datatables-absolute.js @@ -0,0 +1,184 @@ +/** + * When sorting a DataTable you might find that you want to keep a specific + * item at the top or bottom of the table. For example when sorting a column + * of numbers, if a value is `null` or `N/A` you might want to keep it at the + * bottom of the table, regardless of if ascending or descending sorting is + * applied. This plug-in provides that ability. + * + * You must call the `$.fn.dataTable.absoluteOrder` with information about the + * value(s) you wish to make absolute in the sorting order and store the + * returned value, assigning it to the `columns.type` option for the column + * you wish this sorting to be applied to. + * + * For number based columns a `$.fn.dataTable.absoluteOrderNumber` function is + * also available. + * + * @name Absolute sorting + * @summary Keep one or more items at the top and/or bottom of a table when sorting + * @author [Allan Jardine](//datatables.net) + * @depends DataTables 1.10+ + * + * @example + * var namesType = $.fn.dataTable.absoluteOrder( [ + * { value: '', position: 'top' } + * ] ); + * + * var numbersType = $.fn.dataTable.absoluteOrderNumber( [ + * { value: 'N/A', position: 'bottom' } + * ] ); + * + * $('#example').DataTable( { + * columnDefs: [ + * { type: namesType, targets: 0 }, + * { type: numbersType, targets: 1 } + * ] + * } ); + */ + +(function( factory ){ + if ( typeof define === 'function' && define.amd ) { + // AMD + define( ['jquery', 'datatables.net'], function ( $ ) { + return factory( $, window, document ); + } ); + } + else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = function (root, $) { + if ( ! root ) { + root = window; + } + + if ( ! $ || ! $.fn.dataTable ) { + $ = require('datatables.net')(root, $).$; + } + + return factory( $, root, root.document ); + }; + } + else { + // Browser + factory( jQuery, window, document ); + } +}(function( $, window, document, undefined ) { +'use strict'; + +// Unique value allowing multiple absolute ordering use cases on a single page. +var _unique = 0; + +// Function to encapsulate code that is common to both the string and number +// ordering plug-ins. +var _setup = function ( values ) { + if ( ! $.isArray( values ) ) { + values = [ values ]; + } + + var o = { + name: 'absoluteOrder'+(_unique++), + alwaysTop: {}, + alwaysBottom: {} + }; + + // In order to provide performance, the symbols that are to be looked for + // are stored as parameter keys in an object, allowing O(1) lookup, rather + // than O(n) if it were in an array. + for ( var i=0, ien=values.length ; i b) ? 1 : 0)); + }; + + // Descending ordering method + o.desc = function ( a, b, isNumber ) { + if ( o.alwaysTop[ a ] && o.alwaysTop[ b ] ) { + return 0; + } + else if ( o.alwaysBottom[ a ] && o.alwaysBottom[ b ] ) { + return 0; + } + else if ( o.alwaysTop[ a ] || o.alwaysBottom[ b ] ) { + return -1; + } + else if ( o.alwaysBottom[ a ] || o.alwaysTop[ b ] ) { + return 1; + } + + if ( isNumber ) { + if ( typeof a === 'string' ) { + a = a.replace(/[^\d\-\.]/g, '') * 1; + } + if ( typeof b === 'string' ) { + b = b.replace(/[^\d\-\.]/g, '') * 1; + } + } + + return ((a < b) ? 1 : ((a > b) ? -1 : 0)); + }; + + return o; +}; + +// String based ordering +$.fn.dataTable.absoluteOrder = function ( values ) { + var conf = _setup( values ); + + $.fn.dataTable.ext.type.order[ conf.name+'-asc' ] = conf.asc; + $.fn.dataTable.ext.type.order[ conf.name+'-desc' ] = conf.desc; + + // Return the name of the sorting plug-in that was created so it can be used + // with the `columns.type` parameter. There is no auto-detection here. + return conf.name; +}; + +// Number based ordering - strips out everything but the number information +$.fn.dataTable.absoluteOrderNumber = function ( values ) { + var conf = _setup( values ); + + $.fn.dataTable.ext.type.order[ conf.name+'-asc' ] = function ( a, b ) { + return conf.asc( a, b, true ); + }; + $.fn.dataTable.ext.type.order[ conf.name+'-desc' ] = function ( a, b ) { + return conf.desc( a, b, true ); + }; + + return conf.name; +}; + + +})); diff --git a/assets/templates/transactions.html b/assets/templates/transactions.html index de87273..62244dc 100644 --- a/assets/templates/transactions.html +++ b/assets/templates/transactions.html @@ -1,4 +1,5 @@
+ diff --git a/index.html b/index.html index 200f6e9..4b67e8e 100644 --- a/index.html +++ b/index.html @@ -31,6 +31,7 @@ + @@ -84,6 +85,7 @@ require('./renderer/wallets.js'); require('./renderer/blockchain.js'); require('./renderer/transactions.js'); + require('./renderer/tableTransactions.js'); diff --git a/modules/database.js b/modules/database.js index 70b9366..7f11078 100644 --- a/modules/database.js +++ b/modules/database.js @@ -1,6 +1,7 @@ const {app, ipcMain} = require('electron'); const storage = require('electron-storage'); const datastore = require('nedb'); +const moment = require('moment'); const path = require('path'); const dbPath = path.join(app.getPath('userData'), 'storage.db'); @@ -26,9 +27,22 @@ ipcMain.on('storeTransaction', (event, arg) => { }); ipcMain.on('getTransactions', (event, arg) => { - db.find({}).sort({ block: 1 }).exec(function (err, docs) { + db.find({}).exec(function (err, docs) { ResultData = []; + // sort the data + docs.sort((a, b)=>{ + if ((!b.block) && (a.block)) { + return 1; + } else if ((b.block) && (!a.block)) { + return -1; + } else if ((!b.block) && (!a.block)) { + return moment(b.timestamp, "YYYY-MM-DD HH:mm:ss").toDate() - moment(a.timestamp, "YYYY-MM-DD HH:mm:ss").toDate(); + } else { + return b.block - a.block; + } + }); + for (i = 0; i < Math.min(docs.length, 500); i++) { ResultData.push([ docs[i].block, diff --git a/package.json b/package.json index f02b844..adb0c99 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "app-root-path": "^2.1.0", "electron-storage": "^1.0.7", "handlebars": "^4.0.12", + "moment": "^2.23.0", "nedb": "^1.8.0", "single-instance": "0.0.1" }, diff --git a/renderer/send.js b/renderer/send.js index cfe7374..6ebf6f3 100644 --- a/renderer/send.js +++ b/renderer/send.js @@ -145,13 +145,14 @@ $(document).on("render_send", function() { EthoMainGUI.showGeneralError(error); }, function(transaction) { + console.log(JSON.stringify(transaction)); ipcRenderer.send('storeTransaction', { - block: element.block.toString(), - txhash: element.hash.toLowerCase(), - fromaddr: element.fromaddr.toLowerCase(), - timestamp: element.timestamp, - toaddr: element.toaddr.toLowerCase(), - value: element.value + block: transaction.blockNumber, + txhash: transaction.hash.toLowerCase(), + fromaddr: transaction.from.toLowerCase(), + timestamp: moment().format('YYYY-MM-DD HH:mm:ss'), + toaddr: transaction.to.toLowerCase(), + value: transaction.value }); } ); diff --git a/renderer/tableTransactions.js b/renderer/tableTransactions.js new file mode 100644 index 0000000..eace89f --- /dev/null +++ b/renderer/tableTransactions.js @@ -0,0 +1,73 @@ +class tableTransactions { + constructor() { + this.appState = "account"; + } + + initialize(id, data) { + // register the sort datetime format + $.fn.dataTable.moment('MMM Do YYYY HH:mm:ss'); + + var namesType = $.fn.dataTable.absoluteOrder( + [ + { value: null, position: 'top' } + ]); + // render the transactions + $(id).DataTable({ + "paging": false, + "scrollY": "calc(100vh - 115px)", + "responsive": true, + "processing": true, + "order": [[ 1, "desc" ]], + "data": data, + "oSearch": {"sSearch": EthoTransactions.getFilter() }, + "columnDefs": [ + { + "targets": 0, + "render": function ( data, type, row ) { + if (data == 0) { + return ''; + } else if (data == 1) { + return ''; + } else { + return ''; + } + } + }, + { + "className": "transactionsBlockNum", + "type": namesType, + "targets": 1 + }, + { + "targets": 2, + "render": function ( data, type, row ) { + return moment(data, "YYYY-MM-DD HH:mm:ss").format("MMM Do YYYY HH:mm:ss"); + } + }, + { + "targets": 5, + "render": function ( data, type, row ) { + return parseFloat(web3Local.utils.fromWei(EthoUtils.toFixed(parseFloat(data)).toString(), 'ether')).toFixed(2); + } + }, + { + "targets": 6, + "defaultContent": "", + "render": function ( data, type, row ) { + if (row[1]) { + return ''; + } else { + return ''; + } + } + } + ], + "drawCallback": function( settings ) { + $("#loadingTransactionsOverlay").css("display", "none"); + } + }); + } +} + +// create new tables variable +EthoTableTransactions = new tableTransactions(); diff --git a/renderer/transactions.js b/renderer/transactions.js index be547bf..760d848 100644 --- a/renderer/transactions.js +++ b/renderer/transactions.js @@ -104,64 +104,8 @@ class Transactions { element.unshift(2); } }); - - // register the sort datetime format - $.fn.dataTable.moment('MMM Do YYYY HH:mm:ss'); - // render the transactions - $('#tableTransactionsForAll').DataTable({ - "paging": false, - "scrollY": "calc(100vh - 115px)", - "responsive": true, - "processing": true, - "order": [[ 1, "desc" ]], - "data": dataTransactions, - "oSearch": {"sSearch": EthoTransactions.getFilter() }, - "columnDefs": [ - { - "targets": 0, - "render": function ( data, type, row ) { - if (data == 0) { - return ''; - } else if (data == 1) { - return ''; - } else { - return ''; - } - } - }, - { - "className": "transactionsBlockNum", - "targets": 1 - }, - { - "targets": 2, - "render": function ( data, type, row ) { - return moment(data, "YYYY-MM-DD HH:mm:ss").format("MMM Do YYYY HH:mm:ss"); - } - }, - { - "targets": 5, - "render": function ( data, type, row ) { - return parseFloat(web3Local.utils.fromWei(EthoUtils.toFixed(parseFloat(data)).toString(), 'ether')).toFixed(2); - } - }, - { - "targets": 6, - "defaultContent": "", - "render": function ( data, type, row ) { - if (row[1]) { - return ''; - } else if (data == 1) { - return ''; - } - } - } - ], - "drawCallback": function( settings ) { - $("#loadingTransactionsOverlay").css("display", "none"); - } - }); + EthoTableTransactions.initialize('#tableTransactionsForAll', dataTransactions); }, 200); } @@ -206,6 +150,10 @@ $(document).on("onSyncInterval", function() { // store transaction and notify about new transactions ipcRenderer.send('storeTransaction', Transaction); $(document).trigger("onNewAccountTransaction"); + + if (EthoMainGUI.getAppState() == "transactions") { + //$('#tableTransactionsForAll').DataTable().ajax.reload(); + } } }); }