Merge pull request #2221 from matakuka/issue2214

Added user field "number" (fixes #2214)
This commit is contained in:
Norman Jäckel 2016-08-04 10:21:17 +02:00 committed by GitHub
commit 81bcb19847
9 changed files with 67 additions and 14 deletions

View File

@ -11,6 +11,9 @@ Version 2.1 (unreleased)
Agenda: Agenda:
- Added button to remove all speakers from a list of speakers. - Added button to remove all speakers from a list of speakers.
Assignments:
- Remove unused assignment config to publish winner election results only.
Core: Core:
- Used Django Channels instead of Tornado. - Used Django Channels instead of Tornado.
- Added support for big assemblies with lots of users. - Added support for big assemblies with lots of users.
@ -19,11 +22,9 @@ Motions:
- Added origin field. - Added origin field.
- Added button to number all motions in a category. - Added button to number all motions in a category.
Assignments:
- Remove unused assignment config to publish winner election results only.
Users: Users:
- Added field is_committee and new default group Committees. - Added field is_committee and new default group Committees.
- Added field number.
Other: Other:
- Removed config cache to support multiple threads or processes. - Removed config cache to support multiple threads or processes.

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-01 14:54
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0002_user_is_committee'),
]
operations = [
migrations.AddField(
model_name='user',
name='number',
field=models.CharField(blank=True, default='', max_length=50),
),
]

View File

@ -124,6 +124,11 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser):
blank=True, blank=True,
default='') default='')
number = models.CharField(
max_length=50,
blank=True,
default='')
about_me = models.TextField( about_me = models.TextField(
blank=True, blank=True,
default='') default='')

View File

