diff --git a/accountant/api/views/scheduled_operations.py b/accountant/api/views/scheduled_operations.py index c89a9f0..5acaae4 100644 --- a/accountant/api/views/scheduled_operations.py +++ b/accountant/api/views/scheduled_operations.py @@ -16,42 +16,19 @@ """ import dateutil.parser -from flask import json, request from flask.ext.restful import Resource, fields, reqparse, marshal_with_field from sqlalchemy.orm.exc import NoResultFound -from accountant import session_scope, session_aware +from accountant import session_aware from ..models.scheduled_operations import ScheduledOperation -from .. import api, api_api +from .. import api_api from ..fields import Object -@api.route("/scheduled_operations/") -def get_scheduled_operations(account_id): - """ - Return entries for an account, year, and month. - """ - with session_scope() as session: - query = ScheduledOperation.get_scheduled_operations_for_account( - session, account_id) - - return json.dumps([{ - "id": i.id, - "start_date": i.start_date.strftime("%Y-%m-%d"), - "stop_date": i.stop_date.strftime("%Y-%m-%d"), - "day": str(i.day), - "frequency": str(i.frequency), - "label": i.label, - "value": str(i.value), - "category": i.category, - "account_id": i.account_id - } for i in query.all()]) - - resource_fields = { 'id': fields.Integer, 'start_date': fields.DateTime(dt_format='iso8601'), @@ -76,10 +53,23 @@ parser.add_argument('category', type=str) parser.add_argument('account_id', type=int) +get_parser = reqparse.RequestParser() +get_parser.add_argument('account', type=int) + + class ScheduledOperationListResource(Resource): + @session_aware + @marshal_with_field(fields.List(Object(resource_fields))) + def get(self, session): + kwargs = get_parser.parse_args() + + return ScheduledOperation.get_scheduled_operations_for_account( + session, **kwargs + ).all() + @session_aware @marshal_with_field(Object(resource_fields)) - def put(self, session): + def post(self, session): """ Add a new scheduled operation. """ @@ -119,7 +109,7 @@ class ScheduledOperationResource(Resource): @session_aware @marshal_with_field(Object(resource_fields)) - def put(self, scheduled_operation_id, session): + def post(self, scheduled_operation_id, session): kwargs = parser.parse_args() assert (id not in kwargs or kwargs.id is None diff --git a/accountant/frontend/static/js/scheduler.js b/accountant/frontend/static/js/scheduler.js index 31025c6..a9072cb 100644 --- a/accountant/frontend/static/js/scheduler.js +++ b/accountant/frontend/static/js/scheduler.js @@ -14,8 +14,20 @@ You should have received a copy of the GNU Affero General Public License along with Accountant. If not, see . */ -accountantApp.controller( - "SchedulerController", function($scope, $http, $rootScope, $filter, $routeParams) { +accountantApp + +.factory("ScheduledOperations", ["$resource", function($resource) { + return $resource( + "/api/scheduled_operations/:id", { + id: "@id" + } + ); +}]) + +.controller( + "SchedulerController", [ + "$scope", "$http", "$rootScope", "$filter", "$routeParams", "ScheduledOperations", + function($scope, $http, $rootScope, $filter, $routeParams, ScheduledOperations) { // Operations store and selection $scope.operations = []; $scope.selectedOperation = null; @@ -23,54 +35,24 @@ accountantApp.controller( // Placeholder for saved value to cancel entry edition $scope.savedOperation = null; + $scope.categories = []; + + $scope.resetNewOperation = function() { + $scope.newOperation = new ScheduledOperations({}); + }; + + $scope.resetNewOperation(); + $scope.loadOperations = function(accountId) { // Clean up selected entry. $scope.selectedOperation = null; $scope.savedOperation = null; - $http.get("/api/scheduled_operations/" + accountId).success($scope.loadOperations_success); - }; - - $scope.loadOperations_success = function(data) { - var operations = [{ - id: null, - start_date: null, - stop_date: null, - day: null, - frequency: null, - label: null, - account_id: null, - category: null, - state: "edit" - }]; - - if(data) { - operations = operations.concat(angular.fromJson(data)); - } - - $scope.operations = operations; - - $scope.$emit("operationsLoadedEvent", {operations: operations}); - }; - - $scope.iconSaveClass = function(operation) { - if($scope.isNew(operation)) { - return "fa fa-plus"; - } else if ($scope.isEditing(operation)) { - return "fa fa-floppy-o"; - } - }; - - $scope.iconCancelClass = function(operation) { - if($scope.isNew(operation)) { - return "fa fa-times"; - } else if ($scope.isEditing(operation)) { - return "fa fa-ban"; - } - }; - - $scope.isNew = function(operation) { - return !operation.id; + $scope.operations = ScheduledOperations.query({ + account: $routeParams.accountId + }, function(data) { + $scope.$emit("operationsLoadedEvent", {operations: data}); + }); }; // Returns true if the entry is in editing state. @@ -82,73 +64,45 @@ accountantApp.controller( return operation.id && (!operation.state || operation.state === 'display'); }; - $scope.saveOperation = function(operation) { - if(!operation.account_id) { + $scope.createOperation = function(operation) { operation.account_id = $routeParams.accountId; - } - // prepare the Ajax xall to save the sceduled operation. - var type; - var url = "/api/scheduled_operations"; + operation.$save(function(data) { + $scope.resetNewOperation(); - if(!$scope.isNew(operation)) { - url += "/" + operation.id; - } + $scope.$emit("operationCreatedEvent", data); + }); + }; - $http.put(url, angular.toJson(operation)).success(function(data) { + $scope.$on("operationCreatedEvent", function(e, operation) { new PNotify({ type: "success", title: "Save", - text: data + text: "Operation #" + operation.id + " created." }); + }); + $scope.saveOperation = function(operation) { + operation.$save(function(data) { $scope.$emit("operationSavedEvent", operation); }); }; + $scope.$on("operationSavedEvent", function(e, operation) { + new PNotify({ + type: "success", + title: "Save", + text: "Operation #" + operation.id + " saved." + }); + }); + $scope.editOperation = function(operation) { - // Cancel previous editing. - if($scope.selectedOperation) { - $scope.cancelEditOperation($scope.selectedItem); - } - - // Save current entry values. - $scope.savedOperation = angular.copy(operation); - $scope.selectedOperation = operation; - // Enter edit state. operation.state='edit'; }; $scope.cancelEditOperation = function(operation) { - if ($scope.isNew(operation)) { - operation.id = null; - operation.start_date = null; - operation.stop_date = null; - operation.day = null; - operation.frequency = null; - operation.label = null; - operation.value = null; - operation.category = null; - operation.account_id = $routeParams.accountId; - } else if ($scope.isEditing(operation)) { - if($scope.savedOperation) { - operation.id = $scope.savedOperation.id; - operation.start_date = $scope.savedOperation.start_date; - operation.stop_date = $scope.savedOperation.stop_date; - operation.day = $scope.savedOperation.day; - operation.frequency = $scope.savedOperation.frequency; - operation.label = $scope.savedOperation.label; - operation.value = $scope.savedOperation.value; - operation.category = $scope.savedOperation.category; - operation.account_id = $scope.savedOperation.account_id; - } - - $scope.savedOperation = null; - $scope.selectedOperation = null; - - operation.state = 'display'; - } + operation.$get(); }; $scope.removeOperation = function(operation, modalScope) { @@ -189,4 +143,4 @@ accountantApp.controller( }); $scope.loadOperations($routeParams.accountId); -}); +}]); diff --git a/accountant/frontend/static/templates/scheduler.html b/accountant/frontend/static/templates/scheduler.html index 111bf10..f994cef 100644 --- a/accountant/frontend/static/templates/scheduler.html +++ b/accountant/frontend/static/templates/scheduler.html @@ -34,54 +34,67 @@ - + - - [[operation.start_date]] + - - [[operation.stop_date]] + - - [[operation.day]] + - - [[operation.frequency]] + - - [[operation.label]] + - - [[operation.value]] + - - [[operation.category]] + -
- -
+ + -
+ + [[operation.start_date]] + + [[operation.stop_date]] + + [[operation.day]] + + [[operation.frequency]] + + [[operation.label]] + + [[operation.value]] + + [[operation.category]] + + +
@@ -92,6 +105,50 @@
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ +