Merge pull request #2216 from normanjaeckel/IsCommittee

Added new user field is_committee and new default group Committees.
This commit is contained in:
Norman Jäckel 2016-07-29 11:55:00 +02:00 committed by GitHub
commit b96d7d0514
8 changed files with 89 additions and 11 deletions

View File

@ -8,7 +8,7 @@ Version 2.1 (unreleased)
======================== ========================
[https://github.com/OpenSlides/OpenSlides/milestones/2.1] [https://github.com/OpenSlides/OpenSlides/milestones/2.1]
Agenda: Agenda:
- Added button to remove all speakers from a list of speakers. - Added button to remove all speakers from a list of speakers.
Core: Core:
@ -18,6 +18,9 @@ Core:
Motions: Motions:
- Added origin field. - Added origin field.
Users:
- Added field is_committee and new default group Committees.
Other: Other:
- Removed config cache to support multiple threads or processes. - Removed config cache to support multiple threads or processes.
- Fixed bug, that the last change of a config value was not send via autoupdate. - Fixed bug, that the last change of a config value was not send via autoupdate.

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-06-30 12:41
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='user',
name='is_committee',
field=models.BooleanField(default=False),
),
]

View File

@ -143,6 +143,9 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser):
is_present = models.BooleanField( is_present = models.BooleanField(
default=False) default=False)
is_committee = models.BooleanField(
default=False)
objects = UserManager() objects = UserManager()
class Meta: class Meta:

View File

@ -20,6 +20,7 @@ USERSHORTSERIALIZER_FIELDS = (
'structure_level', 'structure_level',
'about_me', 'about_me',
'groups', 'groups',
'is_committee',
) )
@ -62,6 +63,7 @@ class UserFullSerializer(ModelSerializer):
'groups', 'groups',
'default_password', 'default_password',
'is_active', 'is_active',
'is_committee',
) )
def validate(self, data): def validate(self, data):

View File

@ -6,12 +6,13 @@ from .models import Group, User
def create_builtin_groups_and_admin(**kwargs): def create_builtin_groups_and_admin(**kwargs):
""" """
Creates the builtin groups: Anonymous, Registered, Delegates and Staff. Creates the builtin groups: Anonymous, Registered, Delegates, Staff and
Committees.
Creates the builtin user: admin. Creates the builtin user: admin.
""" """
# Check whether the group pks 1 to 4 are free # Check whether the group pk's 1 to 5 are free.
if Group.objects.filter(pk__in=range(1, 5)).exists(): if Group.objects.filter(pk__in=range(1, 6)).exists():
# Do completely nothing if there are already some of our groups in the database. # Do completely nothing if there are already some of our groups in the database.
return return
@ -104,5 +105,13 @@ def create_builtin_groups_and_admin(**kwargs):
group_staff.permissions.add( group_staff.permissions.add(
permission_dict['users.can_see_name']) permission_dict['users.can_see_name'])
# Committees (pk 5)
committees_permissions = (
permission_dict['mediafiles.can_upload'],
permission_dict['motions.can_create'],
permission_dict['motions.can_support'], )
group_committee = Group.objects.create(name='Committees', pk=5)
group_committee.permissions.add(*committees_permissions)
# Create or reset admin user # Create or reset admin user
User.objects.create_or_reset_admin_user() User.objects.create_or_reset_admin_user()

View File

@ -386,6 +386,16 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
'active. Unselect this instead of deleting the account.') 'active. Unselect this instead of deleting the account.')
}, },
defaultValue: true defaultValue: true
},
{
key: 'is_committee',
type: 'checkbox',
templateOptions: {
label: gettextCatalog.getString('Is a committee'),
description: gettextCatalog.getString(
'Designates whether this user should be treated as a committee.')
},
defaultValue: false
}]; }];
} }
}; };
@ -775,6 +785,17 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
} else { } else {
user.is_active = false; user.is_active = false;
} }
// is committee
if (user.is_committee) {
user.is_committee = user.is_committee.replace(quotionRe, '$1');
if (user.is_committee == '1') {
user.is_committee = true;
} else {
user.is_committee = false;
}
} else {
user.is_committee = false;
}
$scope.users.push(user); $scope.users.push(user);
}); });
}); });
@ -801,11 +822,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'], ['title', 'first_name', 'last_name', 'structure_level', 'groups', 'comment', 'is_active', 'is_committee'],
// example entries // example entries
['Dr.', 'Max', 'Mustermann', 'Berlin', '"3,4"', 'xyz', '1'], ['Dr.', 'Max', 'Mustermann', 'Berlin', '"3,4"', 'xyz', '1', ''],
['', 'John', 'Doe', 'Washington', '3', 'abc', '1'], ['', 'John', 'Doe', 'Washington', '3', 'abc', '1', ''],
['', 'Fred', 'Bloggs', 'London', '', '', ''], ['', 'Fred', 'Bloggs', 'London', '', '', '', ''],
['', '', 'Executive Board', '', '5', '', '', '1'],
]; ];
var csvString = csvRows.join("%0A"); var csvString = csvRows.join("%0A");

