diff --git a/openslides/users/static/js/users/site.js b/openslides/users/static/js/users/site.js index 34be843af..51ed5f779 100644 --- a/openslides/users/static/js/users/site.js +++ b/openslides/users/static/js/users/site.js @@ -561,6 +561,9 @@ angular.module('OpenSlidesApp.users.site', [ return User.lastModified(); }, function () { $scope.users = _.orderBy(User.getAll(), ['first_name']); + _.forEach($scope.users, function (user) { + user.has_last_email_send = !!user.last_email_send; + }); }); Group.bindAll({where: {id: {'>': 1}}}, $scope, 'groups'); $scope.$watch(function () { @@ -601,6 +604,12 @@ angular.module('OpenSlidesApp.users.site', [ choiceYes: gettext('Is a committee'), choiceNo: gettext('Is not a committee'), }, + hasLastEmailSend: { + value: undefined, + displayName: gettext('Last email send'), + choiceYes: gettext('Got an email'), + choiceNo: gettext("Didn't get an email"), + }, }; } $scope.filter.propertyList = ['first_name', 'last_name', 'username', 'title', @@ -765,9 +774,54 @@ angular.module('OpenSlidesApp.users.site', [ $http.post('/rest/users/user/mass_invite_email/', { user_ids: user_ids, }).then(function (success) { + var numEmails = success.data.count; + var noEmailIds = success.data.no_email_ids; + var type = 'success', msg; + if (numEmails === 0) { + type = 'danger'; + msg = gettextCatalog.getString('No emails were send.'); + } else if (numEmails === 1) { + msg = gettextCatalog.getString('One email was send sucessfully.'); + } else { + msg = gettextCatalog.getString('%num% emails were send sucessfully.').replace('%num%', numEmails); + } + + if (noEmailIds.length) { + type = 'warning'; + msg += ' '; + + if (noEmailIds.length === 1) { + msg += gettextCatalog.getString('The user %user% has no email, so the invitation email could not be send.'); + } else { + msg += gettextCatalog.getString('The users %user% have no email, so the invitation emails could not be send.'); + } + + // This one builds a username string like "user1, user2 and user3" with the full names. + var lastUsername, userString = _ + .chain(noEmailIds) + .map(function (id) { + var user = User.get(id); + return user ? user.get_full_name() : ''; + }) + .filter(function (username) { + return username; + }) + .tap(function (names) { + if (names.length !== 1) { + lastUsername = names.pop(); + } + }) + .join(', ') + .thru(function (names) { + return lastUsername ? names + ' ' + gettextCatalog.getString('and') + ' ' + lastUsername : names; + }) + .value(); + msg = msg.replace('%user%', userString); + } + $scope.alert = { - msg: gettextCatalog.getString('Send %num% emails sucessfully.').replace('%num%', success.data.count), - type: 'success', + msg: msg, + type: type, show: true, }; $scope.isSelectMode = false; diff --git a/openslides/users/static/templates/users/user-list.html b/openslides/users/static/templates/users/user-list.html index 57a46b5d3..a7fa4822a 100644 --- a/openslides/users/static/templates/users/user-list.html +++ b/openslides/users/static/templates/users/user-list.html @@ -161,6 +161,7 @@ | filter: {is_present: filter.booleanFilters.isPresent.value} | filter: {is_active: filter.booleanFilters.isActive.value} | filter: {is_committee: filter.booleanFilters.isCommittee.value} + | filter: {has_last_email_send: filter.booleanFilters.hasLastEmailSend.value} | MultiselectFilter: filter.multiselectFilters.group : getItemId.group | orderByEmptyLast: sort.column: sort.reverse)"> diff --git a/openslides/users/views.py b/openslides/users/views.py index 6f9188508..aecfcd609 100644 --- a/openslides/users/views.py +++ b/openslides/users/views.py @@ -195,16 +195,22 @@ class UserViewSet(ModelViewSet): raise ValidationError({'detail': '{}: {}'.format(e.errno, e.strerror)}) success_users = [] + user_pks_without_email = [] try: for user in users: - if user.send_invitation_email(connection, skip_autoupdate=True): - success_users.append(user) + if user.email: + if user.send_invitation_email(connection, skip_autoupdate=True): + success_users.append(user) + else: + user_pks_without_email.append(user.pk) except DjangoValidationError as e: raise ValidationError(e.message_dict) connection.close() inform_changed_data(success_users) - return Response({'count': len(success_users)}) + return Response({ + 'count': len(success_users), + 'no_email_ids': user_pks_without_email}) class GroupViewSetMetadata(SimpleMetadata):