Browse Source

#145: populate allPersons from other events with the same Group ID

Davide Alberani 7 years ago
parent
commit
7d79d35992

+ 5 - 1
angular_app/event-edit.html

@@ -9,7 +9,7 @@
                 </button>
                 &nbsp;<button ng-if="event._id && hasPermission('event:tickets-all|create')" ng-click="$state.go('event.ticket.new', {id: event._id})" class="btn btn-success">
                     <span class="fa fa-user-plus vcenter"></span>
-                    {{'Register' | translate}}
+                    {{'Join this event' | translate}}
                 </button>
                 &nbsp;<span ng-if="hasPermission('event|create') && !event.title">{{'New event' | translate}}</span>{{event.title}}
             </h1>
@@ -77,6 +77,10 @@
                         <span class="input-group-addon min100">{{'Where' | translate}}</span>
                         <input type="text" class="form-control" placeholder="{{'Where' | translate}}" ng-model="event.where">
                     </div>
+                    <div class="input-group input-group-lg top5">
+                        <span class="input-group-addon min100">{{'Group ID' | translate}}</span>
+                        <input type="text" class="form-control" placeholder="{{'Used to share persons amongst multiple events. Must be hard to guess (if empty, will be autogenerated)' | translate}}" ng-model="event.group_id">
+                    </div>
                 </fieldset>
 
 

+ 3 - 3
angular_app/event-tickets.html

@@ -45,7 +45,7 @@
                             <thead>
                                 <tr>
                                     <th class="text-right nowrap">#</th>
-                                    <th class="nowrap">{{'Person' | translate}} <a ng-click="updateOrded('name')" href=""><i class="fa fa-caret-up"></i></a>{{'Name' | translate}}<a ng-click="updateOrded('-name')" href=""><i class="fa fa-caret-down"></i></a> <a ng-click="updateOrded('surname')" href=""><i class="fa fa-caret-up"></i></a>{{'Surname' | translate}}<a ng-click="updateOrded('-surname')" href=""><i class="fa fa-caret-down"></i></a></th>
+                                    <th class="nowrap"><a ng-click="updateOrded('name')" href=""><i class="fa fa-caret-up"></i></a>{{'Name' | translate}}<a ng-click="updateOrded('-name')" href=""><i class="fa fa-caret-down"></i></a> <a ng-click="updateOrded('surname')" href=""><i class="fa fa-caret-up"></i></a>{{'Surname' | translate}}<a ng-click="updateOrded('-surname')" href=""><i class="fa fa-caret-down"></i></a></th>
                                     <th class="text-center nowrap"><a ng-click="updateOrded('-attended')" href=""><i class="fa fa-caret-up"></i></a>{{'Attended' | translate}}<a ng-click="updateOrded('attended')" href=""><i class="fa fa-caret-down"></i></a></th>
                                     <th class="text-center nowrap" ng-repeat="col in customFields">
                                         <a ng-click="updateOrded(col.key)" href=""><i class="fa fa-caret-up"></i></a>{{col.label | translate}}<a ng-click="updateOrded('-' + col.key)" href=""><i class="fa fa-caret-down"></i></a>
@@ -61,11 +61,11 @@
                                         <p ng-if="person.company || person.job_title"><i ng-if="person.job_title">{{person.job_title}}</i><span ng-if="person.company && person.job_title">&nbsp;@&nbsp;</span><i ng-if="person.company">{{person.company}}</i></p>
                                     </td>
                                     <td class="text-center">
-                                        <button class="btn btn-link" reset-focus name="switch-attended" ng-click="setPersonAttributeAndRefocus(person, 'attended', !person.attended)"><span class="fa fa-lg {{(person.attended) && 'fa-check-circle text-success' || 'fa-times-circle text-danger'}}"></span></button>
+                                        <button class="btn btn-link" reset-focus name="switch-attended" ng-click="setTicketAttributeAndRefocus(person, 'attended', !person.attended)"><span class="fa fa-lg {{(person.attended) && 'fa-check-circle text-success' || 'fa-times-circle text-danger'}}"></span></button>
                                     </td>
                                     <td class="text-center" ng-repeat="col in customFields">
                                         <span ng-if="col.type == 'boolean'">
