fix(feedback): improve design of feedback flow, correct several logic issues

This commit is contained in:
Jason Dreyzehner 2016-11-16 18:15:55 -05:00
parent 57ab21dd55
commit f7e6f30d12
13 changed files with 85 additions and 75 deletions

View File

@ -32,6 +32,7 @@ angular.module('copayApp.controllers').controller('completeController', function
$scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null; $scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null;
$scope.skipped = (data.stateParams && data.stateParams.skipped) ? true : false; $scope.skipped = (data.stateParams && data.stateParams.skipped) ? true : false;
$scope.rated = (data.stateParams && data.stateParams.rated) ? true : false;
storageService.getFeedbackInfo(function(error, info) { storageService.getFeedbackInfo(function(error, info) {
var feedbackInfo = lodash.isString(info) ? JSON.parse(info) : null; var feedbackInfo = lodash.isString(info) ? JSON.parse(info) : null;
@ -40,6 +41,7 @@ angular.module('copayApp.controllers').controller('completeController', function
}); });
if (!$scope.isCordova) return; if (!$scope.isCordova) return;
$scope.animate = true;
window.plugins.socialsharing.available(function(isAvailable) { window.plugins.socialsharing.available(function(isAvailable) {
// the boolean is only false on iOS < 6 // the boolean is only false on iOS < 6

View File

@ -8,25 +8,21 @@ angular.module('copayApp.controllers').controller('rateAppController', function(
var config = configService.getSync(); var config = configService.getSync();
$scope.skip = function() { $scope.skip = function() {
var dataSrc = { var dataSrc = {
"Email": lodash.values(config.emailFor)[0] || ' ', "Email": lodash.values(config.emailFor)[0] || ' ',
"Feedback": ' ', "Feedback": ' ',
"Score": $stateParams.score "Score": $stateParams.score
}; };
ongoingProcess.set('sendingFeedback', true);
feedbackService.send(dataSrc, function(err) { feedbackService.send(dataSrc, function(err) {
ongoingProcess.set('sendingFeedback', false);
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send feedback')); // try to send, but not essential, since the user didn't add a message
return; $log.warn('Could not send feedback.');
} }
});
$state.go('tabs.rate.complete', { $state.go('tabs.rate.complete', {
score: $stateParams.score, score: $stateParams.score,
skipped: true skipped: true
}); });
});
}; };
$scope.sendFeedback = function() { $scope.sendFeedback = function() {
@ -42,5 +38,9 @@ angular.module('copayApp.controllers').controller('rateAppController', function(
if (isIOS) url = defaults.rateApp.ios; if (isIOS) url = defaults.rateApp.ios;
// if (isWP) url = defaults.rateApp.windows; // TODO // if (isWP) url = defaults.rateApp.windows; // TODO
externalLinkService.open(url); externalLinkService.open(url);
$state.go('tabs.rate.complete', {
score: $stateParams.score,
rated: true
});
}; };
}); });

View File

@ -6,6 +6,7 @@ angular.module('copayApp.controllers').controller('rateCardController', function
$scope.score = 0; $scope.score = 0;
$scope.goFeedbackFlow = function() { $scope.goFeedbackFlow = function() {
$scope.hideCard();
if ($scope.isCordova && $scope.score == 5) { if ($scope.isCordova && $scope.score == 5) {
$state.go('tabs.rate.rateApp', { $state.go('tabs.rate.rateApp', {
score: $scope.score score: $scope.score

View File

@ -2,7 +2,7 @@
angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $timeout, $stateParams, $ionicNavBarDelegate, $ionicHistory, $ionicConfig, $window, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess) { angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $timeout, $stateParams, $ionicNavBarDelegate, $ionicHistory, $ionicConfig, $window, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess) {
$scope.sendFeedback = function(feedback, skip) { $scope.sendFeedback = function(feedback, skip, goHome) {
var config = configService.getSync(); var config = configService.getSync();
@ -15,11 +15,12 @@ angular.module('copayApp.controllers').controller('sendController', function($sc
"DeviceVersion": ionic.Platform.version() "DeviceVersion": ionic.Platform.version()
}; };
ongoingProcess.set('sendingFeedback', true); if(!(goHome || skip)) ongoingProcess.set('sendingFeedback', true);
feedbackService.send(dataSrc, function(err) { feedbackService.send(dataSrc, function(err) {
if(goHome || skip) return;
ongoingProcess.set('sendingFeedback', false); ongoingProcess.set('sendingFeedback', false);
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send feedback')); popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Feedback could not be submitted. Please try again later.'));
return; return;
} }
if (!$stateParams.score) { if (!$stateParams.score) {
@ -30,7 +31,7 @@ angular.module('copayApp.controllers').controller('sendController', function($sc
historyRoot: true historyRoot: true
}); });
$ionicHistory.goBack(); $ionicHistory.goBack();
}); }, gettextCatalog.getString('Finish'));
return; return;
} }
$state.go('tabs.rate.complete', { $state.go('tabs.rate.complete', {
@ -38,6 +39,14 @@ angular.module('copayApp.controllers').controller('sendController', function($sc
skipped: skip skipped: skip
}); });
}); });
if(goHome){
$state.go('tabs.home');
} else if(skip) {
$state.go('tabs.rate.complete', {
score: $stateParams.score,
skipped: skip
});
}
}; };
$scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.$on("$ionicView.beforeEnter", function(event, data) {
@ -71,7 +80,7 @@ angular.module('copayApp.controllers').controller('sendController', function($sc
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay.") + ' ' + gettextCatalog.getString("Is there anything we could do better?"); $scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay.") + ' ' + gettextCatalog.getString("Is there anything we could do better?");
break; break;
default: default:
$scope.reaction = gettextCatalog.getString("Feedback!"); $scope.reaction = gettextCatalog.getString("Send Feedback");
$scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay. How could we improve your experience?"); $scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay. How could we improve your experience?");
break; break;
} }

View File

@ -3,8 +3,9 @@
.close-button { .close-button {
color: $dark-gray; color: $dark-gray;
position: absolute; position: absolute;
top: 10px; top: 5px;
right: 15px; right: 10px;
padding: 15px;
font-size: 36px; font-size: 36px;
} }
.complete-layout { .complete-layout {
@ -13,11 +14,22 @@
height: 100%; height: 100%;
&__expand { &__expand {
display: flex; display: flex;
flex-direction: column;
flex-grow: 1; flex-grow: 1;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center;
opacity: 0;
transition: opacity .3s;
&.fade-in {
opacity: 1;
} }
} }
}
.share-the-love-illustration {
width: 5rem;
margin: 1rem;
}
.title { .title {
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
@ -45,14 +57,23 @@
height: 50px; height: 50px;
} }
.share-buttons { .share-buttons {
padding: 50px 10px; padding: 50px 10px 30px;
background-color: $subtle-gray; background-color: $subtle-gray;
text-align: center; text-align: center;
transition: transform .3s cubic-bezier(0.4, 0.0, 0.2, 1) .2s, opacity .5s ease-in .2s;
transform: translateY(100%);
opacity: 0;
&.slide-up {
transform: translateY(0);
opacity: 1;
}
} }
.share-buttons__action { .share-buttons__action {
display: inline-block; display: inline-block;
color: #667; color: #667;
font-size: .9rem; font-size: .9rem;
width: 90px; width: 90px;
height: 90px;
margin-bottom: 20px;
} }
} }

View File

@ -28,9 +28,11 @@
} }
.user-feedback { .user-feedback {
border-top: 1px solid $subtle-gray; border-top: 1px solid $subtle-gray;
border-bottom: 1px solid $subtle-gray;
padding: 20px; padding: 20px;
width: 100%; width: 100%;
margin-bottom: 20px; margin-bottom: 20px;
-webkit-appearance: none;
} }
.send-feedback-star { .send-feedback-star {
height: 1rem; height: 1rem;

View File

@ -5,7 +5,7 @@
<desc>Created with sketchtool.</desc> <desc>Created with sketchtool.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-277.000000, -769.000000)" stroke="#8F8F90"> <g id="Icons" transform="translate(-277.000000, -769.000000)" stroke="#9b9bab">
<g id="icons/list-items/sync" transform="translate(278.000000, 770.000000)"> <g id="icons/list-items/sync" transform="translate(278.000000, 770.000000)">
<g id="Group" transform="translate(0.347826, 0.378151)"> <g id="Group" transform="translate(0.347826, 0.378151)">
<path d="M14.889225,12.3491049 C16.1172023,11.0140665 16.8846881,9.34526854 16.8846881,7.50959079 C16.8846881,3.33759591 13.1240076,0 8.44234405,0 C3.76068053,0 0,3.33759591 0,7.50959079 C0,11.6815857 3.76068053,15.0191816 8.44234405,15.0191816 C9.28657845,15.0191816 10.0540643,14.9357417 10.8215501,14.685422 L15.3497164,16.6879795 L14.889225,12.3491049 L14.889225,12.3491049 Z" id="Shape"></path> <path d="M14.889225,12.3491049 C16.1172023,11.0140665 16.8846881,9.34526854 16.8846881,7.50959079 C16.8846881,3.33759591 13.1240076,0 8.44234405,0 C3.76068053,0 0,3.33759591 0,7.50959079 C0,11.6815857 3.76068053,15.0191816 8.44234405,15.0191816 C9.28657845,15.0191816 10.0540643,14.9357417 10.8215501,14.685422 L15.3497164,16.6879795 L14.889225,12.3491049 L14.889225,12.3491049 Z" id="Shape"></path>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -5,7 +5,7 @@
<desc>Created with sketchtool.</desc> <desc>Created with sketchtool.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-542.000000, -768.000000)" stroke="#8F8F90"> <g id="Icons" transform="translate(-542.000000, -768.000000)" stroke="#9b9bab">
<g id="icons/list-items/sync" transform="translate(543.000000, 769.000000)"> <g id="icons/list-items/sync" transform="translate(543.000000, 769.000000)">
<g id="Group" transform="translate(0.392391, 0.413043)"> <g id="Group" transform="translate(0.392391, 0.413043)">
<path d="M6.28767826,13.3123913 C6.33555,14.6357826 7.36361522,15.6956522 8.6326087,15.6956522 C9.90160217,15.6956522 10.927313,14.6357826 10.9759696,13.3123913" id="Shape"></path> <path d="M6.28767826,13.3123913 C6.33555,14.6357826 7.36361522,15.6956522 8.6326087,15.6956522 C9.90160217,15.6956522 10.927313,14.6357826 10.9759696,13.3123913" id="Shape"></path>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -5,7 +5,7 @@
<desc>Created with sketchtool.</desc> <desc>Created with sketchtool.</desc>
<defs></defs> <defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons" transform="translate(-666.000000, -770.000000)" stroke="#8F8F90"> <g id="Icons" transform="translate(-666.000000, -770.000000)" stroke="#9b9bab">
<g id="icons/list-items/sync" transform="translate(666.769231, 770.000000)"> <g id="icons/list-items/sync" transform="translate(666.769231, 770.000000)">
<g id="Group" transform="translate(0.368286, 0.383523)"> <g id="Group" transform="translate(0.368286, 0.383523)">
<g id="holidays-24px-outline_message" transform="translate(0.298380, 0.949811)"> <g id="holidays-24px-outline_message" transform="translate(0.298380, 0.949811)">

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -1,81 +1,51 @@
<ion-view id="complete" hide-tabs> <ion-view id="complete" hide-tabs>
<ion-content scroll="false"> <ion-content scroll="false">
<a class="close-button" ng-click="close()"><i class="icon ion-ios-close-empty close-home-tip"></i></a> <a class="close-button" ng-click="close()"><i class="icon ion-ios-close-empty close-home-tip"></i></a>
<div ng-show="skipped && isCordova"> <div class="complete-layout">
<div ng-show="score > 3"> <div class="complete-layout__expand" ng-class="{'fade-in': !animate || socialsharing}">
<div class="title" translate>Invite friends to BitPay!</div> <div ng-switch="score && !skipped || rated">
<div class="text-center"> <div class="title" ng-switch-when="true" translate>Thank you!</div>
<i class="icon addressbook-icon-svg"> <div ng-switch-default>
<img src="img/address-book-add.svg"/> <div class="title" translate>Share BitPay</div>
</i> <img src="img/ico-positive-feedback.svg" class="share-the-love-illustration"/>
</div>
<div class="subtitle">
<span translate>Share the love by inviting your friends.</span>
</div> </div>
</div> </div>
<div ng-show="score <= 3"> <div class="subtitle" ng-show="!skipped && !rated" translate>A member of the team will review your feedback as soon as possible.</div>
<div class="title" translate>Thank you!</div> <img src="img/ico-positive-feedback.svg" ng-if="rated && socialsharing" class="share-the-love-illustration"/>
<div class="subtitle"> <div class="subtitle" ng-if="score > 3 && socialsharing" translate>Share the love by inviting your friends.</div>
<span translate>A member of the team will review your feedback as soon as possible.</span> <div class="subtitle" ng-if="score <= 3 || !socialsharing" translate>If you have additional feedback, please let us know by tapping the "Send feedback" option in the Settings tab.</div>
</div> <div class="text-center" ng-if="score <= 3 || !socialsharing">
<div class="subtitle" ng-if="score <= 3 || !isCordova">
<span translate>If you have additional feedback, please let us know by tapping the "Send feedback" option in the Settings tab.</span>
</div>
<div ng-if="score <= 3 || !isCordova">
<div class="text-center">
<i class="icon icon-svg"> <i class="icon icon-svg">
<img src="img/illustration-send-feedback.png"/> <img src="img/illustration-send-feedback.png"/>
</i> </i>
</div> </div>
</div> </div>
</div> <div class="share-buttons" ng-show="socialsharing" ng-class="{'slide-up': !animate || socialsharing }">
</div> <div class="share-buttons__action" ng-show="facebook" ng-click="shareFacebook()">
<div ng-show="!skipped || !isCordova">
<div class="title" translate>Thank you!</div>
<div class="subtitle">
<span translate>A member of the team will review your feedback as soon as possible.</span>
</div>
<div class="subtitle" ng-if="score <= 3 || !isCordova">
<span translate>If you have additional feedback, please let us know by tapping the "Send feedback" option in the Settings tab.</span>
</div>
<div ng-if="score <= 3 || !isCordova">
<div class="text-center">
<i class="icon icon-svg">
<img src="img/illustration-send-feedback.png"/>
</i>
</div>
</div>
<div class="text-center" ng-if="score > 3 && isCordova">
<span translate>Share the love by inviting your friends.</span>
</div>
</div>
<div class="share-buttons" ng-if="isCordova && score > 3">
<div class="ng-hide" ng-show="socialsharing" ng-if="score >= 4">
<div class="share-buttons__action ng-hide" ng-show="facebook" ng-click="shareFacebook()">
<i class="icon socialsharing-icon"> <i class="icon socialsharing-icon">
<img src="img/social-icons/ico-social-facebook.svg"/> <img src="img/social-icons/ico-social-facebook.svg"/>
</i> </i>
<div>Facebook</div> <div>Facebook</div>
</div> </div>
<div class="share-buttons__action ng-hide" ng-show="twitter" ng-click="shareTwitter()"> <div class="share-buttons__action" ng-show="twitter" ng-click="shareTwitter()">
<i class="icon socialsharing-icon"> <i class="icon socialsharing-icon">
<img src="img/social-icons/ico-social-twitter.svg"/> <img src="img/social-icons/ico-social-twitter.svg"/>
</i> </i>
<div>Twitter</div> <div>Twitter</div>
</div> </div>
<div class="share-buttons__action ng-hide" ng-show="googleplus" ng-click="shareGooglePlus()"> <div class="share-buttons__action" ng-show="googleplus" ng-click="shareGooglePlus()">
<i class="icon socialsharing-icon"> <i class="icon socialsharing-icon">
<img src="img/social-icons/ico-social-googleplus.svg"/> <img src="img/social-icons/ico-social-googleplus.svg"/>
</i> </i>
<div>Google+</div> <div>Google+</div>
</div> </div>
<div class="share-buttons__action ng-hide" ng-show="email" ng-click="shareEmail()"> <div class="share-buttons__action" ng-show="email" ng-click="shareEmail()">
<i class="icon socialsharing-icon"> <i class="icon socialsharing-icon">
<img src="img/social-icons/ico-social-email.svg"/> <img src="img/social-icons/ico-social-email.svg"/>
</i> </i>
<div>Email</div> <div>Email</div>
</div> </div>
<div class="share-buttons__action ng-hide" ng-show="whatsapp" ng-click="shareWhatsapp()"> <div class="share-buttons__action" ng-show="whatsapp" ng-click="shareWhatsapp()">
<i class="icon socialsharing-icon"> <i class="icon socialsharing-icon">
<img src="img/social-icons/ico-social-whatsapp.svg"/> <img src="img/social-icons/ico-social-whatsapp.svg"/>
</i> </i>

View File

@ -2,9 +2,14 @@
<ion-nav-bar class="bar-royal"> <ion-nav-bar class="bar-royal">
<ion-nav-back-button> <ion-nav-back-button>
</ion-nav-back-button> </ion-nav-back-button>
<ion-nav-buttons side="primary">
<button ng-show="score" class="button no-border" ng-click="sendFeedback(null, true, true)" translate>
Cancel
</button>
</ion-nav-buttons>
<ion-nav-buttons side="secondary"> <ion-nav-buttons side="secondary">
<button ng-show="score" class="button no-border" ng-click="sendFeedback(null, true)" translate> <button ng-disabled="!feedback.value" class="button no-border" type="submit" ng-click="sendFeedback(feedback.value, false)" translate>
Skip Send
</button> </button>
</ion-nav-buttons> </ion-nav-buttons>
</ion-nav-bar> </ion-nav-bar>

View File

@ -31,7 +31,7 @@
</a> </a>
<a class="item item-icon-left item-icon-right" ui-sref="tabs.feedback"> <a class="item item-icon-left item-icon-right" ui-sref="tabs.feedback">
<i class="icon big-icon-svg"> <i class="icon big-icon-svg">
<img src="img/icon-send-feedback.svg" class="bg"/> <img src="img/icon-language.svg" class="bg"/>
</i> </i>
<span translate>Send Feedback</span> <span translate>Send Feedback</span>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>