2015-10-21 22:44:07 +02:00
( function ( ) {
2015-06-17 09:45:00 +02:00
2015-10-21 22:44:07 +02:00
'use strict' ;
2015-06-17 09:45:00 +02:00
2016-10-12 16:52:24 +02:00
angular . module ( 'OpenSlidesApp.users.site' , [
'OpenSlidesApp.users' ,
'OpenSlidesApp.core.pdf' ,
2016-12-05 16:22:58 +01:00
'OpenSlidesApp.users.pdf' ,
'OpenSlidesApp.users.csv' ,
2016-10-12 16:52:24 +02:00
] )
2015-06-17 09:45:00 +02:00
2015-09-05 17:15:37 +02:00
. config ( [
'mainMenuProvider' ,
2015-11-30 23:52:42 +01:00
'gettext' ,
function ( mainMenuProvider , gettext ) {
2015-09-05 17:15:37 +02:00
mainMenuProvider . register ( {
'ui_sref' : 'users.user.list' ,
'img_class' : 'user' ,
2015-11-30 23:52:42 +01:00
'title' : gettext ( 'Participants' ) ,
2015-09-05 17:15:37 +02:00
'weight' : 500 ,
'perm' : 'users.can_see_name' ,
} ) ;
}
] )
2017-01-20 11:35:29 +01:00
. config ( [
'SearchProvider' ,
'gettext' ,
function ( SearchProvider , gettext ) {
SearchProvider . register ( {
'verboseName' : gettext ( 'Participants' ) ,
'collectionName' : 'users/user' ,
'urlDetailState' : 'users.user.detail' ,
'weight' : 500 ,
} ) ;
}
] )
2015-09-05 17:15:37 +02:00
2016-01-17 21:16:04 +01:00
. config ( [
'$stateProvider' ,
2016-11-28 15:04:55 +01:00
'gettext' ,
function ( $stateProvider , gettext ) {
2016-01-17 21:16:04 +01:00
$stateProvider
. state ( 'users' , {
url : '/users' ,
abstract : true ,
template : "<ui-view/>" ,
2016-11-28 15:04:55 +01:00
data : {
title : gettext ( 'Participants' ) ,
2017-01-23 16:19:50 +01:00
basePerm : 'users.can_see_name' ,
2016-11-28 15:04:55 +01:00
} ,
2016-01-17 21:16:04 +01:00
} )
. state ( 'users.user' , {
abstract : true ,
template : "<ui-view/>" ,
} )
2017-01-14 13:02:26 +01:00
. state ( 'users.user.list' , { } )
. state ( 'users.user.create' , { } )
2016-01-17 21:16:04 +01:00
. state ( 'users.user.detail' , {
resolve : {
2017-01-14 13:02:26 +01:00
userId : [ '$stateParams' , function ( $stateParams ) {
return $stateParams . id ;
} ]
2015-12-11 21:36:09 +01:00
}
2016-01-17 21:16:04 +01:00
} )
2016-08-25 11:40:37 +02:00
. state ( 'users.user.change-password' , {
url : '/change-password/{id}' ,
controller : 'UserChangePasswordCtrl' ,
templateUrl : 'static/templates/users/user-change-password.html' ,
resolve : {
2017-01-14 13:02:26 +01:00
userId : [ '$stateParams' , function ( $stateParams ) {
return $stateParams . id ;
} ]
2016-08-25 11:40:37 +02:00
}
} )
2016-01-17 21:16:04 +01:00
. state ( 'users.user.import' , {
url : '/import' ,
controller : 'UserImportCtrl' ,
} )
2017-11-21 10:32:31 +01:00
. state ( 'users.user.presence' , {
url : '/presence' ,
controller : 'UserPresenceCtrl' ,
} )
2016-01-17 21:16:04 +01:00
// groups
. state ( 'users.group' , {
url : '/groups' ,
abstract : true ,
template : "<ui-view/>" ,
2016-11-28 15:04:55 +01:00
data : {
title : gettext ( 'Groups' ) ,
} ,
2016-01-17 21:16:04 +01:00
} )
2017-06-21 14:27:22 +02:00
. state ( 'users.group.list' , { } )
2016-01-17 21:16:04 +01:00
. state ( 'login' , {
template : null ,
url : '/login' ,
2017-01-15 10:51:14 +01:00
params : {
guest _enabled : false ,
msg : null ,
} ,
2017-09-19 13:56:12 +02:00
onEnter : [ '$state' , '$stateParams' , 'ngDialog' , 'LoginDialog' , function ( $state , $stateParams , ngDialog , LoginDialog ) {
LoginDialog . id = ngDialog . open ( {
2016-01-17 21:16:04 +01:00
template : 'static/templates/core/login-form.html' ,
controller : 'LoginFormCtrl' ,
showClose : $stateParams . guest _enabled ,
closeByEscape : $stateParams . guest _enabled ,
closeByDocument : $stateParams . guest _enabled ,
2017-09-19 13:56:12 +02:00
} ) . id ;
2016-11-28 15:04:55 +01:00
} ] ,
data : {
title : 'Login' ,
} ,
2016-01-17 21:16:04 +01:00
} ) ;
}
] )
2015-01-30 11:58:36 +01:00
2017-09-26 08:10:13 +02:00
. value ( 'LoginDialog' , { } )
2017-09-19 13:56:12 +02:00
2015-02-12 22:42:54 +01:00
/ *
* Directive to check for permissions
*
* This is the Code from angular . js ngIf .
*
* TODO : find a way not to copy the code .
* /
2015-11-06 15:44:27 +01:00
. directive ( 'osPerms' , [
'$animate' ,
function ( $animate ) {
return {
multiElement : true ,
transclude : 'element' ,
priority : 600 ,
terminal : true ,
restrict : 'A' ,
$$tlb : true ,
link : function ( $scope , $element , $attr , ctrl , $transclude ) {
var block , childScope , previousElements , perms ;
if ( $attr . osPerms [ 0 ] === '!' ) {
2016-09-22 12:34:53 +02:00
perms = _ . trimStart ( $attr . osPerms , '!' ) ;
2015-11-06 15:44:27 +01:00
} else {
perms = $attr . osPerms ;
}
$scope . $watch (
function ( scope ) {
2017-01-14 13:02:26 +01:00
return scope . operator && scope . operator . hasPerms ( perms ) ;
2015-11-06 15:44:27 +01:00
} ,
function ( value ) {
if ( $attr . osPerms [ 0 ] === '!' ) {
value = ! value ;
2015-02-12 22:42:54 +01:00
}
2015-11-06 15:44:27 +01:00
if ( value ) {
if ( ! childScope ) {
$transclude ( function ( clone , newScope ) {
childScope = newScope ;
clone [ clone . length ++ ] = document . createComment ( ' end ngIf: ' + $attr . ngIf + ' ' ) ;
// Note: We only need the first/last node of the cloned nodes.
// However, we need to keep the reference to the jqlite wrapper as it might be changed later
// by a directive with templateUrl when its template arrives.
block = {
clone : clone
} ;
$animate . enter ( clone , $element . parent ( ) , $element ) ;
} ) ;
}
} else {
if ( previousElements ) {
previousElements . remove ( ) ;
2015-02-12 22:42:54 +01:00
previousElements = null ;
2015-11-06 15:44:27 +01:00
}
if ( childScope ) {
childScope . $destroy ( ) ;
childScope = null ;
}
if ( block ) {
previousElements = getBlockNodes ( block . clone ) ;
$animate . leave ( previousElements ) . then ( function ( ) {
previousElements = null ;
} ) ;
block = null ;
}
2015-02-12 22:42:54 +01:00
}
}
2015-11-06 15:44:27 +01:00
) ;
}
} ;
}
] )
2015-02-12 22:42:54 +01:00
2016-08-25 11:40:37 +02:00
. factory ( 'PasswordGenerator' , [
function ( ) {
return {
generate : function ( length ) {
if ( ! length ) {
length = 8 ;
}
var chars = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789' ,
pw = '' ;
for ( var i = 0 ; i < length ; ++ i ) {
pw += chars . charAt ( Math . floor ( Math . random ( ) * chars . length ) ) ;
}
return pw ;
}
} ;
}
] )
2017-05-24 08:38:27 +02:00
. factory ( 'PersonalNoteManager' , [
'PersonalNote' ,
'operator' ,
function ( PersonalNote , operator ) {
var _getPersonalNoteObject = function ( resourceName ) {
var personalNote = _ . find ( PersonalNote . getAll ( ) , function ( pn ) {
return pn . user _id === operator . user . id ;
} ) ;
if ( ! personalNote ) {
personalNote = {
notes : { } ,
} ;
}
if ( ! personalNote . notes [ resourceName ] ) {
personalNote . notes [ resourceName ] = { } ;
}
return personalNote ;
} ;
var get = function ( resourceName , id ) {
return _getPersonalNoteObject ( resourceName ) . notes [ resourceName ] [ id ] ;
} ;
var save = function ( resourceName , id , note ) {
var personalNote = _getPersonalNoteObject ( resourceName ) ;
personalNote . notes [ resourceName ] [ id ] = note ;
if ( personalNote . id ) {
return PersonalNote . save ( personalNote ) ;
} else {
return PersonalNote . create ( personalNote ) ;
}
} ;
return {
getNote : function ( obj ) {
if ( typeof obj . getResourceName === 'undefined' ) {
throw 'The Object has to be a js data model!' ;
}
return get ( obj . getResourceName ( ) , obj . id ) ;
} ,
saveNote : function ( obj , note ) {
if ( typeof obj . getResourceName === 'undefined' ) {
throw 'The Object has to be a js data model!' ;
}
return save ( obj . getResourceName ( ) , obj . id , note ) ;
} ,
} ;
}
] )
2016-01-10 13:47:59 +01:00
// Service for generic assignment form (create and update)
. factory ( 'UserForm' , [
2015-11-27 23:09:38 +01:00
'$http' ,
2015-11-30 23:52:42 +01:00
'gettextCatalog' ,
2016-02-12 00:15:35 +01:00
'Editor' ,
2015-11-27 23:09:38 +01:00
'Group' ,
2016-02-12 00:15:35 +01:00
'Mediafile' ,
2016-08-25 11:40:37 +02:00
'PasswordGenerator' ,
function ( $http , gettextCatalog , Editor , Group , Mediafile , PasswordGenerator ) {
2015-11-27 23:09:38 +01:00
return {
2016-01-10 13:47:59 +01:00
// ngDialog for user form
getDialog : function ( user ) {
return {
template : 'static/templates/users/user-form.html' ,
controller : ( user ) ? 'UserUpdateCtrl' : 'UserCreateCtrl' ,
className : 'ngdialog-theme-default wide-form' ,
closeByEscape : false ,
closeByDocument : false ,
2017-01-14 13:02:26 +01:00
resolve : {
userId : function ( ) { return user ? user . id : void 0 ; } ,
}
2016-02-24 09:42:28 +01:00
} ;
2016-01-10 13:47:59 +01:00
} ,
// angular-formly fields for user form
2016-01-21 22:34:18 +01:00
getFormFields : function ( hideOnCreateForm ) {
2016-02-12 00:15:35 +01:00
var images = Mediafile . getAllImages ( ) ;
2015-11-27 23:09:38 +01:00
return [
2016-01-21 22:34:18 +01:00
{
2016-11-27 22:57:56 +01:00
className : "row" ,
fieldGroup : [
{
key : 'title' ,
type : 'input' ,
className : "col-xs-2 no-padding-left" ,
templateOptions : {
label : gettextCatalog . getString ( 'Title' )
}
} ,
{
key : 'first_name' ,
type : 'input' ,
className : "col-xs-5 no-padding" ,
templateOptions : {
2016-12-07 19:49:25 +01:00
label : gettextCatalog . getString ( 'Given name' )
2016-11-27 22:57:56 +01:00
}
} ,
{
key : 'last_name' ,
type : 'input' ,
className : "col-xs-5 no-padding-right" ,
templateOptions : {
2016-12-07 19:49:25 +01:00
label : gettextCatalog . getString ( 'Surname' )
2016-11-27 22:57:56 +01:00
}
}
]
2015-11-27 23:09:38 +01:00
} ,
2017-11-28 10:47:29 +01:00
{
key : 'email' ,
type : 'input' ,
templateOptions : {
label : gettextCatalog . getString ( 'Email' )
} ,
} ,
2015-11-27 23:09:38 +01:00
{
2016-11-27 22:57:56 +01:00
className : "row" ,
fieldGroup : [
{
key : 'structure_level' ,
type : 'input' ,
className : "col-xs-9 no-padding-left" ,
templateOptions : {
label : gettextCatalog . getString ( 'Structure level' ) ,
}
} ,
{ key : 'number' ,
type : 'input' ,
className : "col-xs-3 no-padding-left no-padding-right" ,
templateOptions : {
label : gettextCatalog . getString ( 'Participant number' )
}
}
]
2015-11-27 23:09:38 +01:00
} ,
{
2016-11-27 22:57:56 +01:00
key : 'username' ,
2016-08-03 16:30:04 +02:00
type : 'input' ,
templateOptions : {
2016-11-27 22:57:56 +01:00
label : gettextCatalog . getString ( 'Username' )
} ,
hide : hideOnCreateForm
2016-08-03 16:30:04 +02:00
} ,
2015-11-27 23:09:38 +01:00
{
2016-04-14 21:29:28 +02:00
key : 'groups_id' ,
2016-03-08 22:55:43 +01:00
type : 'select-multiple' ,
2015-11-27 23:09:38 +01:00
templateOptions : {
2015-11-30 23:52:42 +01:00
label : gettextCatalog . getString ( 'Groups' ) ,
2017-10-24 08:48:15 +02:00
options : Group . filter ( { where : { id : { '>' : 1 } } } ) ,
ngOptions : "option.id as option.name | translate for option in to.options | orderBy: 'id'" ,
2015-12-11 20:04:05 +01:00
placeholder : gettextCatalog . getString ( 'Select or search a group ...' )
2015-11-27 23:09:38 +01:00
}
} ,
{
key : 'default_password' ,
type : 'input' ,
templateOptions : {
2016-08-25 11:40:37 +02:00
label : gettextCatalog . getString ( 'Initial password' ) ,
description : gettextCatalog . getString ( 'Initial password can not be changed.' ) ,
addonRight : {
text : gettextCatalog . getString ( 'Generate' ) ,
class : 'fa fa-magic' ,
onClick : function ( options , scope ) {
scope . $parent . model . default _password = PasswordGenerator . generate ( ) ;
2015-11-27 23:09:38 +01:00
}
}
2016-08-25 11:40:37 +02:00
} ,
hide : ! hideOnCreateForm
2015-11-27 23:09:38 +01:00
} ,
{
key : 'comment' ,
type : 'input' ,
templateOptions : {
2016-01-09 13:32:56 +01:00
label : gettextCatalog . getString ( 'Comment' ) ,
2016-11-27 22:57:56 +01:00
description : gettextCatalog . getString ( 'Only for internal notes.' )
2015-11-27 23:09:38 +01:00
}
} ,
{
2016-11-27 22:57:56 +01:00
key : 'more' ,
type : 'checkbox' ,
2015-11-27 23:09:38 +01:00
templateOptions : {
2016-11-27 22:57:56 +01:00
label : gettextCatalog . getString ( 'Show extended fields' )
2016-02-12 00:15:35 +01:00
}
2015-11-27 23:09:38 +01:00
} ,
2016-11-27 22:57:56 +01:00
{
template : '<hr class="smallhr">' ,
hideExpression : '!model.more'
} ,
2015-11-27 23:09:38 +01:00
{
key : 'is_present' ,
type : 'checkbox' ,
templateOptions : {
2016-01-09 13:32:56 +01:00
label : gettextCatalog . getString ( 'Is present' ) ,
description : gettextCatalog . getString ( 'Designates whether this user is in the room or not.' )
2016-01-18 16:29:15 +01:00
} ,
2016-11-27 22:57:56 +01:00
defaultValue : true ,
hideExpression : '!model.more'
2015-11-27 23:09:38 +01:00
} ,
{
key : 'is_active' ,
type : 'checkbox' ,
templateOptions : {
2016-01-09 13:32:56 +01:00
label : gettextCatalog . getString ( 'Is active' ) ,
description : gettextCatalog . getString (
2016-01-09 16:24:37 +01:00
'Designates whether this user should be treated as ' +
2016-01-09 13:32:56 +01:00
'active. Unselect this instead of deleting the account.' )
2016-01-18 16:29:15 +01:00
} ,
2016-11-27 22:57:56 +01:00
defaultValue : true ,
hideExpression : '!model.more'
2016-06-30 13:06:23 +02:00
} ,
{
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.' )
} ,
2016-11-27 22:57:56 +01:00
defaultValue : false ,
hideExpression : '!model.more'
} ,
{
key : 'about_me' ,
type : 'editor' ,
templateOptions : {
label : gettextCatalog . getString ( 'About me' ) ,
} ,
data : {
2016-12-01 18:13:09 +01:00
ckeditorOptions : Editor . getOptions ( images )
2016-11-27 22:57:56 +01:00
} ,
hideExpression : '!model.more'
}
] ;
2015-11-27 23:09:38 +01:00
}
2016-02-24 09:42:28 +01:00
} ;
2015-11-27 23:09:38 +01:00
}
] )
2017-02-10 14:51:44 +01:00
. factory ( 'UserProfileForm' , [
'gettextCatalog' ,
'Editor' ,
'Mediafile' ,
function ( gettextCatalog , Editor , Mediafile ) {
return {
// ngDialog for user form
2017-11-21 10:32:31 +01:00
getDialog : function ( ) {
2017-02-10 14:51:44 +01:00
return {
template : 'static/templates/users/profile-password-form.html' ,
controller : 'UserProfileCtrl' ,
className : 'ngdialog-theme-default wide-form' ,
closeByEscape : false ,
closeByDocument : false ,
} ;
} ,
// angular-formly fields for user form
getFormFields : function ( hideOnCreateForm ) {
var images = Mediafile . getAllImages ( ) ;
return [
{
key : 'username' ,
type : 'input' ,
templateOptions : {
label : gettextCatalog . getString ( 'Username' ) ,
required : true
} ,
} ,
2017-11-28 10:47:29 +01:00
{
key : 'email' ,
type : 'input' ,
templateOptions : {
label : gettextCatalog . getString ( 'Email' )
} ,
} ,
2017-02-10 14:51:44 +01:00
{
key : 'about_me' ,
type : 'editor' ,
templateOptions : {
label : gettextCatalog . getString ( 'About me' ) ,
} ,
data : {
ckeditorOptions : Editor . getOptions ( images )
} ,
}
] ;
}
} ;
}
] )
. factory ( 'UserPasswordForm' , [
'gettextCatalog' ,
function ( gettextCatalog ) {
return {
// ngDialog for user form
2017-11-21 10:32:31 +01:00
getDialog : function ( ) {
2017-02-10 14:51:44 +01:00
return {
template : 'static/templates/users/profile-password-form.html' ,
controller : 'UserPasswordCtrl' ,
2017-02-22 23:31:50 +01:00
className : 'ngdialog-theme-default' ,
2017-02-10 14:51:44 +01:00
closeByEscape : false ,
closeByDocument : false ,
} ;
} ,
// angular-formly fields for user form
getFormFields : function ( hideOnCreateForm ) {
return [
{
key : 'oldPassword' ,
type : 'password' ,
templateOptions : {
label : gettextCatalog . getString ( 'Old password' ) ,
required : true
} ,
} ,
{
key : 'newPassword' ,
type : 'password' ,
templateOptions : {
label : gettextCatalog . getString ( 'New password' ) ,
required : true
} ,
} ,
{
key : 'newPassword2' ,
type : 'password' ,
templateOptions : {
label : gettextCatalog . getString ( 'Confirm new password' ) ,
required : true
} ,
} ,
] ;
}
} ;
}
] )
2015-10-15 17:27:59 +02:00
. controller ( 'UserListCtrl' , [
'$scope' ,
'$state' ,
2016-09-13 12:52:50 +02:00
'$http' ,
2017-04-26 16:09:27 +02:00
'$q' ,
2015-11-27 23:09:38 +01:00
'ngDialog' ,
2016-01-10 13:47:59 +01:00
'UserForm' ,
2015-10-15 17:27:59 +02:00
'User' ,
'Group' ,
2016-09-13 12:52:50 +02:00
'PasswordGenerator' ,
2016-09-12 11:05:34 +02:00
'Projector' ,
'ProjectionDefault' ,
2016-11-02 13:51:06 +01:00
'Config' ,
2016-10-12 16:52:24 +02:00
'gettextCatalog' ,
2016-11-04 11:57:23 +01:00
'UserCsvExport' ,
2016-11-18 13:50:40 +01:00
'osTableFilter' ,
'osTableSort' ,
'gettext' ,
2017-04-26 16:09:27 +02:00
'UserPdfExport' ,
2017-06-15 14:25:55 +02:00
'ErrorMessage' ,
2017-11-21 10:32:31 +01:00
function ( $scope , $state , $http , $q , ngDialog , UserForm , User , Group , PasswordGenerator ,
Projector , ProjectionDefault , Config , gettextCatalog , UserCsvExport , osTableFilter ,
osTableSort , gettext , UserPdfExport , ErrorMessage ) {
2017-08-11 10:18:50 +02:00
$scope . $watch ( function ( ) {
return User . lastModified ( ) ;
} , function ( ) {
$scope . users = _ . orderBy ( User . getAll ( ) , [ 'first_name' ] ) ;
} ) ;
2016-08-31 16:53:02 +02:00
Group . bindAll ( { where : { id : { '>' : 1 } } } , $scope , 'groups' ) ;
2016-09-12 11:05:34 +02:00
$scope . $watch ( function ( ) {
return Projector . lastModified ( ) ;
} , function ( ) {
var projectiondefault = ProjectionDefault . filter ( { name : 'users' } ) [ 0 ] ;
if ( projectiondefault ) {
$scope . defaultProjectorId = projectiondefault . projector _id ;
}
} ) ;
2015-12-11 21:36:09 +01:00
$scope . alert = { } ;
2015-03-09 15:40:54 +01:00
2016-11-18 13:50:40 +01:00
// Filtering
2016-12-02 09:38:02 +01:00
$scope . filter = osTableFilter . createInstance ( 'UserTableFilter' ) ;
2016-12-05 15:24:43 +01:00
if ( ! $scope . filter . existsStorageEntry ( ) ) {
2016-12-02 09:38:02 +01:00
$scope . filter . multiselectFilters = {
group : [ ] ,
} ;
$scope . filter . booleanFilters = {
isPresent : {
value : undefined ,
displayName : gettext ( 'Present' ) ,
choiceYes : gettext ( 'Is present' ) ,
choiceNo : gettext ( 'Is not present' ) ,
needExtraPermission : true ,
} ,
isActive : {
value : undefined ,
displayName : gettext ( 'Active' ) ,
choiceYes : gettext ( 'Is active' ) ,
choiceNo : gettext ( 'Is not active' ) ,
needExtraPermission : true ,
} ,
isCommittee : {
value : undefined ,
displayName : gettext ( 'Committee' ) ,
2016-12-20 09:14:33 +01:00
choiceYes : gettext ( 'Is a committee' ) ,
choiceNo : gettext ( 'Is not a committee' ) ,
2016-12-02 09:38:02 +01:00
} ,
} ;
}
2017-09-22 10:38:41 +02:00
$scope . filter . propertyList = [ 'first_name' , 'last_name' , 'username' , 'title' ,
'number' , 'comment' , 'structure_level' ] ;
2016-11-18 13:50:40 +01:00
$scope . filter . propertyDict = {
2016-11-04 11:57:23 +01:00
'groups_id' : function ( group _id ) {
return Group . get ( group _id ) . name ;
} ,
} ;
$scope . getItemId = {
group : function ( user ) { return user . groups _id ; } ,
} ;
2016-11-18 13:50:40 +01:00
// Sorting
2017-10-27 09:38:06 +02:00
$scope . sort = osTableSort . createInstance ( 'UserTableSort' ) ;
if ( ! $scope . sort . column ) {
$scope . sort . column = $scope . config ( 'users_sort_by' ) ;
}
2016-11-04 11:57:23 +01:00
$scope . sortOptions = [
{ name : 'first_name' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Given name' ) } ,
2016-11-04 11:57:23 +01:00
{ name : 'last_name' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Surname' ) } ,
2016-11-04 11:57:23 +01:00
{ name : 'is_present' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Present' ) } ,
2016-11-04 11:57:23 +01:00
{ name : 'is_active' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Active' ) } ,
2016-11-04 11:57:23 +01:00
{ name : 'is_committee' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Committee' ) } ,
2016-11-04 11:57:23 +01:00
{ name : 'number' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Number' ) } ,
2016-11-04 11:57:23 +01:00
{ name : 'structure_level' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Structure level' ) } ,
2016-11-04 11:57:23 +01:00
{ name : 'comment' ,
2016-12-06 23:02:25 +01:00
display _name : gettext ( 'Comment' ) } ,
2017-11-28 10:47:29 +01:00
{ name : 'last_email_send' ,
display _name : gettext ( 'Last email send' ) } ,
2016-11-04 11:57:23 +01:00
] ;
2015-02-08 22:37:55 +01:00
2016-02-02 20:54:03 +01:00
// pagination
$scope . currentPage = 1 ;
2017-01-25 16:19:02 +01:00
$scope . itemsPerPage = 25 ;
2016-02-02 20:54:03 +01:00
$scope . limitBegin = 0 ;
$scope . pageChanged = function ( ) {
$scope . limitBegin = ( $scope . currentPage - 1 ) * $scope . itemsPerPage ;
2017-10-13 09:03:18 +02:00
$scope . gotoTop ( ) ;
2016-02-02 20:54:03 +01:00
} ;
2016-11-04 11:57:23 +01:00
// Toggle group from user
$scope . toggleGroup = function ( user , group ) {
if ( _ . indexOf ( user . groups _id , group . id ) > - 1 ) {
user . groups _id = _ . filter ( user . groups _id , function ( group _id ) {
return group _id != group . id ;
} ) ;
} else {
user . groups _id . push ( group . id ) ;
}
$scope . save ( user ) ;
} ;
2016-01-10 13:47:59 +01:00
// open new/edit dialog
$scope . openDialog = function ( user ) {
ngDialog . open ( UserForm . getDialog ( user ) ) ;
2015-10-15 17:27:59 +02:00
} ;
// save changed user
2015-11-27 23:09:38 +01:00
$scope . save = function ( user ) {
2015-12-11 21:36:09 +01:00
User . save ( user ) . then (
2015-11-27 23:09:38 +01:00
function ( success ) {
//user.quickEdit = false;
$scope . alert . show = false ;
} ,
function ( error ) {
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
2015-11-27 23:09:38 +01:00
} ) ;
2015-10-15 17:27:59 +02:00
} ;
2016-12-20 09:14:33 +01:00
// delete single user
$scope . delete = function ( user ) {
User . destroy ( user . id ) ;
} ;
2016-02-23 23:16:13 +01:00
// *** select mode functions ***
$scope . isSelectMode = false ;
2015-10-15 17:27:59 +02:00
// check all checkboxes
$scope . checkAll = function ( ) {
2016-11-04 11:57:23 +01:00
$scope . selectedAll = ! $scope . selectedAll ;
_ . forEach ( $scope . usersFiltered , function ( user ) {
2015-10-15 17:27:59 +02:00
user . selected = $scope . selectedAll ;
} ) ;
} ;
2016-02-23 23:16:13 +01:00
// uncheck all checkboxes if isSelectMode is closed
2015-10-15 17:27:59 +02:00
$scope . uncheckAll = function ( ) {
2016-02-23 23:16:13 +01:00
if ( ! $scope . isSelectMode ) {
2015-10-15 17:27:59 +02:00
$scope . selectedAll = false ;
angular . forEach ( $scope . users , function ( user ) {
user . selected = false ;
} ) ;
}
} ;
2016-12-20 09:14:33 +01:00
var selectModeAction = function ( predicate ) {
angular . forEach ( $scope . usersFiltered , function ( user ) {
2016-02-23 23:16:13 +01:00
if ( user . selected ) {
2016-12-20 09:14:33 +01:00
predicate ( user ) ;
2016-02-23 23:16:13 +01:00
}
2015-10-15 17:27:59 +02:00
} ) ;
2016-02-23 23:16:13 +01:00
$scope . isSelectMode = false ;
2015-10-15 17:27:59 +02:00
$scope . uncheckAll ( ) ;
} ;
2016-12-20 09:14:33 +01:00
// delete all selected users
$scope . deleteMultiple = function ( ) {
selectModeAction ( function ( user ) {
$scope . delete ( user ) ;
} ) ;
2015-11-27 23:09:38 +01:00
} ;
2016-02-23 23:16:13 +01:00
// add group for selected users
$scope . addGroupMultiple = function ( group ) {
2016-12-20 09:14:33 +01:00
if ( group ) {
selectModeAction ( function ( user ) {
2016-04-17 22:42:56 +02:00
user . groups _id . push ( group ) ;
2016-02-23 23:16:13 +01:00
User . save ( user ) ;
2016-12-20 09:14:33 +01:00
} ) ;
}
2016-02-23 23:16:13 +01:00
} ;
// remove group for selected users
$scope . removeGroupMultiple = function ( group ) {
2016-12-20 09:14:33 +01:00
if ( group ) {
selectModeAction ( function ( user ) {
var groupIndex = _ . indexOf ( user . groups _id , parseInt ( group ) ) ;
2016-02-23 23:16:13 +01:00
if ( groupIndex > - 1 ) {
2016-04-17 22:42:56 +02:00
user . groups _id . splice ( groupIndex , 1 ) ;
2016-02-23 23:16:13 +01:00
User . save ( user ) ;
}
2016-12-20 09:14:33 +01:00
} ) ;
}
2016-02-23 23:16:13 +01:00
} ;
2016-09-13 12:52:50 +02:00
// generate new passwords
$scope . generateNewPasswordsMultiple = function ( ) {
2016-12-20 09:14:33 +01:00
selectModeAction ( function ( user ) {
var newPassword = PasswordGenerator . generate ( ) ;
user . default _password = newPassword ;
User . save ( user ) ;
$http . post (
'/rest/users/user/' + user . id + '/reset_password/' ,
{ 'password' : newPassword }
) ;
} ) ;
} ;
// set boolean properties (is_active, is_present, is_committee)
$scope . setBoolPropertyMultiple = function ( property , value ) {
selectModeAction ( function ( user ) {
user [ property ] = value ;
User . save ( user ) ;
2016-09-13 12:52:50 +02:00
} ) ;
} ;
2017-11-28 10:47:29 +01:00
// Send invitation emails
$scope . sendInvitationEmails = function ( ) {
var user _ids = _
. chain ( $scope . usersFiltered )
. filter ( function ( user ) {
return user . selected ;
} )
. map ( function ( user ) {
return user . id ;
} )
. value ( ) ;
$http . post ( '/rest/users/user/mass_invite_email/' , {
user _ids : user _ids ,
} ) . then ( function ( success ) {
$scope . alert = {
msg : gettextCatalog . getString ( 'Send %num% emails sucessfully.' ) . replace ( '%num%' , success . data . count ) ,
type : 'success' ,
show : true ,
} ;
$scope . isSelectMode = false ;
$scope . uncheckAll ( ) ;
} , function ( error ) {
$scope . alert = ErrorMessage . forAlert ( error ) ;
$scope . isSelectMode = false ;
$scope . uncheckAll ( ) ;
} ) ;
} ;
2016-10-12 16:52:24 +02:00
2016-11-04 11:57:23 +01:00
// Export as PDF
$scope . pdfExportUserList = function ( ) {
2017-04-26 16:09:27 +02:00
UserPdfExport . exportUserList ( $scope . usersFiltered ) ;
2016-10-12 16:52:24 +02:00
} ;
2016-11-04 11:57:23 +01:00
$scope . pdfExportUserAccessDataList = function ( ) {
2017-04-26 16:09:27 +02:00
UserPdfExport . exportUserAccessDataList ( $scope . usersFiltered ) ;
2016-11-02 13:51:06 +01:00
} ;
2016-11-04 11:57:23 +01:00
// Export as a csv file
$scope . csvExport = function ( ) {
2017-02-07 12:44:51 +01:00
UserCsvExport . export ( $scope . usersFiltered ) ;
2016-11-04 11:57:23 +01:00
} ;
2015-10-15 17:27:59 +02:00
}
] )
2015-01-30 11:58:36 +01:00
2015-11-06 15:44:27 +01:00
. controller ( 'UserDetailCtrl' , [
'$scope' ,
2016-01-10 13:47:59 +01:00
'ngDialog' ,
'UserForm' ,
2015-11-06 15:44:27 +01:00
'User' ,
2017-01-14 13:02:26 +01:00
'userId' ,
2015-11-06 15:44:27 +01:00
'Group' ,
2016-11-21 15:01:54 +01:00
'Projector' ,
'ProjectionDefault' ,
2017-09-13 14:52:17 +02:00
'gettextCatalog' ,
'WebpageTitle' ,
function ( $scope , ngDialog , UserForm , User , userId , Group , Projector , ProjectionDefault , gettextCatalog ,
WebpageTitle ) {
2016-08-31 16:53:02 +02:00
Group . bindAll ( { where : { id : { '>' : 1 } } } , $scope , 'groups' ) ;
2017-09-13 14:52:17 +02:00
$scope . $watch ( function ( ) {
return User . lastModified ( userId ) ;
} , function ( ) {
$scope . user = User . get ( userId ) ;
WebpageTitle . updateTitle ( gettextCatalog . getString ( 'Participant' ) + ' ' + $scope . user . get _short _name ( ) ) ;
} ) ;
2016-11-21 15:01:54 +01:00
$scope . $watch ( function ( ) {
return Projector . lastModified ( ) ;
} , function ( ) {
var projectiondefault = ProjectionDefault . filter ( { name : 'users' } ) [ 0 ] ;
if ( projectiondefault ) {
$scope . defaultProjectorId = projectiondefault . projector _id ;
}
} ) ;
2016-01-10 13:47:59 +01:00
// open edit dialog
$scope . openDialog = function ( user ) {
ngDialog . open ( UserForm . getDialog ( user ) ) ;
} ;
2015-11-06 15:44:27 +01:00
}
] )
2015-02-12 22:42:54 +01:00
2015-11-06 15:44:27 +01:00
. controller ( 'UserCreateCtrl' , [
'$scope' ,
'$state' ,
'User' ,
2016-01-10 13:47:59 +01:00
'UserForm' ,
2017-02-24 15:15:18 +01:00
'ErrorMessage' ,
2017-10-24 08:48:15 +02:00
function ( $scope , $state , User , UserForm , ErrorMessage ) {
2016-01-18 16:29:15 +01:00
$scope . alert = { } ;
2015-11-27 23:09:38 +01:00
// get all form fields
2016-01-21 22:34:18 +01:00
$scope . formFields = UserForm . getFormFields ( true ) ;
2015-11-27 23:09:38 +01:00
// save user
2015-11-06 15:44:27 +01:00
$scope . save = function ( user ) {
2016-04-17 22:42:56 +02:00
if ( ! user . groups _id ) {
user . groups _id = [ ] ;
2015-09-04 18:26:48 +02:00
}
2015-06-24 15:04:40 +02:00
User . create ( user ) . then (
2017-02-24 15:15:18 +01:00
function ( success ) {
2015-11-27 23:09:38 +01:00
$scope . closeThisDialog ( ) ;
2016-01-18 16:29:15 +01:00
} ,
function ( error ) {
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
2015-06-24 15:04:40 +02:00
}
) ;
2015-11-06 15:44:27 +01:00
} ;
}
] )
. controller ( 'UserUpdateCtrl' , [
'$scope' ,
'$state' ,
'User' ,
2016-01-10 13:47:59 +01:00
'UserForm' ,
2017-01-14 13:02:26 +01:00
'userId' ,
2017-02-24 15:15:18 +01:00
'ErrorMessage' ,
2017-10-24 08:48:15 +02:00
function ( $scope , $state , User , UserForm , userId , ErrorMessage ) {
2016-01-14 22:10:44 +01:00
$scope . alert = { } ;
// set initial values for form model by create deep copy of user object
// so list/detail view is not updated while editing
2017-01-14 13:02:26 +01:00
$scope . model = angular . copy ( User . get ( userId ) ) ;
2016-01-14 22:10:44 +01:00
2015-11-27 23:09:38 +01:00
// get all form fields
2016-01-10 13:47:59 +01:00
$scope . formFields = UserForm . getFormFields ( ) ;
2015-11-27 23:09:38 +01:00
// save user
2015-11-06 15:44:27 +01:00
$scope . save = function ( user ) {
2016-04-17 22:42:56 +02:00
if ( ! user . groups _id ) {
user . groups _id = [ ] ;
2015-10-15 17:27:59 +02:00
}
2016-01-14 22:10:44 +01:00
// inject the changed user (copy) object back into DS store
User . inject ( user ) ;
// save change user object on server
2015-11-06 15:44:27 +01:00
User . save ( user ) . then (
2016-01-14 22:10:44 +01:00
function ( success ) {
2015-11-27 23:09:38 +01:00
$scope . closeThisDialog ( ) ;
2016-01-14 22:10:44 +01:00
} ,
function ( error ) {
// save error: revert all changes by restore
// (refresh) original user object from server
User . refresh ( user ) ;
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
2015-03-09 15:40:54 +01:00
}
) ;
2015-11-06 15:44:27 +01:00
} ;
}
] )
2015-06-24 15:04:40 +02:00
2015-11-06 15:44:27 +01:00
. controller ( 'UserProfileCtrl' , [
'$scope' ,
2016-02-12 00:15:35 +01:00
'Editor' ,
2015-11-06 15:44:27 +01:00
'User' ,
2017-02-10 14:51:44 +01:00
'operator' ,
'UserProfileForm' ,
'gettext' ,
2017-02-24 15:15:18 +01:00
'ErrorMessage' ,
function ( $scope , Editor , User , operator , UserProfileForm , gettext , ErrorMessage ) {
2017-02-10 14:51:44 +01:00
$scope . model = angular . copy ( operator . user ) ;
$scope . title = gettext ( 'Edit profile' ) ;
$scope . formFields = UserProfileForm . getFormFields ( ) ;
2015-11-06 15:44:27 +01:00
$scope . save = function ( user ) {
2017-02-10 14:51:44 +01:00
User . inject ( user ) ;
2016-08-31 16:53:02 +02:00
User . save ( user ) . then (
2015-11-06 15:44:27 +01:00
function ( success ) {
2017-02-10 14:51:44 +01:00
$scope . closeThisDialog ( ) ;
2015-11-06 15:44:27 +01:00
} ,
function ( error ) {
2017-02-10 14:51:44 +01:00
// save error: revert all changes by restore
// (refresh) original user object from server
User . refresh ( user ) ;
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
2015-11-06 15:44:27 +01:00
}
) ;
} ;
}
] )
2015-02-08 22:37:55 +01:00
2016-08-25 11:40:37 +02:00
. controller ( 'UserChangePasswordCtrl' , [
'$scope' ,
'$state' ,
'$http' ,
'User' ,
2017-01-14 13:02:26 +01:00
'userId' ,
2016-08-25 11:40:37 +02:00
'gettextCatalog' ,
'PasswordGenerator' ,
2017-02-24 15:15:18 +01:00
'ErrorMessage' ,
function ( $scope , $state , $http , User , userId , gettextCatalog , PasswordGenerator , ErrorMessage ) {
2017-01-14 13:02:26 +01:00
User . bindOne ( userId , $scope , 'user' ) ;
2017-02-10 14:51:44 +01:00
$scope . alert = { } ;
2016-08-25 11:40:37 +02:00
$scope . generatePassword = function ( ) {
$scope . new _password = PasswordGenerator . generate ( ) ;
} ;
$scope . save = function ( user ) {
if ( $scope . new _password !== '' ) {
$http . post (
'/rest/users/user/' + user . id + '/reset_password/' ,
{ 'password' : $scope . new _password }
) . then (
function ( success ) {
$scope . alert = { type : 'success' , msg : success . data . detail , show : true } ;
$scope . new _password = '' ;
} ,
function ( error ) {
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
2016-08-25 11:40:37 +02:00
}
) ;
}
} ;
}
] )
2017-09-26 08:10:13 +02:00
. directive ( "showPassword" , function ( ) {
return function linkFn ( scope , elem , attrs ) {
scope . $watch ( attrs . showPassword , function ( value ) {
if ( value ) {
elem . attr ( "type" , "text" ) ;
} else {
elem . attr ( "type" , "password" ) ;
}
} ) ;
} ;
} )
2015-11-06 15:44:27 +01:00
. controller ( 'UserPasswordCtrl' , [
'$scope' ,
'$state' ,
'$http' ,
2017-02-10 14:51:44 +01:00
'gettext' ,
'UserPasswordForm' ,
2017-02-24 15:15:18 +01:00
'ErrorMessage' ,
function ( $scope , $state , $http , gettext , UserPasswordForm , ErrorMessage ) {
2017-02-10 14:51:44 +01:00
$scope . title = 'Change password' ;
$scope . alert = { } ;
$scope . model = { } ;
$scope . formFields = UserPasswordForm . getFormFields ( ) ;
$scope . save = function ( data ) {
if ( data . newPassword != data . newPassword2 ) {
data . newPassword = data . newPassword2 = '' ;
$scope . alert = {
type : 'danger' ,
msg : gettext ( 'Password confirmation does not match.' ) ,
show : true ,
} ;
2015-11-06 15:44:27 +01:00
} else {
$http . post (
'/users/setpassword/' ,
2017-02-10 14:51:44 +01:00
{ 'old_password' : data . oldPassword , 'new_password' : data . newPassword }
2015-11-06 15:44:27 +01:00
) . then (
2017-02-10 14:51:44 +01:00
function ( success ) {
$scope . closeThisDialog ( ) ;
2015-11-06 15:44:27 +01:00
} ,
2017-02-10 14:51:44 +01:00
function ( error ) {
2015-11-06 15:44:27 +01:00
// Error, e. g. wrong old password.
2017-02-10 14:51:44 +01:00
$scope . model = { } ;
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
2015-11-06 15:44:27 +01:00
}
) ;
}
} ;
}
] )
2015-02-08 22:37:55 +01:00
2017-11-21 10:32:31 +01:00
. controller ( 'UserPresenceCtrl' , [
'$scope' ,
'User' ,
'gettextCatalog' ,
'ErrorMessage' ,
function ( $scope , User , gettextCatalog , ErrorMessage ) {
$scope . alert = { } ;
$ ( '#userNumber' ) . focus ( ) ;
$scope . changeState = function ( ) {
if ( ! $scope . number ) {
return ;
}
var enteredNumber = $scope . number . trim ( ) ;
var user = _ . find ( User . getAll ( ) , function ( user ) {
return user . number === enteredNumber ;
} ) ;
if ( user ) {
user . is _present = ! user . is _present ;
User . save ( user ) . then ( function ( success ) {
var messageText = user . full _name + ' ' + gettextCatalog . getString ( 'is now' ) + ' ' ;
messageText += gettextCatalog . getString ( user . is _present ? 'present' : 'not present' ) + '.' ;
$scope . alert = {
msg : messageText ,
show : true ,
type : 'success' ,
} ;
$scope . number = '' ;
} , function ( error ) {
$scope . alert = ErrorMessage . forAlert ( error ) ;
} ) ;
} else {
$scope . alert = {
msg : gettextCatalog . getString ( 'Cannot find the participant with the participant number' ) + ' "' + enteredNumber + '".' ,
show : true ,
type : 'danger' ,
} ;
}
$ ( '#userNumber' ) . focus ( ) ;
} ;
}
] )
2015-11-06 15:44:27 +01:00
. controller ( 'UserImportCtrl' , [
'$scope' ,
2017-04-19 09:28:21 +02:00
'$http' ,
2016-08-24 13:32:37 +02:00
'$q' ,
2015-12-11 21:36:09 +01:00
'gettext' ,
2016-08-24 13:32:37 +02:00
'gettextCatalog' ,
2015-11-06 15:44:27 +01:00
'User' ,
2015-12-11 21:36:09 +01:00
'Group' ,
2016-12-09 10:44:23 +01:00
'UserCsvExport' ,
2017-04-19 09:28:21 +02:00
'ErrorMessage' ,
function ( $scope , $http , $q , gettext , gettextCatalog , User , Group , UserCsvExport , ErrorMessage ) {
2015-11-06 15:44:27 +01:00
// import from textarea
$scope . importByLine = function ( ) {
2017-04-19 09:28:21 +02:00
var usernames = $scope . userlist [ 0 ] . split ( "\n" ) ;
// Ignore empty lines.
/ * u s e r n a m e s = _ . f i l t e r ( u s e r n a m e s , f u n c t i o n ( n a m e ) {
return name !== '' ;
} ) ; * /
var users = _ . map ( usernames , function ( name ) {
2015-11-06 15:44:27 +01:00
// Split each full name in first and last name.
// The last word is set as last name, rest is the first name(s).
// (e.g.: "Max Martin Mustermann" -> last_name = "Mustermann")
var names = name . split ( " " ) ;
var last _name = names . slice ( - 1 ) [ 0 ] ;
var first _name = names . slice ( 0 , - 1 ) . join ( " " ) ;
2017-04-19 09:28:21 +02:00
return {
2015-11-06 15:44:27 +01:00
first _name : first _name ,
last _name : last _name ,
2017-04-19 09:28:21 +02:00
groups _id : [ ] ,
2015-11-06 15:44:27 +01:00
} ;
2017-04-19 09:28:21 +02:00
} ) ;
$http . post ( '/rest/users/user/mass_import/' , {
users : users
} ) . then ( function ( success ) {
$scope . alert = {
show : true ,
type : 'success' ,
msg : success . data . detail ,
} ;
} , function ( error ) {
$scope . alert = ErrorMessage . forAlert ( error ) ;
2015-11-06 15:44:27 +01:00
} ) ;
} ;
2015-02-08 22:37:55 +01:00
2016-02-02 20:54:03 +01:00
// pagination
$scope . currentPage = 1 ;
$scope . itemsPerPage = 100 ;
$scope . limitBegin = 0 ;
$scope . pageChanged = function ( ) {
$scope . limitBegin = ( $scope . currentPage - 1 ) * $scope . itemsPerPage ;
} ;
2016-08-24 13:32:37 +02:00
$scope . duplicateActions = [
2016-09-26 12:44:23 +02:00
gettext ( 'keep original' ) ,
gettext ( 'override new' ) ,
gettext ( 'create duplicate' )
2016-08-24 13:32:37 +02:00
] ;
2017-01-06 12:21:37 +01:00
// *** csv import ***
$scope . csvConfig = {
accept : '.csv, .txt' ,
encodingOptions : [ 'UTF-8' , 'ISO-8859-1' ] ,
parseConfig : {
skipEmptyLines : true ,
} ,
} ;
var FIELDS = [ 'title' , 'first_name' , 'last_name' , 'structure_level' , 'number' ,
2017-11-28 10:47:29 +01:00
'groups' , 'comment' , 'is_active' , 'is_present' , 'is_committee' , 'default_password' , 'email' ] ;
2017-01-06 12:21:37 +01:00
$scope . users = [ ] ;
$scope . onCsvChange = function ( csv ) {
2017-04-19 09:28:21 +02:00
$scope . csvImporting = false ;
2016-08-24 13:32:37 +02:00
// All user objects are already loaded via the resolve statement from ui-router.
var users = User . getAll ( ) ;
2015-12-11 21:36:09 +01:00
$scope . users = [ ] ;
2017-01-06 12:21:37 +01:00
var csvUsers = [ ] ;
_ . forEach ( csv . data , function ( row ) {
if ( row . length >= 2 ) {
var filledRow = _ . zipObject ( FIELDS , row ) ;
csvUsers . push ( filledRow ) ;
}
} ) ;
2016-08-24 13:32:37 +02:00
$scope . duplicates = 0 ;
2017-04-19 09:28:21 +02:00
_ . forEach ( csvUsers , function ( user , index ) {
user . importTrackId = index ;
2017-01-06 15:08:51 +01:00
user . selected = true ;
2015-12-11 21:36:09 +01:00
if ( ! user . first _name && ! user . last _name ) {
user . importerror = true ;
2016-12-07 19:49:25 +01:00
user . name _error = gettext ( 'Error: Given name or surname is required.' ) ;
2015-12-11 21:36:09 +01:00
}
2016-08-03 16:30:04 +02:00
// number
2017-01-06 12:21:37 +01:00
if ( ! user . number ) {
2016-08-24 13:32:37 +02:00
user . number = "" ;
2016-08-03 16:30:04 +02:00
}
2015-12-11 21:36:09 +01:00
// groups
2016-12-09 10:44:23 +01:00
user . groups _id = [ ] ; // will be overwritten if there are groups
2015-12-11 21:36:09 +01:00
if ( user . groups ) {
2017-01-06 12:21:37 +01:00
user . groups = user . groups . split ( ',' ) ;
2016-12-09 10:44:23 +01:00
user . groups = _ . map ( user . groups , function ( group ) {
return _ . trim ( group ) ; // remove whitespaces on start or end
} ) ;
// All group objects are already loaded via the resolve statement from ui-router.
var allGroups = Group . getAll ( ) ;
// in allGroupsNames ar all original group names and translated names if a
// translation exists (e.g. for default group Delegates)
var allGroupsNames = [ ] ;
_ . forEach ( allGroups , function ( group ) {
var groupTranslation = gettextCatalog . getString ( group . name ) ;
if ( group . name !== groupTranslation ) {
allGroupsNames . push ( groupTranslation ) ;
}
allGroupsNames . push ( group . name ) ;
} ) ;
user . groupsToCreate = _ . difference ( user . groups , allGroupsNames ) ;
// for template:
user . groupsNotToCreate = _ . difference ( user . groups , user . groupsToCreate ) ;
2017-06-09 14:57:06 +02:00
} else {
user . groups = [ ] ;
2015-12-11 21:36:09 +01:00
}
2017-01-06 12:21:37 +01:00
user . is _active = ( user . is _active !== undefined && user . is _active === '1' ) ;
user . is _present = ( user . is _present !== undefined && user . is _present === '1' ) ;
user . is _committee = ( user . is _committee !== undefined && user . is _committee === '1' ) ;
2016-08-24 13:32:37 +02:00
// Check for duplicates
user . duplicate = false ;
users . forEach ( function ( user _ ) {
2017-04-18 09:55:53 +02:00
user _ . fullname = [
user _ . title ,
user _ . first _name ,
user _ . last _name ,
user _ . structure _level ] . join ( ' ' ) . trim ( ) ;
user . fullname = [
user . title ,
user . first _name ,
user . last _name ,
user . structure _level ] . join ( ' ' ) . trim ( ) ;
if ( user _ . fullname === user . fullname ) {
2016-08-24 13:32:37 +02:00
if ( user . duplicate ) {
// there are multiple duplicates!
user . duplicate _info += '\n' + gettextCatalog . getString ( 'There are more than one duplicates of this user!' ) ;
} else {
user . duplicate = true ;
user . duplicateAction = $scope . duplicateActions [ 1 ] ;
user . duplicate _info = '' ;
if ( user _ . title )
user . duplicate _info += user _ . title + ' ' ;
if ( user _ . first _name )
user . duplicate _info += user _ . first _name ;
if ( user _ . first _name && user _ . last _name )
user . duplicate _info += ' ' ;
if ( user _ . last _name )
user . duplicate _info += user _ . last _name ;
user . duplicate _info += ' (' ;
if ( user _ . number )
2016-12-07 19:49:25 +01:00
user . duplicate _info += gettextCatalog . getString ( 'Number' ) + ': ' + user _ . number + ', ' ;
2016-08-24 13:32:37 +02:00
if ( user _ . structure _level )
2016-12-07 19:49:25 +01:00
user . duplicate _info += gettextCatalog . getString ( 'Structure level' ) + ': ' + user _ . structure _level + ', ' ;
user . duplicate _info += gettextCatalog . getString ( 'Username' ) + ': ' + user _ . username + ') ' +
2016-08-24 13:32:37 +02:00
gettextCatalog . getString ( 'already exists.' ) ;
$scope . duplicates ++ ;
}
}
} ) ;
2015-12-11 21:36:09 +01:00
$scope . users . push ( user ) ;
} ) ;
2016-08-24 13:32:37 +02:00
$scope . calcStats ( ) ;
2017-01-06 12:21:37 +01:00
} ;
2015-12-11 21:36:09 +01:00
2016-08-24 13:32:37 +02:00
// Stats
$scope . calcStats = function ( ) {
// not imported: if importerror or duplicate->keep original
$scope . usersWillNotBeImported = 0 ;
// imported: all others
$scope . usersWillBeImported = 0 ;
$scope . users . forEach ( function ( user ) {
2017-01-06 15:08:51 +01:00
if ( ! user . selected || user . importerror || ( user . duplicate && user . duplicateAction == $scope . duplicateActions [ 0 ] ) ) {
2016-08-24 13:32:37 +02:00
$scope . usersWillNotBeImported ++ ;
} else {
$scope . usersWillBeImported ++ ;
}
} ) ;
} ;
$scope . setGlobalAction = function ( action ) {
$scope . users . forEach ( function ( user ) {
if ( user . duplicate )
user . duplicateAction = action ;
} ) ;
$scope . calcStats ( ) ;
} ;
2015-12-11 21:36:09 +01:00
// import from csv file
$scope . import = function ( ) {
$scope . csvImporting = true ;
2016-12-09 10:44:23 +01:00
// collect all needed groups and create non existing groups
var groupsToCreate = [ ] ;
_ . forEach ( $scope . users , function ( user ) {
2017-01-06 15:08:51 +01:00
if ( user . selected && ! user . importerror && user . groups . length ) {
2016-12-09 10:44:23 +01:00
_ . forEach ( user . groupsToCreate , function ( group ) { // Just append groups, that are not listed yet.
if ( _ . indexOf ( groupsToCreate , group ) == - 1 ) {
groupsToCreate . push ( group ) ;
}
} ) ;
}
} ) ;
var createPromises = [ ] ;
$scope . groupsCreated = 0 ;
_ . forEach ( groupsToCreate , function ( groupname ) {
var group = {
name : groupname ,
permissions : [ ]
} ;
createPromises . push ( Group . create ( group ) . then ( function ( success ) {
$scope . groupsCreated ++ ;
} ) ) ;
} ) ;
$q . all ( createPromises ) . then ( function ( ) {
// reload allGroups, now all new groups are created
var allGroups = Group . getAll ( ) ;
var existingUsers = User . getAll ( ) ;
2017-04-19 09:28:21 +02:00
// For option 'delete existing user' on duplicates
var deletePromises = [ ] ;
// Array of users for mass import
var usersToBeImported = [ ] ;
2016-12-09 10:44:23 +01:00
_ . forEach ( $scope . users , function ( user ) {
2017-01-06 15:08:51 +01:00
if ( user . selected && ! user . importerror ) {
2016-12-09 10:44:23 +01:00
// Assign all groups
_ . forEach ( user . groups , function ( csvGroup ) {
allGroups . forEach ( function ( allGroup ) {
// check with and without translation
if ( csvGroup === allGroup . name ||
csvGroup === gettextCatalog . getString ( allGroup . name ) ) {
user . groups _id . push ( allGroup . id ) ;
}
} ) ;
2016-08-24 13:32:37 +02:00
} ) ;
2016-12-09 10:44:23 +01:00
// Do nothing on duplicateAction==duplicateActions[0] (keep original)
if ( user . duplicate && ( user . duplicateAction == $scope . duplicateActions [ 1 ] ) ) {
// delete existing user
existingUsers . forEach ( function ( user _ ) {
2017-04-18 09:55:53 +02:00
user _ . fullname = [
user _ . title ,
user _ . first _name ,
user _ . last _name ,
user _ . structure _level ] . join ( ' ' ) . trim ( ) ;
user . fullname = [
user . title ,
user . first _name ,
user . last _name ,
user . structure _level ] . join ( ' ' ) . trim ( ) ;
if ( user _ . fullname === user . fullname ) {
2016-12-09 10:44:23 +01:00
deletePromises . push ( User . destroy ( user _ . id ) ) ;
}
} ) ;
2017-04-19 09:28:21 +02:00
usersToBeImported . push ( user ) ;
2016-12-09 10:44:23 +01:00
} else if ( ! user . duplicate ||
( user . duplicateAction == $scope . duplicateActions [ 2 ] ) ) {
// create user
2017-04-19 09:28:21 +02:00
usersToBeImported . push ( user ) ;
2016-12-09 10:44:23 +01:00
}
2016-08-24 13:32:37 +02:00
}
2016-12-09 10:44:23 +01:00
} ) ;
2017-04-19 09:28:21 +02:00
$q . all ( deletePromises ) . then ( function ( ) {
$http . post ( '/rest/users/user/mass_import/' , {
users : usersToBeImported
} ) . then ( function ( success ) {
_ . forEach ( success . data . importedTrackIds , function ( trackId ) {
_ . find ( $scope . users , function ( user ) {
return user . importTrackId === trackId ;
} ) . imported = true ;
} ) ;
$scope . csvimported = true ;
} , function ( error ) {
$scope . alert = ErrorMessage . forAlert ( error ) ;
} ) ;
} ) ;
2015-12-11 21:36:09 +01:00
} ) ;
2015-11-06 15:44:27 +01:00
} ;
$scope . clear = function ( ) {
2017-01-06 12:21:37 +01:00
$scope . users = null ;
2015-11-06 15:44:27 +01:00
} ;
2017-04-19 09:28:21 +02:00
$scope . excludeImportedUsers = function ( ) {
$scope . users = _ . filter ( $scope . users , function ( user ) {
return ! user . imported ;
} ) ;
$scope . csvImporting = false ;
$scope . calcStats ( ) ;
} ;
$scope . someImportedUsers = function ( ) {
return _ . some ( $scope . users , function ( user ) {
return user . imported ;
} ) ;
} ;
2015-12-30 21:56:03 +01:00
// download CSV example file
$scope . downloadCSVExample = function ( ) {
2017-02-07 12:44:51 +01:00
UserCsvExport . downloadExample ( ) ;
2016-02-24 09:42:28 +01:00
} ;
2015-11-06 15:44:27 +01:00
}
] )
2015-02-08 22:37:55 +01:00
2015-11-06 15:44:27 +01:00
. controller ( 'GroupListCtrl' , [
'$scope' ,
2016-08-08 09:37:46 +02:00
'$http' ,
2017-01-14 10:19:23 +01:00
'$filter' ,
2016-08-08 09:37:46 +02:00
'operator' ,
2015-11-06 15:44:27 +01:00
'Group' ,
2016-08-08 09:37:46 +02:00
'permissions' ,
'gettext' ,
'Agenda' ,
'Assignment' ,
'Mediafile' ,
'Motion' ,
'User' ,
'ngDialog' ,
2016-11-25 09:46:33 +01:00
'OpenSlidesPlugins' ,
2017-01-14 10:19:23 +01:00
function ( $scope , $http , $filter , operator , Group , permissions , gettext , Agenda ,
Assignment , Mediafile , Motion , User , ngDialog , OpenSlidesPlugins ) {
2016-08-08 09:37:46 +02:00
$scope . permissions = permissions ;
$scope . $watch ( function ( ) {
return Group . lastModified ( ) ;
} , function ( ) {
2017-01-14 10:19:23 +01:00
$scope . groups = $filter ( 'orderBy' ) ( Group . getAll ( ) , 'id' ) ;
2016-08-08 09:37:46 +02:00
// find all groups with the 2 dangerous permissions
var groups _danger = [ ] ;
$scope . groups . forEach ( function ( group ) {
if ( ( _ . indexOf ( group . permissions , 'users.can_see_name' ) > - 1 ) &&
( _ . indexOf ( group . permissions , 'users.can_manage' ) > - 1 ) ) {
2017-01-15 10:51:14 +01:00
if ( operator . isInGroup ( group ) ) {
2016-08-08 09:37:46 +02:00
groups _danger . push ( group ) ;
}
}
} ) ;
// if there is only one dangerous group, block it.
$scope . group _danger = groups _danger . length == 1 ? groups _danger [ 0 ] : null ;
} ) ;
2016-11-25 09:46:33 +01:00
// Dict to map plugin name -> display_name
var pluginTranslation = { } ;
_ . forEach ( OpenSlidesPlugins . getAll ( ) , function ( plugin ) {
pluginTranslation [ plugin . name ] = plugin . display _name ;
} ) ;
2016-08-08 09:37:46 +02:00
$scope . apps = [ ] ;
// Create the main clustering with appname->permissions
angular . forEach ( permissions , function ( perm ) {
var permissionApp = perm . value . split ( '.' ) [ 0 ] ; // get appname
// To insert perm in the right spot in $scope.apps
var insert = function ( id , perm , verboseName ) {
if ( ! $scope . apps [ id ] ) {
$scope . apps [ id ] = {
app _name : verboseName ,
app _visible : true ,
permissions : [ ]
} ;
}
$scope . apps [ id ] . permissions . push ( perm ) ;
} ;
switch ( permissionApp ) {
case 'core' : // id 0 (projector) and id 6 (general)
if ( perm . value . indexOf ( 'projector' ) > - 1 ) {
insert ( 0 , perm , gettext ( 'Projector' ) ) ;
} else {
insert ( 6 , perm , gettext ( 'General' ) ) ;
}
break ;
case 'agenda' : // id 1
insert ( 1 , perm , Agenda . verboseName ) ;
break ;
case 'motions' : // id 2
insert ( 2 , perm , Motion . verboseNamePlural ) ;
break ;
case 'assignments' : // id 3
insert ( 3 , perm , Assignment . verboseNamePlural ) ;
break ;
case 'mediafiles' : // id 4
insert ( 4 , perm , Mediafile . verboseNamePlural ) ;
break ;
case 'users' : // id 5
insert ( 5 , perm , User . verboseNamePlural ) ;
break ;
default : // plugins: id>5
2016-11-25 09:46:33 +01:00
var display _name = pluginTranslation [ permissionApp ] || permissionApp . charAt ( 0 ) . toUpperCase ( ) +
permissionApp . slice ( 1 ) ;
2016-08-08 09:37:46 +02:00
// does the app exists?
var result = - 1 ;
angular . forEach ( $scope . apps , function ( app , index ) {
if ( app . app _name === display _name )
result = index ;
} ) ;
var id = result == - 1 ? $scope . apps . length : result ;
insert ( id , perm , display _name ) ;
break ;
}
} ) ;
// sort each app: first all permission with 'see', then 'manage', then the rest
// save the permissions in different lists an concat them in the right order together
// Special Users: the two "see"-permissions are normally swapped. To create the right
// order, we could simply reverse the whole permissions.
angular . forEach ( $scope . apps , function ( app , index ) {
if ( index == 5 ) { // users
app . permissions . reverse ( ) ;
} else { // rest
var see = [ ] ;
var manage = [ ] ;
var others = [ ] ;
angular . forEach ( app . permissions , function ( perm ) {
if ( perm . value . indexOf ( 'see' ) > - 1 ) {
see . push ( perm ) ;
} else if ( perm . value . indexOf ( 'manage' ) > - 1 ) {
manage . push ( perm ) ;
} else {
others . push ( perm ) ;
}
} ) ;
app . permissions = see . concat ( manage . concat ( others ) ) ;
}
} ) ;
// check if the given group has the given permission
$scope . hasPerm = function ( group , permission ) {
return _ . indexOf ( group . permissions , permission . value ) > - 1 ;
} ;
// The current user is not allowed to lock himself out of the configuration:
// - if the permission is 'users.can_manage' or 'users.can_see'
// - if the user is in only one group with these permissions (group_danger is set)
$scope . danger = function ( group , permission ) {
if ( $scope . group _danger ) {
if ( permission . value == 'users.can_see_name' ||
permission . value == 'users.can_manage' ) {
return $scope . group _danger == group ;
}
}
return false ;
} ;
2015-11-06 15:44:27 +01:00
// delete selected group
$scope . delete = function ( group ) {
Group . destroy ( group . id ) ;
} ;
2016-08-08 09:37:46 +02:00
// save changed permission
$scope . changePermission = function ( group , perm ) {
if ( ! $scope . danger ( group , perm ) ) {
if ( ! $scope . hasPerm ( group , perm ) ) { // activate perm
group . permissions . push ( perm . value ) ;
} else {
// delete perm in group.permissions
group . permissions = _ . filter ( group . permissions , function ( value ) {
return value != perm . value ; // remove perm
} ) ;
2015-11-06 15:44:27 +01:00
}
2016-08-08 09:37:46 +02:00
Group . save ( group ) ;
}
} ;
$scope . openDialog = function ( group ) {
ngDialog . open ( {
template : 'static/templates/users/group-edit.html' ,
controller : group ? 'GroupRenameCtrl' : 'GroupCreateCtrl' ,
className : 'ngdialog-theme-default wide-form' ,
closeByEscape : false ,
closeByDocument : false ,
2017-01-14 13:02:26 +01:00
resolve : {
group : function ( ) { return group ; } ,
}
2016-08-08 09:37:46 +02:00
} ) ;
2015-11-06 15:44:27 +01:00
} ;
}
] )
2016-08-08 09:37:46 +02:00
. controller ( 'GroupRenameCtrl' , [
2015-11-06 15:44:27 +01:00
'$scope' ,
'Group' ,
'group' ,
2017-02-24 15:15:18 +01:00
'ErrorMessage' ,
function ( $scope , Group , group , ErrorMessage ) {
2016-08-08 09:37:46 +02:00
$scope . group = group ;
$scope . new _name = group . name ;
$scope . alert = { } ;
$scope . save = function ( ) {
var old _name = $scope . group . name ;
$scope . group . name = $scope . new _name ;
Group . save ( $scope . group ) . then (
function ( success ) {
$scope . closeThisDialog ( ) ;
} ,
function ( error ) {
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
$scope . group . name = old _name ;
2015-11-06 15:44:27 +01:00
}
) ;
} ;
}
] )
2016-08-08 09:37:46 +02:00
. controller ( 'GroupCreateCtrl' , [
2015-11-06 15:44:27 +01:00
'$scope' ,
'Group' ,
2017-02-24 15:15:18 +01:00
'ErrorMessage' ,
function ( $scope , Group , ErrorMessage ) {
2016-08-08 09:37:46 +02:00
$scope . new _name = '' ;
$scope . alert = { } ;
$scope . save = function ( ) {
var group = {
name : $scope . new _name ,
permissions : [ ]
} ;
Group . create ( group ) . then (
function ( success ) {
$scope . closeThisDialog ( ) ;
} ,
function ( error ) {
2017-02-24 15:15:18 +01:00
$scope . alert = ErrorMessage . forAlert ( error ) ;
2016-02-24 20:50:32 +01:00
}
2016-08-08 09:37:46 +02:00
) ;
} ;
2015-11-06 15:44:27 +01:00
}
] )
. controller ( 'userMenu' , [
'$scope' ,
'$http' ,
2017-03-31 08:48:43 +02:00
'OpenSlides' ,
2015-11-21 20:14:19 +01:00
'ngDialog' ,
2017-02-10 14:51:44 +01:00
'UserProfileForm' ,
'UserPasswordForm' ,
2017-03-31 08:48:43 +02:00
function ( $scope , $http , OpenSlides , ngDialog , UserProfileForm , UserPasswordForm ) {
2015-12-11 16:28:56 +01:00
$scope . logout = function ( ) {
$http . post ( '/users/logout/' ) . then ( function ( response ) {
2017-03-31 08:48:43 +02:00
// Success: User logged out, so reboot OpenSlides.
OpenSlides . reboot ( ) ;
2015-11-06 15:44:27 +01:00
} ) ;
} ;
2017-02-10 14:51:44 +01:00
$scope . editProfile = function ( ) {
ngDialog . open ( UserProfileForm . getDialog ( ) ) ;
} ;
$scope . changePassword = function ( ) {
ngDialog . open ( UserPasswordForm . getDialog ( ) ) ;
} ;
2015-11-21 20:14:19 +01:00
}
] )
. controller ( 'LoginFormCtrl' , [
2016-01-21 21:13:24 +01:00
'$rootScope' ,
2015-11-21 20:14:19 +01:00
'$scope' ,
'$http' ,
2017-01-14 13:02:26 +01:00
'$state' ,
2015-12-10 08:35:56 +01:00
'$stateParams' ,
2017-01-14 13:02:26 +01:00
'$q' ,
2015-11-21 20:14:19 +01:00
'operator' ,
2016-11-08 12:46:19 +01:00
'gettext' ,
2017-01-14 13:02:26 +01:00
'autoupdate' ,
'mainMenu' ,
'DS' ,
2017-01-15 10:51:14 +01:00
'ngDialog' ,
function ( $rootScope , $scope , $http , $state , $stateParams , $q , operator , gettext ,
autoupdate , mainMenu , DS , ngDialog ) {
2015-11-21 20:14:19 +01:00
$scope . alerts = [ ] ;
2017-01-15 10:51:14 +01:00
if ( $stateParams . msg ) {
$scope . alerts . push ( {
type : 'danger' ,
msg : $stateParams . msg ,
} ) ;
}
// check if guest login is allowed
$scope . guestAllowed = $rootScope . guest _enabled ;
2016-01-09 14:22:32 +01:00
// get login info-text from server
2017-02-24 15:15:18 +01:00
$http . get ( '/users/login/' ) . then ( function ( success ) {
if ( success . data . info _text ) {
2016-01-09 14:22:32 +01:00
$scope . alerts . push ( {
type : 'success' ,
2017-02-24 15:15:18 +01:00
msg : success . data . info _text
2016-01-09 14:22:32 +01:00
} ) ;
}
2016-02-24 09:42:28 +01:00
} ) ;
2016-11-08 12:46:19 +01:00
// check if cookies are enabled
if ( ! navigator . cookieEnabled ) {
$scope . alerts . push ( {
type : 'danger' ,
msg : gettext ( 'You have to enable cookies to use OpenSlides.' ) ,
} ) ;
}
2015-11-21 20:14:19 +01:00
// close alert function
$scope . closeAlert = function ( index ) {
$scope . alerts . splice ( index , 1 ) ;
} ;
// login
$scope . login = function ( ) {
2017-01-15 10:51:14 +01:00
$scope . closeThisDialog ( ) ;
2016-01-10 00:38:59 +01:00
$scope . alerts = [ ] ;
2016-12-19 14:14:46 +01:00
var data = { 'username' : $scope . username , 'password' : $scope . password } ;
if ( ! navigator . cookieEnabled ) {
data . cookies = false ;
}
$http . post ( '/users/login/' , data ) . then (
2015-12-11 16:28:56 +01:00
function ( response ) {
// Success: User logged in.
2017-01-14 13:02:26 +01:00
// Clear store and reset deferred first message, if guests was enabled before.
DS . clear ( ) ;
autoupdate . firstMessageDeferred = $q . defer ( ) ;
// The next lines are partly the same lines as in core/start.js
autoupdate . newConnect ( ) ;
autoupdate . firstMessageDeferred . promise . then ( function ( ) {
operator . setUser ( response . data . user _id , response . data . user ) ;
$rootScope . operator = operator ;
mainMenu . updateMainMenu ( ) ;
$state . go ( 'home' ) ;
2017-01-15 10:51:14 +01:00
$rootScope . openslidesBootstrapDone = true ;
2017-01-14 13:02:26 +01:00
} ) ;
2015-12-11 16:28:56 +01:00
} ,
2017-01-15 10:51:14 +01:00
function ( error ) {
2015-12-11 16:28:56 +01:00
// Error: Username or password is not correct.
2017-04-19 14:56:15 +02:00
$state . transitionTo ( $state . current , { msg : error . data . detail } , {
2017-01-15 10:51:14 +01:00
reload : true , inherit : false , notify : true
2015-11-21 20:14:19 +01:00
} ) ;
}
2015-12-11 16:28:56 +01:00
) ;
2015-11-21 20:14:19 +01:00
} ;
// guest login
$scope . guestLogin = function ( ) {
$scope . closeThisDialog ( ) ;
2017-01-15 10:51:14 +01:00
$state . go ( 'home' ) ;
2015-11-21 20:14:19 +01:00
} ;
2015-11-06 15:44:27 +01:00
}
2016-01-27 13:41:19 +01:00
] )
2016-06-28 10:05:52 +02:00
// Mark all users strings for translation in JavaScript.
2016-01-27 13:41:19 +01:00
. config ( [
'gettext' ,
function ( gettext ) {
2016-06-28 10:05:52 +02:00
// permission strings (see models.py of each Django app)
2016-01-27 13:41:19 +01:00
// agenda
2016-02-24 09:42:28 +01:00
gettext ( 'Can see agenda' ) ;
gettext ( 'Can manage agenda' ) ;
2017-08-18 13:13:53 +02:00
gettext ( 'Can manage list of speakers' ) ;
2016-02-24 09:42:28 +01:00
gettext ( 'Can see hidden items and time scheduling of agenda' ) ;
gettext ( 'Can put oneself on the list of speakers' ) ;
2016-01-27 13:41:19 +01:00
// assignments
2016-02-24 09:42:28 +01:00
gettext ( 'Can see elections' ) ;
gettext ( 'Can nominate another participant' ) ;
gettext ( 'Can nominate oneself' ) ;
gettext ( 'Can manage elections' ) ;
2016-01-27 13:41:19 +01:00
// core
2016-02-24 09:42:28 +01:00
gettext ( 'Can see the projector' ) ;
gettext ( 'Can manage the projector' ) ;
gettext ( 'Can see the front page' ) ;
gettext ( 'Can manage tags' ) ;
gettext ( 'Can manage configuration' ) ;
gettext ( 'Can use the chat' ) ;
2016-11-01 23:30:54 +01:00
gettext ( 'Can manage the chat' ) ;
2017-04-12 20:03:07 +02:00
gettext ( 'Can manage logos' ) ;
2016-01-27 13:41:19 +01:00
// mediafiles
2016-02-24 09:42:28 +01:00
gettext ( 'Can see the list of files' ) ;
gettext ( 'Can upload files' ) ;
gettext ( 'Can manage files' ) ;
2016-12-12 16:15:04 +01:00
gettext ( 'Can see hidden files' ) ;
2016-01-27 13:41:19 +01:00
// motions
2016-02-24 09:42:28 +01:00
gettext ( 'Can see motions' ) ;
gettext ( 'Can create motions' ) ;
gettext ( 'Can support motions' ) ;
gettext ( 'Can manage motions' ) ;
2016-09-08 09:44:47 +02:00
gettext ( 'Can see and manage comments' ) ;
2016-01-27 13:41:19 +01:00
// users
2016-02-24 09:42:28 +01:00
gettext ( 'Can see names of users' ) ;
2016-03-18 11:00:31 +01:00
gettext ( 'Can see extra data of users (e.g. present and comment)' ) ;
2016-02-24 09:42:28 +01:00
gettext ( 'Can manage users' ) ;
2016-06-28 10:05:52 +02:00
// config strings in users/config_variables.py
2016-11-04 13:26:44 +01:00
gettext ( 'General' ) ;
gettext ( 'Sort name of participants by' ) ;
2017-11-21 10:32:31 +01:00
gettext ( 'Enable participant presence view' ) ;
2016-06-28 10:05:52 +02:00
gettext ( 'Participants' ) ;
2016-12-07 19:49:25 +01:00
gettext ( 'Given name' ) ;
gettext ( 'Surname' ) ;
2016-11-04 13:26:44 +01:00
gettext ( 'PDF' ) ;
2016-06-28 10:05:52 +02:00
gettext ( 'Welcome to OpenSlides' ) ;
2016-06-09 16:12:13 +02:00
gettext ( 'Title for access data and welcome PDF' ) ;
2016-11-04 13:26:44 +01:00
gettext ( '[Place for your welcome and help text.]' ) ;
2016-06-09 16:12:13 +02:00
gettext ( 'Help text for access data and welcome PDF' ) ;
gettext ( 'System URL' ) ;
gettext ( 'Used for QRCode in PDF of access data.' ) ;
gettext ( 'WLAN name (SSID)' ) ;
gettext ( 'Used for WLAN QRCode in PDF of access data.' ) ;
gettext ( 'WLAN password' ) ;
gettext ( 'Used for WLAN QRCode in PDF of access data.' ) ;
gettext ( 'WLAN encryption' ) ;
gettext ( 'Used for WLAN QRCode in PDF of access data.' ) ;
gettext ( 'WEP' ) ;
gettext ( 'WPA/WPA2' ) ;
gettext ( 'No encryption' ) ;
2017-11-28 10:47:29 +01:00
gettext ( 'Email' ) ;
gettext ( 'Email sender' ) ;
gettext ( 'Email subject' ) ;
gettext ( 'Your login for {event_name}' ) ;
gettext ( 'You can use {event_name} as a placeholder.' ) ;
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 ( 'Use these placeholders: {name}, {event_name}, {url}, {username}, {password}. The url referrs to the system url.' ) ;
2016-01-27 13:41:19 +01:00
}
2015-11-06 15:44:27 +01:00
] ) ;
2015-06-17 09:45:00 +02:00
2016-01-27 13:41:19 +01:00
2015-02-12 22:42:54 +01:00
// this is code from angular.js. Find a way to call this function from this file
function getBlockNodes ( nodes ) {
// TODO(perf): just check if all items in `nodes` are siblings and if they are return the original
// collection, otherwise update the original collection.
var node = nodes [ 0 ] ;
var endNode = nodes [ nodes . length - 1 ] ;
var blockNodes = [ node ] ;
do {
node = node . nextSibling ;
if ( ! node ) break ;
blockNodes . push ( node ) ;
} while ( node !== endNode ) ;
return $ ( blockNodes ) ;
}
2015-10-21 22:44:07 +02:00
} ( ) ) ;