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.
This commit is contained in:
Tanshu 2012-11-03 14:55:12 +05:30
parent b990158554
commit bccad85099
12 changed files with 321 additions and 126 deletions

View File

@ -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{

View File

@ -0,0 +1,26 @@
<form method="post" autocomplete="off">
<div class="modal-header">
<h3 id="myModalLabel">Edit Journal</h3>
</div>
<div class="modal-body">
<div class=" control-group">
<label for="editAccount">Account</label>
<autocomplete id="editAccount" url="/Services/Accounts" selname="edit.Ledger.Name"
selid="edit.Ledger.LedgerID"></autocomplete>
<label for="editAmount">Amount</label>
<div class="input-prepend input-append">
<span class="add-on"></span><input type="text" id="editAmount" class="span2" autocomplete="off"
placeholder="Amount" ng-model="edit.Amount"/>
<button id="editDebit" type="button" class="btn" ng-click="toggleDebit()" on-action="toggleEdit(true)"
on-cancel="toggleEdit(false)">{{edit.Debit | debit}}
</button>
</div>
</div>
<hr>
</div>
<div class="modal-footer">
<button id="cancel" class="btn">Cancel</button>
<button id="action" class="btn btn-primary">Update</button>
</div>
</form>

View File

@ -50,7 +50,17 @@
<td class="Name">{{journal.Ledger.Name}}</td>
<td data-column="Amount" class="Amount Editable">{{journal.Amount}}</td>
<td class="Delete">
<button class="btn" ng-click="removeJournal(journal)">Delete</button>
<div class="btn-group">
<a class="btn btn-danger" ng-click="removeJournal(journal)"><i
class="icon-trash icon-white"></i> Delete</a>
<a class="btn btn-danger dropdown-toggle" data-toggle="dropdown" href="#"><span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a ng-confirm url="/partial/journal-modal.html" before="toggleEdit(journal)"
on-action="toggleEdit(journal, true)" on-cancel="toggleEdit(journal, false)"><i
class="icon-pencil"></i> Edit</a></li>
</ul>
</div>
</td>
</tr>
</tbody>

View File

@ -1,31 +1,27 @@
<div class="row">
<h2>Login</h2>
<form method="post" autocomplete="off" class="form-horizontal">
<legend>Login</legend>
<div class="control-group">
<label class="control-label" for="username">Username</label>
<form action="/login" method="post" autocomplete="off" class="form-horizontal">
<!--${h.HiddenInput('came_from', value=came_from)}-->
<div class="control-group">
<label class="control-label" for="username">Username</label>
<div class="controls">
<input type="text" ng-model="username" id="username" required placeholder="Username"/>
</div>
</div>
<div class="control-group">
<label class="control-label" for="password">Password</label>
<div class="controls">
<input type="text" name="username" id="username" required placeholder="Username"/>
</div>
<div class="controls">
<input type="password" ng-model="password" id="password" required placeholder="Password"/>
</div>
<div class="control-group">
<label class="control-label" for="password">Password</label>
</div>
<div class="control-group">
<label class="control-label" for="forgot"></label>
<div class="controls">
<input type="password" name="password" id="password" required placeholder="Password"/>
</div>
<div class="controls">
<span id="forgot">Forgot <a href="#">Username</a> / <a href="#">Password</a></span>
</div>
<div class="control-group">
<label class="control-label" for="forgot"></label>
<div class="controls">
<span id="forgot">Forgot <a href="#">Username</a> / <a href="#">Password</a></span>
</div>
</div>
<div class="form-actions">
<button type="submit" id="log_in" class="btn btn-primary">Login</button>
</div>
</form>
</div>
</div>
<div class="form-actions">
<button ng-click="submit()" class="btn btn-primary">Login</button>
</div>
</form>

View File

@ -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);
})(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;
});

View File

@ -0,0 +1,82 @@
overlord_service.factory('modal', function ($http, $compile) {
var modal = {};
modal.get = function (create) {
if (!modal.dialog && create) {
modal.dialog = $('<div class="modal hide"></div>');
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 += "<div class=\"modal-header\"><h1>" + title + "</h1></div>";
}
html += "<div class=\"modal-body\">" + text + "</div>"
+ "<div class=\"modal-footer\">";
html += "<button id=\"button\" class=\"" + button.class + "\">" + button.text + "</button>";
html += "</div>";
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 += "<div class=\"modal-header\"><h1>" + title + "</h1></div>";
}
html += "<div class=\"modal-body\">" + actionText + "</div>"
+ "<div class=\"modal-footer\">";
html += "<button id=\"action\" class=\"" + actionButton.class + "\">" + actionButton.text + "</button>";
html += "<button id=\"cancel\" class=\"btn btn-cancel\">" + cancelButton.text + "</button>";
html += "</div>";
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;
});

View File

@ -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 = {

View File

@ -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 () {

View File

@ -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 += "<div class=\"modal-body\">" + text + "</div>"
+ "<div class=\"modal-footer\">";
if (alertFunction) {
html += "<button class=\"btn\" ng-click=\"" + alertFunction + "\">" + buttonText + "</button>";
}
else {
html += "<button class=\"btn\">" + buttonText + "</button>";
}
html += "<button id=\"button\" class=\"" + button.class + "\">" + button.text + "</button>";
html += "</div>";
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');
}
}

View File

@ -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});
}
});

View File

@ -203,7 +203,7 @@
<hr>
<footer>
<p>&copy; Company 2012</p>
<p>&copy; Amritanshu 2012</p>
</footer>
</div>

View File

@ -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