Added toast config and messages when saving from vault. Persist scroll position when returning to vault from other pages.

This commit is contained in:
Kyle Spearrin 2016-09-12 19:48:36 -04:00
parent ba5286c438
commit 5f39939d65
17 changed files with 154 additions and 30 deletions

View File

@ -81,16 +81,20 @@ gulp.task('lib', ['clean:lib'], function () {
src: paths.npmDir + 'angular-ui-router/release/*.js',
dest: paths.libDir + 'angular-ui-router'
},
{
src: [paths.npmDir + 'angular-toastr/dist/angular-toastr.tpls.js', paths.npmDir + 'angular-toastr/dist/angular-toastr.css'],
dest: paths.libDir + 'angular-toastr'
},
{
src: [paths.npmDir + 'sjcl/core/cbc.js', paths.npmDir + 'sjcl/core/bitArray.js', paths.npmDir + 'sjcl/sjcl.js'],
dest: paths.libDir + 'sjcl'
},
{
src: paths.npmDir + 'ngclipboard/dist/ngclipboard*.js',
src: paths.npmDir + 'ngclipboard/dist/ngclipboard.js',
dest: paths.libDir + 'ngclipboard'
},
{
src: paths.npmDir + 'clipboard/dist/clipboard*.js',
src: paths.npmDir + 'clipboard/dist/clipboard.js',
dest: paths.libDir + 'clipboard'
}
];

View File

@ -22,6 +22,7 @@
"run-sequence": "1.2.2",
"ngclipboard": "1.1.1",
"clipboard": "1.5.12",
"merge-stream": "1.0.0"
"merge-stream": "1.0.0",
"angular-toastr": "2.1.1"
}
}

View File

@ -3,6 +3,7 @@
'ui.router',
'angular-jwt',
'ngAnimate',
'toastr',
'bit.directives',
'bit.services',

View File

