Merge pull request #1619 from emanuelschuetze/agenda-template
Agenda item list: new multiselect delete mode
This commit is contained in:
commit
d79bad80f6
@ -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",
|
||||||
|
@ -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;
|
}
|
||||||
})
|
]);
|
||||||
});
|
|
||||||
|
@ -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">–</span>
|
<span ng-repeat="n in [].constructor(item.parentCount) track by $index">–</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>
|
||||||
|
@ -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>
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user