improve WebSocket handling
This commit is contained in:
parent
24d6689abe
commit
c183595124
5 changed files with 87 additions and 47 deletions
|
@ -51,7 +51,7 @@
|
|||
<a ui-sref="event.ticket.edit({id: event._id, ticket_id: ticket._id})"><span>{{ticket.name}}</span> <span>{{ticket.surname}}</span></a>
|
||||
</strong>
|
||||
</span>
|
||||
<span ng-if="ticket.email"> <{{ticket.email}}></span>
|
||||
<span ng-if="ticket.email"> <{{ticket.email}}></span><span ng-if="ticket.cancelled"> ({{'cancelled' | translate}})</span>
|
||||
<p ng-if="ticket.company || ticket.job_title"><i ng-if="ticket.job_title">{{ticket.job_title}}</i><span ng-if="ticket.company && ticket.job_title"> @ </span><i ng-if="ticket.company">{{ticket.company}}</i></p>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
|
|
53
angular_app/js/controllers.js
vendored
53
angular_app/js/controllers.js
vendored
|
@ -179,7 +179,7 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
|
|||
$scope.formData = {};
|
||||
$scope.guiOptions = {dangerousActionsEnabled: false};
|
||||
$scope.customFields = Setting.query({setting: 'ticket_custom_field', in_event_details: true});
|
||||
$scope.registeredFilterOptions = {all: true};
|
||||
$scope.registeredFilterOptions = {all: false};
|
||||
|
||||
$scope.formFieldsMap = {};
|
||||
$scope.formFieldsMapRev = {};
|
||||
|
@ -224,10 +224,12 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
|
|||
return $scope.EventUpdates.data;
|
||||
}, function(new_collection, old_collection) {
|
||||
if (!($scope.EventUpdates.data && $scope.EventUpdates.data.update)) {
|
||||
$log.debug('no data received from the WebSocket');
|
||||
return;
|
||||
}
|
||||
var data = $scope.EventUpdates.data.update;
|
||||
$log.debug('received ' + data.action + ' action from websocket source ' + data.uuid);
|
||||
$log.debug('received ' + data.action + ' action from websocket source ' + data.uuid + ' . Full data:');
|
||||
$log.debug(data);
|
||||
if ($rootScope.app_uuid == data.uuid) {
|
||||
$log.debug('do not process our own message');
|
||||
return false;
|
||||
|
@ -235,8 +237,9 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
|
|||
if (!$scope.event.tickets) {
|
||||
$scope.event.tickets = [];
|
||||
}
|
||||
var ticket_id = data._id || (data.ticket && data.ticket._id);
|
||||
var ticket_idx = $scope.event.tickets.findIndex(function(el, idx, array) {
|
||||
return data._id == el._id;
|
||||
return ticket_id && (ticket_id == el._id);
|
||||
});
|
||||
if (ticket_idx != -1) {
|
||||
$log.debug('_id ' + data._id + ' found');
|
||||
|
@ -415,17 +418,46 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
|
|||
});
|
||||
};
|
||||
|
||||
/* event listners; needed because otherwise, adding a ticket with the Quick add form,
|
||||
* we'd be changing the $scope outside of the AngularJS's $digest. */
|
||||
|
||||
$rootScope.$on('event:ticket:new', function(evt, ticket, callback) {
|
||||
$scope._localAddTicket(ticket);
|
||||
if (callback) {
|
||||
callback(ticket);
|
||||
}
|
||||
});
|
||||
|
||||
$rootScope.$on('event:ticket:update', function(evt, ticket) {
|
||||
if (!$scope.event.tickets) {
|
||||
$scope.event.tickets = [];
|
||||
}
|
||||
var ticket_idx = $scope.event.tickets.findIndex(function(el, idx, array) {
|
||||
return ticket._id == el._id;
|
||||
});
|
||||
if (ticket_idx == -1) {
|
||||
$log.debug('ticket not present: not updated');
|
||||
return false;
|
||||
}
|
||||
$scope.event.tickets[ticket_idx] = ticket;
|
||||
});
|
||||
|
||||
$rootScope.$on('event:ticket:set-attr', function(evt, ticket, key, value, callback, hideMessage) {
|
||||
$scope.setTicketAttribute(ticket, key, value, callback, hideMessage);
|
||||
});
|
||||
|
||||
$scope.addTicket = function(ticket) {
|
||||
ticket.event_id = $state.params.id;
|
||||
EventTicket.add(ticket, function(ret_ticket) {
|
||||
$log.debug('addTicket');
|
||||
$log.debug(ret_ticket);
|
||||
$scope._localAddTicket(ret_ticket, ticket);
|
||||
$rootScope.$emit('event:ticket:new', ret_ticket, function() {
|
||||
$rootScope.$emit('event:ticket:set-attr', ret_ticket, 'attended', true, null, true);
|
||||
});
|
||||
if (!$state.is('event.tickets')) {
|
||||
$state.go('event.ticket.edit', {id: $scope.event._id, ticket_id: ret_ticket._id});
|
||||
} else {
|
||||
$scope.query = '';
|
||||
$scope._setAttended(ret_ticket);
|
||||
if ($scope.$close) {
|
||||
// Close the Quick ticket modal.
|
||||
$scope.$close();
|
||||
|
@ -437,7 +469,7 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
|
|||
$scope.updateTicket = function(ticket, cb) {
|
||||
ticket.event_id = $state.params.id;
|
||||
EventTicket.update(ticket, function(t) {
|
||||
$scope._localUpdateTicket(t.ticket);
|
||||
$rootScope.$emit('event:ticket:update', t.ticket);
|
||||
if (cb) {
|
||||
cb(t);
|
||||
}
|
||||
|
@ -459,8 +491,7 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
|
|||
templateUrl: 'modal-quick-add-ticket.html',
|
||||
controller: 'EventTicketsCtrl'
|
||||
});
|
||||
modalInstance.result.then(function() {
|
||||
});
|
||||
modalInstance.result.then(function() {});
|
||||
};
|
||||
|
||||
$scope.submitForm = function(dataModelSubmitted) {
|
||||
|
@ -468,10 +499,10 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
|
|||
key = $scope.formFieldsMap[key] || key;
|
||||
$scope.ticket[key] = value;
|
||||
});
|
||||
if (!$state.params.ticket_id) {
|
||||
$scope.addTicket($scope.ticket);
|
||||
} else {
|
||||
if ($state.is('event.ticket.edit')) {
|
||||
$scope.updateTicket($scope.ticket);
|
||||
} else {
|
||||
$scope.addTicket($scope.ticket);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
15
angular_app/js/services.js
vendored
15
angular_app/js/services.js
vendored
|
@ -241,8 +241,8 @@ eventManServices.factory('User', ['$resource', '$rootScope',
|
|||
|
||||
|
||||
/* WebSocket collection used to update the list of tickets of an Event. */
|
||||
eventManApp.factory('EventUpdates', ['$websocket', '$location', '$log',
|
||||
function($websocket, $location, $log) {
|
||||
eventManApp.factory('EventUpdates', ['$websocket', '$location', '$log', '$rootScope',
|
||||
function($websocket, $location, $log, $rootScope) {
|
||||
var dataStream = null;
|
||||
var data = {};
|
||||
|
||||
|
@ -253,18 +253,19 @@ eventManApp.factory('EventUpdates', ['$websocket', '$location', '$log',
|
|||
dataStream.close();
|
||||
},
|
||||
open: function() {
|
||||
$log.debug('open WebSocket connection');
|
||||
dataStream && dataStream.close();
|
||||
var proto = $location.protocol() == 'https' ? 'wss' : 'ws';
|
||||
dataStream = $websocket(proto + '://' + $location.host() + ':' + $location.port() +
|
||||
'/ws/' + $location.path() + '/updates');
|
||||
var url = proto + '://' + $location.host() + ':' + $location.port() +
|
||||
'/ws/' + $location.path() + '/updates?uuid=' + $rootScope.app_uuid;
|
||||
$log.debug('open WebSocket connection to ' + url);
|
||||
//dataStream && dataStream.close();
|
||||
dataStream = $websocket(url);
|
||||
|
||||
dataStream.onMessage(function(message) {
|
||||
$log.debug('EventUpdates message received');
|
||||
data.update = angular.fromJson(message.data);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return methods;
|
||||
}]
|
||||
);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#!/usr/bin/env python
|
||||
"""print_label.py - print a label with the name, the company and the person_id (in a barcode) of an attendee
|
||||
"""print_label.py - print a label with the name, the company and SEQ_HEX (in a barcode) of an attendee
|
||||
|
||||
Copyright 2015 Emiliano Mattioli <oloturia AT gmail.com>
|
||||
Davide Alberani <da@erlug.linux.it>
|
||||
RaspiBO <info@raspibo.org>
|
||||
Copyright 2015-2016 Emiliano Mattioli <oloturia AT gmail.com>
|
||||
Davide Alberani <da@erlug.linux.it>
|
||||
RaspiBO <info@raspibo.org>
|
||||
|
||||
Licensed under the Apache License 2.0
|
||||
"""
|
||||
|
|
|
@ -540,7 +540,11 @@ class CollectionHandler(BaseHandler):
|
|||
|
||||
def build_ws_url(self, path, proto='ws', host=None):
|
||||
"""Return a WebSocket url from a path."""
|
||||
return 'ws://127.0.0.1:%s/ws/%s' % (self.listen_port + 1, path)
|
||||
try:
|
||||
args = '?uuid=%s' % self.get_argument('uuid')
|
||||
except:
|
||||
args = ''
|
||||
return 'ws://127.0.0.1:%s/ws/%s%s' % (self.listen_port + 1, path, args)
|
||||
|
||||
@gen.coroutine
|
||||
def send_ws_message(self, path, message):
|
||||
|
@ -647,12 +651,7 @@ class EventsHandler(CollectionHandler):
|
|||
operation='appendUnique',
|
||||
create=False)
|
||||
if doc:
|
||||
msg_ret = ret.copy()
|
||||
msg_ret['ticket'] = msg_ret['ticket'].copy()
|
||||
# Do not send ticket IDs over the WebSocket.
|
||||
if '_id' in msg_ret['ticket']:
|
||||
del msg_ret['ticket']['_id']
|
||||
self.send_ws_message('event/%s/tickets/updates' % id_, json.dumps(msg_ret))
|
||||
self.send_ws_message('event/%s/tickets/updates' % id_, json.dumps(ret))
|
||||
return ret
|
||||
|
||||
def handle_put_tickets(self, id_, ticket_id, data):
|
||||
|
@ -877,33 +876,42 @@ class InfoHandler(BaseHandler):
|
|||
|
||||
|
||||
class WebSocketEventUpdatesHandler(tornado.websocket.WebSocketHandler):
|
||||
"""Manage websockets."""
|
||||
"""Manage WebSockets."""
|
||||
def _clean_url(self, url):
|
||||
return re_slashes.sub('/', url)
|
||||
url = re_slashes.sub('/', url)
|
||||
ridx = url.rfind('?')
|
||||
if ridx != -1:
|
||||
url = url[:ridx]
|
||||
return url
|
||||
|
||||
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))
|
||||
self.uuid = self.get_argument('uuid')
|
||||
url = self._clean_url(self.request.uri)
|
||||
logging.debug('WebSocketEventUpdatesHandler.on_open event_id:%s url:%s' % (event_id, url))
|
||||
_ws_clients.setdefault(url, {})
|
||||
if self.uuid not in _ws_clients[url]:
|
||||
_ws_clients[url][self.uuid] = self
|
||||
logging.debug('WebSocketEventUpdatesHandler.on_open %s clients connected' % len(_ws_clients[url]))
|
||||
|
||||
def on_message(self, message):
|
||||
logging.debug('WebSocketEventUpdatesHandler.on_message')
|
||||
url = self._clean_url(self.request.uri)
|
||||
logging.debug('WebSocketEventUpdatesHandler.on_message url:%s' % url)
|
||||
count = 0
|
||||
for client in _ws_clients.get(self._clean_url(self.request.uri), []):
|
||||
if client == self:
|
||||
_to_delete = set()
|
||||
for uuid, client in _ws_clients.get(url, {}).iteritems():
|
||||
try:
|
||||
client.write_message(message)
|
||||
except:
|
||||
_to_delete.add(uuid)
|
||||
continue
|
||||
client.write_message(message)
|
||||
count += 1
|
||||
for uuid in _to_delete:
|
||||
try:
|
||||
del _ws_clients[url][uuid]
|
||||
except KeyError:
|
||||
pass
|
||||
logging.debug('WebSocketEventUpdatesHandler.on_message sent message to %d clients' % count)
|
||||
|
||||
def on_close(self):
|
||||
logging.debug('WebSocketEventUpdatesHandler.on_close')
|
||||
try:
|
||||
if self in _ws_clients.get(self._clean_url(self.request.uri), []):
|
||||
_ws_clients[self._clean_url(self.request.uri)].remove(self)
|
||||
except Exception as e:
|
||||
logging.warn('WebSocketEventUpdatesHandler.on_close error closing websocket: %s', str(e))
|
||||
|
||||
|
||||
class LoginHandler(RootHandler):
|
||||
"""Handle user authentication requests."""
|
||||
|
|
Loading…
Reference in a new issue