@ -1,7 +1,7 @@
angular
.module('bit')
.config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider) {
.config(function ($stateProvider, $urlRouterProvider, $httpProvider, jwtInterceptorProvider, toastrConfig) {
jwtInterceptorProvider.urlParam = 'access_token';
jwtInterceptorProvider.tokenGetter = /*@ngInject*/ function (config, appSettings, tokenService) {
if (config.url.indexOf(appSettings.apiUri) === 0) {
@ -11,6 +11,13 @@
}
};
angular.extend(toastrConfig, {
closeButton: true,
progressBar: true,
showMethod: 'slideDown',
positionClass: 'toast-bottom-center'
});
if ($httpProvider.defaults.headers.post) {
$httpProvider.defaults.headers.post = {};
}
@ -56,7 +63,8 @@
.state('tabs.vault', {
url: "/vault",
templateUrl: "app/vault/views/vault.html",
controller: 'vaultController'
controller: 'vaultController',
params: { scrollY: 0 }
})
.state('tabs.settings', {
url: "/settings",
@ -74,21 +82,21 @@
templateUrl: "app/vault/views/vaultViewSite.html",
controller: 'vaultViewSiteController',
data: { authorize: true },
params: { animation: null }
params: { animation: null, returnScrollY: 0 }
})
.state('addSite', {
url: "/add-site",
templateUrl: "app/vault/views/vaultAddSite.html",
controller: 'vaultAddSiteController',
data: { authorize: true },
params: { animation: null }
params: { animation: null, returnScrollY: 0 }
})
.state('editSite', {
url: "/edit-site?siteId",
templateUrl: "app/vault/views/vaultEditSite.html",
controller: 'vaultEditSiteController',
data: { authorize: true },
params: { animation: null, fromView: true }
params: { animation: null, fromView: true, returnScrollY: 0 }
});
})
.run(function ($rootScope, userService, loginService, tokenService, $state) {

View File

@ -1,7 +1,9 @@
angular
.module('bit.vault')
.controller('vaultAddSiteController', function ($scope, $state, siteService, folderService, cipherService, $q) {
.controller('vaultAddSiteController', function ($scope, $state, $stateParams, siteService, folderService, cipherService, $q) {
var returnScrollY = $stateParams.returnScrollY;
$scope.site = {
folderId: null
};
@ -39,14 +41,14 @@
var site = new Site(siteModel, true);
return site;
}).then(function (site) {
return saveSite(site, function (site) {
alert('Saved ' + site.id + '!');
return saveSite(site).then(function (site) {
toastr.success('Added site');
});
});
};
$scope.close = function () {
$state.go('tabs.vault', { animation: 'out-slide-down' });
$state.go('tabs.vault', { animation: 'out-slide-down', scrollY: returnScrollY || 0 });
};
function saveSite(site) {

View File

@ -1,10 +1,10 @@
angular
.module('bit.vault')
.controller('vaultController', function ($scope, $rootScope, siteService, folderService, $q, cipherService) {
.controller('vaultController', function ($scope, $rootScope, siteService, folderService, $q, cipherService, $state, $stateParams) {
var delayLoad = true;
if (!$rootScope.vaultSites) {
$rootScope.vaultSites =[];
$rootScope.vaultSites = [];
delayLoad = false;
}
if (!$rootScope.vaultFolders) {
@ -13,6 +13,7 @@
}
if (delayLoad) {
setTimeout(setScrollY, 100);
setTimeout(loadVault, 1000);
}
else {
@ -64,6 +65,9 @@
$q.all(promises).then(function () {
$rootScope.vaultSites = decSites;
$rootScope.vaultFolders = decFolders;
if (!delayLoad) {
setScrollY();
}
});
});
});
@ -76,4 +80,31 @@
return item.name.toLowerCase();
};
$scope.addSite = function () {
$state.go('addSite', {
animation: 'in-slide-up',
returnScrollY: getScrollY()
});
};
$scope.viewSite = function (site) {
$state.go('viewSite', {
siteId: site.id,
animation: 'in-slide-up',
returnScrollY: getScrollY()
});
};
function getScrollY() {
var content = document.getElementsByClassName('content')[0];
return content.scrollTop;
};
function setScrollY() {
if ($stateParams.scrollY) {
var content = document.getElementsByClassName('content')[0];
content.scrollTop = $stateParams.scrollY;
}
};
});

View File

@ -1,7 +1,9 @@
angular
angular
.module('bit.vault')
.controller('vaultEditSiteController', function ($scope, $state, $stateParams, siteService, folderService, cipherService, $q) {
.controller('vaultEditSiteController', function ($scope, $state, $stateParams, siteService, folderService, cipherService, $q, toastr) {
var returnScrollY = $stateParams.returnScrollY;
$scope.site = {
folderId: null
};
@ -44,8 +46,8 @@
var site = new Site(siteModel, true);
return site;
}).then(function (site) {
return saveSite(site, function (site) {
alert('Saved ' + site.id + '!');
return saveSite(site).then(function (site) {
toastr.success('Edited site');
});
});
};
@ -55,7 +57,7 @@
$state.go('viewSite', { siteId: $stateParams.siteId, animation: 'out-slide-down' });
}
else {
$state.go('tabs.vault', { animation: 'out-slide-down' });
$state.go('tabs.vault', { animation: 'out-slide-down', scrollY: returnScrollY || 0 });
}
};

View File

@ -1,2 +1,2 @@
angular
.module('bit.vault', ['ngAnimate']);
.module('bit.vault', ['ngAnimate', 'toastr']);

View File

@ -1,7 +1,9 @@
angular
.module('bit.vault')
.controller('vaultViewSiteController', function ($scope, $stateParams, siteService, cipherService) {
.controller('vaultViewSiteController', function ($scope, $state, $stateParams, siteService, cipherService) {
var returnScrollY = $stateParams.returnScrollY;
$scope.site = null;
siteService.get($stateParams.siteId, function (site) {
cipherService.decryptSite(site).then(function (model) {
@ -17,4 +19,8 @@
}
});
});
$scope.close = function () {
$state.go('tabs.vault', { animation: 'out-slide-down', scrollY: returnScrollY || 0 });
};
});

View File

@ -1,6 +1,6 @@
<div class="header">
<div class="right">
<a ui-sref="addSite({animation: 'in-slide-up'})"><i class="fa fa-plus fa-lg"></i></a>
<a href="" ng-click="addSite()"><i class="fa fa-plus fa-lg"></i></a>
</div>
<div class="title">My Vault</div>
</div>
@ -10,7 +10,7 @@
<div class="list-grouped-header">
<i class="fa fa-folder-open"></i> {{folder.name}}
</div>
<a ui-sref="viewSite({siteId: site.id, animation: 'in-slide-up'})" class="list-grouped-item condensed" ng-repeat="site in folderSites = (vaultSites | filter: { folderId: folder.id } | orderBy: ['name', 'username'])">
<a href="" ng-click="viewSite(site)" class="list-grouped-item condensed" ng-repeat="site in folderSites = (vaultSites | filter: { folderId: folder.id } | orderBy: ['name', 'username'])">
<span class="btn-list"><i class="fa fa-lg fa-ellipsis-h text-muted"></i></span>
<span class="text">{{site.name}}</span>
<span class="detail">{{site.username}}</span>

View File

@ -1,6 +1,6 @@
<div class="header">
<div class="left">
<a href="" ui-sref="tabs.vault({animation: 'out-slide-down'})">Close</a>
<a href="" ng-click="close()">Close</a>
</div>
<div class="right">
<a href="" ui-sref="editSite({animation: 'in-slide-up', siteId: site.id, fromView: true})">Edit</a>

View File

@ -7,6 +7,7 @@
<title>bitwarden</title>
<link rel="stylesheet" href="../lib/font-awesome/css/font-awesome.css">
<link rel="stylesheet" href="../lib/angular-toastr/angular-toastr.css">
<link rel="stylesheet" href="css/popup.css">
<script src="../lib/jquery/jquery.js"></script>
@ -17,6 +18,7 @@
<script src="../lib/angular-animate/angular-animate.js"></script>
<script src="../lib/angular-ui-router/angular-ui-router.js"></script>
<script src="../lib/angular-jwt/angular-jwt.js"></script>
<script src="../lib/angular-toastr/angular-toastr.tpls.js"></script>
<script src="app/app.js"></script>
<script src="app/settings.js"></script>

View File

@ -1,4 +1,6 @@
.in-slide-up {
@import (reference) "variables.less";
.in-slide-up {
.main-view.ng-enter,
.main-view.ng-leave {
-webkit-transition: all 0.4s ease;

View File

@ -1,6 +1,4 @@
@import (reference) "../../../node_modules/bootstrap/less/mixins.less";
@import (reference) "../../../node_modules/bootstrap/less/variables.less";
@import (reference) "variables.less";
@import (reference) "variables.less";
.header {
min-height: 44px;

View File

@ -0,0 +1,60 @@
@import (reference) "variables.less";
/* Toastr */
#toast-container {
&.toast-bottom-center .toast {
width: 100%;
margin-bottom: 0;
margin-top: 6px;
}
.toast {
background-image: none !important;
border-radius: 0;
.box-shadow(0 0 8px rgba(0, 0, 0, 0.5));
&.toast-danger, &.toast-error {
background-image: none !important;
background-color: @brand-danger;
&:before {
content: "\f0e7";
}
}
&.toast-warning {
background-image: none !important;
background-color: @brand-warning;
&:before {
content: "\f071";
}
}
&.toast-info {
background-image: none !important;
background-color: @brand-info;
&:before {
content: "\f005";
}
}
&.toast-success {
background-image: none !important;
background-color: @brand-success;
&:before {
content: "\f00C";
}
}
&:before {
position: fixed;
font-family: FontAwesome;
font-size: 24px;
line-height: 24px;
float: left;
color: #ffffff;
padding-right: 0.5em;
margin: auto 0.5em auto -1.5em;
}
}
}

View File

@ -2,6 +2,7 @@
@import "variables.less";
@import "components.less";
@import "animations.less";
@import "plugins.less";
body {
width: 320px;

View File

@ -1,10 +1,16 @@
@import (reference) "../../../node_modules/bootstrap/less/mixins.less";
@import (reference) "../../../node_modules/bootstrap/less/bootstrap.less";
@import (reference) "../../../node_modules/bootstrap/less/mixins.less";
@import (reference) "../../../node_modules/bootstrap/less/variables.less";
@font-family-sans-serif: "Open Sans", sans-serif;
@text-color: #000000;
@brand-primary: #3c8dbc;
@background-color: #efeff4;
@border-color: #f0f0f0;
@border-color-dark: #ddd;
@list-item-hover: #fbfbfb;
@brand-primary: #3c8dbc;
@brand-danger: #dd4b39;
@brand-success: #00a65a;
@brand-info: #00c0ef;
@brand-warning: #f39c12;