@ -23,8 +23,7 @@ def users_to_pdf(pdf):
""" """
Create a list of all users as PDF. Create a list of all users as PDF.
""" """
data = [['#', _('Title'), _('Last Name'), _('First Name'), data = [['#', _('Name'), _('Structure level'), _('Group')]]
_('Structure level'), _('Group')]]
if config['users_sort_users_by_first_name']: if config['users_sort_users_by_first_name']:
sort = 'first_name' sort = 'first_name'
else: else:
@ -36,11 +35,19 @@ def users_to_pdf(pdf):
for group in user.groups.all(): for group in user.groups.all():
if group.pk != 2: if group.pk != 2:
groups += "%s<br/>" % escape(_(group.name)) groups += "%s<br/>" % escape(_(group.name))
if sort == 'last_name':
name = "%s" % escape(user.last_name)
if user.first_name:
name = "%s, %s" % (name, escape(user.first_name))
else:
name = "%s %s" % (escape(user.first_name), escape(user.last_name))
if user.title:
name = "%s %s" % (user.title, name)
if user.number:
name = "%s<br/>%s" % (name, user.number)
data.append([ data.append([
counter, counter,
Paragraph(user.title, stylesheet['Tablecell']), Paragraph(name, stylesheet['Tablecell']),
Paragraph(escape(user.last_name), stylesheet['Tablecell']),
Paragraph(escape(user.first_name), stylesheet['Tablecell']),
Paragraph(escape(user.structure_level), stylesheet['Tablecell']), Paragraph(escape(user.structure_level), stylesheet['Tablecell']),
Paragraph(groups, stylesheet['Tablecell'])]) Paragraph(groups, stylesheet['Tablecell'])])
t = LongTable(data, style=[ t = LongTable(data, style=[
@ -65,6 +72,7 @@ def users_passwords_to_pdf(pdf):
users_pdf_url = config["users_pdf_url"] or "-" users_pdf_url = config["users_pdf_url"] or "-"
users_pdf_welcometitle = config["users_pdf_welcometitle"] users_pdf_welcometitle = config["users_pdf_welcometitle"]
users_pdf_welcometext = config["users_pdf_welcometext"] users_pdf_welcometext = config["users_pdf_welcometext"]
if config['users_sort_users_by_first_name']: if config['users_sort_users_by_first_name']:
sort = 'first_name' sort = 'first_name'
else: else:
@ -88,6 +96,7 @@ def users_passwords_to_pdf(pdf):
for user in User.objects.all().order_by(sort): for user in User.objects.all().order_by(sort):
pdf.append(Paragraph(escape(user.get_full_name()), stylesheet['h1'])) pdf.append(Paragraph(escape(user.get_full_name()), stylesheet['h1']))
pdf.append(Paragraph(escape(user.number), stylesheet['h3']))
pdf.append(Spacer(0, 1 * cm)) pdf.append(Spacer(0, 1 * cm))
data = [] data = []
# WLAN access data # WLAN access data

View File

@ -18,6 +18,7 @@ USERSHORTSERIALIZER_FIELDS = (
'first_name', 'first_name',
'last_name', 'last_name',
'structure_level', 'structure_level',
'number',
'about_me', 'about_me',
'groups', 'groups',
'is_committee', 'is_committee',
@ -57,6 +58,7 @@ class UserFullSerializer(ModelSerializer):
'title', 'title',
'first_name', 'first_name',
'last_name', 'last_name',
'number',
'structure_level', 'structure_level',
'about_me', 'about_me',
'comment', 'comment',

View File

@ -318,6 +318,12 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
description: gettextCatalog.getString('Will be shown after the name.') description: gettextCatalog.getString('Will be shown after the name.')
} }
}, },
{ key: 'number',
type: 'input',
templateOptions: {
label:gettextCatalog.getString('Participant number')
}
},
{ {
key: 'groups_id', key: 'groups_id',
type: 'select-multiple', type: 'select-multiple',
@ -750,6 +756,10 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
if (user.structure_level) { if (user.structure_level) {
user.structure_level = user.structure_level.replace(quotionRe, '$1'); user.structure_level = user.structure_level.replace(quotionRe, '$1');
} }
// number
if (user.number) {
user.number = user.number.replace(quotionRe, '$1');
}
// groups // groups
if (user.groups) { if (user.groups) {
var csvGroups = user.groups.replace(quotionRe, '$1').split(","); var csvGroups = user.groups.replace(quotionRe, '$1').split(",");
@ -822,12 +832,12 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
var element = document.getElementById('downloadLink'); var element = document.getElementById('downloadLink');
var csvRows = [ var csvRows = [
// column header line // column header line
['title', 'first_name', 'last_name', 'structure_level', 'groups', 'comment', 'is_active', 'is_committee'], ['title', 'first_name', 'last_name', 'structure_level', 'number', 'groups', 'comment', 'is_active', 'is_committee'],
// example entries // example entries
['Dr.', 'Max', 'Mustermann', 'Berlin', '"3,4"', 'xyz', '1', ''], ['Dr.', 'Max', 'Mustermann', 'Berlin','1234567890', '"3,4"', 'xyz', '1', ''],
['', 'John', 'Doe', 'Washington', '3', 'abc', '1', ''], ['', 'John', 'Doe', 'Washington','75/99/8-2', '3', 'abc', '1', ''],
['', 'Fred', 'Bloggs', 'London', '', '', '', ''], ['', 'Fred', 'Bloggs', 'London', '', '', '', '', ''],
['', '', 'Executive Board', '', '5', '', '', '1'], ['', '', 'Executive Board', '', '', '5', '', '', '1'],
]; ];
var csvString = csvRows.join("%0A"); var csvString = csvRows.join("%0A");

View File

@ -34,6 +34,8 @@
<div ng-repeat="group in user.groups_id"> <div ng-repeat="group in user.groups_id">
{{ (groups | filter: {id: group})[0].name | translate }} {{ (groups | filter: {id: group})[0].name | translate }}
</div> </div>
<label translate>Participant number</label>
{{ user.number }}
<label translate>About me</label> <label translate>About me</label>
<div ng-bind-html="user.about_me"></div> <div ng-bind-html="user.about_me"></div>
</fieldset> </fieldset>

View File

@ -68,7 +68,7 @@
<h4 translate>Please note:</h4> <h4 translate>Please note:</h4>
<ul> <ul>
<li><translate>Required comma or semicolon separated values with these column header names in the first row</translate>:<br> <li><translate>Required comma or semicolon separated values with these column header names in the first row</translate>:<br>
<code>title, first_name, last_name, structure_level, groups, comment, is_active, is_committee</code> <code>title, first_name, last_name, structure_level, number, groups, comment, is_active, is_committee</code>
<li><translate>Default groups</translate>: <li><translate>Default groups</translate>:
<translate>Delegates</translate> <code>3</code>, <translate>Delegates</translate> <code>3</code>,
<translate>Staff</translate> <code>4</code> <translate>Staff</translate> <code>4</code>
@ -90,6 +90,7 @@
<th translate>First name <th translate>First name
<th translate>Last name <th translate>Last name
<th translate>Structure level <th translate>Structure level
<th translate>Participant number
<th translate>Groups <th translate>Groups
<th translate>Comment <th translate>Comment
<th translate>Is active <th translate>Is active
@ -123,6 +124,8 @@
{{ user.last_name }} {{ user.last_name }}
<td> <td>
{{ user.structure_level }} {{ user.structure_level }}
<td>
{{ user.number }}
<td> <td>
<div ng-repeat="groupname in user.groupnames"> <div ng-repeat="groupname in user.groupnames">
{{ groupname | translate }} {{ groupname | translate }}

View File

@ -196,6 +196,7 @@
<div ng-if="user.comment"> <div ng-if="user.comment">
<small><i class="fa fa-info-circle"></i> {{ user.comment }}</small> <small><i class="fa fa-info-circle"></i> {{ user.comment }}</small>
</div> </div>
<div ng-if="user.number"> {{ user.number }} </div>
<div os-perms="users.can_manage" class="hoverActions" ng-class="{'hiddenDiv': !user.hover}"> <div os-perms="users.can_manage" class="hoverActions" ng-class="{'hiddenDiv': !user.hover}">
<a href="" ng-click="openDialog(user)" translate>Edit</a> | <a href="" ng-click="openDialog(user)" translate>Edit</a> |
<a href="" class="text-danger" <a href="" class="text-danger"