723 lines
28 KiB
JavaScript
723 lines
28 KiB
JavaScript
(function () {
|
|
|
|
'use strict';
|
|
|
|
angular.module('OpenSlidesApp.agenda.site', [
|
|
'OpenSlidesApp.agenda',
|
|
'OpenSlidesApp.core.pdf',
|
|
'OpenSlidesApp.agenda.pdf',
|
|
'OpenSlidesApp.agenda.csv',
|
|
])
|
|
|
|
.config([
|
|
'mainMenuProvider',
|
|
'gettext',
|
|
function (mainMenuProvider, gettext) {
|
|
mainMenuProvider.register({
|
|
'ui_sref': 'agenda.item.list',
|
|
'img_class': 'calendar-o',
|
|
'title': gettext('Agenda'),
|
|
'weight': 200,
|
|
'perm': 'agenda.can_see',
|
|
});
|
|
}
|
|
])
|
|
|
|
.config([
|
|
'SearchProvider',
|
|
'gettext',
|
|
function (SearchProvider, gettext) {
|
|
SearchProvider.register({
|
|
'verboseName': gettext('Agenda'),
|
|
'collectionName': 'agenda/item',
|
|
'urlDetailState': 'agenda.item.detail',
|
|
'weight': 200,
|
|
});
|
|
}
|
|
])
|
|
|
|
.config([
|
|
'$stateProvider',
|
|
'gettext',
|
|
function($stateProvider, gettext) {
|
|
$stateProvider
|
|
.state('agenda', {
|
|
url: '/agenda',
|
|
abstract: true,
|
|
template: "<ui-view/>",
|
|
data: {
|
|
title: gettext('Agenda'),
|
|
basePerm: 'agenda.can_see',
|
|
},
|
|
})
|
|
.state('agenda.item', {
|
|
abstract: true,
|
|
template: "<ui-view/>",
|
|
})
|
|
.state('agenda.item.list', {})
|
|
.state('agenda.item.detail', {
|
|
resolve: {
|
|
itemId: ['$stateParams', function($stateParams) {
|
|
return $stateParams.id;
|
|
}],
|
|
}
|
|
})
|
|
.state('agenda.item.sort', {
|
|
url: '/sort',
|
|
controller: 'AgendaSortCtrl',
|
|
})
|
|
.state('agenda.current-list-of-speakers', {
|
|
url: '/speakers',
|
|
controller: 'CurrentListOfSpeakersViewCtrl',
|
|
data: {
|
|
title: gettext('Current list of speakers'),
|
|
},
|
|
});
|
|
}
|
|
])
|
|
|
|
.controller('ItemListCtrl', [
|
|
'$scope',
|
|
'$filter',
|
|
'$http',
|
|
'$state',
|
|
'DS',
|
|
'operator',
|
|
'ngDialog',
|
|
'Agenda',
|
|
'TopicForm', // TODO: Remove this dependency. Use template hook for "New" and "Import" buttons.
|
|
'AgendaTree',
|
|
'Projector',
|
|
'ProjectionDefault',
|
|
'AgendaContentProvider',
|
|
'PdfMakeDocumentProvider',
|
|
'gettextCatalog',
|
|
'gettext',
|
|
'osTableFilter',
|
|
'AgendaCsvExport',
|
|
'PdfCreate',
|
|
'ErrorMessage',
|
|
function($scope, $filter, $http, $state, DS, operator, ngDialog, Agenda, TopicForm,
|
|
AgendaTree, Projector, ProjectionDefault, AgendaContentProvider, PdfMakeDocumentProvider,
|
|
gettextCatalog, gettext, osTableFilter, AgendaCsvExport, PdfCreate, ErrorMessage) {
|
|
// Bind agenda tree to the scope
|
|
$scope.$watch(function () {
|
|
return Agenda.lastModified();
|
|
}, function () {
|
|
// Filter out items that doesn't have the list_item_title. This happens, if the
|
|
// item is a hidden item but provides the list of speakers, but should not be
|
|
// visible in the list view.
|
|
var allowedItems = _.filter(Agenda.getAll(), function (item) {
|
|
return item.list_view_title;
|
|
});
|
|
$scope.items = AgendaTree.getFlatTree(allowedItems);
|
|
var subitems = $filter('filter')($scope.items, {'parent_id': ''});
|
|
if (subitems.length) {
|
|
$scope.agendaHasSubitems = true;
|
|
}
|
|
});
|
|
Projector.bindAll({}, $scope, 'projectors');
|
|
$scope.mainListTree = true;
|
|
$scope.$watch(function () {
|
|
return Projector.lastModified();
|
|
}, function () {
|
|
var projectiondefault = ProjectionDefault.filter({name: 'agenda_all_items'})[0];
|
|
if (projectiondefault) {
|
|
$scope.defaultProjectorId_all_items = projectiondefault.projector_id;
|
|
}
|
|
$scope.projectionDefaults = ProjectionDefault.getAll();
|
|
});
|
|
$scope.alert = {};
|
|
|
|
|
|
// Filtering
|
|
$scope.filter = osTableFilter.createInstance('AgendaTableFilter');
|
|
|
|
if (!$scope.filter.existsStorageEntry()) {
|
|
$scope.filter.booleanFilters = {
|
|
closed: {
|
|
value: undefined,
|
|
displayName: gettext('Closed items'),
|
|
choiceYes: gettext('Closed items'),
|
|
choiceNo: gettext('Open items'),
|
|
},
|
|
is_hidden: {
|
|
value: undefined,
|
|
displayName: gettext('Internal items'),
|
|
choiceYes: gettext('Internal items'),
|
|
choiceNo: gettext('No internal items'),
|
|
permission: 'agenda.can_see_hidden_items',
|
|
},
|
|
};
|
|
}
|
|
$scope.filter.propertyList = ['item_number', 'title', 'title_list_view', 'comment', 'duration'];
|
|
$scope.filter.propertyFunctionList = [
|
|
function (item) {return item.getListViewTitle();},
|
|
];
|
|
$scope.filter.propertyDict = {
|
|
'speakers' : function (speaker) {
|
|
return '';
|
|
},
|
|
};
|
|
|
|
// pagination
|
|
$scope.currentPage = 1;
|
|
$scope.itemsPerPage = 25;
|
|
$scope.limitBegin = 0;
|
|
$scope.pageChanged = function() {
|
|
$scope.limitBegin = ($scope.currentPage - 1) * $scope.itemsPerPage;
|
|
};
|
|
|
|
// parse duration for inline editing
|
|
$scope.generateDurationText = function (item) {
|
|
//convert data from model format (m) to view format (hh:mm)
|
|
if (item.duration) {
|
|
var time = "",
|
|
totalminutes = item.duration;
|
|
if (totalminutes < 0) {
|
|
time = "-";
|
|
totalminutes = -totalminutes;
|
|
}
|
|
var hh = Math.floor(totalminutes / 60);
|
|
var mm = Math.floor(totalminutes % 60);
|
|
// Add leading "0" for double digit values
|
|
mm = ("0"+mm).slice(-2);
|
|
time += hh + ":" + mm;
|
|
item.durationText = time;
|
|
} else {
|
|
item.durationText = "";
|
|
}
|
|
};
|
|
$scope.setDurationText = function (item) {
|
|
//convert data from view format (hh:mm) to model format (m)
|
|
var time = item.durationText.replace('h', '').split(':');
|
|
var data;
|
|
if (time.length > 1 && !isNaN(time[0]) && !isNaN(time[1])) {
|
|
data = (+time[0]) * 60 + (+time[1]);
|
|
if (data < 0) {
|
|
data = "-"+data;
|
|
}
|
|
item.duration = parseInt(data);
|
|
} else if (time.length == 1 && !isNaN(time[0])) {
|
|
data = (+time[0]);
|
|
item.duration = parseInt(data);
|
|
} else {
|
|
item.duration = 0;
|
|
}
|
|
$scope.save(item);
|
|
};
|
|
|
|
/** Duration calculations **/
|
|
$scope.sumDurations = function () {
|
|
var totalDuration = 0;
|
|
$scope.items.forEach(function (item) {
|
|
if (item.duration) {
|
|
totalDuration += item.duration;
|
|
}
|
|
});
|
|
return totalDuration;
|
|
};
|
|
$scope.calculateEndTime = function () {
|
|
var totalDuration = $scope.sumDurations();
|
|
var startTimestamp = $scope.config('agenda_start_event_date_time');
|
|
if (startTimestamp) {
|
|
var endTimestamp = startTimestamp + totalDuration * 60 * 1000;
|
|
var endDate = new Date(endTimestamp);
|
|
var mm = ("0" + endDate.getMinutes()).slice(-2);
|
|
var dateStr = endDate.getHours() + ':' + mm;
|
|
return dateStr;
|
|
} else {
|
|
return '';
|
|
}
|
|
};
|
|
|
|
/** Agenda item functions **/
|
|
// open dialog for new topics // TODO Remove this. Don't forget import button in template.
|
|
$scope.newDialog = function () {
|
|
ngDialog.open(TopicForm.getDialog());
|
|
};
|
|
// save changed item
|
|
$scope.save = function (item) {
|
|
Agenda.save(item).then(
|
|
function (success) {
|
|
$scope.alert.show = false;
|
|
},
|
|
function (error) {
|
|
$scope.alert = ErrorMessage.forAlert(error);
|
|
});
|
|
};
|
|
// delete related item
|
|
$scope.deleteRelatedItem = function (item) {
|
|
DS.destroy(item.content_object.collection, item.content_object.id);
|
|
};
|
|
// auto numbering of agenda items
|
|
$scope.autoNumbering = function() {
|
|
$http.post('/rest/agenda/item/numbering/', {});
|
|
};
|
|
// check open permission
|
|
// TODO: Use generic solution here.
|
|
$scope.isAllowedToSeeOpenLink = function (item) {
|
|
var collection = item.content_object.collection;
|
|
switch (collection) {
|
|
case 'topics/topic':
|
|
return operator.hasPerms('agenda.can_see');
|
|
case 'motions/motion':
|
|
return operator.hasPerms('motions.can_see');
|
|
case 'motions/motion-block':
|
|
return operator.hasPerms('motions.can_see');
|
|
case 'assignments/assignment':
|
|
return operator.hasPerms('assignments.can_see');
|
|
default:
|
|
return false;
|
|
}
|
|
};
|
|
$scope.edit = function (item) {
|
|
ngDialog.open(item.getContentObjectForm().getDialog({id: item.content_object.id}));
|
|
};
|
|
// export
|
|
$scope.pdfExport = function () {
|
|
var filename = gettextCatalog.getString('Agenda') + '.pdf';
|
|
var agendaContentProvider = AgendaContentProvider.createInstance($scope.itemsFiltered);
|
|
var documentProvider = PdfMakeDocumentProvider.createInstance(agendaContentProvider);
|
|
PdfCreate.download(documentProvider.getDocument(), filename);
|
|
};
|
|
$scope.csvExport = function () {
|
|
AgendaCsvExport.export($scope.itemsFiltered);
|
|
};
|
|
|
|
/** select mode functions **/
|
|
$scope.isSelectMode = false;
|
|
// check all checkboxes
|
|
$scope.checkAll = function () {
|
|
$scope.selectedAll = !$scope.selectedAll;
|
|
angular.forEach($scope.items, function (item) {
|
|
item.selected = $scope.selectedAll;
|
|
});
|
|
};
|
|
// uncheck all checkboxes if isDeleteMode is closed
|
|
$scope.uncheckAll = function () {
|
|
if (!$scope.isSelectMode) {
|
|
$scope.selectedAll = false;
|
|
angular.forEach($scope.items, function (item) {
|
|
item.selected = false;
|
|
});
|
|
}
|
|
};
|
|
// delete selected items
|
|
$scope.deleteMultiple = function () {
|
|
angular.forEach($scope.items, function (item) {
|
|
if (item.selected) {
|
|
DS.destroy(item.content_object.collection, item.content_object.id);
|
|
}
|
|
});
|
|
$scope.isSelectMode = false;
|
|
$scope.uncheckAll();
|
|
};
|
|
|
|
/** Project functions **/
|
|
// get ProjectionDefault for item
|
|
$scope.getProjectionDefault = function (item) {
|
|
if (item.tree) {
|
|
return $scope.defaultProjectorId_all_items;
|
|
} else {
|
|
var app_name = item.content_object.collection.split('/')[0];
|
|
var id = 1;
|
|
$scope.projectionDefaults.forEach(function (projectionDefault) {
|
|
if (projectionDefault.name == app_name) {
|
|
id = projectionDefault.projector_id;
|
|
}
|
|
});
|
|
return id;
|
|
}
|
|
};
|
|
// project agenda
|
|
$scope.projectAgenda = function (projectorId, tree, id) {
|
|
var isAgendaProjectedIds = $scope.isAgendaProjected($scope.mainListTree);
|
|
_.forEach(isAgendaProjectedIds, function (id) {
|
|
$http.post('/rest/core/projector/' + id + '/clear_elements/');
|
|
});
|
|
if (_.indexOf(isAgendaProjectedIds, projectorId) == -1) {
|
|
$http.post('/rest/core/projector/' + projectorId + '/prune_elements/',
|
|
[{name: 'agenda/item-list', tree: tree, id: id}]);
|
|
}
|
|
};
|
|
// change whether all items or only main items should be projected
|
|
$scope.changeMainListTree = function () {
|
|
var isAgendaProjectedId = $scope.isAgendaProjected($scope.mainListTree);
|
|
$scope.mainListTree = !$scope.mainListTree;
|
|
if (isAgendaProjectedId > 0) {
|
|
$scope.projectAgenda(isAgendaProjectedId, $scope.mainListTree);
|
|
}
|
|
};
|
|
// change whether one item or all subitems should be projected
|
|
$scope.changeItemTree = function (item) {
|
|
var isProjected = item.isProjected(item.tree);
|
|
if (isProjected > 0) {
|
|
// Deactivate and reactivate
|
|
item.project(isProjected, item.tree);
|
|
item.project(isProjected, !item.tree);
|
|
}
|
|
item.tree = !item.tree;
|
|
};
|
|
// check if agenda is projected
|
|
$scope.isAgendaProjected = function (tree) {
|
|
// Returns the ids of all projectors with an element with
|
|
// the name 'agenda/item-list'. Else returns an empty list.
|
|
var predicate = function (element) {
|
|
var value;
|
|
if (tree) {
|
|
// tree with all agenda items
|
|
value = element.name == 'agenda/item-list' &&
|
|
typeof element.id === 'undefined' &&
|
|
element.tree;
|
|
} else {
|
|
// only main agenda items
|
|
value = element.name == 'agenda/item-list' &&
|
|
typeof element.id === 'undefined' &&
|
|
!element.tree;
|
|
}
|
|
return value;
|
|
};
|
|
var projectorIds = [];
|
|
$scope.projectors.forEach(function (projector) {
|
|
if (typeof _.findKey(projector.elements, predicate) === 'string') {
|
|
projectorIds.push(projector.id);
|
|
}
|
|
});
|
|
return projectorIds;
|
|
};
|
|
}
|
|
])
|
|
|
|
.controller('ItemDetailCtrl', [
|
|
'$scope',
|
|
'$filter',
|
|
'Agenda',
|
|
'itemId',
|
|
'Projector',
|
|
'ProjectionDefault',
|
|
'ErrorMessage',
|
|
function ($scope, $filter, Agenda, itemId, Projector, ProjectionDefault, ErrorMessage) {
|
|
$scope.alert = {};
|
|
|
|
$scope.$watch(function () {
|
|
return Agenda.lastModified(itemId);
|
|
}, function () {
|
|
$scope.item = Agenda.get(itemId);
|
|
// all speakers
|
|
$scope.speakers = $filter('orderBy')($scope.item.speakers, 'weight');
|
|
// next speakers
|
|
$scope.nextSpeakers = $filter('filter')($scope.speakers, {'begin_time': null});
|
|
// current speaker
|
|
$scope.currentSpeaker = $filter('filter')($scope.speakers, {'begin_time': '!!', 'end_time': null});
|
|
// last speakers
|
|
$scope.lastSpeakers = $filter('filter')($scope.speakers, {'end_time': '!!'});
|
|
$scope.lastSpeakers = $filter('orderBy')($scope.lastSpeakers, 'begin_time');
|
|
});
|
|
$scope.$watch(function () {
|
|
return Projector.lastModified();
|
|
}, function () {
|
|
var item_app_name = $scope.item.content_object.collection.split('/')[0];
|
|
var projectiondefaultItem = ProjectionDefault.filter({name: item_app_name})[0];
|
|
if (projectiondefaultItem) {
|
|
$scope.defaultProjectorItemId = projectiondefaultItem.projector_id;
|
|
}
|
|
var projectiondefaultListOfSpeakers = ProjectionDefault.filter({name: 'agenda_list_of_speakers'})[0];
|
|
if (projectiondefaultListOfSpeakers) {
|
|
$scope.defaultProjectorListOfSpeakersId = projectiondefaultListOfSpeakers.projector_id;
|
|
}
|
|
});
|
|
}
|
|
])
|
|
|
|
/* This is the controller for the list of speakers partial management template.
|
|
* The parent controller needs to provide a $scope.item, $scope.speakers, $scope.nextSpeakers,
|
|
* $scope.currentSpeakers, $scope.lastSpeakers. See (as example) ItemDetailCtrl. */
|
|
.controller('ListOfSpeakersManagementCtrl', [
|
|
'$scope',
|
|
'$http',
|
|
'$filter',
|
|
'Agenda',
|
|
'User',
|
|
'operator',
|
|
'ErrorMessage',
|
|
function ($scope, $http, $filter, Agenda, User, operator, ErrorMessage) {
|
|
User.bindAll({}, $scope, 'users');
|
|
$scope.speakerSelectBox = {};
|
|
|
|
// close/open list of speakers of current item
|
|
$scope.closeList = function (listClosed) {
|
|
$scope.item.speaker_list_closed = listClosed;
|
|
Agenda.save($scope.item);
|
|
};
|
|
|
|
// add user to list of speakers
|
|
$scope.addSpeaker = function (userId) {
|
|
$http.post('/rest/agenda/item/' + $scope.item.id + '/manage_speaker/', {'user': userId}).then(
|
|
function (success) {
|
|
$scope.alert.show = false;
|
|
$scope.speakers = $scope.item.speakers;
|
|
$scope.speakerSelectBox = {};
|
|
}, function (error) {
|
|
$scope.alert = ErrorMessage.forAlert(error);
|
|
$scope.speakerSelectBox = {};
|
|
}
|
|
);
|
|
};
|
|
|
|
// delete speaker(!) from list of speakers
|
|
$scope.removeSpeaker = function (speakerId) {
|
|
$http.delete(
|
|
'/rest/agenda/item/' + $scope.item.id + '/manage_speaker/',
|
|
{headers: {'Content-Type': 'application/json'},
|
|
data: JSON.stringify({speaker: speakerId})}
|
|
)
|
|
.then(function (success) {
|
|
$scope.speakers = $scope.item.speakers;
|
|
}, function (error) {
|
|
$scope.alert = ErrorMessage.forAlert(error);
|
|
});
|
|
$scope.speakers = $scope.item.speakers;
|
|
};
|
|
|
|
//delete all speakers from list of speakers
|
|
$scope.removeAllSpeakers = function () {
|
|
var speakersOnList = [];
|
|
angular.forEach($scope.item.speakers, function (speaker) {
|
|
speakersOnList.push(speaker.id);
|
|
});
|
|
$http.delete(
|
|
'/rest/agenda/item/' + $scope.item.id + '/manage_speaker/',
|
|
{headers: {'Content-Type': 'application/json'},
|
|
data: JSON.stringify({speaker: speakersOnList})}
|
|
)
|
|
.then(function (success) {
|
|
$scope.speakers = $scope.item.speakers;
|
|
}, function (error) {
|
|
$scope.alert = ErrorMessage.forAlert(error);
|
|
});
|
|
$scope.speakers = $scope.item.speakers;
|
|
};
|
|
|
|
// Return true if the requested user is allowed to do a specific action
|
|
// and see the corresponding button (e.g. 'add me' or 'remove me').
|
|
$scope.isAllowed = function (action) {
|
|
var nextUsers = [];
|
|
angular.forEach($scope.nextSpeakers, function (speaker) {
|
|
nextUsers.push(speaker.user_id);
|
|
});
|
|
switch (action) {
|
|
case 'add':
|
|
return (operator.hasPerms('agenda.can_be_speaker') &&
|
|
!$scope.item.speaker_list_closed &&
|
|
$.inArray(operator.user.id, nextUsers) == -1);
|
|
case 'remove':
|
|
if (operator.user) {
|
|
return ($.inArray(operator.user.id, nextUsers) != -1);
|
|
}
|
|
return false;
|
|
case 'removeAll':
|
|
return (operator.hasPerms('agenda.can_manage') &&
|
|
$scope.speakers.length > 0);
|
|
case 'beginNextSpeech':
|
|
return (operator.hasPerms('agenda.can_manage') &&
|
|
$scope.nextSpeakers.length > 0);
|
|
case 'endCurrentSpeech':
|
|
return (operator.hasPerms('agenda.can_manage') &&
|
|
$scope.currentSpeaker.length > 0);
|
|
case 'showLastSpeakers':
|
|
return $scope.lastSpeakers.length > 0;
|
|
}
|
|
};
|
|
|
|
// begin speech of selected/next speaker
|
|
$scope.beginSpeech = function (speakerId) {
|
|
$http.put('/rest/agenda/item/' + $scope.item.id + '/speak/', {'speaker': speakerId})
|
|
.then(function (success) {
|
|
$scope.alert.show = false;
|
|
}, function (error) {
|
|
$scope.alert = ErrorMessage.forAlert(error);
|
|
});
|
|
};
|
|
|
|
// end speech of current speaker
|
|
$scope.endSpeech = function () {
|
|
$http.delete(
|
|
'/rest/agenda/item/' + $scope.item.id + '/speak/',
|
|
{headers: {'Content-Type': 'application/json'}, data: {}}
|
|
).then(
|
|
function (success) {},
|
|
function (error) {
|
|
$scope.alert = ErrorMessage.forAlert(error);
|
|
}
|
|
);
|
|
};
|
|
// gets speech duration of selected speaker in seconds
|
|
$scope.getDuration = function (speaker) {
|
|
var beginTimestamp = new Date(speaker.begin_time).getTime();
|
|
var endTimestamp = new Date(speaker.end_time).getTime();
|
|
// calculate duration in seconds
|
|
return Math.floor((endTimestamp - beginTimestamp) / 1000);
|
|
|
|
};
|
|
// save reordered list of speakers
|
|
$scope.treeOptions = {
|
|
dropped: function (event) {
|
|
var sortedSpeakers = [];
|
|
var nextSpeakers = $filter('filter')($scope.speakers, {'begin_time': null});
|
|
angular.forEach(nextSpeakers, function (speaker) {
|
|
sortedSpeakers.push(speaker.id);
|
|
});
|
|
$http.post('/rest/agenda/item/' + $scope.item.id + '/sort_speakers/',
|
|
{speakers: sortedSpeakers}
|
|
);
|
|
}
|
|
};
|
|
}
|
|
])
|
|
|
|
.controller('AgendaSortCtrl', [
|
|
'$scope',
|
|
'$http',
|
|
'Agenda',
|
|
'AgendaTree',
|
|
'ErrorMessage',
|
|
function($scope, $http, Agenda, AgendaTree, ErrorMessage) {
|
|
// Bind agenda tree to the scope
|
|
$scope.$watch(function () {
|
|
return Agenda.lastModified();
|
|
}, function () {
|
|
$scope.items = AgendaTree.getTree(Agenda.getAll());
|
|
});
|
|
$scope.showInternalItems = true;
|
|
$scope.alert = {};
|
|
|
|
// save parent and weight of moved agenda item (and all items on same level)
|
|
$scope.treeOptions = {
|
|
dropped: function(event) {
|
|
var parentID = null;
|
|
var droppedItemID = event.source.nodeScope.$modelValue.id;
|
|
if (event.dest.nodesScope.item) {
|
|
parentID = event.dest.nodesScope.item.id;
|
|
}
|
|
$http.post('/rest/agenda/item/sort/', {
|
|
nodes: event.dest.nodesScope.$modelValue,
|
|
parent_id: parentID}
|
|
).then(
|
|
function(success) {},
|
|
function(error){
|
|
$scope.alert = ErrorMessage.forAlert(error);
|
|
}
|
|
);
|
|
}
|
|
};
|
|
}
|
|
])
|
|
|
|
.controller('CurrentListOfSpeakersViewCtrl', [
|
|
'$scope',
|
|
'$http',
|
|
'$filter',
|
|
'Projector',
|
|
'ProjectionDefault',
|
|
'Agenda',
|
|
'Config',
|
|
'CurrentListOfSpeakersItem',
|
|
'CurrentListOfSpeakersSlide',
|
|
function($scope, $http, $filter, Projector, ProjectionDefault, Agenda, Config,
|
|
CurrentListOfSpeakersItem, CurrentListOfSpeakersSlide) {
|
|
$scope.alert = {};
|
|
$scope.currentListOfSpeakers = CurrentListOfSpeakersSlide;
|
|
|
|
// Watch for changes in the current list of speakers reference
|
|
$scope.$watch(function () {
|
|
return Config.lastModified('projector_currentListOfSpeakers_reference');
|
|
}, function () {
|
|
$scope.currentListOfSpeakersReference = $scope.config('projector_currentListOfSpeakers_reference');
|
|
$scope.updateCurrentListOfSpeakersItem();
|
|
});
|
|
$scope.$watch(function () {
|
|
return Projector.lastModified();
|
|
}, function() {
|
|
$scope.projectors = Projector.getAll();
|
|
// If there is just one projector we provide just the overlay.
|
|
if ($scope.projectors.length === 1) {
|
|
$scope.currentListOfSpeakersAsOverlay = true;
|
|
}
|
|
$scope.updateCurrentListOfSpeakersItem();
|
|
|
|
$scope.listOfSpeakersDefaultProjectorId = ProjectionDefault.filter({name: 'agenda_current_list_of_speakers'})[0].projector_id;
|
|
});
|
|
|
|
$scope.$watch(function () {
|
|
return $scope.item ? Agenda.lastModified($scope.item.id) : void 0;
|
|
}, function () {
|
|
$scope.updateCurrentListOfSpeakersItem();
|
|
});
|
|
|
|
$scope.updateCurrentListOfSpeakersItem = function () {
|
|
$scope.item = CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference);
|
|
if ($scope.item) {
|
|
// all speakers
|
|
$scope.speakers = $filter('orderBy')($scope.item.speakers, 'weight');
|
|
// next speakers
|
|
$scope.nextSpeakers = $filter('filter')($scope.speakers, {'begin_time': null});
|
|
// current speaker
|
|
$scope.currentSpeaker = $filter('filter')($scope.speakers, {'begin_time': '!!', 'end_time': null});
|
|
// last speakers
|
|
$scope.lastSpeakers = $filter('filter')($scope.speakers, {'end_time': '!!'});
|
|
$scope.lastSpeakers = $filter('orderBy')($scope.lastSpeakers, 'begin_time');
|
|
} else {
|
|
$scope.speakers = void 0;
|
|
$scope.nextSpeakers = void 0;
|
|
$scope.currentSpeaker = void 0;
|
|
$scope.lastSpeakers = void 0;
|
|
}
|
|
};
|
|
|
|
// Set the current overlay status
|
|
if ($scope.currentListOfSpeakers.isProjected().length) {
|
|
var isProjected = $scope.currentListOfSpeakers.isProjectedWithOverlayStatus();
|
|
$scope.currentListOfSpeakersAsOverlay = isProjected[0].overlay;
|
|
} else {
|
|
$scope.currentListOfSpeakersAsOverlay = true;
|
|
}
|
|
$scope.setOverlay = function (overlay) {
|
|
$scope.currentListOfSpeakersAsOverlay = overlay;
|
|
var isProjected = $scope.currentListOfSpeakers.isProjectedWithOverlayStatus();
|
|
if (isProjected.length) {
|
|
_.forEach(isProjected, function (mapping) {
|
|
if (mapping.overlay != overlay) { // change the overlay if it is different
|
|
$scope.currentListOfSpeakers.project(mapping.projectorId, overlay);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
}
|
|
])
|
|
|
|
//mark all agenda config strings for translation with Javascript
|
|
.config([
|
|
'gettext',
|
|
function (gettext) {
|
|
gettext('Numbering prefix for agenda items');
|
|
gettext('This prefix will be set if you run the automatic agenda numbering.');
|
|
gettext('Agenda');
|
|
gettext('Invalid input.');
|
|
gettext('Numeral system for agenda items');
|
|
gettext('Arabic');
|
|
gettext('Roman');
|
|
gettext('Begin of event');
|
|
gettext('Input format: DD.MM.YYYY HH:MM');
|
|
gettext('Number of last speakers to be shown on the projector');
|
|
gettext('List of speakers');
|
|
gettext('Show orange countdown in the last x seconds of speaking time');
|
|
gettext('Enter duration in seconds. Choose 0 to disable warning color.');
|
|
gettext('Couple countdown with the list of speakers');
|
|
gettext('[Begin speech] starts the countdown, [End speech] stops the ' +
|
|
'countdown.');
|
|
}
|
|
]);
|
|
|
|
}());
|