From bccad850997bf539bbd859b99b985675face15f2 Mon Sep 17 00:00:00 2001 From: Tanshu Date: Sat, 3 Nov 2012 14:55:12 +0530 Subject: [PATCH] Login was not angular, made it angular. Editing entries in journal.html built. modal-service.js now supports loading partials from urls. Redirect from login to came_from enabled. Created getOldJournal in JournalCtrl to enable editting of individual entries. --- brewman/brewman/static/css/spinner.css | 91 ++++++++++--------- .../brewman/static/partial/journal-modal.html | 26 ++++++ brewman/brewman/static/partial/journal.html | 12 ++- brewman/brewman/static/partial/login.html | 48 +++++----- .../static/scripts/angular_directive.js | 50 +++++++--- .../static/scripts/delete-button-service.js | 82 +++++++++++++++++ brewman/brewman/static/scripts/journal.js | 57 +++++++++--- brewman/brewman/static/scripts/login.js | 12 ++- .../brewman/static/scripts/modal-service.js | 52 +++++++---- brewman/brewman/static/scripts/overlord.js | 3 +- brewman/brewman/templates/angular_base.mako | 2 +- brewman/brewman/views/services/session.py | 12 +-- 12 files changed, 321 insertions(+), 126 deletions(-) create mode 100644 brewman/brewman/static/partial/journal-modal.html create mode 100644 brewman/brewman/static/scripts/delete-button-service.js diff --git a/brewman/brewman/static/css/spinner.css b/brewman/brewman/static/css/spinner.css index 18677de9..52cb5c55 100644 --- a/brewman/brewman/static/css/spinner.css +++ b/brewman/brewman/static/css/spinner.css @@ -12,57 +12,58 @@ z-index: 101; } -#circleG{ - width:112px; +#circleG { + width: 112px; } -.circleG{ - background-color:#FFFFFF; - float:left; - height:24px; - margin-left:13px; - width:24px; - -webkit-animation-name:bounce_circleG; - -webkit-border-radius:16px; - -webkit-animation-duration:1.9500000000000002s; - -webkit-animation-iteration-count:infinite; - -webkit-animation-direction:linear; - -moz-animation-name:bounce_circleG; - -moz-border-radius:16px; - -moz-animation-duration:1.9500000000000002s; - -moz-animation-iteration-count:infinite; - -moz-animation-direction:linear; - opacity:0.3; - -o-animation-name:bounce_circleG; - border-radius:16px; - -o-animation-duration:1.9500000000000002s; - -o-animation-iteration-count:infinite; - -o-animation-direction:linear; - -ms-animation-name:bounce_circleG; - -ms-animation-duration:1.9500000000000002s; - -ms-animation-iteration-count:infinite; - -ms-animation-direction:linear; - opacity:0.3} - -#circleG_1{ - -webkit-animation-delay:0.39s; - -moz-animation-delay:0.39s; - -o-animation-delay:0.39s; - -ms-animation-delay:0.39s; +.circleG { + background-color: #FFFFFF; + float: left; + height: 24px; + margin-left: 13px; + width: 24px; + -webkit-animation-name: bounce_circleG; + -webkit-border-radius: 16px; + -webkit-animation-duration: 1.9500000000000002s; + -webkit-animation-iteration-count: infinite; + -webkit-animation-direction: linear; + -moz-animation-name: bounce_circleG; + -moz-border-radius: 16px; + -moz-animation-duration: 1.9500000000000002s; + -moz-animation-iteration-count: infinite; + -moz-animation-direction: linear; + opacity: 0.3; + -o-animation-name: bounce_circleG; + border-radius: 16px; + -o-animation-duration: 1.9500000000000002s; + -o-animation-iteration-count: infinite; + -o-animation-direction: linear; + -ms-animation-name: bounce_circleG; + -ms-animation-duration: 1.9500000000000002s; + -ms-animation-iteration-count: infinite; + -ms-animation-direction: linear; + opacity: 0.3 } -#circleG_2{ - -webkit-animation-delay:0.91s; - -moz-animation-delay:0.91s; - -o-animation-delay:0.91s; - -ms-animation-delay:0.91s; +#circleG_1 { + -webkit-animation-delay: 0.39s; + -moz-animation-delay: 0.39s; + -o-animation-delay: 0.39s; + -ms-animation-delay: 0.39s; } -#circleG_3{ - -webkit-animation-delay:1.17s; - -moz-animation-delay:1.17s; - -o-animation-delay:1.17s; - -ms-animation-delay:1.17s; +#circleG_2 { + -webkit-animation-delay: 0.91s; + -moz-animation-delay: 0.91s; + -o-animation-delay: 0.91s; + -ms-animation-delay: 0.91s; +} + +#circleG_3 { + -webkit-animation-delay: 1.17s; + -moz-animation-delay: 1.17s; + -o-animation-delay: 1.17s; + -ms-animation-delay: 1.17s; } @-webkit-keyframes bounce_circleG{ diff --git a/brewman/brewman/static/partial/journal-modal.html b/brewman/brewman/static/partial/journal-modal.html new file mode 100644 index 00000000..1f46f7f0 --- /dev/null +++ b/brewman/brewman/static/partial/journal-modal.html @@ -0,0 +1,26 @@ +
+ + + +
diff --git a/brewman/brewman/static/partial/journal.html b/brewman/brewman/static/partial/journal.html index fc02e3d4..68a27fe2 100644 --- a/brewman/brewman/static/partial/journal.html +++ b/brewman/brewman/static/partial/journal.html @@ -50,7 +50,17 @@ {{journal.Ledger.Name}} {{journal.Amount}} - +
+ Delete + + +
diff --git a/brewman/brewman/static/partial/login.html b/brewman/brewman/static/partial/login.html index 7f55d499..753bf476 100644 --- a/brewman/brewman/static/partial/login.html +++ b/brewman/brewman/static/partial/login.html @@ -1,31 +1,27 @@ -
-

