Merge pull request #2216 from normanjaeckel/IsCommittee
Added new user field is_committee and new default group Committees.
This commit is contained in:
commit
b96d7d0514
@ -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.
|
||||||
|
20
openslides/users/migrations/0002_user_is_committee.py
Normal file
20
openslides/users/migrations/0002_user_is_committee.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
@ -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:
|
||||||
|
@ -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):
|
||||||
|
@ -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()
|
||||||
|
@ -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");
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user