-                                            <button class="btn btn-link" ng-click="setPersonAttribute(person, col.key, !person[col.key])"><span class="fa fa-lg {{(person[col.key]) && 'fa-check-circle text-success' || 'fa-times-circle text-danger'}}"></span></button>
+                                            <button class="btn btn-link" ng-click="setTicketAttribute(person, col.key, !person[col.key])"><span class="fa fa-lg {{(person[col.key]) && 'fa-check-circle text-success' || 'fa-times-circle text-danger'}}"></span></button>
                                         </span>
                                         <span ng-if="col.type != 'boolean'">
                                             {{person[col.key]}}

+ 42 - 31
angular_app/js/controllers.js

@@ -180,7 +180,7 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
 
             // Managing the list of tickets.
             if ($state.is('event.tickets')) {
-                $scope.allPersons = Person.all();
+                $scope.allPersons = Event.group_persons({id: $state.params.id});
 
                 // Handle WebSocket connection used to update the list of persons.
                 $scope.EventUpdates = EventUpdates;
@@ -203,7 +203,6 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
                         var person_idx = $scope.event.persons.findIndex(function(el, idx, array) {
                             return data._id == el._id;
                         });
-                        $log.debug(data);
                         if (person_idx != -1) {
                             $log.debug('_id ' + data._id + ' found');
                         } else {
@@ -238,21 +237,43 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
 
         /* Stuff to do when a ticket is added, modified or removed locally. */
 
-        $scope._localAddTicket = function(person) {
+        $scope._localAddTicket = function(ticket, original_person) {
+            var ret = true;
             if (!$scope.event.persons) {
                 $scope.event.persons = [];
             }
-            var person_idx = $scope.event.persons.findIndex(function(el, idx, array) {
-                    return person._id == el._id;
+            var ticket_idx = $scope.event.persons.findIndex(function(el, idx, array) {
+                    return ticket._id == el._id;
             });
-            if (person_idx != -1) {
-                $log.debug('person already present: not added');
-                return false;
+            if (ticket_idx != -1) {
+                $log.warn('ticket already present: not added');
+                ret = false;
+            } else {
+                $scope.event.persons.push(ticket);
+            }
+
+            // Try to remove this person from the allPersons list using ID or email.
+            var field = null;
+            var field_value = null;
+            if (original_person && original_person._id) {
+                field = '_id';
+                field_value = original_person._id;
+            } else if (ticket.email) {
+                field = 'email';
+                field_value = ticket.email;
             }
-            $scope.event.persons.push(person);
+            if (field) {
+                var all_person_idx = $scope.allPersons.findIndex(function(el, idx, array) {
+                    return field_value == el[field];
+                });
+                if (all_person_idx != -1) {
+                    $scope.allPersons.splice(all_person_idx, 1);
+                }
+            }
+            return ret;
         };
 
-        $scope._localUpdateTicket(ticket) {
+        $scope._localUpdateTicket = function(ticket) {
             if (!$scope.event.persons) {
                 $scope.event.persons = [];
             }
@@ -260,15 +281,13 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
                 return ticket._id == el._id;
             });
             if (ticket_idx == -1) {
-                $log.debug('person not present: not updated');
+                $log.warn('ticket not present: not updated');
                 return false;
             }
             $scope.event.persons[ticket_idx] = ticket;
-        });
+        };
 
         $scope._localRemoveTicket = function(person) {
-            $log.debug('_localRemoveTicket');
-            $log.debug(person);
             if (!(person && person._id && $scope.event.persons)) {
                 return;
             }
@@ -292,10 +311,8 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
             }
         };
 
-        $scope.setPersonAttribute = function(person, key, value, callback, hideMessage) {
-            $log.debug('EventDetailsCtrl.setPersonAttribute.event_id: ' + $state.params.id);
-            $log.debug('EventDetailsCtrl.setPersonAttribute._id: ' + person._id);
-            $log.debug('EventDetailsCtrl.setPersonAttribute.key: ' + key + ' value: ' + value);
+        $scope.setTicketAttribute = function(person, key, value, callback, hideMessage) {
+            $log.debug('setTicketAttribute for _id ' + person._id + ' key: ' + key + ' value: ' + value);
             var newData = {event_id: $state.params.id, _id: person._id};
             newData[key] = value;
             EventTicket.update(newData, function(data) {
@@ -328,20 +345,13 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
             });
         };
 
-        $scope.setPersonAttributeAndRefocus = function(person, key, value) {
-            $scope.setPersonAttribute(person, key, value);
+        $scope.setTicketAttributeAndRefocus = function(person, key, value) {
+            $scope.setTicketAttribute(person, key, value);
             $scope.query = '';
         };
 
         $scope._setAttended = function(person) {
-            $scope.setPersonAttribute(person, 'attended', true, function() {
-                var all_person_idx = $scope.allPersons.findIndex(function(el, idx, array) {
-                    return person._id == el._id;
-                });
-                if (all_person_idx != -1) {
-                    $scope.allPersons.splice(all_person_idx, 1);
-                }
-            }, true);
+            $scope.setTicketAttribute(person, 'attended', true, null, true);
         };
 
         $scope.deleteTicket = function(person) {
@@ -356,8 +366,9 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
         $scope.addTicket = function(person) {
             person.event_id = $state.params.id;
             EventTicket.add(person, function(ticket) {
+                $log.debug('addTicket');
                 $log.debug(ticket);
-                $scope._localAddTicket(ticket);
+                $scope._localAddTicket(ticket, person);
                 if (!$state.is('event.tickets')) {
                     $state.go('event.ticket.edit', {id: $scope.event._id, ticket_id: ticket._id});
                 } else {
@@ -385,7 +396,7 @@ eventManControllers.controller('EventTicketsCtrl', ['$scope', '$state', 'Event',
                 return;
             }
             $scope.ticket.cancelled = !$scope.ticket.cancelled;
-            $scope.setPersonAttribute($scope.ticket, 'cancelled', $scope.ticket.cancelled, function() {
+            $scope.setTicketAttribute($scope.ticket, 'cancelled', $scope.ticket.cancelled, function() {
                 $scope.guiOptions.dangerousActionsEnabled = false;
             });
         };
@@ -570,7 +581,7 @@ eventManControllers.controller('PersonDetailsCtrl', ['$scope', '$state', 'Person
             $scope.personForm.$setPristine(false);
         };
 
-        $scope.setPersonAttributeAtEvent = function(evnt, key, value) {
+        $scope.setTicketAttributeAtEvent = function(evnt, key, value) {
             var attrs = {_id: evnt._id, person_id: $state.params.id};
             attrs[key] = value;
             Event.updatePerson(attrs,

+ 11 - 1
angular_app/js/services.js

@@ -18,7 +18,7 @@ function convert_dates(obj) {
 
 eventManServices.factory('Event', ['$resource', '$rootScope',
     function($resource, $rootScope) {
-        return $resource('events/:id', {id: '@_id', ticket_id: '@_id'}, {
+        return $resource('events/:id', {id: '@_id'}, {
 
             all: {
                 method: 'GET',
@@ -58,6 +58,16 @@ eventManServices.factory('Event', ['$resource', '$rootScope',
             update: {
                 method: 'PUT',
                 interceptor : {responseError: $rootScope.errorHandler}
+            },
+
+            group_persons: {
+                method: 'GET',
+                url: 'events/:id/group_persons',
+                isArray: true,
+                transformResponse: function(data, headers) {
+                    data = angular.fromJson(data);
+                    return data.persons || [];
+                }
             }
         });
     }]

+ 26 - 0
eventman_server.py

@@ -576,6 +576,15 @@ class EventsHandler(CollectionHandler):
                     event['persons'] = []
         return output
 
+    def filter_input_post(self, data):
+        # Auto-generate the group_id, if missing.
+        if 'group_id' not in data:
+            data['group_id'] = self.gen_id()
+        return data
+
+    filter_input_post_all = filter_input_post
+    filter_input_put = filter_input_post
+
     def filter_input_post_tickets(self, data):
         if not self.has_permission('event|update'):
             if 'attended' in data:
@@ -584,6 +593,23 @@ class EventsHandler(CollectionHandler):
 
     filter_input_put_tickets = filter_input_post_tickets
 
+    def handle_get_group_persons(self, id_, resource_id=None):
+        persons = []
+        this_query = {'_id': id_}
+        this_event = self.db.query('events', this_query)[0]
+        group_id = this_event.get('group_id')
+        if group_id is None:
+            return {'persons': persons}
+        this_persons = [p for p in (this_event.get('persons') or []) if not p.get('cancelled')]
+        this_emails = filter(None, [p.get('email') for p in this_persons])
+        all_query = {'group_id': group_id}
+        events = self.db.query('events', all_query)
+        for event in events:
+            if str(event.get('_id')) == id_:
+                continue
+            persons += [p for p in (event.get('persons') or []) if p.get('email') and p.get('email') not in this_emails]
+        return {'persons': persons}
+
     def _get_person_data(self, person_id_or_query, persons):
         """Filter a list of persons returning the first item with a given person_id
         or which set of keys specified in a dictionary match their respective values."""