Login

+
+ Login +
+ - - -
- +
+ +
+
+
+ -
- -
+
+
-
- +
+
+ -
- -
+
+ Forgot Username / Password
-
- - -
- Forgot Username / Password -
-
-
- -
- -
+
+
+ +
+ diff --git a/brewman/brewman/static/scripts/angular_directive.js b/brewman/brewman/static/scripts/angular_directive.js index 8a489548..39832d03 100644 --- a/brewman/brewman/static/scripts/angular_directive.js +++ b/brewman/brewman/static/scripts/angular_directive.js @@ -127,24 +127,34 @@ overlord_directive.directive('fadey', function () { return directiveDefinitionObject; }); -overlord_directive.directive('ngConfirm', function(modal) { +overlord_directive.directive('ngConfirm', function (modal, $parse) { return { - restrict: 'A', - link: function postLink(scope, element, attrs) { + restrict:'A', + link:function postLink(scope, element, attrs) { // Could have custom or boostrap modal options here var options = {}; - element.bind("click", function() - { - var actionButton = {text:attrs["actionButtonText"], click:attrs["actionFunction"], class:attrs['class']}; - var cancelButton = {text:attrs["cancelButtonText"], click:attrs["cancelFunction"]}; - modal.confirm(attrs["title"], attrs["actionText"], actionButton, cancelButton, scope, options); - }); + if (typeof attrs.url !== 'undefined') { + element.bind("click", function () { + if (typeof attrs.before !== 'undefined') { + var fn = $parse(attrs.before); + scope.$apply(function () { + fn(scope); + }); + } + modal.template(attrs.url, attrs.onAction, attrs.onCancel, scope, options); + }); + } else { + element.bind("click", function () { + var actionButton = {text:attrs["actionButtonText"], click:attrs["actionFunction"], class:attrs['class']}; + var cancelButton = {text:attrs["cancelButtonText"], click:attrs["cancelFunction"]}; + modal.confirm(attrs["title"], attrs["actionText"], actionButton, cancelButton, scope, options); + }); + } } }; }); - (function (angular) { /* * Defines the ng:if tag. This is useful if jquery mobile does not allow @@ -183,4 +193,22 @@ overlord_directive.directive('ngConfirm', function(modal) { overlord_directive.directive('ngmIf', function () { return ngIfDirective; }); -})(angular); \ No newline at end of file +})(angular); + + +overlord_directive.directive('journal-edit', function () { + var directiveDefinitionObject = { + restrict:'A', + replace:true, + transclude:true, + templateUrl:'/partial/journal-modal.html', + link:function (scope, element, attrs) { + element.bind("click", function () { + var actionButton = {text:attrs["actionButtonText"], click:attrs["actionFunction"], class:attrs['class']}; + var cancelButton = {text:attrs["cancelButtonText"], click:attrs["cancelFunction"]}; + modal.confirm(attrs["title"], attrs["actionText"], actionButton, cancelButton, scope, options); + }); + } + }; + return directiveDefinitionObject; +}); diff --git a/brewman/brewman/static/scripts/delete-button-service.js b/brewman/brewman/static/scripts/delete-button-service.js new file mode 100644 index 00000000..394fd271 --- /dev/null +++ b/brewman/brewman/static/scripts/delete-button-service.js @@ -0,0 +1,82 @@ +overlord_service.factory('modal', function ($http, $compile) { + var modal = {}; + + modal.get = function (create) { + if (!modal.dialog && create) { + modal.dialog = $(''); + modal.dialog.appendTo('BODY'); + } + return modal.dialog; + } + + modal.compileAndRun = function (dialog, scope, options) { + $compile(dialog)(scope); + dialog.modal(options); + } + + modal.alert = function (title, text, button, scope, options) { + text = (text) ? text : "Alert"; + button.text = (button.text) ? button.text : "Ok"; + button.class = (button.class) ? button.class : "btn"; + var dialog = modal.get(true), + html = ""; + if (title) { + html += "

" + title + "

"; + } + html += "
" + text + "
" + + "
"; + html += ""; + html += "
"; + dialog.html(html); + dialog.find("#button").click(function () { + if (button.click) { + scope.$eval(button.click); + } + modal.close(); + }); + modal.compileAndRun(dialog, scope, options); + } + + modal.confirm = function (title, actionText, actionButton, cancelButton, scope, options) { + actionText = (actionText) ? actionText : "Are you sure?"; + actionButton.text = (actionButton.text) ? actionButton.text : "Ok"; + cancelButton.text = (cancelButton.text) ? cancelButton.text : "Cancel"; + + var dialog = modal.get(true), + html = ""; + if (title) { + html += "

" + title + "

"; + } + html += "
" + actionText + "
" + + "
"; + html += ""; + html += ""; + html += "
"; + dialog.html(html); + + dialog.find("#action").click(function () { + if (actionButton.click) { + scope.$eval(actionButton.click); + } + modal.close(); + }); + dialog.find("#cancel").click(function () { + if (cancelButton.click) { + scope.$eval(cancelButton.click); + } + modal.close(); + }); + modal.compileAndRun(dialog, scope, options); + + } + + modal.close = function () { + var dialog = modal.get() + if (dialog) { + dialog.modal('hide'); + } + } + + return modal; + +}); diff --git a/brewman/brewman/static/scripts/journal.js b/brewman/brewman/static/scripts/journal.js index 8e070c77..66450ff9 100644 --- a/brewman/brewman/static/scripts/journal.js +++ b/brewman/brewman/static/scripts/journal.js @@ -2,21 +2,27 @@ $scope.voucher = voucher; $scope.name = ''; $scope.debit = 1; - $scope.addJournal = function () { - for (var i = 0, l = this.voucher.Journals.length; i < l; i++) { - if (this.voucher.Journals[i].Ledger.LedgerID === $scope.id) { - var amount = (this.voucher.Journals[i].Debit * this.voucher.Journals[i].Amount) + (parseInt($scope.debit) * Number($scope.amount)); - if (amount < 0) { - this.voucher.Journals[i].Debit = -1; - this.voucher.Journals[i].Amount = amount * -1; - } else { - this.voucher.Journals[i].Debit = 1; - this.voucher.Journals[i].Amount = amount; - } - break; + function getOldJournal(ledgerID, journals) { + for (var i = 0, l = journals.length; i < l; i++) { + if (journals[i].Ledger.LedgerID === ledgerID) { + return journals[i]; } } - if (i >= l) { + + } + + $scope.addJournal = function () { + var oldJournal = getOldJournal($scope.ledger.LedgerID, this.voucher.Journals); + if (typeof oldJournal !== 'undefined') { + var amount = (oldJournal.Debit * oldJournal.Amount) + (parseInt($scope.debit) * Number($scope.amount)); + if (amount < 0) { + oldJournal.Debit = -1; + oldJournal.Amount = amount * -1; + } else { + oldJournal.Debit = 1; + oldJournal.Amount = amount; + } + } else { this.voucher.Journals.push({Debit:$scope.debit, Amount:Number($scope.amount), Ledger:$scope.ledger}); } delete $scope.ledger; @@ -87,6 +93,31 @@ $scope.toasts.push({Type:'Error', Message:data.data}); }); }; + + $scope.toggleDebit = function () { + $("#editDebit").button('toggle'); + $scope.edit.Debit = ($scope.edit.Debit === 1) ? -1 : 1; + } + $scope.toggleEdit = function (journal, update) { + if (typeof update === 'undefined') { + $scope.edit = {}; + angular.copy(journal, $scope.edit); + } else { + if (update === true && typeof $scope.edit !== 'undefined') { + if (journal.Ledger.LedgerID !== $scope.edit.Ledger.LedgerID) { + var oldJournal = getOldJournal($scope.edit.Ledger.LedgerID, $scope.voucher.Journals); + if (typeof oldJournal !== 'undefined') { + return false; + } + } + angular.copy($scope.edit, journal); + $scope.$apply(); + return true; + } else if (update === false) { + delete $scope.edit; + } + } + } } JournalCtrl.resolve = { diff --git a/brewman/brewman/static/scripts/login.js b/brewman/brewman/static/scripts/login.js index 696fabbe..fed0561b 100644 --- a/brewman/brewman/static/scripts/login.js +++ b/brewman/brewman/static/scripts/login.js @@ -1,9 +1,13 @@ -function LoginCtrl($scope, $http, $location) { +function LoginCtrl($scope, $http, $location, $route, $routeParams) { $scope.submit = function () { $http. - post('/login', {'username':$scope.name, 'password':$scope.password}). + post('/login', {username:$scope.username, password:$scope.password}). success(function () { - $location.path('/') + var came_from = $routeParams.came_from; + if (typeof came_from === 'undefined' || came_from === "" || came_from === "/login" || came_from === "/logout") { + came_from = "/"; + } + $location.path(came_from); }). error(function (errorMessage) { $scope.toasts.push({Type:'Error', Message:errorMessage}); @@ -12,7 +16,7 @@ $('#username').focus(); } -function LogoutCtrl($rootScope, $scope, $http, $location) { +function LogoutCtrl($scope, $http, $location) { $http. post('/logout'). success(function () { diff --git a/brewman/brewman/static/scripts/modal-service.js b/brewman/brewman/static/scripts/modal-service.js index 4adced52..9858cf2a 100644 --- a/brewman/brewman/static/scripts/modal-service.js +++ b/brewman/brewman/static/scripts/modal-service.js @@ -14,9 +14,10 @@ overlord_service.factory('modal', function ($http, $compile) { dialog.modal(options); } - modal.alert = function (title, text, buttonText, alertFunction, scope, options) { + modal.alert = function (title, text, button, scope, options) { text = (text) ? text : "Alert"; - buttonText = (buttonText) ? buttonText : "Ok"; + button.text = (button.text) ? button.text : "Ok"; + button.class = (button.class) ? button.class : "btn"; var dialog = modal.get(true), html = ""; if (title) { @@ -24,19 +25,15 @@ overlord_service.factory('modal', function ($http, $compile) { } html += "
" + text + "
" + "
"; - if (alertFunction) { - html += ""; - } - else { - html += ""; - } + html += ""; html += "
"; dialog.html(html); - if (!alertFunction) { - dialog.find(".btn").click(function () { - modal.close(); - }); - } + dialog.find("#button").click(function () { + if (button.click) { + scope.$eval(button.click); + } + modal.close(); + }); modal.compileAndRun(dialog, scope, options); } @@ -73,10 +70,33 @@ overlord_service.factory('modal', function ($http, $compile) { } + modal.template = function (url, onSuccess, onCancel, scope, options) { + $http.get(url).success(function (data) { + + var dialog = modal.get(true); + dialog.html(data); + dialog.find("#action").click(function () { + if (!onSuccess || scope.$eval(onSuccess)) { + modal.close(); + } + }); + dialog.on('hide', function () { + console.log('hide called'); + if (onCancel) { + scope.$eval(onCancel); + } + }) + dialog.find("#cancel").click(function () { + modal.close(); + }); + modal.compileAndRun(dialog, scope, options); + }); + } + modal.close = function () { - var popup = modal.get() - if (popup) { - popup.modal('hide'); + var dialog = modal.get() + if (dialog) { + dialog.modal('hide'); } } diff --git a/brewman/brewman/static/scripts/overlord.js b/brewman/brewman/static/scripts/overlord.js index 87582db3..c71fc04e 100644 --- a/brewman/brewman/static/scripts/overlord.js +++ b/brewman/brewman/static/scripts/overlord.js @@ -129,7 +129,8 @@ function BaseCtrl($rootScope, $scope, Auth, $location) { if ($rootScope.auth.isAuthenticated) { $location.path('/'); } else { - $location.path('/login'); + var came_from = $location.path(); + $location.path('/login').search({came_from:came_from}); } }); diff --git a/brewman/brewman/templates/angular_base.mako b/brewman/brewman/templates/angular_base.mako index 7b56441f..478f808f 100644 --- a/brewman/brewman/templates/angular_base.mako +++ b/brewman/brewman/templates/angular_base.mako @@ -203,7 +203,7 @@
diff --git a/brewman/brewman/views/services/session.py b/brewman/brewman/views/services/session.py index dc994be6..3614799d 100644 --- a/brewman/brewman/views/services/session.py +++ b/brewman/brewman/views/services/session.py @@ -48,17 +48,13 @@ def user_permission(request): @view_config(request_method='POST', route_name='login', renderer='json') def login(request): - username = request.POST['username'] - password = request.POST['password'] - login_url = request.route_url('login') - referrer = request.url - if referrer == login_url: - referrer = request.route_url('home') # never use the login form itself as came_from - came_from = referrer + username = request.json_body['username'] + password = request.json_body['password'] found, user = User.auth(username, password) if found: headers = remember(request, str(user.id)) - return HTTPFound(location=came_from, headers=headers) + request.response.headers = headers + return request.response else: response = Response("Login failed") response.status_int = 500