Template improvements

- Activate slides for users, customslides, motions, assignments.
- Add delete confirm message.
- Fixed required form fields.
- Added version template.
- Improved user import. Updated csv files.
This commit is contained in:
Emanuel Schuetze 2015-06-24 15:04:40 +02:00
parent fe16afa1a7
commit c2920407bb
31 changed files with 397 additions and 260 deletions

View File

@ -1,44 +1,44 @@
"Titel";"Vorname";"Nachname";"Geschlecht";"E-Mail";"Gruppen-ID";"Gliederungsebene";"Amt";"Über mich";"Kommentar";"Aktiviert"
;"Fred";"Nurk";"male";;3;"Australien";;;;1
;"Jan";"Jansen";"male";;3;"Belgien";;;;1
;"Juan";"Pérez";"male";;3;"Chile";;;;1
"Dr.";"Max";"Mustermann";"male";"max@example.com";4;"Deutschland";"Versammlungsleitung";"Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.";"Demo-Account
title,first_name,last_name,structure_level,groups,comment,is_active
,Fred,Nurk,Australien,3,,1
,Jan,Jansen,Belgien,3,,1
,Juan,Pérez,Chile,3,,1
Dr.,Max,Mustermann,Deutschland,4,"Demo-Account
Teilnehmer/innen-Namen aus http://de.wikipedia.org/wiki/Otto_Normalverbraucher";1
;"Otto";"Normalverbraucher";"male";"otto@example.com";3;"Deutschland";"Haushaltsausschuss";;"Demo-Account";1
;"Erika";"Mustermann";"female";"erika@example.com";;"Deutschland";;;;0
;"Morten";"Meinigmand";"male";;3;"Dänemark";;;;1
;"Juan";"Piguabe";"male";;3;"Ecuador";;;;1
;"Tädi";"Maali";"female";;3;"Estland";;;;1
;"Maija";"Maikäläinen";"female";;3;"Finnland";;;;1
;"Jean";"Dupont";"male";;3;"Frankreich";;;;1
;"Paul";"Martin";"male";;"3,4";"Frankreich";"Versammlungsleitung";;;1
;"Fred";"Bloggs";"male";;3;"Großbritanien";;;;0
;"John";"Smith";"male";;4;"Großbritanien";"Versammlungsleitung";;;1
;"Ashok";"Kumar";"male";;3;"Indien";;;;1
;"Si";"Polan";"male";;;"Indonesien";;;;1
;"Seán";"Citizen";"male";;3;"Irland";;;;1
;"Jóna";"Jónsson";"female";;3;"Island";;;;1
;"Israel";"Israeli";"male";;3;"Israel";;;;1
;"Mario";"Rossi";"male";;3;"Italien";;;;1
;"Jos";"Bleau";"male";;3;"Kanada";;;;1
;"Fulano";"de Tal";"male";;3;"Kolumbien";;;;1
;"Jenni";"a Menni";"female";;3;"Luxemburg";;;;1
;"Joe";"Borg";"male";;3;"Malta";;;;1
;"Bob";"Smith";"male";;;"Neuseeland";;;;1
;"Harry";"Holland";"male";;3;"Niederlande";;;;1
"Prof.";"Hans";"Maier";"male";;3;"Österreich";;;;1
;"Jan";"Kowalski";"male";;3;"Polen";;;;1
;"Manuel";"Dos Santos";"male";;3;"Portugal";;;;1
;"Cutare";"Cutărică";"male";;3;"Rumänien";;;;1
;"Nils";"Holgersson";"male";;3;"Schweden";;;;1
;"Max";"Schweizer";"male";;;"Schweiz";;;;1
;"Janez";"Novak";"male";;3;"Slowenien";;;;1
;"Koos";"van der Merwe";"male";;3;"Südafrika";;;;1
;"Jan";"Novák";"male";;3;"Tschechien";;;;1
;"Sade";"Vatandaş";"male";;3;"Türkei";;;;1
;"Gipsz";"Jakab";"male";;3;"Ungarn";;;;1
;"John";"Doe";"male";"john@example.com";3;"USA";;;;1
;"Jane";"Doe";"female";;;"USA";;;;0
;"Nguoi";"La";"male";;3;"Vietnam";;;;0
Teilnehmer/innen-Namen aus
http://de.wikipedia.org/wiki/Otto_Normalverbraucher",1
,Otto,Normalverbraucher,Deutschland,3,Demo-Account,1
,Erika,Mustermann,Deutschland,,,0
,Morten,Meinigmand,Dänemark,3,,1
,Juan,Piguabe,Ecuador,3,,1
,Tädi,Maali,Estland,3,,1
,Maija,Maikäläinen,Finnland,3,,1
,Jean,Dupont,Frankreich,3,,1
,Paul,Martin,Frankreich,"3,4",,1
,Fred,Bloggs,Großbritanien,3,,0
,John,Smith,Großbritanien,4,,1
,Ashok,Kumar,Indien,3,,1
,Si,Polan,Indonesien,,,1
,Seán,Citizen,Irland,3,,1
,Jóna,Jónsson,Island,3,,1
,Israel,Israeli,Israel,3,,1
,Mario,Rossi,Italien,3,,1
,Jos,Bleau,Kanada,3,,1
,Fulano,de Tal,Kolumbien,3,,1
,Jenni,a Menni,Luxemburg,3,,1
,Joe,Borg,Malta,3,,1
,Bob,Smith,Neuseeland,,,1
,Harry,Holland,Niederlande,3,,1
Prof.,Hans,Maier,Österreich,3,,1
,Jan,Kowalski,Polen,3,,1
,Manuel,Dos Santos,Portugal,3,,1
,Cutare,Cutărică,Rumänien,3,,1
,Nils,Holgersson,Schweden,3,,1
,Max,Schweizer,Schweiz,,,1
,Janez,Novak,Slowenien,3,,1
,Koos,van der Merwe,Südafrika,3,,1
,Jan,Novák,Tschechien,3,,1
,Sade,Vatandaş,Türkei,3,,1
,Gipsz,Jakab,Ungarn,3,,1
,John,Doe,USA,3,,1
,Jane,Doe,USA,,,0
,Nguoi,La,Vietnam,3,,0

1 Titel title Vorname first_name Nachname last_name Geschlecht Gliederungsebene structure_level E-Mail Gruppen-ID groups Kommentar comment Aktiviert is_active Amt Über mich
2 Fred Nurk male Australien 3 1
3 Jan Jansen male Belgien 3 1
4 Juan Pérez male Chile 3 1
5 Dr. Max Mustermann male Deutschland max@example.com 4 Demo-Account Teilnehmer/innen-Namen aus http://de.wikipedia.org/wiki/Otto_Normalverbraucher Demo-Account Teilnehmer/innen-Namen aus http://de.wikipedia.org/wiki/Otto_Normalverbraucher 1 Versammlungsleitung Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Otto Normalverbraucher male Deutschland otto@example.com 3 Demo-Account 1 Haushaltsausschuss
6 Erika Otto Mustermann Normalverbraucher female Deutschland erika@example.com 3 Demo-Account 0 1
7 Morten Erika Meinigmand Mustermann male Dänemark Deutschland 3 1 0
8 Juan Morten Piguabe Meinigmand male Ecuador Dänemark 3 1
9 Tädi Juan Maali Piguabe female Estland Ecuador 3 1
10 Maija Tädi Maikäläinen Maali female Finnland Estland 3 1
11 Jean Maija Dupont Maikäläinen male Frankreich Finnland 3 1
12 Paul Jean Martin Dupont male Frankreich 3,4 3 1 Versammlungsleitung
13 Fred Paul Bloggs Martin male Großbritanien Frankreich 3 3,4 0 1
14 John Fred Smith Bloggs male Großbritanien 4 3 1 0 Versammlungsleitung
15 Ashok John Kumar Smith male Indien Großbritanien 3 4 1
16 Si Ashok Polan Kumar male Indonesien Indien 3 1
17 Seán Si Citizen Polan male Irland Indonesien 3 1
18 Jóna Seán Jónsson Citizen female Island Irland 3 1
19 Israel Jóna Israeli Jónsson male Israel Island 3 1
20 Mario Israel Rossi Israeli male Italien Israel 3 1
21 Jos Mario Bleau Rossi male Kanada Italien 3 1
22 Fulano Jos de Tal Bleau male Kolumbien Kanada 3 1
23 Jenni Fulano a Menni de Tal female Luxemburg Kolumbien 3 1
24 Joe Jenni Borg a Menni male Malta Luxemburg 3 1
25 Bob Joe Smith Borg male Neuseeland Malta 3 1
26 Harry Bob Holland Smith male Niederlande Neuseeland 3 1
27 Prof. Hans Harry Maier Holland male Österreich Niederlande 3 1
28 Prof. Jan Hans Kowalski Maier male Polen Österreich 3 1
29 Manuel Jan Dos Santos Kowalski male Portugal Polen 3 1
30 Cutare Manuel Cutărică Dos Santos male Rumänien Portugal 3 1
31 Nils Cutare Holgersson Cutărică male Schweden Rumänien 3 1
32 Max Nils Schweizer Holgersson male Schweiz Schweden 3 1
33 Janez Max Novak Schweizer male Slowenien Schweiz 3 1
34 Koos Janez van der Merwe Novak male Südafrika Slowenien 3 1
35 Jan Koos Novák van der Merwe male Tschechien Südafrika 3 1
36 Sade Jan Vatandaş Novák male Türkei Tschechien 3 1
37 Gipsz Sade Jakab Vatandaş male Ungarn Türkei 3 1
38 John Gipsz Doe Jakab male USA Ungarn john@example.com 3 1
39 Jane John Doe female USA 3 0 1
40 Nguoi Jane La Doe male Vietnam USA 3 0
41 Nguoi La Vietnam 3 0
42
43
44

View File

@ -1,44 +1,43 @@
"Title";"First Name";"Last Name";"Gender";"Email";"Group id";"Structure Level";"Committee";"About me";"Comment";"Is active"
;"Fred";"Nurk";"male";;3;"Australia";;;;1
;"Jan";"Jansen";"male";;3;"Belgium";;;;1
;"Juan";"Pérez";"male";;3;"Chile";;;;1
"Dr.";"Max";"Mustermann";"male";"max@example.com";4;"Germany";"Leadership of the assembly";"Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.";"Demo account
title,first_name,last_name,structure_level,groups,comment,is_active
,Fred,Nurk,Australia,3,,1
,Jan,Jansen,Belgium,3,,1
,Juan,Pérez,Chile,3,,1
Dr.,Max,Mustermann,Germany,4,"Demo account
Names from http:///en.wikipedia.org/wiki/Otto_Normalverbraucher";1
;"Otto";"Normalverbraucher";"male";"otto@example.com";3;"Germany";"Budget committee";;"Demo account";1
;"Erika";"Mustermann";"female";"erika@example.com";;"Germany";;;;0
;"Morten";"Meinigmand";"male";;3;"Denmark";;;;1
;"Juan";"Piguabe";"male";;3;"Ecuador";;;;1
;"Tädi";"Maali";"female";;3;"Estonia";;;;1
;"Maija";"Maikäläinen";"female";;3;"Finland";;;;1
;"Jean";"Dupont";"male";;3;"France";;;;1
;"Paul";"Martin";"female";;4;"France";"Leadership of the assembly";;;1
;"Fred";"Bloggs";"male";;3;"United Kingdom";;;;0
;"John";"Smith";"male";;4;"United Kingdom";"Leadership of the assembly";;;1
;"Ashok";"Kumar";"male";;3;"India";;;;1
;"Si";"Polan";"male";;;"Indonesia";;;;1
;"Seán";"Citizen";"male";;3;"Ireland";;;;1
;"Jóna";"Jónsson";"female";;3;"Ireland";;;;1
;"Israel";"Israeli";"male";;3;"Israel";;;;1
;"Mario";"Rossi";"male";;3;"Italy";;;;1
;"Jos";"Bleau";"male";;3;"Canada";;;;1
;"Fulano";"de Tal";"male";;3;"Colombia";;;;1
;"Jenni";"a Menni";"female";;3;"Luxembourg";;;;1
;"Joe";"Borg";"male";;3;"Malta";;;;1
;"Bob";"Smith";"male";;;"New Zealand";;;;1
;"Harry";"Holland";"male";;3;"Netherlands";;;;1
"Prof.";"Hans";"Maier";"male";;3;"Austria";;;;1
;"Jan";"Kowalski";"male";;3;"Poland";;;;1
;"Manuel";"Dos Santos";"male";;3;"Portugal";;;;1
;"Cutare";"Cutărică";"male";;3;"Rumania";;;;1
;"Nils";"Holgersson";"male";;3;"Sweden";;;;1
;"Max";"Schweizer";"male";;;"Switzerland";;;;1
;"Janez";"Novak";"male";;3;"Slovenia";;;;1
;"Koos";"van der Merwe";"male";;3;"South Africa";;;;1
;"Jan";"Novák";"male";;3;"Czech Republic";;;;1
;"Sade";"Vatandaş";"male";;3;"Turkey";;;;1
;"Gipsz";"Jakab";"male";;3;"Hungary";;;;1
;"John";"Doe";"male";"john@example.com";3;"USA";;;;1
;"Jane";"Doe";"female";;;"USA";;;;0
;"Nguoi";"La";"male";;3;"Vietnam";;;;0
Names from http:///en.wikipedia.org/wiki/Otto_Normalverbraucher",1
,Otto,Normalverbraucher,Germany,3,Demo account,1
,Erika,Mustermann,Germany,,,0
,Morten,Meinigmand,Denmark,3,,1
,Juan,Piguabe,Ecuador,3,,1
,Tädi,Maali,Estonia,3,,1
,Maija,Maikäläinen,Finland,3,,1
,Jean,Dupont,France,3,,1
,Paul,Martin,France,4,,1
,Fred,Bloggs,United Kingdom,3,,0
,John,Smith,United Kingdom,4,,1
,Ashok,Kumar,India,3,,1
,Si,Polan,Indonesia,,,1
,Seán,Citizen,Ireland,3,,1
,Jóna,Jónsson,Ireland,3,,1
,Israel,Israeli,Israel,3,,1
,Mario,Rossi,Italy,3,,1
,Jos,Bleau,Canada,3,,1
,Fulano,de Tal,Colombia,3,,1
,Jenni,a Menni,Luxembourg,3,,1
,Joe,Borg,Malta,3,,1
,Bob,Smith,New Zealand,,,1
,Harry,Holland,Netherlands,3,,1
Prof.,Hans,Maier,Austria,3,,1
,Jan,Kowalski,Poland,3,,1
,Manuel,Dos Santos,Portugal,3,,1
,Cutare,Cutărică,Rumania,3,,1
,Nils,Holgersson,Sweden,3,,1
,Max,Schweizer,Switzerland,,,1
,Janez,Novak,Slovenia,3,,1
,Koos,van der Merwe,South Africa,3,,1
,Jan,Novák,Czech Republic,3,,1
,Sade,Vatandaş,Turkey,3,,1
,Gipsz,Jakab,Hungary,3,,1
,John,Doe,USA,3,,1
,Jane,Doe,USA,,,0
,Nguoi,La,Vietnam,3,,0

1 Title title First Name first_name Last Name last_name Gender Structure Level structure_level Email Group id groups Comment comment Is active is_active Committee About me
2 Fred Nurk male Australia 3 1
3 Jan Jansen male Belgium 3 1
4 Juan Pérez male Chile 3 1
5 Dr. Max Mustermann male Germany max@example.com 4 Demo account Names from http:///en.wikipedia.org/wiki/Otto_Normalverbraucher 1 Leadership of the assembly Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Otto Normalverbraucher male Germany otto@example.com 3 Demo account 1 Budget committee
6 Erika Otto Mustermann Normalverbraucher female Germany erika@example.com 3 Demo account 0 1
7 Morten Erika Meinigmand Mustermann male Denmark Germany 3 1 0
8 Juan Morten Piguabe Meinigmand male Ecuador Denmark 3 1
9 Tädi Juan Maali Piguabe female Estonia Ecuador 3 1
10 Maija Tädi Maikäläinen Maali female Finland Estonia 3 1
11 Jean Maija Dupont Maikäläinen male France Finland 3 1
12 Paul Jean Martin Dupont female France 4 3 1 Leadership of the assembly
13 Fred Paul Bloggs Martin male United Kingdom France 3 4 0 1
14 John Fred Smith Bloggs male United Kingdom 4 3 1 0 Leadership of the assembly
15 Ashok John Kumar Smith male India United Kingdom 3 4 1
16 Si Ashok Polan Kumar male Indonesia India 3 1
17 Seán Si Citizen Polan male Ireland Indonesia 3 1
18 Jóna Seán Jónsson Citizen female Ireland 3 1
19 Israel Jóna Israeli Jónsson male Israel Ireland 3 1
20 Mario Israel Rossi Israeli male Italy Israel 3 1
21 Jos Mario Bleau Rossi male Canada Italy 3 1
22 Fulano Jos de Tal Bleau male Colombia Canada 3 1
23 Jenni Fulano a Menni de Tal female Luxembourg Colombia 3 1
24 Joe Jenni Borg a Menni male Malta Luxembourg 3 1
25 Bob Joe Smith Borg male New Zealand Malta 3 1
26 Harry Bob Holland Smith male Netherlands New Zealand 3 1
27 Prof. Hans Harry Maier Holland male Austria Netherlands 3 1
28 Prof. Jan Hans Kowalski Maier male Poland Austria 3 1
29 Manuel Jan Dos Santos Kowalski male Portugal Poland 3 1
30 Cutare Manuel Cutărică Dos Santos male Rumania Portugal 3 1
31 Nils Cutare Holgersson Cutărică male Sweden Rumania 3 1
32 Max Nils Schweizer Holgersson male Switzerland Sweden 3 1
33 Janez Max Novak Schweizer male Slovenia Switzerland 3 1
34 Koos Janez van der Merwe Novak male South Africa Slovenia 3 1
35 Jan Koos Novák van der Merwe male Czech Republic South Africa 3 1
36 Sade Jan Vatandaş Novák male Turkey Czech Republic 3 1
37 Gipsz Sade Jakab Vatandaş male Hungary Turkey 3 1
38 John Gipsz Doe Jakab male USA Hungary john@example.com 3 1
39 Jane John Doe female USA 3 0 1
40 Nguoi Jane La Doe male Vietnam USA 3 0
41 Nguoi La Vietnam 3 0
42
43

