Merge pull request #648 from msalcala11/txDetailStyling

Better transaction detail view styling
This commit is contained in:
Matias Alejo Garcia 2016-10-22 21:52:17 -03:00 committed by GitHub
commit 8f46973240
9 changed files with 183 additions and 217 deletions

View File

@ -1,7 +1,7 @@
'use strict';
angular.module('copayApp.controllers').controller('activityController',
function($timeout, $scope, $log, $ionicModal, lodash, txpModalService, profileService, walletService, ongoingProcess, popupService, gettextCatalog) {
function($timeout, $scope, $log, $ionicModal, lodash, txpModalService, profileService, walletService, ongoingProcess, popupService, gettextCatalog, $state) {
$scope.openTxpModal = txpModalService.open;
$scope.fetchingNotifications = true;
@ -66,11 +66,9 @@ angular.module('copayApp.controllers').controller('activityController',
$scope.wallet = wallet;
$scope.btx = lodash.cloneDeep(tx);
$ionicModal.fromTemplateUrl('views/modals/tx-details.html', {
scope: $scope
}).then(function(modal) {
$scope.txDetailsModal = modal;
$scope.txDetailsModal.show();
$state.transitionTo('tabs.wallet.tx-details', {
txid: $scope.btx.txid,
walletId: $scope.walletId
});
walletService.getTxNote(wallet, n.txid, function(err, note) {

View File

@ -1,38 +1,55 @@
'use strict';
angular.module('copayApp.controllers').controller('txDetailsController', function($log, $timeout, $scope, $filter, $stateParams, ongoingProcess, walletService, lodash, gettextCatalog, profileService, configService, txFormatService, externalLinkService, popupService) {
angular.module('copayApp.controllers').controller('txDetailsController', function($log, $timeout, $ionicHistory, $scope, $filter, $stateParams, ongoingProcess, walletService, lodash, gettextCatalog, profileService, configService, txFormatService, externalLinkService, popupService) {
var config = configService.getSync();
var configWallet = config.wallet;
var walletSettings = configWallet.settings;
var wallet;
var wallet = profileService.getWallet($stateParams.walletId);
$scope.wallet = wallet;
$scope.title = gettextCatalog.getString('Transaction');
$scope.init = function() {
wallet = $scope.wallet;
$scope.alternativeIsoCode = walletSettings.alternativeIsoCode;
$scope.color = wallet.color;
$scope.copayerId = wallet.credentials.copayerId;
$scope.isShared = wallet.credentials.n > 1;
$scope.btx.feeLevel = walletSettings.feeLevel;
walletService.getTx(wallet, $stateParams.txid, function(err, tx) {
if (err) {
$log.warn('Could not get tx');
$ionicHistory.goBack();
return;
}
$scope.btx = tx;
$scope.btx.feeLevel = walletSettings.feeLevel;
if ($scope.btx.action != 'invalid') {
if ($scope.btx.action == 'sent') $scope.title = gettextCatalog.getString('Sent Funds');
if ($scope.btx.action == 'received') $scope.title = gettextCatalog.getString('Received Funds');
if ($scope.btx.action == 'moved') $scope.title = gettextCatalog.getString('Moved Funds');
}
if ($scope.btx.action != 'invalid') {
if ($scope.btx.action == 'sent') $scope.title = gettextCatalog.getString('Sent Funds');
if ($scope.btx.action == 'received') $scope.title = gettextCatalog.getString('Received Funds');
if ($scope.btx.action == 'moved') $scope.title = gettextCatalog.getString('Moved Funds');
}
$scope.displayAmount = getDisplayAmount($scope.btx.amountStr);
$scope.displayUnit = getDisplayUnit($scope.btx.amountStr);
updateMemo();
initActionList();
getAlternativeAmount();
updateMemo();
initActionList();
});
};
function getDisplayAmount(amountStr) {
return amountStr.split(' ')[0];
}
function getDisplayUnit(amountStr) {
return amountStr.split(' ')[1];
}
function updateMemo() {
walletService.getTxNote(wallet, $scope.btx.txid, function(err, note) {
if (err) {
$log.warn('Could not fetch transaction note: ' + err);
return;
}
if (!note) return;
$scope.btx.note = note;
@ -49,7 +66,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
});
});
});
};
}
function initActionList() {
$scope.actionList = [];
@ -83,10 +100,13 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
time: $scope.btx.time,
description: actionDescriptions['broadcasted'],
});
};
}
$scope.showCommentPopup = function() {
var opts = {};
if ($scope.btx.message) {
opts.defaultText = $scope.btx.message;
}
if ($scope.btx.note && $scope.btx.note.body) opts.defaultText = $scope.btx.note.body;
popupService.showPrompt(wallet.name, gettextCatalog.getString('Memo'), opts, function(text) {
@ -114,27 +134,12 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
});
};
var getAlternativeAmount = function() {
var satToBtc = 1 / 100000000;
wallet.getFiatRate({
code: $scope.alternativeIsoCode,
ts: $scope.btx.time * 1000
}, function(err, res) {
if (err) {
$log.debug('Could not get historic rate');
return;
}
if (res && res.rate) {
var alternativeAmountBtc = ($scope.btx.amount * satToBtc).toFixed(8);
$scope.rateDate = res.fetchedOn;
$scope.rateStr = res.rate + ' ' + $scope.alternativeIsoCode;
$scope.alternativeAmountStr = $filter('formatFiatAmount')(alternativeAmountBtc * res.rate) + ' ' + $scope.alternativeIsoCode;
$timeout(function() {
$scope.$apply();
});
}
});
$scope.viewOnBlockchain = function() {
var btx = $scope.btx;
var url = 'https://' + ($scope.getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + btx.txid;
var title = 'View Transaction on Insight';
var message = 'Would you like to view this transaction on the Insight blockchain explorer?';
$scope.openExternalLink(url, true, title, message, 'Open Insight', 'Go back');
};
$scope.openExternalLink = function(url, optIn, title, message, okText, cancelText) {
@ -149,4 +154,6 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
$scope.cancel = function() {
$scope.txDetailsModal.hide();
};
$scope.init();
});

View File

@ -68,11 +68,9 @@ angular.module('copayApp.controllers').controller('tabHomeController',
$scope.wallet = wallet;
$scope.btx = lodash.cloneDeep(tx);
$ionicModal.fromTemplateUrl('views/modals/tx-details.html', {
scope: $scope
}).then(function(modal) {
$scope.txDetailsModal = modal;
$scope.txDetailsModal.show();
$state.transitionTo('tabs.wallet.tx-details', {
txid: $scope.btx.txid,
walletId: $scope.walletId
});
walletService.getTxNote(wallet, n.txid, function(err, note) {

View File

@ -86,17 +86,15 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
$scope.close = function() {
$scope.searchModal.hide();
}
};
};
$scope.openTxModal = function(btx) {
$scope.btx = lodash.cloneDeep(btx);
$scope.walletId = $scope.wallet.id;
$ionicModal.fromTemplateUrl('views/modals/tx-details.html', {
scope: $scope
}).then(function(modal) {
$scope.txDetailsModal = modal;
$scope.txDetailsModal.show();
$state.transitionTo('tabs.wallet.tx-details', {
txid: $scope.btx.txid,
walletId: $scope.walletId
});
};

View File

@ -177,6 +177,15 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
}
})
.state('tabs.wallet.tx-details', {
url: '/tx-details/:txid',
views: {
'tab-home@tabs': {
controller: 'txDetailsController',
templateUrl: 'views/modals/tx-details.html'
}
}
})
/*
*
@ -847,7 +856,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
*
*/
.state('tabs.bitpayCardIntro', {
.state('tabs.bitpayCardIntro', {
url: '/bitpay-card-intro/:secret/:email/:otp',
views: {
'tab-home@tabs': {

View File

@ -24,6 +24,10 @@
img {
margin-right: 1rem;
}
span {
text-transform: capitalize;
}
}
.amount-label{
line-height: 30px;
@ -191,7 +195,7 @@
}
> div {
border: 3px solid #09C286;
border: 3px solid #13e5b6;
border-radius: 50%;
display: flex;
height: 26px;
@ -201,7 +205,7 @@
justify-content: center;
font-weight: 600;
vertical-align: middle;
color: #09C286;
color: #13e5b6;
&.rejected {
background: #E15061;
@ -231,4 +235,10 @@
color: $item-label-color;
padding: 1rem 2rem;
}
.view-on-blockchain-btn {
background: #e8e7e7;
color: rgba(58, 58, 58, .6);
margin-bottom: 1.5rem;
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="25px" height="25px" viewBox="0 0 25 25" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Wallet" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="1.4---Transaction-(Detail)" transform="translate(-39.000000, -914.000000)">
<g id="Group-2-Copy-6" transform="translate(41.000000, 909.000000)">
<g id="Group" transform="translate(0.000000, 7.000000)">
<path d="M10.5,21 C16.2989899,21 21,16.2989899 21,10.5 C21,4.70101013 16.2989899,0 10.5,0 C4.70101013,0 0,4.70101013 0,10.5 C0,16.2989899 4.70101013,21 10.5,21 Z" id="Oval-2-Copy-3" stroke="#13E5B6" stroke-width="3" fill="#13E5B6"></path>
<path d="M4.8565172,10.7739543 L17.6308211,10.7739543 M9.55650668,16.6261508 L3.82082067,10.8572239 L9.35708555,5.17917933" id="Line" stroke="#FFFFFF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="translate(10.725821, 10.902665) scale(1, -1) rotate(-135.000000) translate(-10.725821, -10.902665) "></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="33px" height="33px" viewBox="0 0 33 33" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons/Transaction/Complete" transform="translate(-8.000000, -8.000000)">
<g id="Icons/Send">
<g id="Group" transform="translate(8.000000, 8.000000)">
<path d="M16.5,33 C25.6126984,33 33,25.6126984 33,16.5 C33,7.38730163 25.6126984,0 16.5,0 C7.38730163,0 0,7.38730163 0,16.5 C0,25.6126984 7.38730163,33 16.5,33 Z" id="Oval-204" fill="#F2FEF7"></path>
<polyline id="Shape" stroke="#12E5B6" stroke-width="2" points="8 17 15 24 25.5 10"></polyline>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -1,178 +1,90 @@
<ion-modal-view ng-controller="txDetailsController" ng-init="init()" id="tx-details">
<ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color, 'border-color': color}">
<button class="button button-clear" ng-click="cancel()">
{{'Close' | translate}}
</button>
<div class="title">
<ion-view id="view-confirm" hide-tabs>
<ion-nav-bar class="bar-royal">
<ion-nav-title>
{{title}}
</div>
</ion-header-bar>
</ion-nav-title>
<ion-nav-back-button>
</ion-nav-back-button>
</ion-nav-bar>
<ion-content>
<div class="header-modal text-center" ng-init="showRate = false">
<div ng-show="btx.action != 'invalid'">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-style="{'background-color': color}" class="bg"/>
</i>
<div class="size-36 m20t" copy-to-clipboard="btx.amountStr">
{{btx.amountStr}}
</div>
<div class="m10t" style="height:20px;" ng-click="showRate =! showRate">
<span ng-show="!showRate && alternativeAmountStr">
{{alternativeAmountStr}}
</span>
<span ng-show="showRate && alternativeAmountStr">
{{rateStr}} ({{rateDate | amDateFormat:'MM/DD/YYYY HH:mm a'}})
</span>
</div>
</div>
<div ng-show="btx.action == 'sent'">
<div>
<span translate>Sent from</span>
<strong ng-style="{'color': color}">{{wallet.credentials.walletName}}</strong>
</div>
<i class="icon ion-ios-arrow-thin-down size-24"></i>
</div>
<div ng-show="btx.action == 'received'">
<div class="padding-vertical">
<i class="icon ion-ios-arrow-thin-up size-24"></i>
</div>
<span translate>Received Funds</span>
</div>
<div ng-show="btx.action == 'moved'">
<span translate>Moved Funds</span>
</div>
<div ng-show="btx.action == 'invalid'">
-
</div>
</div>
<div class="list">
<div class="item item-icon-left" ng-show="btx.action == 'sent' && !btx.hasMultiplesOutputs && btx.addressTo && btx.addressTo != 'N/A'">
<i class="icon icon-svg"><img src="img/icon-bitcoin-symbol.svg"></i>
<div copy-to-clipboard="btx.addressTo">
<span ng-if="btx.merchant">
<span ng-show="btx.merchant.pr.ca"><i class="fi-lock color-greeni"></i> {{btx.merchant.domain}}</span>
<span ng-show="!btx.merchant.pr.ca"><i class="fi-unlock color-yellowi"></i> {{btx.merchant.domain}}</span>
</span>
<span ng-if="!btx.merchant">
<span ng-show="btx.labelTo">{{btx.labelTo}}</span>
<contact ng-show="!btx.labelTo" address="{{btx.addressTo}}"></contact>
</span>
<div class="item head">
<div class="sending-label">
<img src="img/icon-check-circled.svg">
<span translate>{{btx.action | translate}}</span>
</div>
<div class="amount-label">
<div class="amount">{{displayAmount}} <span class="unit">{{displayUnit}}</span></div>
<div class="alternative">{{btx.alternativeAmountStr}}</div>
</div>
</div>
<div ng-show="btx.hasMultiplesOutputs" class="item item-icon-right item-heading" ng-click="showMultiplesOutputs = !showMultiplesOutputs">
{{'Recipients'|translate}}
[ {{btx.recipientCount}} ]
<i class="icon bp-arrow-up" ng-show="showMultiplesOutputs"></i>
<i class="icon bp-arrow-down" ng-show="!showMultiplesOutputs"></i>
</div>
<div class="item" ng-show="btx.hasMultiplesOutputs && showMultiplesOutputs"
ng-repeat="output in btx.outputs"
ng-include="'views/includes/output.html'">
</div>
<div class="item item-icon-left"
ng-click="openExternalLink('https://' + (getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + btx.txid, true, 'View Transaction on Insight', 'Would you like to view this transaction on the Insight blockchain explorer?', 'Open Insight', 'Go back')">
<i class="icon ion-ios-upload-outline"></i>
<span class="text-gray" translate>View transaction on the blockchain</span>
</div>
<div class="item">
<div ng-if="btx.action == 'received' || btx.action == 'moved'">
{{'Date'|translate}}
<span class="item-note">
<time>{{ btx.time * 1000 | amDateFormat:'MM/DD/YYYY HH:mm a'}}</time>
</span>
</div>
<div ng-if="btx.action == 'sent'">
{{'Created by'|translate}} <strong>{{btx.creatorName}}</strong>
<span class="item-note">
<time>{{ btx.createdOn * 1000 | amDateFormat:'MM/DD/YYYY HH:mm a'}}</time>
</span>
</div>
</div>
<div class="item" ng-if="btx.action != 'received' && btx.feeStr" copy-to-clipboard="btx.feeStr">
{{'Fee'|translate}}: {{btx.feeStr}}
<span class="item-note">
<span class="text-warning" ng-show="!btx.confirmations || btx.confirmations == 0" translate>
Unconfirmed
</span>
<span class="label gray radius" ng-show="btx.confirmations>0 && !btx.safeConfirmed">
{{btx.confirmations}}
</span>
<span class="label gray radius" ng-show="btx.safeConfirmed">
{{btx.safeConfirmed}}
</span>
<span ng-show="btx.confirmations && btx.confirmations > 0" translate>Confirmations</span>
</span>
</div>
<div class="item" ng-if="btx.message && btx.action != 'received'" copy-to-clipboard="btx.message">
{{'Description'|translate}}
<span class="item-note">
{{btx.message}}
</span>
</div>
<div ng-if="btx.merchant" class="item" copy-to-clipboard="btx.merchant.pr.pd.memo">
{{'Merchant message'|translate}}
<span class="item-note">
{{btx.merchant.pr.pd.memo}}
</span>
</div>
<div ng-if="btx.action == 'invalid'" class="item">
<span class="right" translate>
This transaction has become invalid; possibly due to a double spend attempt.
</span>
</div>
<div class="item" ng-click="showCommentPopup()">
{{'Memo'|translate}}
<span class="item-note" translate ng-if="!btx.note">
<i class="icon ion-ios-plus-empty"></i>
</span>
<span class="item-note" ng-if="btx.note && btx.note.body">
{{btx.note.body}}
<div>
<span translate>Edited by</span> {{btx.note.editedByName}},
<time>{{btx.note.editedOn * 1000 | amTimeAgo}}</time>
</div>
</span>
</div>
<div ng-if="actionList[0]">
<div class="item item-divider" translate>Timeline</div>
<div class="item" ng-class="{'action-created' : a.type == 'created' || a.type == 'accept', 'action-rejected' : a.type == 'reject'}" ng-repeat="a in actionList | orderBy: 'time' :true track by $index">
<div class="row">
<div class="col col-10">
<span id="timeline-icon">{{actionList.length - $index}}</span>
<div class="info">
<div class="item" ng-if="btx.action === 'sent'">
<span class="label" translate>To</span>
<span class="payment-proposal-to">
<img ng-if="!cardId" src="img/icon-bitcoin-small.svg">
<img ng-if="cardId" src="img/icon-card.svg" width="34">
<div copy-to-clipboard="toAddress" class="ellipsis">
<contact ng-if="!toName" address="{{btx.addressTo}}" class="ellipsis" style="display: block;"></contact>
<span class="m15l size-14" ng-if="toName">{{toName}}</span>
</div>
<div class="col">
<div>{{a.description}}</div>
</span>
</div>
<div class="item">
<span class="label" ng-if="btx.action === 'sent'" translate>From</span>
<span class="label" ng-if="btx.action !== 'sent'" translate>To</span>
<div class="wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-style="{'background-color': wallet.color}" class="bg"/>
</i>
<div>{{wallet.name}}</div>
</div>
</div>
<a class="item single-line item-icon-right" ng-hide="insuffientFunds" ng-click="showCommentPopup()">
<span class="label" translate>Memo</span>
<span class="item-note m10l">
{{btx.note.body || btx.message}}
</span>
<i class="icon bp-arrow-right"></i>
</a>
<div class="item single-line" ng-hide="insuffientFunds">
<span class="label" translate>Fee</span>
<span class="item-note">
{{btx.feeStr}}
</span>
</div>
<div ng-if="actionList[0]">
<div class="item item-divider" translate>Timeline</div>
<div class="item timeline-item" ng-class="{'action-created' : a.type == 'created' || a.type == 'accept', 'action-rejected' : a.type == 'reject'}" ng-repeat="a in actionList | orderBy: 'time' :true track by $index">
<div class="timeline-content">
<div class="timeline-content__icon">
<div class="rejected" ng-if="a.type === 'reject'">!</div>
<img src="img/icon-broadcasted.svg" ng-if="a.type === 'broadcasted'">
<div ng-if="a.type !== 'reject' && a.type !== 'broadcasted'">
{{actionList.length - $index}}
</div>
</div>
<div class="timeline-content__label">
<div class="action">{{a.description}}</div>
<div class="name">{{a.by}}</div>
</div>
<div>
<span>{{a.by}}</span>
<span class="item-note">
<time>{{ a.time * 1000 | amDateFormat:'MM/DD/YYYY HH:mm a'}}</time>
<time>{{ a.time * 1000 | amDateFormat:'hh:mm a'}}</time>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<button class="view-on-blockchain-btn button button-standard button-primary" ng-click="viewOnBlockchain()" translate>
View on blockchain
</button>
</ion-content>
</ion-modal-view>
</ion-view>