diff --git a/gulpfile.js b/gulpfile.js index fc430ecaf7..f1c844a953 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -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' } ]; diff --git a/package.json b/package.json index 2020d0be35..49a57c22cb 100644 --- a/package.json +++ b/package.json @@ -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" } } diff --git a/src/popup/app/app.js b/src/popup/app/app.js index 7217c52833..0adffc4509 100644 --- a/src/popup/app/app.js +++ b/src/popup/app/app.js @@ -3,6 +3,7 @@ 'ui.router', 'angular-jwt', 'ngAnimate', + 'toastr', 'bit.directives', 'bit.services', diff --git a/src/popup/app/config.js b/src/popup/app/config.js index c01441591f..f292d6e480 100644 --- a/src/popup/app/config.js +++ b/src/popup/app/config.js @@ -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) { diff --git a/src/popup/app/vault/vaultAddSiteController.js b/src/popup/app/vault/vaultAddSiteController.js index 6d52833c38..9f7527901c 100644 --- a/src/popup/app/vault/vaultAddSiteController.js +++ b/src/popup/app/vault/vaultAddSiteController.js @@ -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) { diff --git a/src/popup/app/vault/vaultController.js b/src/popup/app/vault/vaultController.js index 6b8e90619f..db34c31fb8 100644 --- a/src/popup/app/vault/vaultController.js +++ b/src/popup/app/vault/vaultController.js @@ -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; + } + }; }); diff --git a/src/popup/app/vault/vaultEditSiteController.js b/src/popup/app/vault/vaultEditSiteController.js index 30d9d157ac..3aae81a18f 100644 --- a/src/popup/app/vault/vaultEditSiteController.js +++ b/src/popup/app/vault/vaultEditSiteController.js @@ -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 }); } }; diff --git a/src/popup/app/vault/vaultModule.js b/src/popup/app/vault/vaultModule.js index 02b6c4f5a2..5ae60f9d5b 100644 --- a/src/popup/app/vault/vaultModule.js +++ b/src/popup/app/vault/vaultModule.js @@ -1,2 +1,2 @@ angular - .module('bit.vault', ['ngAnimate']); + .module('bit.vault', ['ngAnimate', 'toastr']); diff --git a/src/popup/app/vault/vaultViewSiteController.js b/src/popup/app/vault/vaultViewSiteController.js index 66cf9cd665..b80aa3278a 100644 --- a/src/popup/app/vault/vaultViewSiteController.js +++ b/src/popup/app/vault/vaultViewSiteController.js @@ -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 }); + }; }); diff --git a/src/popup/app/vault/views/vault.html b/src/popup/app/vault/views/vault.html index 7526e3470b..48ae771188 100644 --- a/src/popup/app/vault/views/vault.html +++ b/src/popup/app/vault/views/vault.html @@ -1,6 +1,6 @@ 
- +
My Vault
@@ -10,7 +10,7 @@
{{folder.name}}
- + {{site.name}} {{site.username}} diff --git a/src/popup/app/vault/views/vaultViewSite.html b/src/popup/app/vault/views/vaultViewSite.html index c7d9fc551a..fcdd243353 100644 --- a/src/popup/app/vault/views/vaultViewSite.html +++ b/src/popup/app/vault/views/vaultViewSite.html @@ -1,6 +1,6 @@ 
- Close + Close
Edit diff --git a/src/popup/index.html b/src/popup/index.html index 77d8ffaf26..d70e8a2136 100644 --- a/src/popup/index.html +++ b/src/popup/index.html @@ -7,6 +7,7 @@ bitwarden + @@ -17,6 +18,7 @@ + diff --git a/src/popup/less/animations.less b/src/popup/less/animations.less index 4e8690857a..aaffb9b768 100644 --- a/src/popup/less/animations.less +++ b/src/popup/less/animations.less @@ -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; diff --git a/src/popup/less/components.less b/src/popup/less/components.less index bd7049c603..931d5036ea 100644 --- a/src/popup/less/components.less +++ b/src/popup/less/components.less @@ -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; diff --git a/src/popup/less/plugins.less b/src/popup/less/plugins.less new file mode 100644 index 0000000000..2caea14fa7 --- /dev/null +++ b/src/popup/less/plugins.less @@ -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; + } + } +} diff --git a/src/popup/less/popup.less b/src/popup/less/popup.less index fadcb27528..0a2d288f86 100644 --- a/src/popup/less/popup.less +++ b/src/popup/less/popup.less @@ -2,6 +2,7 @@ @import "variables.less"; @import "components.less"; @import "animations.less"; +@import "plugins.less"; body { width: 320px; diff --git a/src/popup/less/variables.less b/src/popup/less/variables.less index 168ae85a3f..08083d0c07 100644 --- a/src/popup/less/variables.less +++ b/src/popup/less/variables.less @@ -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;