Fixed email translations, motion sorting, undefined in DOCX, reduced motion search
This commit is contained in:
parent
ec2fcbdd73
commit
0b04b7478f
@ -30,6 +30,6 @@ script:
|
|||||||
- coverage report --fail-under=44
|
- coverage report --fail-under=44
|
||||||
|
|
||||||
- DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py test tests.integration
|
- DJANGO_SETTINGS_MODULE='tests.settings' coverage run ./manage.py test tests.integration
|
||||||
- coverage report --fail-under=74
|
- coverage report --fail-under=73
|
||||||
|
|
||||||
- DJANGO_SETTINGS_MODULE='tests.settings' ./manage.py test tests.old
|
- DJANGO_SETTINGS_MODULE='tests.settings' ./manage.py test tests.old
|
||||||
|
@ -80,7 +80,7 @@ angular.module('OpenSlidesApp.motions.docx', ['OpenSlidesApp.core.docx'])
|
|||||||
var getMotionShortData = function (motions) {
|
var getMotionShortData = function (motions) {
|
||||||
return _.map(motions, function (motion) {
|
return _.map(motions, function (motion) {
|
||||||
return {
|
return {
|
||||||
identifier: motion.identifier,
|
identifier: motion.identifier || '',
|
||||||
title: motion.getTitle(),
|
title: motion.getTitle(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -113,7 +113,7 @@ angular.module('OpenSlidesApp.motions.docx', ['OpenSlidesApp.core.docx'])
|
|||||||
sequential_enabled: sequential_enabled,
|
sequential_enabled: sequential_enabled,
|
||||||
// Actual data
|
// Actual data
|
||||||
id: motion.id,
|
id: motion.id,
|
||||||
identifier: motion.identifier,
|
identifier: motion.identifier || '',
|
||||||
title: motion.getTitle(),
|
title: motion.getTitle(),
|
||||||
submitters: params.include.submitters ? _.map(motion.submitters, function (submitter) {
|
submitters: params.include.submitters ? _.map(motion.submitters, function (submitter) {
|
||||||
return submitter.get_full_name();
|
return submitter.get_full_name();
|
||||||
|
@ -782,21 +782,6 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
},
|
},
|
||||||
hideExpression: "model.format !== 'csv'",
|
hideExpression: "model.format !== 'csv'",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: 'include',
|
|
||||||
type: 'checkbox-buttons',
|
|
||||||
templateOptions: {
|
|
||||||
label: gettextCatalog.getString('Meta information'),
|
|
||||||
options: getMetaInformationOptions({
|
|
||||||
state: true,
|
|
||||||
votingResult: true,
|
|
||||||
motionBlock: true,
|
|
||||||
origin: true,
|
|
||||||
recommendation: true,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
hideExpression: "model.format !== 'docx'",
|
|
||||||
},
|
|
||||||
]);
|
]);
|
||||||
if (commentsAvailable) {
|
if (commentsAvailable) {
|
||||||
fields.push({
|
fields.push({
|
||||||
@ -855,6 +840,7 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
}
|
}
|
||||||
if ($scope.params.format === 'docx') {
|
if ($scope.params.format === 'docx') {
|
||||||
$scope.params.include.state = false;
|
$scope.params.include.state = false;
|
||||||
|
$scope.params.include.submitter = true;
|
||||||
$scope.params.include.motionBlock = false;
|
$scope.params.include.motionBlock = false;
|
||||||
$scope.params.include.origin = false;
|
$scope.params.include.origin = false;
|
||||||
$scope.params.include.recommendation = false;
|
$scope.params.include.recommendation = false;
|
||||||
@ -1127,12 +1113,9 @@ angular.module('OpenSlidesApp.motions.site', [
|
|||||||
$scope.filter.propertyList = ['identifier', 'origin'];
|
$scope.filter.propertyList = ['identifier', 'origin'];
|
||||||
$scope.filter.propertyFunctionList = [
|
$scope.filter.propertyFunctionList = [
|
||||||
function (motion) {return motion.getTitle();},
|
function (motion) {return motion.getTitle();},
|
||||||
function (motion) {return motion.getText();},
|
|
||||||
function (motion) {return motion.getReason();},
|
|
||||||
function (motion) {return motion.category ? motion.category.name : '';},
|
function (motion) {return motion.category ? motion.category.name : '';},
|
||||||
function (motion) {return motion.motionBlock ? motion.motionBlock.name : '';},
|
function (motion) {return motion.motionBlock ? motion.motionBlock.name : '';},
|
||||||
function (motion) {return motion.recommendation ? motion.getRecommendationName() : '';},
|
function (motion) {return motion.recommendation ? motion.getRecommendationName() : '';},
|
||||||
function (motion) {return _.filter(motion.comments).join(' ');},
|
|
||||||
];
|
];
|
||||||
$scope.filter.propertyDict = {
|
$scope.filter.propertyDict = {
|
||||||
'submitters': function (submitter) {
|
'submitters': function (submitter) {
|
||||||
|
@ -239,7 +239,7 @@
|
|||||||
<translate>Motion</translate>
|
<translate>Motion</translate>
|
||||||
</span>
|
</span>
|
||||||
<ul uib-dropdown-menu class="dropdown-menu" aria-labelledby="motion-dropdown">
|
<ul uib-dropdown-menu class="dropdown-menu" aria-labelledby="motion-dropdown">
|
||||||
<li ng-repeat="m in motions">
|
<li ng-repeat="m in motions | orderBy: identifier">
|
||||||
<a href ng-click="addMotionToRecommendationField(m)">
|
<a href ng-click="addMotionToRecommendationField(m)">
|
||||||
{{ m.identifier ? m.identifier + ':' : '' }} {{ m.getTitle() }}
|
{{ m.identifier ? m.identifier + ':' : '' }} {{ m.getTitle() }}
|
||||||
</a>
|
</a>
|
||||||
|
@ -240,7 +240,7 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser):
|
|||||||
"""
|
"""
|
||||||
raise RuntimeError('Do not use user.has_perm() but use openslides.utils.auth.has_perm')
|
raise RuntimeError('Do not use user.has_perm() but use openslides.utils.auth.has_perm')
|
||||||
|
|
||||||
def send_invitation_email(self, connection, skip_autoupdate=False):
|
def send_invitation_email(self, connection, subject, message, skip_autoupdate=False):
|
||||||
"""
|
"""
|
||||||
Sends an invitation email to the users. Returns True on success, False on failiure.
|
Sends an invitation email to the users. Returns True on success, False on failiure.
|
||||||
May raise an ValidationError, if something went wrong.
|
May raise an ValidationError, if something went wrong.
|
||||||
@ -260,10 +260,10 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser):
|
|||||||
'url': config['users_pdf_url'],
|
'url': config['users_pdf_url'],
|
||||||
'username': self.username,
|
'username': self.username,
|
||||||
'password': self.default_password})
|
'password': self.default_password})
|
||||||
message = config['users_email_body'].format(**message_format)
|
message = message.format(**message_format)
|
||||||
|
|
||||||
subject_format = format_dict({'event_name': config['general_event_name']})
|
subject_format = format_dict({'event_name': config['general_event_name']})
|
||||||
subject = config['users_email_subject'].format(**subject_format)
|
subject = subject.format(**subject_format)
|
||||||
|
|
||||||
# Create an email and send it.
|
# Create an email and send it.
|
||||||
email = mail.EmailMessage(subject, message, config['users_email_sender'], [self.email])
|
email = mail.EmailMessage(subject, message, config['users_email_sender'], [self.email])
|
||||||
|
@ -771,8 +771,13 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
return user.id;
|
return user.id;
|
||||||
})
|
})
|
||||||
.value();
|
.value();
|
||||||
|
var subject = gettextCatalog.getString(Config.get('users_email_subject').value);
|
||||||
|
var message = gettextCatalog.getString(Config.get('users_email_body').value);
|
||||||
|
|
||||||
$http.post('/rest/users/user/mass_invite_email/', {
|
$http.post('/rest/users/user/mass_invite_email/', {
|
||||||
user_ids: user_ids,
|
user_ids: user_ids,
|
||||||
|
subject: subject,
|
||||||
|
message: message,
|
||||||
}).then(function (success) {
|
}).then(function (success) {
|
||||||
var numEmails = success.data.count;
|
var numEmails = success.data.count;
|
||||||
var noEmailIds = success.data.no_email_ids;
|
var noEmailIds = success.data.no_email_ids;
|
||||||
@ -1833,7 +1838,7 @@ angular.module('OpenSlidesApp.users.site', [
|
|||||||
gettext('Your login for {event_name}');
|
gettext('Your login for {event_name}');
|
||||||
gettext('You can use {event_name} as a placeholder.');
|
gettext('You can use {event_name} as a placeholder.');
|
||||||
gettext('Email body');
|
gettext('Email body');
|
||||||
gettext('Dear {name},\n\nthis is your OpenSlides login for the event "{event_name}":\n {url}\n username: {username}\n password: {password}\n\nThis email was generated automatically.');
|
gettext('Dear {name},\n\nthis is your OpenSlides login for the event "{event_name}":\n {url}\n\n username: {username}\n password: {password}\n\nThis email was generated automatically.');
|
||||||
gettext('Use these placeholders: {name}, {event_name}, {url}, {username}, {password}. The url referrs to the system url.');
|
gettext('Use these placeholders: {name}, {event_name}, {url}, {username}, {password}. The url referrs to the system url.');
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
@ -180,6 +180,14 @@ class UserViewSet(ModelViewSet):
|
|||||||
for user_id in user_ids:
|
for user_id in user_ids:
|
||||||
if not isinstance(user_id, int):
|
if not isinstance(user_id, int):
|
||||||
raise ValidationError({'detail': 'User_id has to be an int.'})
|
raise ValidationError({'detail': 'User_id has to be an int.'})
|
||||||
|
# Get subject and body from the response. Do not use the config values
|
||||||
|
# because they might not be translated.
|
||||||
|
subject = request.data.get('subject')
|
||||||
|
message = request.data.get('message')
|
||||||
|
if not isinstance(subject, str):
|
||||||
|
raise ValidationError({'detail': 'Subject has to be a string.'})
|
||||||
|
if not isinstance(message, str):
|
||||||
|
raise ValidationError({'detail': 'Message has to be a string.'})
|
||||||
users = User.objects.filter(pk__in=user_ids)
|
users = User.objects.filter(pk__in=user_ids)
|
||||||
|
|
||||||
# Sending Emails. Keep track, which users gets an email.
|
# Sending Emails. Keep track, which users gets an email.
|
||||||
@ -199,7 +207,7 @@ class UserViewSet(ModelViewSet):
|
|||||||
try:
|
try:
|
||||||
for user in users:
|
for user in users:
|
||||||
if user.email:
|
if user.email:
|
||||||
if user.send_invitation_email(connection, skip_autoupdate=True):
|
if user.send_invitation_email(connection, subject, message, skip_autoupdate=True):
|
||||||
success_users.append(user)
|
success_users.append(user)
|
||||||
else:
|
else:
|
||||||
user_pks_without_email.append(user.pk)
|
user_pks_without_email.append(user.pk)
|
||||||
|
@ -351,9 +351,14 @@ class UserSendIntivationEmail(TestCase):
|
|||||||
self.admin.save()
|
self.admin.save()
|
||||||
|
|
||||||
def test_email_sending(self):
|
def test_email_sending(self):
|
||||||
|
data = {
|
||||||
|
'user_ids': [self.admin.pk],
|
||||||
|
'subject': config['users_email_subject'],
|
||||||
|
'message': config['users_email_body']
|
||||||
|
}
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse('user-mass-invite-email'),
|
reverse('user-mass-invite-email'),
|
||||||
{'user_ids': [self.admin.pk]},
|
data,
|
||||||
format='json')
|
format='json')
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.data['count'], 1)
|
self.assertEqual(response.data['count'], 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user