Several important fixes for beta4

- Fix socket error in autoupdate (Check if socket exists)
- Add missing translation string for core permission
- Fix KeyError in extract_default_password function in users/views.py
- Improve Pagination. Fix users list for users without can_see_extra_data permissions.
- Limit the number of users in ui-select field
- Fix csv header names in users import help text.
- Use config options (enable logo/title) on projector.
- Nicer font style for main and sub items on agenda slide.
- Fix JS error if this.groups is undefined for anonymous.
This commit is contained in:
Emanuel Schuetze 2016-02-17 13:46:20 +01:00
parent 956bba9a13
commit 84ea0bf1f5
17 changed files with 65 additions and 27 deletions

View File

@ -216,6 +216,10 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
$scope.speakerSelectBox = {}; $scope.speakerSelectBox = {};
$scope.alert = {}; $scope.alert = {};
$scope.speakers = $filter('orderBy')(item.speakers, 'weight'); $scope.speakers = $filter('orderBy')(item.speakers, 'weight');
// limit the number of users in ui-select field
$scope.limitUsers = 50;
$scope.$watch(function () { $scope.$watch(function () {
return Agenda.lastModified(); return Agenda.lastModified();
}, function () { }, function () {

View File

@ -135,7 +135,7 @@
<ui-select-match placeholder="{{ 'Select or search a participant ...' | translate }}"> <ui-select-match placeholder="{{ 'Select or search a participant ...' | translate }}">
{{ $select.selected.get_full_name() }} {{ $select.selected.get_full_name() }}
</ui-select-match> </ui-select-match>
<ui-select-choices repeat="user in users | filter: $select.search"> <ui-select-choices repeat="user in users | filter: $select.search | limitTo: limitUsers">
<div ng-bind-html="user.get_full_name() | highlight: $select.search"></div> <div ng-bind-html="user.get_full_name() | highlight: $select.search"></div>
</ui-select-choices> </ui-select-choices>
</ui-select> </ui-select>

View File

@ -203,5 +203,8 @@
<a href="" ng-click="editDialog(item)" class="pull-right"><translate>Edit ...</translate></a> <a href="" ng-click="editDialog(item)" class="pull-right"><translate>Edit ...</translate></a>
</div> </div>
</table> </table>
<uib-pagination total-items="itemsFiltered.length" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()"></uib-pagination> <uib-pagination ng-if="itemsFiltered.length > itemsPerPage" total-items="itemsFiltered.length" items-per-page="itemsPerPage" ng-model="currentPage"
ng-change="pageChanged()"
class="pagination-sm" direction-links="false" boundary-links="true" first-text="&laquo;" last-text="&raquo;">
</uib-pagination>
</div> </div>

View File

@ -18,12 +18,14 @@
<li ng-repeat="item in items" ui-tree-node ng-include="'nodes_renderer.html'"> <li ng-repeat="item in items" ui-tree-node ng-include="'nodes_renderer.html'">
</ol> </ol>
</div> </div>
<p class="spacer">* <translate>Internal item</translate</p>
</div> </div>
<!-- Nested node template --> <!-- Nested node template -->
<script type="text/ng-template" id="nodes_renderer.html"> <script type="text/ng-template" id="nodes_renderer.html">
<div ui-tree-handle> <div ui-tree-handle>
<span ng-if="item.item.is_hidden">*</span>
{{ item.item.getTitle() }} {{ item.item.getTitle() }}
</div> </div>
<ol ui-tree-nodes="" ng-model="item.children"> <ol ui-tree-nodes="" ng-model="item.children">

View File

@ -3,8 +3,9 @@
<div class="agendalist"> <div class="agendalist">
<!-- item type: AGENDA_ITEM = 1, HIDDEN_ITEM = 2 --> <!-- item type: AGENDA_ITEM = 1, HIDDEN_ITEM = 2 -->
<p ng-repeat="item in items | filter: {type: 1}" ng-class="{ 'spacer-top': !item.parent_id }"> <p ng-repeat="item in items | filter: {type: 1}"
<span ng-repeat="n in [].constructor(item.parentCount) track by $index">&nbsp;&nbsp;</span> ng-class="item.parent_id ? 'subitem' : 'mainitem'">
<span ng-repeat="n in [].constructor(item.parentCount) track by $index">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
{{ item.getListViewTitle() }} {{ item.getListViewTitle() }}
<i ng-if="item.closed" class="fa fa-check"></i> <i ng-if="item.closed" class="fa fa-check"></i>
</p> </p>

View File

@ -278,6 +278,9 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
$scope.phases = phases; $scope.phases = phases;
$scope.alert = {}; $scope.alert = {};
// limit the number of users in ui-select field
$scope.limitUsers = 50;
// open edit dialog // open edit dialog
$scope.openDialog = function (assignment) { $scope.openDialog = function (assignment) {
ngDialog.open(AssignmentForm.getDialog(assignment)); ngDialog.open(AssignmentForm.getDialog(assignment));

View File

@ -95,7 +95,7 @@
<ui-select-match placeholder="{{ 'Select or search a participant ...' | translate }}"> <ui-select-match placeholder="{{ 'Select or search a participant ...' | translate }}">
{{ $select.selected.get_full_name() }} {{ $select.selected.get_full_name() }}
</ui-select-match> </ui-select-match>
<ui-select-choices repeat="user in users | filter: $select.search"> <ui-select-choices repeat="user in users | filter: $select.search | limitTo: limitUsers">
<div ng-bind-html="user.get_full_name() | highlight: $select.search"></div> <div ng-bind-html="user.get_full_name() | highlight: $select.search"></div>
</ui-select-choices> </ui-select-choices>
</ui-select> </ui-select>

View File

@ -23,12 +23,12 @@ body{
left: 50px; left: 50px;
top: 10px; top: 10px;
height: 50px; height: 50px;
margin-right: 35px; margin-right: 25px;
float: left; float: left;
} }
#eventdata { #eventdata {
position: relative; position: relative;
left: 30px; left: 50px;
top: 12px; top: 12px;
height: 50px; height: 50px;
overflow: hidden; overflow: hidden;
@ -297,12 +297,17 @@ tr.elected td {
.agendalist p { .agendalist p {
font-size: 140%; font-size: 140%;
} }
.agendalist .mainitem {
margin-top: 25px;
}
.agendalist .subitem {
font-size: 100%;
margin-bottom: 4px;
}
.spacer { .spacer {
margin-top: 10px; margin-top: 10px;
} }
.spacer-top {
margin-top: 25px;
}
/*** List of speakers ***/ /*** List of speakers ***/
.slimlabel.label { .slimlabel.label {

View File

@ -49,7 +49,9 @@ angular.module('OpenSlidesApp.core', [
this.messageReceivers.push(receiver); this.messageReceivers.push(receiver);
}, },
reconnect: function () { reconnect: function () {
socket.close(); if (socket) {
socket.close();
}
} }
}; };
var newConnect = function () { var newConnect = function () {

View File

@ -19,8 +19,8 @@
<div id="header"> <div id="header">
<img id="logo" src="/static/img/logo-projector.png" alt="OpenSlides" /> <img ng-if="config('projector_enable_logo')" id="logo" src="/static/img/logo-projector.png" alt="OpenSlides" />
<div id="eventdata"> <div ng-if="config('projector_enable_title')" id="eventdata">
<div class="title"> <div class="title">
{{ config('general_event_name') }} {{ config('general_event_name') }}
</div> </div>

View File

@ -28,7 +28,7 @@
<ui-select-match placeholder="{{ 'Select or search a participant ...' | translate }}" data-allow-clear="true"> <ui-select-match placeholder="{{ 'Select or search a participant ...' | translate }}" data-allow-clear="true">
{{ $select.selected.get_full_name() }} {{ $select.selected.get_full_name() }}
</ui-select-match> </ui-select-match>
<ui-select-choices repeat="user.id as user in users | filter: $select.search"> <ui-select-choices repeat="user.id as user in users | filter: $select.search | limitTo: 50">
<div ng-bind-html="user.get_full_name() | highlight: $select.search"></div> <div ng-bind-html="user.get_full_name() | highlight: $select.search"></div>
</ui-select-choices> </ui-select-choices>
</ui-select> </ui-select>

View File

@ -207,7 +207,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
label: gettextCatalog.getString('Submitters'), label: gettextCatalog.getString('Submitters'),
optionsAttr: 'bs-options', optionsAttr: 'bs-options',
options: User.getAll(), options: User.getAll(),
ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search | limitTo: 50',
valueProp: 'id', valueProp: 'id',
labelProp: 'full_name', labelProp: 'full_name',
placeholder: gettextCatalog.getString('Select or search a submitter ...') placeholder: gettextCatalog.getString('Select or search a submitter ...')
@ -318,7 +318,7 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
label: gettextCatalog.getString('Supporters'), label: gettextCatalog.getString('Supporters'),
optionsAttr: 'bs-options', optionsAttr: 'bs-options',
options: User.getAll(), options: User.getAll(),
ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search', ngOptions: 'option[to.valueProp] as option in to.options | filter: $select.search | limitTo: 50',
valueProp: 'id', valueProp: 'id',
labelProp: 'full_name', labelProp: 'full_name',
placeholder: gettextCatalog.getString('Select or search a supporter ...') placeholder: gettextCatalog.getString('Select or search a supporter ...')

View File

@ -121,7 +121,10 @@ angular.module('OpenSlidesApp.users', [])
}, },
getPerms: function() { getPerms: function() {
var allPerms = []; var allPerms = [];
var allGroups = this.groups.slice(0); var allGroups = [];
if (this.groups) {
allGroups = this.groups.slice(0);
}
// Add registered group // Add registered group
allGroups.push(2); allGroups.push(2);
_.forEach(allGroups, function(groupId) { _.forEach(allGroups, function(groupId) {

View File

@ -912,7 +912,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
// core // core
gettext('Can see the projector') gettext('Can see the projector')
gettext('Can manage the projector') gettext('Can manage the projector')
gettext('Can see the dashboard') gettext('Can see the front page')
gettext('Can manage tags') gettext('Can manage tags')
gettext('Can manage configuration') gettext('Can manage configuration')
gettext('Can use the chat') gettext('Can use the chat')

View File

@ -67,7 +67,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</code> <code>title, first_name, last_name, structure_level, groups, comment, is_active</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>

View File

@ -56,7 +56,7 @@
placeholder="{{ 'Search' | translate}}"> placeholder="{{ 'Search' | translate}}">
</div> </div>
</div> </div>
<button class="btn btn-default" ng-click="isFilterOpen = !isFilterOpen" <button os-perms="users.can_see_extra_data" class="btn btn-default" ng-click="isFilterOpen = !isFilterOpen"
ng-class="isFilterOpen ? 'btn-primary' : 'btn-default'"> ng-class="isFilterOpen ? 'btn-primary' : 'btn-default'">
<i class="fa fa-filter"></i> <i class="fa fa-filter"></i>
<translate>Filter ...</translate> <translate>Filter ...</translate>
@ -64,7 +64,7 @@
</div> </div>
</div> </div>
</div> </div>
<div uib-collapse="!isFilterOpen" class="row spacer"> <div os-perms="users.can_see_extra_data" uib-collapse="!isFilterOpen" class="row spacer">
<div class="col-sm-6 text-right"></div> <div class="col-sm-6 text-right"></div>
<div class="col-sm-6 text-right form-inline"> <div class="col-sm-6 text-right form-inline">
<!-- group filter --> <!-- group filter -->
@ -94,6 +94,14 @@
{{ users.length }} {{ "participants" | translate }}<span ng-if="(users|filter:{selected:true}).length > 0">, {{ users.length }} {{ "participants" | translate }}<span ng-if="(users|filter:{selected:true}).length > 0">,
{{(users|filter:{selected:true}).length}} {{ "selected" | translate }}</span> {{(users|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
</div> </div>
<!-- set filtered users (for user with/without can_see_extra_data permissions-->
<div os-perms="users.can_see_extra_data"
ng-repeat="user in usersFiltered = (users | filter: filter.search | filter: {groups: groupFilter} |
filter: {is_present: filterPresent} | orderBy: sortColumn:reverse)"></div>
<div os-perms="!users.can_see_extra_data"
ng-repeat="user in usersFiltered = (users | filter: filter.search | orderBy: sortColumn:reverse)"></div>
<table class="table table-striped table-bordered table-hover"> <table class="table table-striped table-bordered table-hover">
<thead> <thead>
<tr> <tr>
@ -124,9 +132,7 @@
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'"> ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i> </i>
<tbody> <tbody>
<tr ng-repeat="user in usersFiltered = (users | filter: filter.search | filter: {groups: groupFilter} | <tr ng-repeat="user in usersFiltered | limitTo : itemsPerPage : limitBegin" class="animate-item"
filter: {is_present: filterPresent} | orderBy: sortColumn:reverse) | limitTo : itemsPerPage : limitBegin"
class="animate-item"
ng-class="{ 'activeline': user.isProjected(), 'selected': user.selected }"> ng-class="{ 'activeline': user.isProjected(), 'selected': user.selected }">
<!-- projector column --> <!-- projector column -->
<td ng-show="!isDeleteMode" os-perms="core.can_manage_projector"> <td ng-show="!isDeleteMode" os-perms="core.can_manage_projector">
@ -163,5 +169,8 @@
</span> </span>
<input os-perms="users.can_manage" type="checkbox" ng-model="user.is_present" ng-click="save(user)"> <input os-perms="users.can_manage" type="checkbox" ng-model="user.is_present" ng-click="save(user)">
</table> </table>
<uib-pagination total-items="usersFiltered.length" items-per-page="itemsPerPage" ng-model="currentPage" ng-change="pageChanged()"></uib-pagination> <uib-pagination total-items="usersFiltered.length" items-per-page="itemsPerPage" ng-model="currentPage"
ng-change="pageChanged()"
class="pagination-sm" direction-links="false" boundary-links="true" first-text="&laquo;" last-text="&raquo;">
</uib-pagination>
</div> </div>

View File

@ -89,10 +89,16 @@ class UserViewSet(ModelViewSet):
""" """
if not self.request.user.has_perm('users.can_manage'): if not self.request.user.has_perm('users.can_manage'):
if isinstance(response.data, dict): if isinstance(response.data, dict):
del response.data['default_password'] try:
del response.data['default_password']
except KeyError:
pass
elif isinstance(response.data, list): elif isinstance(response.data, list):
for user in response.data: for user in response.data:
del user['default_password'] try:
del user['default_password']
except KeyError:
pass
def update(self, request, *args, **kwargs): def update(self, request, *args, **kwargs):
""" """