Skip to content
Snippets Groups Projects
Commit c76fd942 authored by Benoit Lavenier's avatar Benoit Lavenier
Browse files

[enh] TX view: add UD, using ES data - fix #576 - fix #232

parent 56a80a28
No related branches found
No related tags found
No related merge requests found
...@@ -1006,6 +1006,20 @@ $screen-menu: 845px; ...@@ -1006,6 +1006,20 @@ $screen-menu: 845px;
} }
} }
/******
* TX view (wallet or identity)
*******/
.item-tx .badge-energized {
background-color: rgba(255,201,0,0.3);
color: #888 !important;
}
/******
* Cards
*******/
.card .card-header, .card .card-header,
.card .card-header{ .card .card-header{
font-size: 90%; font-size: 90%;
......
source diff could not be displayed: it is too large. Options to address this: view the blob.
...@@ -258,6 +258,10 @@ ...@@ -258,6 +258,10 @@
} }
/**********
Drop zone component
**********/
.dropzone { .dropzone {
cursor: pointer; cursor: pointer;
} }
......
...@@ -173,6 +173,8 @@ ...@@ -173,6 +173,8 @@
<script src="dist/dist_js/plugins/es/js/services/invitation-services.js"></script> <script src="dist/dist_js/plugins/es/js/services/invitation-services.js"></script>
<script src="dist/dist_js/plugins/es/js/services/subscription-services.js"></script> <script src="dist/dist_js/plugins/es/js/services/subscription-services.js"></script>
<script src="dist/dist_js/plugins/es/js/services/wallet-services.js"></script> <script src="dist/dist_js/plugins/es/js/services/wallet-services.js"></script>
<script src="dist/dist_js/plugins/es/js/services/wot-services.js"></script>
<script src="dist/dist_js/plugins/es/js/services/tx-services.js"></script>
<script src="dist/dist_js/plugins/es/js/services/geo-services.js"></script> <script src="dist/dist_js/plugins/es/js/services/geo-services.js"></script>
<script src="dist/dist_js/plugins/es/js/controllers/common-controllers.js"></script> <script src="dist/dist_js/plugins/es/js/controllers/common-controllers.js"></script>
<script src="dist/dist_js/plugins/es/js/controllers/app-controllers.js"></script> <script src="dist/dist_js/plugins/es/js/controllers/app-controllers.js"></script>
......
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
'cesium.settings.services', 'cesium.wot.services' ]) 'cesium.settings.services', 'cesium.wot.services' ])
.factory('csTx', function($q, $timeout, $filter, $translate, UIUtils, BMA, Api, csConfig, csSettings, csWot, FileSaver) { .factory('csTx', function($q, $timeout, $filter, $translate, FileSaver, UIUtils, BMA, Api,
csConfig, csSettings, csWot, csCurrency) {
'ngInject'; 'ngInject';
function factory(id, BMA) { function factory(id, BMA) {
...@@ -152,7 +153,9 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ...@@ -152,7 +153,9 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
// get TX history since // get TX history since
if (fromTime !== -1) { if (fromTime !== -1) {
var sliceTime = csSettings.data.walletHistorySliceSecond; var sliceTime = csSettings.data.walletHistorySliceSecond;
for(var i = fromTime - (fromTime % sliceTime); i - sliceTime < nowInSec; i += sliceTime) { fromTime = fromTime - (fromTime % sliceTime);
for(var i = fromTime; i - sliceTime < nowInSec; i += sliceTime) {
var startTime = Math.max(i, fromTime);
jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1}) jobs.push(BMA.tx.history.times({pubkey: pubkey, from: i, to: i+sliceTime-1})
.then(_reduceTx) .then(_reduceTx)
); );
...@@ -170,10 +173,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ...@@ -170,10 +173,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
} }
// get UD history // get UD history
// FIXME issue#232
/*
if (csSettings.data.showUDHistory) { if (csSettings.data.showUDHistory) {
jobs.push( /*jobs.push(
BMA.ud.history({pubkey: pubkey}) BMA.ud.history({pubkey: pubkey})
.then(function(res){ .then(function(res){
udHistory = !res.history || !res.history.history ? [] : udHistory = !res.history || !res.history.history ? [] :
...@@ -187,9 +188,26 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ...@@ -187,9 +188,26 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
block_number: ud.block_number block_number: ud.block_number
}); });
}, []); }, []);
})); }));*/
// API extension
jobs.push(
api.data.raisePromise.loadUDs({
pubkey: pubkey,
fromTime: fromTime
})
.then(function(res) {
if (!res || !res.length) return;
udHistory = res.reduce(function(res, hits) {
return res.concat(hits);
}, udHistory);
})
.catch(function(err) {
console.debug('Error while loading UDs history, on extension point.');
console.error(err);
})
);
} }
*/
// Execute jobs // Execute jobs
$q.all(jobs) $q.all(jobs)
...@@ -353,10 +371,10 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ...@@ -353,10 +371,10 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
$translate(['ACCOUNT.HEADERS.TIME', $translate(['ACCOUNT.HEADERS.TIME',
'COMMON.UID', 'COMMON.UID',
'COMMON.PUBKEY', 'COMMON.PUBKEY',
'COMMON.UNIVERSAL_DIVIDEND',
'ACCOUNT.HEADERS.AMOUNT', 'ACCOUNT.HEADERS.AMOUNT',
'ACCOUNT.HEADERS.COMMENT']), 'ACCOUNT.HEADERS.COMMENT']),
//TODO : Utiliser plutôt csCurency pour avoir le bloc courant csCurrency.blockchain.current(true/*withCache*/),
BMA.blockchain.current(),
loadData(pubkey, options.fromTime) loadData(pubkey, options.fromTime)
]) ])
.then(function(result){ .then(function(result){
...@@ -396,7 +414,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ...@@ -396,7 +414,7 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
tx.uid, tx.uid,
tx.pubkey, tx.pubkey,
formatDecimal(tx.amount/100), formatDecimal(tx.amount/100),
'"' + tx.comment + '"' '"' + (tx.isUD ? translations['COMMON.UNIVERSAL_DIVIDEND'] : tx.comment) + '"'
].join(';') + '\n'); ].join(';') + '\n');
}, [headers.join(';') + '\n']); }, [headers.join(';') + '\n']);
...@@ -406,6 +424,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services', ...@@ -406,6 +424,8 @@ angular.module('cesium.tx.services', ['ngApi', 'cesium.bma.services',
}); });
}; };
// Register extension points
api.registerEvent('data', 'loadUDs');
return { return {
id: id, id: id,
......
...@@ -16,6 +16,8 @@ angular.module('cesium.es.services', [ ...@@ -16,6 +16,8 @@ angular.module('cesium.es.services', [
'cesium.es.wallet.services', 'cesium.es.wallet.services',
'cesium.es.invitation.services', 'cesium.es.invitation.services',
'cesium.es.subscription.services', 'cesium.es.subscription.services',
'cesium.es.wot.services',
'cesium.es.tx.services',
'cesium.es.geo.services' 'cesium.es.geo.services'
]) ])
; ;
angular.module('cesium.es.tx.services', ['ngResource', 'cesium.services', 'cesium.es.http.services', 'cesium.es.wot.services'])
.config(function(PluginServiceProvider, csConfig) {
'ngInject';
var enable = csConfig.plugins && csConfig.plugins.es;
if (enable) {
// Will force to load this service
PluginServiceProvider.registerEagerLoadingService('esTx');
}
})
.factory('esTx', function($q, $rootScope, csCurrency, csTx, esHttp, esWot) {
'ngInject';
var
raw = {
block: {
search: esHttp.post('/:currency/block/_search')
}
};
function _powBase(amount, base) {
return base <= 0 ? amount : amount * Math.pow(10, base);
}
function onLoadUDs(options, deferred) {
deferred = deferred || $q.defer();
options = options || {};
if (!options.pubkey) deferred.reject('Missing [pubkey] when calling [loadUDs] extension point');
$q.all([
// Get currency
csCurrency.get(),
// Get user memberships
esWot.memberships(options.pubkey)
])
.then(function(res) {
var currency = res[0] && res[0].name;
var memberships = res[1];
if (!currency || !memberships || !memberships.length) return;
// Filter memberships using options.fromTime
if (options.fromTime !== -1) {
memberships = memberships.reduce(function(res, membership) {
if (membership.leaveTime < options.fromTime) return res;
membership.joinTime = Math.max(membership.joinTime, options.fromTime);
return res.concat(membership);
}, []);
}
return $q.all(memberships.reduce(function(res, membership) {
var request = {
query: {
filtered: {
filter: {
bool: {
must: [
{
exists: {
field: 'dividend'
}
},
{
range: {
medianTime: {
from: membership.joinTime,
to: membership.leaveTime
}
}
}
]
}
}
}
},
size: options.size || 10000, // TODO: use scroll ?
from: options.from || 0,
sort: {"medianTime" : "desc"},
_source: ["medianTime", "number", "dividend", "unitbase"]
};
return res.concat(raw.block.search(request, {currency: currency}));
}, []));
})
.then(function(res){
if (!res || !res.length) return;
return res.reduce(function(uds, res){
if (!res.hits.total || !res.hits.hits.length) return res;
return uds.concat(res.hits.hits.reduce(function(res, hit){
var block = hit._source;
return res.concat({
time: block.medianTime,
amount: _powBase(block.dividend, block.unitbase),
isUD: true,
block_number: block.number
});
}, []));
}, []);
})
.then(function(res){
deferred.resolve(res);
})
.catch(function(err) {
deferred.reject(err);
});
return deferred.promise;
}
// Register extensions
csTx.api.data.on.loadUDs($rootScope, onLoadUDs, this);
// Exports
return {};
});
...@@ -129,7 +129,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c ...@@ -129,7 +129,7 @@ angular.module('cesium.es.wallet.services', ['ngResource', 'cesium.platform', 'c
} }
function addListeners() { function addListeners() {
// Extend csWallet events // Extend API events
listeners = [ listeners = [
csWallet.api.data.on.login($rootScope, onWalletLogin, this), csWallet.api.data.on.login($rootScope, onWalletLogin, this),
csWallet.api.data.on.load($rootScope, onWalletLoad, this), csWallet.api.data.on.load($rootScope, onWalletLoad, this),
......
angular.module('cesium.es.wot.services', ['ngResource', 'cesium.es.http.services'])
.factory('esWot', function($q, esHttp) {
'ngInject';
var
raw = {
user: {
event: esHttp.post('/user/event/_search?pretty')
}
},
loadMemberships = function(pubkey) {
// Get user events on membership state
var request = {
"size": 1000,
"query": {
"bool": {
"filter": [
{"term": {"recipient" : pubkey }},
{"terms": {"code" : ["MEMBER_JOIN","MEMBER_ACTIVE","MEMBER_LEAVE","MEMBER_EXCLUDE","MEMBER_REVOKE"] }}
]
}
},
"sort" : [
{ "time" : {"order" : "asc"}}
],
_source: ["code", "time"]
};
return raw.user.event(request)
.then(function(res) {
if (!res.hits || !res.hits.total) return;
// Compute member periods
var lastJoinTime;
var result = res.hits.hits.reduce(function(res, hit){
var isMember = hit._source.code == 'MEMBER_JOIN' || hit._source.code == 'MEMBER_ACTIVE';
// If join
if (isMember && !lastJoinTime) {
lastJoinTime = hit._source.time;
}
// If leave
else if (!isMember && lastJoinTime) {
// Add an entry
res = res.concat({
joinTime: lastJoinTime,
leaveTime: hit._source.time
});
lastJoinTime = 0; // reset
}
return res;
}, []);
if (lastJoinTime) {
// Add last entry if need
result.push({
joinTime: lastJoinTime,
leaveTime: moment().utc().unix()
});
}
return result;
});
};
return {
memberships: loadMemberships
};
});
angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es.http.services']) angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es.http.services', 'cesium.es.wot.services'])
.factory('gpData', function($rootScope, $q, $timeout, esHttp, BMA, csWot, csCache) { .factory('gpData', function($rootScope, $q, $timeout, esHttp, BMA, csWot, csCache, esWot) {
'ngInject'; 'ngInject';
var var
...@@ -155,7 +155,7 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es. ...@@ -155,7 +155,7 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es.
}; };
var promise = $q.all([ var promise = $q.all([
// Get the current block is need // Get the current block (if need)
options.withCurrent ? options.withCurrent ?
BMA.blockchain.current() BMA.blockchain.current()
.catch(function(err) { .catch(function(err) {
...@@ -450,9 +450,10 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es. ...@@ -450,9 +450,10 @@ angular.module('cesium.graph.data.services', ['cesium.wot.services', 'cesium.es.
// If need and missing: load membership periods // If need and missing: load membership periods
if (options.withUD && !options.memberships) { if (options.withUD && !options.memberships) {
return exports.wot.memberships(options) return esWot.memberships(options.pubkey)
.then(function(res) { .then(function(res) {
options.memberships = res || []; options.memberships = res || [];
// loop, with membership filled
return exports.blockchain.movement(currency, options); return exports.blockchain.movement(currency, options);
}); });
} }
......
...@@ -119,8 +119,8 @@ ...@@ -119,8 +119,8 @@
</label> </label>
</div> </div>
<!-- FIXME see issue on UD history --> <!-- FIXME see issue #232 on UD history -->
<!--span class="item item-divider" translate>SETTINGS.HISTORY_SETTINGS</span> <span class="item item-divider" translate>SETTINGS.HISTORY_SETTINGS</span>
<div class="item item-toggle dark"> <div class="item item-toggle dark">
<div class="col col-75 input-label" translate>SETTINGS.DISPLAY_UD_HISTORY</div> <div class="col col-75 input-label" translate>SETTINGS.DISPLAY_UD_HISTORY</div>
...@@ -130,7 +130,7 @@ ...@@ -130,7 +130,7 @@
<div class="handle"></div> <div class="handle"></div>
</div> </div>
</label> </label>
</div--> </div>
<!-- Allow extension here --> <!-- Allow extension here -->
<cs-extension-point name="history"></cs-extension-point> <cs-extension-point name="history"></cs-extension-point>
......
...@@ -21,9 +21,9 @@ ...@@ -21,9 +21,9 @@
{{::tx.comment}}<br/> {{::tx.comment}}<br/>
</p> </p>
<h4> <h4>
<span class="gray" > <a class="gray underline" ui-sref="app.view_block({number: tx.block_number})">
{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}} {{::tx.time | formatFromNow}} | {{::tx.time | formatDate}}
</span> </a>
</h4> </h4>
</div> </div>
<div class="col col-50 no-padding" ng-if="::tx.comment"> <div class="col col-50 no-padding" ng-if="::tx.comment">
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
<!-- not locked TX --> <!-- not locked TX -->
<span ng-if="::!tx.lockedOutputs" class="badge item-note" ng-class="{'badge-calm': tx.amount > 0}"> <span ng-if="::!tx.lockedOutputs" class="badge item-note" ng-class="{'badge-calm': tx.amount > 0}">
<!--<span class="hidden-xs" ng-if=":rebind:tx.amount>0">+</span>-->
<span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span> <span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span>
</span> </span>
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
ng-class="{'badge-calm': tx.amount > 0}" ng-class="{'badge-calm': tx.amount > 0}"
ng-click="showLockedOutputsPopover(tx, $event)"> ng-click="showLockedOutputsPopover(tx, $event)">
<i class="icon ion-locked" ></i> <i class="icon ion-locked" ></i>
<!--<span class="hidden-xs" ng-if=":rebind:tx.amount>0">+</span>-->
<span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span> <span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span>
</a> </a>
......
<i class="icon item-image ion-arrow-up-c energized"></i>
<div class="row no-padding">
<div class="col no-padding">
<span class="energized" translate>COMMON.UNIVERSAL_DIVIDEND</span>
<h4>
<a class="gray underline" ui-sref="app.view_block({number: tx.block_number})">
{{::tx.time | formatFromNow}} | {{::tx.time | formatDate}}
</a>
</h4>
</div>
<div class="col col-10 no-padding">
<span class="badge item-note badge-energized">
<!--<span class="hidden-xs" ng-if=":rebind:tx.amount>0">+</span>-->
<span ng-bind-html=":rebind:tx.amount| formatAmount:{currency:$root.currency.name}"></span>
</span>
<div class="badge badge-secondary" ng-if="$root.settings.expertMode">
(<span ng-bind-html=":rebind:tx.amount| formatAmount:{useRelative: !$root.settings.useRelative, currency:$root.currency.name}"></span>)
</div>
</div>
</div>
...@@ -96,8 +96,8 @@ ...@@ -96,8 +96,8 @@
<div ng-repeat="tx in formData.tx.history" <div ng-repeat="tx in formData.tx.history"
class="item item-tx item-icon-left" class="item item-tx item-icon-left"
ng-include="'templates/wallet/item_tx.html'"> ng-include="!tx.isUD ? 'templates/wallet/item_tx.html' : 'templates/wallet/item_ud.html'">
</div> </div>
<div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0"> <div class="item item-text-wrap text-center" ng-if="formData.tx.fromTime > 0">
<p> <p>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment