Merge pull request #1619 from emanuelschuetze/agenda-template

Agenda item list: new multiselect delete mode
This commit is contained in:
Emanuel Schütze 2015-09-14 20:43:39 +02:00
commit d79bad80f6
6 changed files with 467 additions and 348 deletions

View File

@ -14,6 +14,7 @@
"angular-loading-bar": "~0.7.1", "angular-loading-bar": "~0.7.1",
"angular-ui-router": "~0.2.13", "angular-ui-router": "~0.2.13",
"angular-ui-select": "~0.12", "angular-ui-select": "~0.12",
"angular-ui-switch": "~0.1.0",
"angular-ui-tree": "~2.2.0", "angular-ui-tree": "~2.2.0",
"angular-gettext": "~2.0.2", "angular-gettext": "~2.0.2",
"angular-sanitize": "~1.3.15", "angular-sanitize": "~1.3.15",

View File

@ -2,44 +2,52 @@
angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users']) angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users'])
.factory('Speaker', ['DS', function(DS) { .factory('Speaker', [
return DS.defineResource({ 'DS',
name: 'agenda/speaker', function(DS) {
relations: { return DS.defineResource({
belongsTo: { name: 'agenda/speaker',
'users/user': { relations: {
localField: 'user', belongsTo: {
localKey: 'user_id', 'users/user': {
localField: 'user',
localKey: 'user_id',
}
} }
} }
} });
}); }
}]) ])
.factory('Agenda', ['DS', 'Speaker', 'jsDataModel', function(DS, Speaker, jsDataModel) { .factory('Agenda', [
var name = 'agenda/item' 'DS',
return DS.defineResource({ 'Speaker',
name: name, 'jsDataModel',
useClass: jsDataModel, function(DS, Speaker, jsDataModel) {
methods: { var name = 'agenda/item'
getResourceName: function () { return DS.defineResource({
return name; name: name,
} useClass: jsDataModel,
}, methods: {
relations: { getResourceName: function () {
hasMany: { return name;
'core/tag': { }
localField: 'tags', },
localKeys: 'tags_id', relations: {
}, hasMany: {
'agenda/speaker': { 'core/tag': {
localField: 'speakers', localField: 'tags',
foreignKey: 'item_id', localKeys: 'tags_id',
},
'agenda/speaker': {
localField: 'speakers',
foreignKey: 'item_id',
}
} }
} }
} });
}); }
}]) ])
// Make sure that the Agenda resource is loaded. // Make sure that the Agenda resource is loaded.
.run(['Agenda', function(Agenda) {}]); .run(['Agenda', function(Agenda) {}]);
@ -60,79 +68,82 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
} }
]) ])
.config(function($stateProvider) { .config([
$stateProvider '$stateProvider',
.state('agenda', { function($stateProvider) {
url: '/agenda', $stateProvider
abstract: true, .state('agenda', {
template: "<ui-view/>", url: '/agenda',
}) abstract: true,
.state('agenda.item', { template: "<ui-view/>",
abstract: true, })
template: "<ui-view/>", .state('agenda.item', {
}) abstract: true,
.state('agenda.item.list', { template: "<ui-view/>",
resolve: { })
items: function(Agenda) { .state('agenda.item.list', {
return Agenda.findAll(); resolve: {
items: function(Agenda) {
return Agenda.findAll();
}
} }
} })
}) .state('agenda.item.create', {
.state('agenda.item.create', { resolve: {
resolve: { types: function($http) {
types: function($http) { // get all item types
// get all item types return $http({ 'method': 'OPTIONS', 'url': '/rest/agenda/item/' });
return $http({ 'method': 'OPTIONS', 'url': '/rest/agenda/item/' }); },
tags: function(Tag) {
return Tag.findAll();
}
}
})
.state('agenda.item.detail', {
resolve: {
item: function(Agenda, $stateParams) {
return Agenda.find($stateParams.id);
},
users: function(User) {
return User.findAll();
},
tags: function(Tag) {
return Tag.findAll();
}
}
})
.state('agenda.item.detail.update', {
views: {
'@agenda.item': {}
}, },
tags: function(Tag) { resolve: {
return Tag.findAll(); types: function($http) {
// get all item types
return $http({ 'method': 'OPTIONS', 'url': '/rest/agenda/item/' });
}
} }
} })
}) .state('agenda.item.sort', {
.state('agenda.item.detail', { resolve: {
resolve: { items: function(Agenda) {
item: function(Agenda, $stateParams) { return Agenda.findAll();
return Agenda.find($stateParams.id); }
}, },
users: function(User) { url: '/sort',
return User.findAll(); controller: 'AgendaSortCtrl',
}, })
tags: function(Tag) { .state('agenda.item.import', {
return Tag.findAll(); url: '/import',
} controller: 'AgendaImportCtrl',
} });
}) }
.state('agenda.item.detail.update', { ])
views: {
'@agenda.item': {}
},
resolve: {
types: function($http) {
// get all item types
return $http({ 'method': 'OPTIONS', 'url': '/rest/agenda/item/' });
}
}
})
.state('agenda.item.sort', {
resolve: {
items: function(Agenda) {
return Agenda.findAll();
}
},
url: '/sort',
controller: 'AgendaSortCtrl',
})
.state('agenda.item.import', {
url: '/import',
controller: 'AgendaImportCtrl',
});
})
.factory('AgendaTree', [ .factory('AgendaTree', [
function () { function () {
return { return {
getTree: function (items) { getTree: function (items) {
// sortieren nach weight??? // TODO: sortieren nach weight???
// Build a dict with all children (dict-value) to a specific // Build a dict with all children (dict-value) to a specific
// item id (dict-key). // item id (dict-key).
@ -190,199 +201,270 @@ angular.module('OpenSlidesApp.agenda.site', ['OpenSlidesApp.agenda'])
} }
]) ])
.controller('ItemListCtrl', function($scope, $http, Agenda, Projector, AgendaTree) { .controller('ItemListCtrl', [
// Bind agenda tree to the scope '$scope',
$scope.$watch(function () { '$http',
return Agenda.lastModified(); '$state',
}, function () { 'Agenda',
$scope.items = AgendaTree.getFlatTree(Agenda.getAll()); 'AgendaTree',
}); 'Projector',
function($scope, $http, $state, Agenda, AgendaTree, Projector) {
// save changed item // Bind agenda tree to the scope
$scope.save = function (item) { $scope.$watch(function () {
Agenda.save(item); return Agenda.lastModified();
}; }, function () {
// delete selected item $scope.items = AgendaTree.getFlatTree(Agenda.getAll());
$scope.delete = function (id) {
Agenda.destroy(id);
};
// project agenda
$scope.projectAgenda = function () {
$http.post('/rest/core/projector/1/prune_elements/',
[{name: 'agenda/item-list'}]);
};
// check if agenda is projected
$scope.isAgendaProjected = function () {
// Returns true if there is a projector element with the same
// name and agenda is active.
var projector = Projector.get(1);
if (typeof projector === 'undefined') return false;
var self = this;
return _.findIndex(projector.elements, function(element) {
return element.name == 'agenda/item-list'
}) > -1;
};
})
.controller('ItemDetailCtrl', function($scope, $http, Agenda, User, item) {
Agenda.bindOne(item.id, $scope, 'item');
User.bindAll({}, $scope, 'users');
$scope.speaker = {};
$scope.alert = {};
// close/open list of speakers of current item
$scope.closeList = function (listClosed) {
item.speaker_list_closed = listClosed;
Agenda.save(item);
};
// add user to list of speakers
$scope.addSpeaker = function (userId) {
$http.post('/rest/agenda/item/' + item.id + '/manage_speaker/', {'user': userId})
.success(function(data){
$scope.alert.show = false;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// delete speaker(!) from list of speakers
$scope.removeSpeaker = function (speakerId) {
$http.delete('/rest/agenda/item/' + item.id + '/manage_speaker/',
{headers: {'Content-Type': 'application/json'},
data: JSON.stringify({speaker: speakerId})})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// begin speech of selected/next speaker
$scope.beginSpeech = function (speakerId) {
$http.put('/rest/agenda/item/' + item.id + '/speak/', {'speaker': speakerId})
.success(function(data){
$scope.alert.show = false;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// end speech of current speaker
$scope.endSpeech = function () {
$http.delete('/rest/agenda/item/' + item.id + '/speak/',
{headers: {'Content-Type': 'application/json'},
data: JSON.stringify()})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// project list of speakers
$scope.projectListOfSpeakers = function () {
$http.post('/rest/core/projector/1/prune_elements/',
[{name: 'agenda/item', id: item.id, list_of_speakers: true}]);
};
})
.controller('ItemCreateCtrl', function($scope, $state, Agenda, Tag, types) {
$scope.types = types.data.actions.POST.type.choices; // get all item types
Tag.bindAll({}, $scope, 'tags');
$scope.save = function (item) {
if (!item)
return null;
Agenda.create(item).then(
function(success) {
$state.go('agenda.item.list');
}
);
};
})
.controller('ItemUpdateCtrl', function($scope, $state, Agenda, Tag, types, item) {
$scope.types = types.data.actions.POST.type.choices; // get all item types
Tag.bindAll({}, $scope, 'tags');
$scope.item = item;
$scope.save = function (item) {
Agenda.save(item).then(
function(success) {
$state.go('agenda.item.list');
}
);
};
})
.controller('AgendaSortCtrl', function($scope, $http, Agenda, AgendaTree) {
// Bind agenda tree to the scope
$scope.$watch(function () {
return Agenda.lastModified();
}, function () {
$scope.items = AgendaTree.getTree(Agenda.getAll());
});
// set changed agenda tree
$scope.treeOptions = {
dropped: function() {
$http.put('/rest/agenda/item/tree/', {tree: $scope.items});
}
};
})
.controller('AgendaImportCtrl', function($scope, $state, Agenda) {
// import from textarea
$scope.importByLine = function () {
$scope.items = $scope.itemlist[0].split("\n");
$scope.importcounter = 0;
$scope.items.forEach(function(title) {
var item = {title: title};
// TODO: create all items in bulk mode
Agenda.create(item).then(
function(success) {
$scope.importcounter++;
}
);
}); });
}
// import from csv file // open detail view link
$scope.csv = { $scope.openDetail = function (id) {
content: null, $state.go('agenda.item.detail', {id: id});
header: true, }
separator: ',',
result: null // save changed item
}; $scope.save = function (item) {
$scope.importByCSV = function (result) { Agenda.save(item);
var obj = JSON.parse(JSON.stringify(result)); };
$scope.csvimporting = true;
$scope.csvlines = Object.keys(obj).length; // *** delete mode functions ***
$scope.csvimportcounter = 0; $scope.isDeleteMode = false;
for (var i = 0; i < obj.length; i++) { // check all checkboxes
var item = {}; $scope.checkAll = function () {
item.title = obj[i].title; angular.forEach($scope.items, function (item) {
item.text = obj[i].text; item.selected = $scope.selectedAll;
item.duration = obj[i].duration; });
};
// uncheck all checkboxes if isDeleteMode is closed
$scope.uncheckAll = function () {
if (!$scope.isDeleteMode) {
$scope.selectedAll = false;
angular.forEach($scope.items, function (item) {
item.selected = false;
});
}
};
// delete selected item
$scope.delete = function () {
angular.forEach($scope.items, function (item) {
if (item.selected)
Agenda.destroy(item.id);
});
$scope.isDeleteMode = false;
$scope.uncheckAll();
};
// project agenda
$scope.projectAgenda = function () {
$http.post('/rest/core/projector/1/prune_elements/',
[{name: 'agenda/item-list'}]);
};
// check if agenda is projected
$scope.isAgendaProjected = function () {
// Returns true if there is a projector element with the same
// name and agenda is active.
var projector = Projector.get(1);
if (typeof projector === 'undefined') return false;
var self = this;
return _.findIndex(projector.elements, function(element) {
return element.name == 'agenda/item-list'
}) > -1;
};
}
])
.controller('ItemDetailCtrl', [
'$scope',
'$http',
'Agenda',
'User',
'item',
function ($scope, $http, Agenda, User, item) {
Agenda.bindOne(item.id, $scope, 'item');
User.bindAll({}, $scope, 'users');
$scope.speaker = {};
$scope.alert = {};
// close/open list of speakers of current item
$scope.closeList = function (listClosed) {
item.speaker_list_closed = listClosed;
Agenda.save(item);
};
// add user to list of speakers
$scope.addSpeaker = function (userId) {
$http.post('/rest/agenda/item/' + item.id + '/manage_speaker/', {'user': userId})
.success(function(data){
$scope.alert.show = false;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// delete speaker(!) from list of speakers
$scope.removeSpeaker = function (speakerId) {
$http.delete('/rest/agenda/item/' + item.id + '/manage_speaker/',
{headers: {'Content-Type': 'application/json'},
data: JSON.stringify({speaker: speakerId})})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// begin speech of selected/next speaker
$scope.beginSpeech = function (speakerId) {
$http.put('/rest/agenda/item/' + item.id + '/speak/', {'speaker': speakerId})
.success(function(data){
$scope.alert.show = false;
})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// end speech of current speaker
$scope.endSpeech = function () {
$http.delete('/rest/agenda/item/' + item.id + '/speak/',
{headers: {'Content-Type': 'application/json'},
data: JSON.stringify()})
.error(function(data){
$scope.alert = { type: 'danger', msg: data.detail, show: true };
});
};
// project list of speakers
$scope.projectListOfSpeakers = function () {
$http.post('/rest/core/projector/1/prune_elements/',
[{name: 'agenda/item', id: item.id, list_of_speakers: true}]);
};
}
])
.controller('ItemCreateCtrl', [
'$scope',
'$state',
'Agenda',
'Tag',
'types',
function($scope, $state, Agenda, Tag, types) {
$scope.types = types.data.actions.POST.type.choices; // get all item types
Tag.bindAll({}, $scope, 'tags');
$scope.save = function (item) {
if (!item)
return null;
Agenda.create(item).then( Agenda.create(item).then(
function(success) { function(success) {
$scope.csvimportcounter++; $state.go('agenda.item.list');
} }
); );
} };
$scope.csvimported = true;
} }
])
$scope.clear = function () { .controller('ItemUpdateCtrl', [
$scope.csv.result = null; '$scope',
}; '$state',
'Agenda',
'Tag',
'types',
'item',
function($scope, $state, Agenda, Tag, types, item) {
$scope.types = types.data.actions.POST.type.choices; // get all item types
Tag.bindAll({}, $scope, 'tags');
$scope.item = item;
$scope.save = function (item) {
Agenda.save(item).then(
function(success) {
$state.go('agenda.item.list');
}
);
};
}
])
}); .controller('AgendaSortCtrl', [
'$scope',
'$http',
'Agenda',
'AgendaTree',
function($scope, $http, Agenda, AgendaTree) {
// Bind agenda tree to the scope
$scope.$watch(function () {
return Agenda.lastModified();
}, function () {
$scope.items = AgendaTree.getTree(Agenda.getAll());
});
// set changed agenda tree
$scope.treeOptions = {
dropped: function() {
$http.put('/rest/agenda/item/tree/', {tree: $scope.tree});
}
};
}
])
.controller('AgendaImportCtrl', [
'$scope',
'$state',
'Agenda',
function($scope, $state, Agenda) {
// import from textarea
$scope.importByLine = function () {
$scope.items = $scope.itemlist[0].split("\n");
$scope.importcounter = 0;
$scope.items.forEach(function(title) {
var item = {title: title};
// TODO: create all items in bulk mode
Agenda.create(item).then(
function(success) {
$scope.importcounter++;
}
);
});
}
// import from csv file
$scope.csv = {
content: null,
header: true,
separator: ',',
result: null
};
$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 item = {};
item.title = obj[i].title;
item.text = obj[i].text;
item.duration = obj[i].duration;
Agenda.create(item).then(
function(success) {
$scope.csvimportcounter++;
}
);
}
$scope.csvimported = true;
}
$scope.clear = function () {
$scope.csv.result = null;
};
}
]);
angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda']) angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda'])
.config(function(slidesProvider) { .config([
slidesProvider.registerSlide('agenda/item', { 'slidesProvider',
template: 'static/templates/agenda/slide-item-detail.html', function(slidesProvider) {
}); slidesProvider.registerSlide('agenda/item', {
slidesProvider.registerSlide('agenda/item-list', { template: 'static/templates/agenda/slide-item-detail.html',
template: 'static/templates/agenda/slide-item-list.html', });
}); slidesProvider.registerSlide('agenda/item-list', {
}) template: 'static/templates/agenda/slide-item-list.html',
});
}
])
.controller('SlideItemDetailCtrl', [ .controller('SlideItemDetailCtrl', [
'$scope', '$scope',
@ -401,18 +483,21 @@ angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda'])
} }
]) ])
.controller('SlideItemListCtrl', function($scope, $http, Agenda) { .controller('SlideItemListCtrl', [
// Attention! Each object that is used here has to be dealt on server side. '$scope',
// Add it to the coresponding get_requirements method of the ProjectorElement '$http',
// class. 'Agenda',
Agenda.findAll(); 'AgendaTree',
Agenda.bindAll({}, $scope, 'items'); function($scope, $http, Agenda, AgendaTree) {
$scope.ids = []; // Attention! Each object that is used here has to be dealt on server side.
var tree = $http.get('/rest/agenda/item/tree/').success(function(data) { // Add it to the coresponding get_requirements method of the ProjectorElement
var ids = []; // class.
angular.forEach(data,function(element) {
ids.push(element.id) // Bind agenda tree to the scope
$scope.$watch(function () {
return Agenda.lastModified();
}, function () {
$scope.items = AgendaTree.getFlatTree(Agenda.getAll());
}); });
$scope.ids = ids; }
}) ]);
});

View File

@ -23,74 +23,93 @@
</a> </a>
</div> </div>
<div class="row form-group">
<div class="row">
<div class="col-sm-8"> <div class="col-sm-8">
<!-- project agenda --> <form class="form-inline">
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm" <!-- delete mode -->
ng-click="projectAgenda()" <div os-perms-lite="agenda.can_manage" class="form-group">
ng-class="{ 'btn-primary': isAgendaProjected() }"> <label for="deleteSwitcher" translate>Delete mode</label>
<i class="fa fa-video-camera"></i> <switch id="deleteSwitcher" ng-model="isDeleteMode" ng-change="uncheckAll()"
<translate>Project agenda</translate> on="{{'On'|translate}}" off="{{'Off'|translate}}"
</a> class="green wide form-control">
</switch>
</div>
<div class="form-group">
<!-- project agenda button -->
<a ng-show="!isDeleteMode" os-perms="core.can_manage_projector"
class="btn btn-default btn-sm form-control"
ng-click="projectAgenda()"
ng-class="{ 'btn-primary': isAgendaProjected() }">
<i class="fa fa-video-camera"></i>
<translate>Project agenda</translate>
</a>
<!-- delete button -->
<a ng-show="isDeleteMode && (items|filter:{selected:true}).length > 0"
os-perms="agenda.can_manage" ng-click="delete()"
class="btn btn-primary btn-sm form-control">
<i class="fa fa-trash fa-lg"></i>
<translate>Delete selected items</translate>
</a>
</div>
</form>
</div> </div>
<div class="col-sm-4"> <div class="col-sm-4">
<input type="text" os-focus-me ng-model="filter.search" class="form-control" <div class="input-group">
placeholder="{{ 'Filter' | translate}}"> <div class="input-group-addon"><i class="fa fa-filter"></i></div>
<input type="text" os-focus-me ng-model="filter.search" class="form-control"
placeholder="{{ 'Filter' | translate}}">
</div>
</div> </div>
</div> </div>
<i>{{ items.length }} {{ "items" | translate }}</i> <i>
{{ items.length }} {{ "items" | translate }}<span ng-if="(items|filter:{selected:true}).length > 0">,
{{(items|filter:{selected:true}).length}} {{ "selected" | translate }}</span>
</i>
<table class="table table-striped table-bordered table-hover"> <table class="table table-striped table-bordered table-hover">
<thead> <thead>
<tr> <tr>
<th class="minimum"> <!-- projector column -->
<translate>Closed</translate> <th ng-show="!isDeleteMode" os-perms="core.can_manage_projector" class="firstColumn">
<!-- delete selection column -->
<th ng-show="isDeleteMode" os-perms-lite="agenda.can_manage" class="firstColumn deleteColumn"
ng-click="$event.stopPropagation();">
<input type="checkbox" ng-model="selectedAll" ng-change="checkAll()">
<!-- agenda item column -->
<th> <th>
<translate>Agenda item</translate> <translate>Agenda item</translate>
<th os-perms="agenda.can_manage"> <th os-perms="agenda.can_manage">
<translate>Duration</translate> <translate>Duration</translate>
<th os-perms="agenda.can_manage core.can_manage_projector" class="minimum"> <th class="minimum">
<translate>Actions</translate> <translate>Done</translate>
<tbody> <tbody>
<tr ng-repeat="item in items" <tr ng-repeat="item in items | filter: filter.search"
ng-class="{ 'activeline': item.isProjected() }"> ng-click="openDetail(item.id)"
<td> ng-class="{ 'activeline': item.isProjected() }"
<!-- Please do not use ng-click, but ng-change --> class="pointer">
<input type="checkbox" ng-model="item.closed" ng-click="save(item.id)"> <!-- projector column -->
<td ng-show="!isDeleteMode" os-perms="core.can_manage_projector">
<a class="btn btn-default btn-sm"
ng-class="{ 'btn-primary': item.isProjected() }"
ng-click="item.project(); $event.stopPropagation();"
title="{{ 'Project item' | translate }}">
<i class="fa fa-video-camera"></i>
</a>
<!-- delete selection column -->
<td ng-show="isDeleteMode" os-perms="agenda.can_manage" class="deleteColumn"
ng-click="$event.stopPropagation();">
<input type="checkbox" ng-model="item.selected">
<!-- agenda item column -->
<td> <td>
<span ng-repeat="n in [].constructor(item.parentCount) track by $index">&ndash;</span> <span ng-repeat="n in [].constructor(item.parentCount) track by $index">&ndash;</span>
<a ui-sref="agenda.item.detail({id: item.id})"> {{ item.item_number }} {{ item.title }}
{{ item.item_number }}
{{ item.title }}
</a>
<div ng-if="item.comment"> <div ng-if="item.comment">
<small><i class="fa fa-info-circle"></i> {{ item.comment }}</small> <small><i class="fa fa-info-circle"></i> {{ item.comment }}</small>
</div> </div>
<td os-perms="agenda.can_manage" class="optional"> <td os-perms="agenda.can_manage" class="optional">
<a href="#" editable-number="item.duration" e-min="1" onaftersave="save(item.id)"> {{ item.duration }}
{{ item.duration }} <span ng-if="item.duration" translate>h</span>
</a> <td ng-click="$event.stopPropagation();">
<span ng-if="item.duration" translate>min</span> <input type="checkbox" ng-model="item.closed" ng-change="save(item.id);">
<td os-perms="agenda.can_manage core.can_manage_projector" class="nobr">
<!-- project -->
<a os-perms="core.can_manage_projector" class="btn btn-default btn-sm"
ng-class="{ 'btn-primary': item.isProjected() }"
ng-click="item.project()"
title="{{ 'Project item' | translate }}">
<i class="fa fa-video-camera"></i>
</a>
<!-- edit -->
<a ui-sref="agenda.item.detail.update({id: item.id })" os-perms="agenda.can_manage"
class="btn btn-default btn-sm"
title="{{ 'Edit' | translate }}">
<i class="fa fa-pencil"></i>
</a>
<!-- delete -->
<a os-perms="agenda.can_manage" class="btn btn-danger btn-sm"
ng-bootbox-confirm="Are you sure you want to delete
<b>{{ item.title }}</b>?"
ng-bootbox-confirm-action="delete(item.id)"
title="{{ 'Delete' | translate }}">
<i class="fa fa-trash-o"></i>
</a>
</table> </table>

View File

@ -2,10 +2,10 @@
<h1 translate>Agenda</h1> <h1 translate>Agenda</h1>
<table class="tablelist"> <table class="tablelist">
<tr ng-repeat="id in ids"> <tr ng-repeat="item in items">
<td class="leftcolumn nobr" ng-class="{ 'closed': (items | filter: {id: id})[0].closed }"> <td class="leftcolumn nobr" ng-class="{ 'closed': item.closed }">
{{ (items | filter: {id: id})[0].item_number }} {{ item.item_number }}
<td class="rightcolumn" ng-class="{ 'closed': (items | filter: {id: id})[0].closed }"> <td class="rightcolumn" ng-class="{ 'closed': item.closed }">
{{ (items | filter: {id: id})[0].title }} {{ item.title }}
</table> </table>
</div> </div>

View File

@ -184,7 +184,7 @@ a:hover {
} }
/* List tables */ /* List tables */
th.sortable:hover { th.sortable:hover, tr.pointer:hover {
cursor: pointer; cursor: pointer;
} }
@ -246,7 +246,7 @@ tr.offline td, li.offline {
background-color: #EAEAEA !important; background-color: #EAEAEA !important;
} }
tr.activeline td, li.activeline { tr.activeline td, li.activeline {
background-color: #bed4de !important; background-color: #bed4de;
} }
.nopadding { .nopadding {
padding: 0; padding: 0;
@ -266,6 +266,19 @@ tr.total td {
.indentation { .indentation {
margin-left: 12px; margin-left: 12px;
} }
.firstColumn {
width: 55px;
}
.deleteColumn {
text-align: center;
background-color: #ff9999 !important;
}
.switch.checked {
background-color: #ff9999 !important;
border-color: #ff9999;
}
.minimum, .mini_width { .minimum, .mini_width {
width: 1px; width: 1px;
} }

View File

@ -8,6 +8,7 @@ angular.module('OpenSlidesApp.core', [
'ngAnimate', 'ngAnimate',
'ui.bootstrap', 'ui.bootstrap',
'ui.tree', 'ui.tree',
'uiSwitch',
]) ])
.config(['DSProvider', 'DSHttpAdapterProvider', function(DSProvider, DSHttpAdapterProvider) { .config(['DSProvider', 'DSHttpAdapterProvider', function(DSProvider, DSHttpAdapterProvider) {