diff --git a/angular_app/event-edit.html b/angular_app/event-edit.html index b7b7ec0..648a4de 100644 --- a/angular_app/event-edit.html +++ b/angular_app/event-edit.html @@ -5,7 +5,7 @@

{{event.title}} {{'New event' | translate}} -   diff --git a/angular_app/events-list.html b/angular_app/events-list.html index e60e469..6700b25 100644 --- a/angular_app/events-list.html +++ b/angular_app/events-list.html @@ -47,11 +47,11 @@

{{'Begins:' | translate}} {{event['begin-date'] | date:'fullDate'}} {{event['begin-time'] | date:'HH:mm'}}
{{'Ends:' | translate}} {{event['end-date'] | date:'fullDate' }} {{event['end-time'] | date:'HH:mm'}}

- +

{{attendeesNr}} / {{((event.tickets || []) | registeredFilter).length}} ({{((attendeesNr / ((event.tickets || []) | registeredFilter).length * 100) || 0).toFixed()}}%)

- + diff --git a/angular_app/js/controllers.js b/angular_app/js/controllers.js index 48f9327..d6433f1 100644 --- a/angular_app/js/controllers.js +++ b/angular_app/js/controllers.js @@ -312,6 +312,9 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event', }; $scope._localUpdateTicket = function(ticket) { + if (!$state.is('event.tickets')) { + return; + } if (!$scope.event.tickets) { $scope.event.tickets = []; } @@ -362,19 +365,22 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event', if (!(data && data._id && data.ticket)) { return; } + if (callback) { + callback(data); + } + if (!$state.is('event.tickets')) { + return; + } var ticket_idx = $scope.event.tickets.findIndex(function(el, idx, array) { return data._id == el._id; }); if (ticket_idx == -1) { - $log.warn('unable to find ticket _id ' + _id); + $log.warn('unable to find ticket _id ' + data._id); return; } if ($scope.event.tickets[ticket_idx] != data.ticket) { $scope.event.tickets[ticket_idx] = data.ticket; } - if (callback) { - callback(data); - } if (key === 'attended' && !hideMessage) { var msg = {}; if (value) { diff --git a/angular_app/ticket-edit.html b/angular_app/ticket-edit.html index e323296..3d6a221 100644 --- a/angular_app/ticket-edit.html +++ b/angular_app/ticket-edit.html @@ -20,7 +20,7 @@ {{'Edit event' | translate}} -   diff --git a/eventman_server.py b/eventman_server.py index 5666745..0290420 100755 --- a/eventman_server.py +++ b/eventman_server.py @@ -46,9 +46,12 @@ API_VERSION = '1.0' re_env_key = re.compile('[^A-Z_]+') re_slashes = re.compile(r'//+') +# Keep track of WebSocket connections. +_ws_clients = {} + def authenticated(method): - """Decorator to handle authentication.""" + """Decorator to handle forced authentication.""" original_wrapper = tornado.web.authenticated(method) @tornado.web.functools.wraps(method) def my_wrapper(self, *args, **kwargs): @@ -85,7 +88,9 @@ class BaseHandler(tornado.web.RequestHandler): """Base class for request handlers.""" permissions = { 'event|read': True, - 'event:tickets|all': True, + 'event:tickets|read': True, + 'event:tickets|create': True, + 'event:tickets|update': True, 'event:tickets-all|create': True, 'events|read': True, 'users|create': True @@ -228,7 +233,13 @@ class BaseHandler(tornado.web.RequestHandler): return (False, {}) def build_error(self, message='', status=400): - """Build and write an error message.""" + """Build and write an error message. + + :param message: textual message + :type message: str + :param status: HTTP status code + :type status: int + """ self.set_status(status) self.write({'error': True, 'message': message}) @@ -250,9 +261,6 @@ class RootHandler(BaseHandler): self.write(fd.read()) -# Keep track of WebSocket connections. -_ws_clients = {} - class CollectionHandler(BaseHandler): """Base class for handlers that need to interact with the database backend. @@ -856,7 +864,7 @@ class SettingsHandler(BaseHandler): """Handle requests for Settings.""" @gen.coroutine @authenticated - def get(self, **kwds): + def get(self, **kwargs): query = self.arguments_tobool() settings = self.db.query('settings', query) self.write({'settings': settings}) @@ -865,7 +873,7 @@ class SettingsHandler(BaseHandler): class InfoHandler(BaseHandler): """Handle requests for information about the logged in user.""" @gen.coroutine - def get(self, **kwds): + def get(self, **kwargs): info = {} user_info = self.current_user_info if user_info: @@ -879,7 +887,7 @@ class WebSocketEventUpdatesHandler(tornado.websocket.WebSocketHandler): def _clean_url(self, url): return re_slashes.sub('/', url) - def open(self, event_id, *args, **kwds): + def open(self, event_id, *args, **kwargs): logging.debug('WebSocketEventUpdatesHandler.on_open event_id:%s' % event_id) _ws_clients.setdefault(self._clean_url(self.request.uri), set()).add(self) logging.debug('WebSocketEventUpdatesHandler.on_open %s clients connected' % len(_ws_clients)) @@ -907,7 +915,7 @@ class LoginHandler(RootHandler): """Handle user authentication requests.""" @gen.coroutine - def get(self, **kwds): + def get(self, **kwargs): # show the login page if self.is_api(): self.set_status(401) @@ -943,7 +951,7 @@ class LoginHandler(RootHandler): class LogoutHandler(BaseHandler): """Handle user logout requests.""" @gen.coroutine - def get(self, **kwds): + def get(self, **kwargs): # log the user out logging.info('logout') self.logout() @@ -1020,7 +1028,7 @@ def run(): template_path=os.path.join(os.path.dirname(__file__), "templates"), static_path=os.path.join(os.path.dirname(__file__), "static"), cookie_secret='__COOKIE_SECRET__', - login_url='/#/login', + login_url='/login', debug=options.debug) ssl_options = {} if os.path.isfile(options.ssl_key) and os.path.isfile(options.ssl_cert):