View File

@ -32,7 +32,7 @@
<div class="form-group">
<label for="selectType" translate>Type</label>
<select ng-options="type.value as type.display_name for type in types"
ng-model="item.type" class="form-control" name="selectType" required>
ng-model="item.type" class="form-control" name="selectType">
</select>
</div>
<div class="form-group">

View File

@ -36,7 +36,7 @@ Keep each item in a single line.</p>
<li><translate>Required comma separated values</translate>:<br>
<code translate>'title, text, duration'</code>
<li translate>Text and duration are optional and may be empty.
<li translate>The first line (header) is ignored.
<li translate>The header in first line is required.
<li translate>Required CSV file encoding is UTF-8.
<li><a href="https://github.com/OpenSlides/OpenSlides/wiki/CSV-Import" translate>
Use the CSV example file from OpenSlides Wiki.

View File

@ -77,7 +77,7 @@
</a>
<!-- delete -->
<a os-perms="agenda.can_manage" class="btn btn-danger btn-sm"
ng-bootbox-confirm="Are you sure you want to delete item
ng-bootbox-confirm="Are you sure you want to delete
<b>{{ (items | filter: {id: node.id})[0].title }}</b>?"
ng-bootbox-confirm-action="delete(node.id)"
title="{{ 'Delete' | translate }}">

View File

@ -1,9 +1,16 @@
angular.module('OpenSlidesApp.assignments', [])
.factory('Assignment', function(DS) {
.factory('Assignment', function(DS, jsDataModel) {
var name = 'assignments/assignment'
return DS.defineResource({
name: 'assignments/assignment',
endpoint: '/rest/assignments/assignment/'
name: name,
endpoint: '/rest/assignments/assignment/',
useClass: jsDataModel,
methods: {
getResourceName: function () {
return name;
}
}
});
})
@ -66,14 +73,9 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
$scope.sortColumn = column;
};
// delete assignment
// delete selected assignment
$scope.delete = function (assignment) {
//TODO: add confirm message
Assignment.destroy(assignment.id).then(
function(success) {
//TODO: success message
}
);
Assignment.destroy(assignment.id);
};
})
@ -104,3 +106,19 @@ angular.module('OpenSlidesApp.assignments.site', ['OpenSlidesApp.assignments'])
};
});
angular.module('OpenSlidesApp.assignments.projector', ['OpenSlidesApp.assignments'])
.config(function(slidesProvider) {
slidesProvider.registerSlide('assignments/assignment', {
template: 'static/templates/assignments/slide_assignment.html',
});
})
.controller('SlideAssignmentCtrl', function($scope, Assignment) {
// Attention! Each object that is used here has to be dealt on server side.
// Add it to the coresponding get_requirements method of the ProjectorElement
// class.
var id = $scope.element.context.id;
Assignment.find(id);
Assignment.bindOne(id, $scope, 'assignment');
});

View File

@ -47,7 +47,7 @@
<translate>Actions</translate>
<tbody>
<tr ng-repeat="assignment in assignments | filter: filter.search |
orderBy: sortColumn:reverse">
orderBy: sortColumn:reverse" ng-class="{ 'activeline': assignment.isProjected() }">
<td><a ui-sref="assignments.assignment.detail({id: assignment.id})">{{ assignment.title }}</a>
<td class="optional">{{ assignment.open_posts }}
<td class="optional">
@ -57,9 +57,11 @@
{{ phases[assignment.phase].display_name }}
</span>
<td os-perms="assignments.can_manage core.can_manage_projector" class="nobr">
<!-- projector, TODO: add link to activate slide -->
<a href="#TODO" os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
title="{{ 'Show' | translate }}">
<!-- project -->
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
ng-class="{ 'btn-primary': assignment.isProjected() }"
ng-click="assignment.project()"
title="{{ 'Project election' | translate }}">
<i class="fa fa-video-camera"></i>
</a>
<!-- edit -->
@ -69,7 +71,9 @@
<i class="fa fa-pencil"></i>
</a>
<!-- delete -->
<a ng-click="delete(assignment)" os-perms="assignments.can_manage" class="btn btn-danger btn-sm"
<a os-perms="assignments.can_manage" class="btn btn-danger btn-sm"
ng-bootbox-confirm="Are you sure you want to delete <b>{{ assignment.title }}</b>?"
ng-bootbox-confirm-action="delete(assignment)"
title="{{ 'Delete' | translate }}">
<i class="fa fa-trash-o"></i>
</a>

View File

@ -0,0 +1,4 @@
<div ng-controller="SlideAssignmentCtrl" class="content">
<h1>{{ assignment.title }}</h1>
{{ assignment.description }}
</div>

View File

@ -50,7 +50,6 @@ body{
top:110px;
right:40px;
padding-left:30px;
background: url(../img/glyphicons_054_clock_big.png) no-repeat scroll 0px 0px;
}
/*** CONTENT with base style elements ***/

View File

@ -11,8 +11,8 @@ angular.module('OpenSlidesApp.projector', [
'OpenSlidesApp',
'OpenSlidesApp.core.projector',
'OpenSlidesApp.agenda',
'OpenSlidesApp.motions',
'OpenSlidesApp.assignments',
'OpenSlidesApp.motions.projector',
'OpenSlidesApp.assignments.projector',
'OpenSlidesApp.users.projector',
'OpenSlidesApp.mediafiles',
]);

View File