View File

@ -68,10 +68,11 @@
<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</code> <code>title, first_name, last_name, structure_level, 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>
<translate>Committees</translate> <code>5</code>
<li translate>At least first name or last name have to be filled in. All <li translate>At least first name or last name have to be filled in. All
other fields are optional and may be empty. other fields are optional and may be empty.
<li translate>Only double quotes are accepted as text delimiter (no single quotes). <li translate>Only double quotes are accepted as text delimiter (no single quotes).
@ -91,7 +92,8 @@
<th translate>Structure level <th translate>Structure level
<th translate>Groups <th translate>Groups
<th translate>Comment <th translate>Comment
<th translate>Is active</th> <th translate>Is active
<th translate>Is committee</th>
<tbody> <tbody>
<tr ng-repeat="user in users | limitTo : itemsPerPage : limitBegin"> <tr ng-repeat="user in users | limitTo : itemsPerPage : limitBegin">
<td class="minimum" <td class="minimum"
@ -129,6 +131,8 @@
{{ user.comment }} {{ user.comment }}
<td> <td>
<i ng-if="user.is_active" class="fa fa-check-square-o"></i> <i ng-if="user.is_active" class="fa fa-check-square-o"></i>
<td>
<i ng-if="user.is_committee" class="fa fa-check-square-o"></i>
</table> </table>
<uib-pagination total-items="users.length" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()"></uib-pagination> <uib-pagination total-items="users.length" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()"></uib-pagination>

View File

@ -137,25 +137,34 @@
<tr> <tr>
<!-- projector column --> <!-- projector column -->
<th ng-show="!isSelectMode" os-perms="core.can_manage_projector" class="minimum"> <th ng-show="!isSelectMode" os-perms="core.can_manage_projector" class="minimum">
<!-- selection column --> <!-- selection column -->
<th ng-show="isSelectMode" os-perms="users.can_manage" class="minimum deleteColumn"> <th ng-show="isSelectMode" os-perms="users.can_manage" class="minimum deleteColumn">
<input type="checkbox" ng-model="$parent.selectedAll" ng-change="checkAll()"> <input type="checkbox" ng-model="$parent.selectedAll" ng-change="checkAll()">
<!-- name column -->
<th ng-click="toggleSort('first_name')" class="sortable"> <th ng-click="toggleSort('first_name')" class="sortable">
<translate>Name</translate> <translate>Name</translate>
<!-- TODO: sort by first OR last name --> <!-- TODO: sort by first OR last name -->
<i class="pull-right fa" ng-show="sortColumn === 'first_name' && header.sortable != false" <i class="pull-right fa" ng-show="sortColumn === 'first_name' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'"> ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i> </i>
<!-- structure level column -->
<th ng-click="toggleSort('structure_level')" class="sortable optional"> <th ng-click="toggleSort('structure_level')" class="sortable optional">
<translate>Structure level</translate> <translate>Structure level</translate>
<i class="pull-right fa" ng-show="sortColumn === 'structure_level' && header.sortable != false" <i class="pull-right fa" ng-show="sortColumn === 'structure_level' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'"> ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i> </i>
<!-- groups column -->
<th ng-click="toggleSort('groups')" class="sortable optional"> <th ng-click="toggleSort('groups')" class="sortable optional">
<translate>Groups</translate> <translate>Groups</translate>
<i class="pull-right fa" ng-show="sortColumn === 'groups' && header.sortable != false" <i class="pull-right fa" ng-show="sortColumn === 'groups' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'"> ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i> </i>
<!-- present column -->
<th os-perms="users.can_see_extra_data" ng-click="toggleSort('is_present')" class="sortable minimum"> <th os-perms="users.can_see_extra_data" ng-click="toggleSort('is_present')" class="sortable minimum">
<translate>Present</translate> <translate>Present</translate>
<i class="pull-right fa" ng-show="sortColumn === 'is_present' && header.sortable != false" <i class="pull-right fa" ng-show="sortColumn === 'is_present' && header.sortable != false"
@ -177,7 +186,13 @@
<input type="checkbox" ng-model="user.selected"> <input type="checkbox" ng-model="user.selected">
<!-- user data colums --> <!-- user data colums -->
<td ng-mouseover="user.hover=true" ng-mouseleave="user.hover=false"> <td ng-mouseover="user.hover=true" ng-mouseleave="user.hover=false">
<strong><a ui-sref="users.user.detail({id: user.id})">{{ user.get_short_name() }}</a></strong> <strong>
<i ng-show="!user.is_active" class="fa fa-ban"
title="{{ 'Is inactive' | translate }}"></i>
<i ng-show="user.is_committee" class="fa fa-users"
title="{{ 'Is a committee' | translate }}"></i>
<a ui-sref="users.user.detail({id: user.id})">{{ user.get_short_name() }}</a>
</strong>
<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>