@ -94,6 +94,7 @@ angular.module('OpenSlidesApp.core', [])
// Returns true if there is a projector element with the same
// name and the same id.
var projector = Projector.get(id=1);
if (typeof projector === 'undefined') return false;
var self = this;
return _.findIndex(projector.elements, function(element) {
return element.name == self.getResourceName() &&
@ -109,6 +110,7 @@ angular.module('OpenSlidesApp.core', [])
return DS.defineResource({
name: name,
endpoint: '/rest/core/customslide/',
useClass: jsDataModel,
methods: {
getResourceName: function () {
return name;
@ -237,6 +239,10 @@ angular.module('OpenSlidesApp.core.site', ['OpenSlidesApp.core'])
abstract: true,
template: "<ui-view/>",
})
.state('version', {
url: '/version',
controller: 'VersionCtrl',
})
// customslide
.state('core.customslide', {
url: '/customslide',
@ -373,6 +379,14 @@ angular.module('OpenSlidesApp.core.site', ['OpenSlidesApp.core'])
};
})
// Version Controller
.controller('VersionCtrl', function($scope, $http) {
$http.get('/core/version/').success(function(data) {
$scope.core_version = data.openslides_version;
$scope.plugins = data.plugins;
});
})
// Customslide Controller
.controller('CustomslideListCtrl', function($scope, Customslide) {
Customslide.bindAll({}, $scope, 'customslides');
@ -552,7 +566,7 @@ angular.module('OpenSlidesApp.core.projector', ['OpenSlidesApp.core'])
});
})
.controller('SlideCustomSlideCtr', function($scope, Customslide) {
.controller('SlideCustomSlideCtrl', function($scope, Customslide) {
// Attention! Each object that is used here has to be dealt on server side.
// Add it to the coresponding get_requirements method of the ProjectorElement
// class.
@ -561,7 +575,7 @@ angular.module('OpenSlidesApp.core.projector', ['OpenSlidesApp.core'])
Customslide.bindOne(id, $scope, 'customslide');
})
.controller('SlideClockCtr', function($scope) {
.controller('SlideClockCtrl', function($scope) {
// Attention! Each object that is used here has to be dealt on server side.
// Add it to the coresponding get_requirements method of the ProjectorElement
// class.

View File

@ -25,9 +25,15 @@
<translate>Actions</translate>
<tbody>
<tr ng-repeat="customslide in customslides | filter: filter.search |
orderBy: sortColumn:reverse">
orderBy: sortColumn:reverse" ng-class="{ 'activeline': customslide.isProjected() }">
<td><a ui-sref="core.customslide.detail({id: customslide.id})">{{ customslide.title }}</a>
<td os-perms="core.can_manage_projector" class="nobr">
<!-- project -->
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm" ng-class="{ 'btn-primary': customslide.isProjected() }"
ng-click="customslide.project()"
title="{{ 'Project user' | translate }}">
<i class="fa fa-video-camera"></i>
</a>
<!-- edit -->
<a ui-sref="core.customslide.detail.update({id: customslide.id })"
class="btn btn-default btn-sm"

View File

@ -1,4 +1,4 @@
<div ng-controller="SlideClockCtr" id="currentTime">
<div ng-controller="SlideClockCtrl" id="currentTime">
<i class="fa fa-clock-o"></i>
{{ serverOffset | osServertime | date:'HH:mm' }}
</div>

View File

@ -1,4 +1,4 @@
<div ng-controller="SlideCustomSlideCtr" class="content">
<div ng-controller="SlideCustomSlideCtrl" class="content">
<h1>{{ customslide.title }}</h1>
{{ customslide.text }}
</div>

View File

@ -182,7 +182,7 @@
<small>
&copy; Copyright 2011-2015 |
Powered by <a href="http://openslides.org" target="_blank">OpenSlides</a> |
<a href="{% url 'core_version' %}">Version</a>
<a ui-sref="version">Version</a>
</small>
</footer>
</div><!--/#content-->

View File

@ -0,0 +1,12 @@
<h1 translate>Version</h1>
<p>OpenSlides Version {{ core_version }}
<div ng-show="plugins.length">
<p translate>Installed plugins:</p>
<ol>
<li ng-repeat="plugin in plugins">
{{ plugin.verbose_name }}: {{ plugin.version }}
</ol>
</div>

View File

@ -14,7 +14,7 @@
<input type="text" ng-model="mediafile.title" class="form-control" name="inputTitle">
</div>
<div class="form-group" ng-class="{'has-error has-feedback': mediafileForm.inputFile.$error.required}">
<div class="form-group">
<input type="file" ng-model="mediafile.mediafile"/>
</div>

View File

@ -33,14 +33,15 @@ class MotionDetailSlide(ProjectorElement):
view_class=MotionViewSet,
view_action='retrieve',
pk=str(motion.pk))
yield ProjectorRequirement(
view_class=CategoryViewSet,
view_action='retrieve',
pk=str(motion.category.pk))
if motion.category:
yield ProjectorRequirement(
view_class=CategoryViewSet,
view_action='retrieve',
pk=str(motion.category.pk))
yield ProjectorRequirement(
view_class=WorkflowViewSet,
view_action='retrieve',
pk=str(motion.workflow.pk))
pk=str(motion.workflow))
for submitter in motion.submitters.all():
yield ProjectorRequirement(
view_class=submitter.get_view_class(),

View File

@ -1,10 +1,15 @@
angular.module('OpenSlidesApp.motions', [])
.factory('Motion', function(DS) {
.factory('Motion', function(DS, jsDataModel) {
var name = 'motions/motion'
return DS.defineResource({
name: 'motions/motion',
name: name,
endpoint: '/rest/motions/motion/',
useClass: jsDataModel,
methods: {
getResourceName: function () {
return name;
},
getVersion: function(versionId) {
versionId = versionId || this.active_version;
if (versionId == -1) {
@ -183,13 +188,9 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
$scope.save = function (motion) {
Motion.save(motion);
};
// delete selected motion
$scope.delete = function (motion) {
//TODO: add confirm message
Motion.destroy(motion.id).then(
function(success) {
//TODO: success message
}
);
Motion.destroy(motion.id);
};
})
@ -256,13 +257,9 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
.controller('CategoryListCtrl', function($scope, Category) {
Category.bindAll({}, $scope, 'categories');
// delete selected category
$scope.delete = function (category) {
//TODO: add confirm message
Category.destroy(category.id).then(
function(success) {
//TODO: success message
}
);
Category.destroy(category.id);
};
})
@ -291,3 +288,20 @@ angular.module('OpenSlidesApp.motions.site', ['OpenSlidesApp.motions'])
);
};
});
angular.module('OpenSlidesApp.motions.projector', ['OpenSlidesApp.motions'])
.config(function(slidesProvider) {
slidesProvider.registerSlide('motions/motion', {
template: 'static/templates/motions/slide_motion.html',
});
})
.controller('SlideMotionCtrl', function($scope, Motion) {
// Attention! Each object that is used here has to be dealt on server side.
// Add it to the coresponding get_requirements method of the ProjectorElement
// class.
var id = $scope.element.context.id;
Motion.find(id);
Motion.bindOne(id, $scope, 'motion');
});

View File

@ -1,7 +1,7 @@
<h1 translate>Categories</h1>
<div id="submenu">
<a ui-sref="motions.category.create" os-perms="users.can_manage" class="btn btn-primary btn-sm">
<a ui-sref="motions.category.create" os-perms="motions.can_manage" class="btn btn-primary btn-sm">
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
@ -47,7 +47,9 @@
<i class="fa fa-pencil"></i>
</a>
<!-- delete -->
<a ng-click="delete(category)" os-perms="motions.can_manage" class="btn btn-danger btn-sm"
<a os-perms="motions.can_manage" class="btn btn-danger btn-sm"
ng-bootbox-confirm="Are you sure you want to delete <b>{{ category.name }}</b>?"
ng-bootbox-confirm-action="delete(category)"
title="{{ 'Delete' | translate }}">
<i class="fa fa-trash-o"></i>
</a>

View File

@ -62,22 +62,25 @@
<translate>Actions</translate>
<tbody>
<tr ng-repeat="motion in motions | filter: filter.search |
orderBy: sortColumn:reverse">
orderBy: sortColumn:reverse" ng-class="{ 'activeline': motion.isProjected() }">
<td> <!--TOOD: add agenda item reference -->
<td><a ui-sref="motions.motion.detail({id: motion.id})">{{ motion.identifier }}</a>
<td><a ui-sref="motions.motion.detail({id: motion.id})">
<!-- TODO: make it easier to get active version -->
{{ (motion.versions | filter: {id: motion.active_version})[0].title }}</a>
<!-- TODO: make it easier to get active version -->
{{ (motion.versions | filter: {id: motion.active_version})[0].title }}
</a>
<td class="optional">
<div ng-repeat="submitter in motion.submitters">
{{ (users | filter: {id: submitter})[0].get_full_name() }}<br>
</div>
<td class="optional">
{{ (categories | filter: {id: motion.category})[0].name }}</a>
{{ (categories | filter: {id: motion.category})[0].name }}
<td os-perms="motions.can_manage core.can_manage_projector" class="nobr">
<!-- projector, TODO: add link to activate slide -->
<a href="#TODO" os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
title="{{ 'Show' | translate }}">
<!-- project -->
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
ng-class="{ 'btn-primary': motion.isProjected() }"
ng-click="motion.project()"
title="{{ 'Project motion' | translate }}">
<i class="fa fa-video-camera"></i>
</a>
<!-- edit -->
@ -87,7 +90,9 @@
<i class="fa fa-pencil"></i>
</a>
<!-- delete -->
<a ng-click="delete(motion)" os-perms="motions.can_manage" class="btn btn-danger btn-sm"
<a os-perms="motions.can_manage" class="btn btn-danger btn-sm"
ng-bootbox-confirm="Are you sure you want to delete <b>{{ motion.getTitle() }}</b>?"
ng-bootbox-confirm-action="delete(motion)"
title="{{ 'Delete' | translate }}">
<i class="fa fa-trash-o"></i>
</a>

View File

@ -0,0 +1,4 @@
<div ng-controller="SlideMotionCtrl" class="content">
<h1>{{ motion.getTitle() }}</h1>
{{ motion.getText() }}
</div>

View File

@ -134,9 +134,9 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
}
}
})
.state('users.user.csv-import', {
url: '/csv-import',
controller: 'UserCSVImportCtrl',
.state('users.user.import', {
url: '/import',
controller: 'UserImportCtrl',
})
// groups
.state('users.group', {
@ -285,8 +285,9 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
};
}])
.controller('UserListCtrl', function($scope, User) {
.controller('UserListCtrl', function($scope, User, Group) {
User.bindAll({}, $scope, 'users');
Group.bindAll({}, $scope, 'groups');
// setup table sorting
$scope.sortColumn = 'first_name'; //TODO: sort by first OR last name
@ -306,7 +307,7 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
User.save(user);
};
// delete user
// delete selected user
$scope.delete = function (user) {
User.destroy(user.id);
};
@ -320,6 +321,9 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
Group.bindAll({where: {id: {'>': 2}}}, $scope, 'groups');
$scope.user = {};
$scope.save = function (user) {
if (!user.groups) {
user.groups = [];
}
User.create(user).then(
function(success) {
$state.go('users.user.list');
@ -332,6 +336,9 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
Group.bindAll({where: {id: {'>': 2}}}, $scope, 'groups');
$scope.user = user; // autoupdate is not activated
$scope.save = function (user) {
if (!user.groups) {
user.groups = [];
}
User.save(user).then(
function(success) {
$state.go('users.user.list');
@ -340,7 +347,22 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
};
})
.controller('UserCSVImportCtrl', function($scope, $state, User) {
.controller('UserImportCtrl', function($scope, $state, User) {
// import from textarea
$scope.importByLine = function () {
$scope.users = $scope.userlist[0].split("\n");
$scope.importcounter = 0;
$scope.users.forEach(function(name) {
var user = {last_name: name, groups: []}; // use default group 'Registered' (#2)
User.create(user).then(
function(success) {
$scope.importcounter++;
}
);
});
}
// import from csv file
$scope.csv = {
content: null,
header: true,
@ -348,30 +370,37 @@ angular.module('OpenSlidesApp.users.site', ['OpenSlidesApp.users'])
result: null
};
$scope.import = function (result) {
var obj = JSON.parse(result);
console.log(obj);
var imported_users = 0;
$scope.importByCSV = function (result) {
var obj = JSON.parse(JSON.stringify(result));
$scope.csvimporting = true;
$scope.csvlines = Object.keys(obj).length;
$scope.csvimportcounter = 0;
for (var i = 0; i < obj.length; i++) {
var user = {};
// TODO: use generic solution to get csv column values
user.title = obj[i].Titel;
user.first_name = obj[i].Vorname;
user.last_name = obj[i].Nachname;
user.groups = "3";
user.title = obj[i].titel;
user.first_name = obj[i].first_name;
user.last_name = obj[i].last_name;
user.structure_level = obj[i].structure_level;
user.groups = obj[i].groups;
user.comment = obj[i].comment;
User.create(user).then(
function(success) {
imported_users++;
$scope.csvimportcounter++;
}
);
}
$state.go('users.user.list');
$scope.csvimported = true;
}
$scope.clear = function () {
$scope.csv.result = null;
};
})
.controller('GroupListCtrl', function($scope, Group) {
Group.bindAll({}, $scope, 'groups');
// delete selected group
$scope.delete = function (group) {
Group.destroy(group.id);
};
@ -426,7 +455,7 @@ angular.module('OpenSlidesApp.users.projector', ['OpenSlidesApp.users'])
});
})
.controller('SlideUserCtr', function($scope, User) {
.controller('SlideUserCtrl', function($scope, User) {
// Attention! Each object that is used here has to be dealt on server side.
// Add it to the coresponding get_requirements method of the ProjectorElement
// class.

View File

@ -11,12 +11,12 @@
<form name="groupForm">
<div class="form-group">
<label for="inputName" translate>Name</label>
<input type="text" ng-model="group.name" class="form-control" name="inputName" ng-required="true">
<input type="text" ng-model="group.name" class="form-control" name="inputName" required>
</div>
<div class="form-group">
<label for="selectPermissions" translate>Permissions</label>
<select multiple size="15" ng-options="permission.value as permission.display_name for permission in permissions"
ng-model="group.permissions" class="form-control" name="selectPermissions">
ng-model="group.permissions" class="form-control" name="selectPermissions" required>
</select>
</div>

View File

@ -2,7 +2,7 @@
<div id="submenu">
<a ui-sref="users.group.create" os-perms="users.can_manage" class="btn btn-primary btn-sm">
<i class="fa fa-user-plus fa-lg"></i>
<i class="fa fa-plus fa-lg"></i>
<translate>New</translate>
</a>
<a ui-sref="users.user.list" class="btn btn-sm btn-default">
@ -47,7 +47,7 @@
<i class="fa fa-pencil"></i>
</a>
<!-- delete -->
<a ng-click="delete(group)" os-perms="users.can_manage" class="btn btn-danger btn-sm"
<a os-perms="users.can_manage" class="btn btn-danger btn-sm"
ng-bootbox-confirm="Are you sure you want to delete <b>{{ group.name }}</b>?"
ng-bootbox-confirm-action="delete(group)"
title="{{ 'Delete' | translate }}">

View File

@ -1,3 +1,3 @@
<div ng-controller="SlideUserCtr">
<h1>{{ user.username }}</h1>
<div ng-controller="SlideUserCtrl" class="content">
<h1>{{ user.get_full_name() }}</h1>
</div>

View File

@ -1,53 +0,0 @@
<h1 translate>Import participants</h1>
<div id="submenu">
<a ui-sref="users.user.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to overview</translate>
</a>
</div>
<p translate>Select a CSV file to import users!
<p translate>Please note:</p>
<ul>
<li><translate>Required comma separated values</translate>:<br>
<code translate>'title, first name, last name, gender, email, group id, structure level,
committee, about me, comment, is active'</code>
<li><translate>Default groups</translate>:
<translate>Delegate</translate> <code>3</code>,
<translate>Staff</translate> <code>4</code>
<li translate>At least first name or last name have to be filled in. All
other fields are optional and may be empty.
<li translate>The first line (header) is ignored.
<li translate>Required CSV file encoding is UTF-8.
<li><a href="https://github.com/OpenSlides/OpenSlides/wiki/CSV-Import" translate>
Use the CSV example file from OpenSlides Wiki.
</a>
</ul>
<ng-csv-import
content="csv.content"
class="import"
header="csv.header"
separator="csv.separator"
result="csv.result"></ng-csv-import>
<div ng-if="csv.content">
<h2>CSV</h2>
<div class="content"><pre>{{ csv.content }}</pre></div>
</div>
<div ng-if="csv.result">
<h2>JSON</h2>
<div class="content"><pre>{{ csv.result }}</pre></div>
</div>
<div class="form-group">
<button ng-click="import(csv.result)" class="btn btn-primary" translate>
Import
</button>
<button ui-sref="users.user.list" class="btn btn-default" translate>
Cancel
</button>
</div>

View File

@ -38,7 +38,7 @@
<div class="form-group">
<label for="selectGroups" translate>Groups</label>
<select multiple ng-options="group.id as group.name for group in groups"
ng-model="user.groups" class="form-control" name="selectGroups" required>
ng-model="user.groups" class="form-control" name="selectGroups">
</select>
</div>
<div class="form-group row">

View File

@ -0,0 +1,98 @@
<h1 translate>Import participants</h1>
<div id="submenu">
<a ui-sref="users.user.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to overview</translate>
</a>
</div>
<h2 translate>Import by copy/paste</h2>
<p translate>Copy and paste your participant names in this textbox.
Keep each person in a single line.</p>
<div class="row">
<div class="form-group col-sm-6">
<textarea ng-model="userlist" rows="5" class="form-control" ng-list="/\n/"></textarea>
</div>
</div>
<div class="clearfix">
<button ng-click="importByLine()" class="btn btn-primary pull-left" translate>Import</button>
<div class="col-xs-5" ng-if="items">
<progressbar animate="false" type="success" max="items.length" value="importcounter">
<i>{{ importcounter }} / {{ users.length }} {{ "imported" | translate }}</i>
</progressbar>
</div>
</div>
<hr>
<h2 translate>Import by CSV file</h2>
<p translate>Select a CSV file to import users!
<p translate>Please note:</p>
<ul>
<li><translate>Required comma separated values</translate>:<br>
<code translate>'title, first_name, last_name, structure level, groups, comment, is active'</code>
<li><translate>Default groups</translate>:
<translate>Delegate</translate> <code>3</code>,
<translate>Staff</translate> <code>4</code>
<li translate>At least first name or lastname have to be filled in. All
other fields are optional and may be empty.
<li translate>The header in first line is required.
<li translate>Required CSV file encoding is UTF-8.
<li><a href="https://github.com/OpenSlides/OpenSlides/wiki/CSV-Import" translate>
Use the CSV example file from OpenSlides Wiki.
</a>
</ul>
<ng-csv-import
content="csv.content"
class="import"
header="csv.header"
separator="csv.separator"
result="csv.result"></ng-csv-import>
<div ng-if="csv.result" class="col-sm-10 well">
<h3 translate>Preview</h3>
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>#
<th translate>Title
<th translate>First name
<th translate>Last name
<th translate>Structure level
<th translate>Groups
<th translate>Comment
<tbody ng-repeat="user in csv.result">
<tr>
<td>{{ $index+1 }}
<td>{{ user.title }}
<td>{{ user.first_name }}
<td>{{ user.last_name }}
<td>{{ user.structure_level }}
<td>{{ user.groups }}
<td>{{ user.comment }}
</table>
<div class="clearfix">
<button ng-if="!csvimporting" ng-click="importByCSV(csv.result)" class="btn btn-primary pull-left" translate>Import</button>
<div ng-if="csvimporting">
<progressbar animate="false" type="success" max="csvlines" value="csvimportcounter">
<i>{{ csvimportcounter }} / {{ csvlines }} {{ "imported" | translate }}</i>
</progressbar>
</div>
<a ng-if="csvimported" ui-sref="users.user.list" class="btn btn-sm btn-default">
<i class="fa fa-angle-double-left fa-lg"></i>
<translate>Back to agenda overview</translate>
</a>
</div>
<p>
<div class="form-group">
<button ng-if="!csvimporting" ng-click="clear()" class="btn btn-default" translate>
Clear
</button>
</div>
</div>

View File

@ -1,36 +1,20 @@
<h1 translate>Participants</h1>
<div id="submenu">
<div os-perms="users.can_manage" class="btn-group">
<a ui-sref="users.user.create" class="btn btn-primary btn-sm">
<i class="fa fa-user-plus fa-lg"></i>
<translate>New</translate>
</a>
<button class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown">
<span class="fa fa-caret-down"></span>
</button>
<ul class="dropdown-menu">
<li><a ui-sref="users.user.create">
<i class="fa fa-user fa-fw"></i>
<translate>Single participant</translate>
</a>
<li><a href="#TODO">
<i class="fa fa-group fa-fw"></i>
<translate>Multiple participants</translate>
</a>
</ul>
</div>
<a ui-sref="users.user.create" os-perms="users.can_manage" class="btn btn-primary btn-sm">
<i class="fa fa-user-plus fa-lg"></i>
<translate>New</translate>
</a>
<a ui-sref="users.group.list" os-perms="users.can_manage" class="btn btn-default btn-sm">
<i class="fa fa-group fa-lg"></i>
<translate>Groups</translate>
</a>
<a ui-sref="users.user.csv-import" os-perms="users.can_manage" class="btn btn-default btn-sm">
<a ui-sref="users.user.import" os-perms="users.can_manage" class="btn btn-default btn-sm">
<i class="fa fa-download fa-lg"></i>
<translate>Import</translate>
</a>
<div class="btn-group">
<!-- TODO: use ui-sref -->
<a href="/users/print/" class="btn btn-default btn-sm" target="_blank">
<a ui-sref="user_print" class="btn btn-default btn-sm" target="_blank">
<i class="fa fa-file-pdf-o fa-lg"></i>
<translate>PDF</translate>
</a>
@ -39,13 +23,12 @@
<i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<!-- TODO: use ui-sref -->
<li><a href="/users/print/" target="_blank">
<li><a ui-sref="user_listpdf" target="_blank">
<i class="fa fa-list fa-fw"></i>
<translate>List of participants</translate>
</a>
<li os-perms="users.can_manage">
<a href="/users/passwords/print/" target="_blank">
<a ui-sref="user_passwordspdf" target="_blank">
<i class="fa fa-qrcode fa-fw"></i>
<translate>List of access data</translate>
</a>
@ -84,31 +67,29 @@
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i>
<th ng-click="toggleSort('groups')" class="sortable optional">
<translate>Group</translate>
<translate>Groups</translate>
<i class="pull-right fa" ng-show="sortColumn === 'groups' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i>
<th os-perms="users.can_manage" ng-click="toggleSort('last_login')" class="sortable optional">
<translate>Last Login</translate>
<i class="pull-right fa" ng-show="sortColumn === 'last_login' && header.sortable != false"
ng-class="reverse ? 'fa-sort-desc' : 'fa-sort-asc'">
</i>
<th os-perms="users.can_manage core.can_manage_projector" class="minimum">
<translate>Actions</translate>
<tbody>
<tr ng-repeat="user in users | filter: filter.search | filter: {is_present: filterPresent} |
orderBy: sortColumn:reverse">
orderBy: sortColumn:reverse" ng-class="{ 'activeline': user.isProjected() }">
<td><input type="checkbox" ng-model="user.is_present" ng-click="togglePresent(user)">
<td><a ui-sref="users.user.detail({id: user.id})">{{ user.get_short_name() }}</a>
<div ng-if="user.comment"><small><i class="fa fa-info-circle"></i> {{ user.comment }}</small></div>
<td class="optional">{{ user.structure_level }}
<td class="optional">{{ user.groups }}
<td os-perms="users.can_manage" class="optional">{{ user.last_login | date:'yyyy-MM-dd HH:mm:ss'}}
<td class="optional">
<div ng-repeat="group in user.groups">
{{ (groups | filter: {id: group})[0].name }}
</div>
<td os-perms="users.can_manage core.can_manage_projector" class="nobr">
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
<!-- project -->
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm" ng-class="{ 'btn-primary': user.isProjected() }"
ng-click="user.project()"
title="{{ 'Show' | translate }}">
<i class="fa fa-video-camera"><span ng-if="user.isProjected()">projected</span></i>
title="{{ 'Project user' | translate }}">
<i class="fa fa-video-camera"></i>
</a>
<!-- edit -->
<a ui-sref="users.user.detail.update({id: user.id})" os-perms="users.can_manage"

View File

@ -8,11 +8,11 @@ urlpatterns = patterns(
# PDF
url(r'^print/$',
views.UsersListPDF.as_view(),
name='user_print'),
name='user_listpdf'),
url(r'^passwords/print/$',
views.UsersPasswordsPDF.as_view(),
name='print_passwords'),
name='user_passwordspdf'),
# auth
url(r'^login/$',