Reorganize the current list of speakers. Fixes #2669 and find()-calls.
This commit is contained in:
parent
45c3da22f9
commit
3c36cd5757
@ -12,6 +12,8 @@ Agenda:
|
||||
- Added button to remove all speakers from a list of speakers.
|
||||
- Added option to create or edit agenda items as subitems of others.
|
||||
- Fixed security issue: Comments were shown for unprivileged users.
|
||||
- Added option to choose whether to show the current list of speakers slide
|
||||
as a slide or an overlay.
|
||||
|
||||
Core:
|
||||
- Added support for multiple projectors.
|
||||
|
@ -73,13 +73,19 @@ class ListOfSpeakersSlide(ProjectorElement):
|
||||
return {'agenda_item_id': self.config_entry.get('id')}
|
||||
|
||||
|
||||
class CurrentListOfSpeakersMetaClass(ProjectorElement):
|
||||
class CurrentListOfSpeakersSlide(ProjectorElement):
|
||||
"""
|
||||
Main class for the list of speaker slides.
|
||||
Slide for the current list of speakers.
|
||||
"""
|
||||
name = 'agenda/current-list-of-speakers'
|
||||
|
||||
"""
|
||||
def get_requirements(self, config_entry):
|
||||
items = self.get_agenda_items(config['projector_currentListOfSpeakers_reference'])
|
||||
# The query mechanism on client needs the referenced projector.
|
||||
reference_projector = Projector.objects.get(
|
||||
pk=config['projector_currentListOfSpeakers_reference'])
|
||||
yield reference_projector
|
||||
|
||||
items = self.get_agenda_items(reference_projector)
|
||||
for item in items:
|
||||
yield item
|
||||
for speaker in item.speakers.filter(end_time=None):
|
||||
@ -90,8 +96,7 @@ class CurrentListOfSpeakersMetaClass(ProjectorElement):
|
||||
# Yield last speakers
|
||||
yield speaker.user
|
||||
|
||||
def get_agenda_items(self, projector_id):
|
||||
projector = Projector.objects.get(pk=projector_id)
|
||||
def get_agenda_items(self, projector):
|
||||
for element in projector.elements.values():
|
||||
agenda_item_id = element.get('agenda_item_id')
|
||||
if agenda_item_id is not None:
|
||||
@ -99,26 +104,23 @@ class CurrentListOfSpeakersMetaClass(ProjectorElement):
|
||||
|
||||
def get_collection_elements_required_for_this(self, collection_element, config_entry):
|
||||
output = super().get_collection_elements_required_for_this(collection_element, config_entry)
|
||||
# Full update if agenda_item changes because then we may have new
|
||||
# candidates and therefor need new users.
|
||||
items = self.get_agenda_items(config['projector_currentListOfSpeakers_reference'])
|
||||
# Full update if agenda_item or referenced projector changes because
|
||||
# then we may have new candidates and therefor need new users.
|
||||
reference_projector = Projector.objects.get(
|
||||
pk=config['projector_currentListOfSpeakers_reference'])
|
||||
is_reference_projector = collection_element == CollectionElement.from_values(
|
||||
reference_projector.get_collection_string(),
|
||||
reference_projector.pk)
|
||||
is_config = (
|
||||
collection_element.collection_string == 'core/config' and
|
||||
collection_element.information.get('changed_config') == 'projector_currentListOfSpeakers_reference')
|
||||
|
||||
if is_reference_projector or is_config:
|
||||
output.extend(self.get_requirements_as_collection_elements(config_entry))
|
||||
else:
|
||||
items = self.get_agenda_items(reference_projector)
|
||||
for item in items:
|
||||
if collection_element == CollectionElement.from_values(item.get_collection_string(), item.pk):
|
||||
output.extend(self.get_requirements_as_collection_elements(config_entry))
|
||||
break
|
||||
return output
|
||||
|
||||
|
||||
class CurrentListOfSpeakersSlide(CurrentListOfSpeakersMetaClass):
|
||||
"""
|
||||
Slide for the current list of speakers.
|
||||
"""
|
||||
name = 'agenda/current-list-of-speakers'
|
||||
|
||||
|
||||
class CurrentListOfSpeakersOverlaySlide(CurrentListOfSpeakersMetaClass):
|
||||
"""
|
||||
List of speakers overlay.
|
||||
Subclass of ListOfSpeakers
|
||||
"""
|
||||
name = 'agenda/current-list-of-speakers-overlay'
|
||||
|
@ -289,101 +289,73 @@ angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users'])
|
||||
}
|
||||
])
|
||||
|
||||
// TODO: Remove all find() calls from the projector logic. It is also used on the site so this has to be
|
||||
// changed with the refactoring of the site autoupdate.
|
||||
.factory('CurrentListOfSpeakersItem', [
|
||||
'Projector',
|
||||
'Assignment', // TODO: Remove this after refactoring of data loading on start.
|
||||
'Topic', // TODO: Remove this after refactoring of data loading on start.
|
||||
'Motion', // TODO: Remove this after refactoring of data loading on start.
|
||||
'MotionBlock', // TODO: Remove this after refactoring of data loading on start.
|
||||
'Agenda',
|
||||
function (Projector, Assignment, Topic, Motion, MotionBlock, Agenda) {
|
||||
function (Projector, Agenda) {
|
||||
return {
|
||||
getItem: function (projectorId) {
|
||||
var elementPromise;
|
||||
return Projector.find(projectorId).then(function (projector) {
|
||||
// scan all elements
|
||||
var projector = Projector.get(projectorId), item;
|
||||
if (projector) {
|
||||
_.forEach(projector.elements, function(element) {
|
||||
switch(element.name) {
|
||||
case 'motions/motion':
|
||||
elementPromise = Motion.find(element.id).then(function(motion) {
|
||||
return Motion.loadRelations(motion, 'agenda_item').then(function() {
|
||||
return motion.agenda_item;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'motions/motion-block':
|
||||
elementPromise = MotionBlock.find(element.id).then(function(motionBlock) {
|
||||
return MotionBlock.loadRelations(motionBlock, 'agenda_item').then(function() {
|
||||
return motionBlock.agenda_item;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'topics/topic':
|
||||
elementPromise = Topic.find(element.id).then(function(topic) {
|
||||
return Topic.loadRelations(topic, 'agenda_item').then(function() {
|
||||
return topic.agenda_item;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'assignments/assignment':
|
||||
elementPromise = Assignment.find(element.id).then(function(assignment) {
|
||||
return Assignment.loadRelations(assignment, 'agenda_item').then(function() {
|
||||
return assignment.agenda_item;
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'agenda/list-of-speakers':
|
||||
elementPromise = Agenda.find(element.id).then(function(item) {
|
||||
return item;
|
||||
});
|
||||
if (element.agenda_item_id) {
|
||||
item = Agenda.get(element.agenda_item_id);
|
||||
}
|
||||
});
|
||||
return elementPromise;
|
||||
});
|
||||
}
|
||||
return item;
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
|
||||
.factory('ListOfSpeakersOverlay', [
|
||||
.factory('CurrentListOfSpeakersSlide', [
|
||||
'$http',
|
||||
'Projector',
|
||||
'gettextCatalog',
|
||||
'gettext',
|
||||
function($http, Projector, gettextCatalog, gettext) {
|
||||
var name = 'agenda/current-list-of-speakers-overlay';
|
||||
function($http, Projector) {
|
||||
var name = 'agenda/current-list-of-speakers';
|
||||
return {
|
||||
name: name,
|
||||
verboseName: gettext('List of speakers overlay'),
|
||||
project: function (projectorId, overlay) {
|
||||
var isProjectedId = this.isProjected(overlay);
|
||||
if (isProjectedId.length > 0) {
|
||||
// Deactivate
|
||||
var projector = Projector.get(isProjectedId[0]);
|
||||
var uuid;
|
||||
_.forEach(projector.elements, function (element) {
|
||||
if (element.name == 'agenda/current-list-of-speakers-overlay') {
|
||||
uuid = element.uuid;
|
||||
}
|
||||
var isProjected = this.isProjectedWithOverlayStatus();
|
||||
_.forEach(isProjected, function (mapping) {
|
||||
$http.post('/rest/core/projector/' + mapping.projectorId + '/deactivate_elements/',
|
||||
[mapping.uuid]
|
||||
);
|
||||
});
|
||||
$http.post('/rest/core/projector/' + isProjectedId + '/deactivate_elements/',
|
||||
[uuid]);
|
||||
|
||||
// The slide was projected, if the id matches. If the overlay is given, also
|
||||
// the overlay is checked
|
||||
var wasProjectedBefore = _.some(isProjected, function (mapping) {
|
||||
var value = (mapping.projectorId === projectorId);
|
||||
if (overlay !== undefined) {
|
||||
value = value && (mapping.overlay === overlay);
|
||||
}
|
||||
// Activate, if the projector_id is a new projector.
|
||||
if (isProjectedId != projectorId) {
|
||||
return value;
|
||||
});
|
||||
overlay = overlay || false; // set overlay if it wasn't defined
|
||||
|
||||
if (!wasProjectedBefore) {
|
||||
var activate = function () {
|
||||
return $http.post(
|
||||
'/rest/core/projector/' + projectorId + '/activate_elements/',
|
||||
[{name: 'agenda/current-list-of-speakers-overlay',stable: true}]);
|
||||
[{name: name,
|
||||
stable: overlay, // if this is an overlay, it should not be
|
||||
// removed by changing the main content
|
||||
overlay: overlay}]
|
||||
);
|
||||
};
|
||||
if (!overlay) {
|
||||
// clear all elements on this projector, because we are _not_ using the overlay.
|
||||
$http.post('/rest/core/projector/' + projectorId + '/clear_elements/').then(activate);
|
||||
} else {
|
||||
activate();
|
||||
}
|
||||
}
|
||||
},
|
||||
isProjected: function () {
|
||||
// Returns the ids of all projectors with an agenda-item element. Else return an empty list.
|
||||
var predicate = function (element) {
|
||||
var value;
|
||||
value = element.name == 'agenda/current-list-of-speakers-overlay';
|
||||
return value;
|
||||
return element.name === name;
|
||||
};
|
||||
var isProjectedIds = [];
|
||||
Projector.getAll().forEach(function (projector) {
|
||||
@ -392,7 +364,23 @@ angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users'])
|
||||
}
|
||||
});
|
||||
return isProjectedIds;
|
||||
},
|
||||
// Returns a list of mappings between pojector id, overlay and uuid.
|
||||
isProjectedWithOverlayStatus: function () {
|
||||
var mapping = [];
|
||||
_.forEach(Projector.getAll(), function (projector) {
|
||||
_.forEach(projector.elements, function (element, uuid) {
|
||||
if (element.name === name) {
|
||||
mapping.push({
|
||||
projectorId: projector.id,
|
||||
uuid: uuid,
|
||||
overlay: element.overlay || false,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
return mapping;
|
||||
},
|
||||
};
|
||||
}
|
||||
])
|
||||
|
@ -16,9 +16,6 @@ angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda'])
|
||||
slidesProvider.registerSlide('agenda/current-list-of-speakers', {
|
||||
template: 'static/templates/agenda/slide-current-list-of-speakers.html',
|
||||
});
|
||||
slidesProvider.registerSlide('agenda/current-list-of-speakers-overlay', {
|
||||
template: 'static/templates/agenda/slide-current-list-of-speakers-overlay.html',
|
||||
});
|
||||
}
|
||||
])
|
||||
|
||||
@ -27,7 +24,9 @@ angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda'])
|
||||
'Agenda',
|
||||
'CurrentListOfSpeakersItem',
|
||||
'Config',
|
||||
function ($scope, Agenda, CurrentListOfSpeakersItem, Config) {
|
||||
'Projector',
|
||||
function ($scope, Agenda, CurrentListOfSpeakersItem, Config, Projector) {
|
||||
$scope.overlay = $scope.element.overlay;
|
||||
// Watch for changes in the current list of speakers reference
|
||||
$scope.$watch(function () {
|
||||
return Config.lastModified('projector_currentListOfSpeakers_reference');
|
||||
@ -35,6 +34,12 @@ angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda'])
|
||||
$scope.currentListOfSpeakersReference = $scope.config('projector_currentListOfSpeakers_reference');
|
||||
$scope.updateCurrentListOfSpeakers();
|
||||
});
|
||||
// Watch for changes in the referenced projector
|
||||
$scope.$watch(function () {
|
||||
return Projector.lastModified($scope.currentListOfSpeakersReference);
|
||||
}, function () {
|
||||
$scope.updateCurrentListOfSpeakers();
|
||||
});
|
||||
// Watch for changes in the current item.
|
||||
$scope.$watch(function () {
|
||||
return Agenda.lastModified();
|
||||
@ -42,12 +47,7 @@ angular.module('OpenSlidesApp.agenda.projector', ['OpenSlidesApp.agenda'])
|
||||
$scope.updateCurrentListOfSpeakers();
|
||||
});
|
||||
$scope.updateCurrentListOfSpeakers = function () {
|
||||
var itemPromise = CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference);
|
||||
if (itemPromise) {
|
||||
itemPromise.then(function(item) {
|
||||
$scope.agendaItem = item;
|
||||
});
|
||||
}
|
||||
$scope.agendaItem = CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference);
|
||||
};
|
||||
}
|
||||
])
|
||||
|
@ -55,7 +55,7 @@ angular.module('OpenSlidesApp.agenda.site', [
|
||||
})
|
||||
.state('agenda.current-list-of-speakers', {
|
||||
url: '/speakers',
|
||||
controller: 'ListOfSpeakersViewCtrl',
|
||||
controller: 'CurrentListOfSpeakersViewCtrl',
|
||||
data: {
|
||||
title: gettext('Current list of speakers'),
|
||||
},
|
||||
@ -588,7 +588,7 @@ angular.module('OpenSlidesApp.agenda.site', [
|
||||
}
|
||||
])
|
||||
|
||||
.controller('ListOfSpeakersViewCtrl', [
|
||||
.controller('CurrentListOfSpeakersViewCtrl', [
|
||||
'$scope',
|
||||
'$state',
|
||||
'$http',
|
||||
@ -596,7 +596,9 @@ angular.module('OpenSlidesApp.agenda.site', [
|
||||
'ProjectionDefault',
|
||||
'Config',
|
||||
'CurrentListOfSpeakersItem',
|
||||
function($scope, $state, $http, Projector, ProjectionDefault, Config, CurrentListOfSpeakersItem) {
|
||||
'CurrentListOfSpeakersSlide',
|
||||
function($scope, $state, $http, Projector, ProjectionDefault, Config, CurrentListOfSpeakersItem,
|
||||
CurrentListOfSpeakersSlide) {
|
||||
// Watch for changes in the current list of speakers reference
|
||||
$scope.$watch(function () {
|
||||
return Config.lastModified('projector_currentListOfSpeakers_reference');
|
||||
@ -608,52 +610,44 @@ angular.module('OpenSlidesApp.agenda.site', [
|
||||
return Projector.lastModified();
|
||||
}, function() {
|
||||
$scope.projectors = Projector.getAll();
|
||||
$scope.updateCurrentListOfSpeakers();
|
||||
var projectiondefault = ProjectionDefault.filter({name: 'agenda_current_list_of_speakers'})[0];
|
||||
if (projectiondefault) {
|
||||
$scope.defaultProjectorId = projectiondefault.projector_id;
|
||||
if ($scope.projectors.length === 1) {
|
||||
$scope.currentListOfSpeakersAsOverlay = true;
|
||||
}
|
||||
$scope.updateCurrentListOfSpeakers();
|
||||
$scope.listOfSpeakersDefaultProjectorId = ProjectionDefault.filter({name: 'agenda_current_list_of_speakers'})[0].projector_id;
|
||||
});
|
||||
$scope.updateCurrentListOfSpeakers = function () {
|
||||
var itemPromise = CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference);
|
||||
if (itemPromise) {
|
||||
itemPromise.then(function(item) {
|
||||
$scope.AgendaItem = item;
|
||||
});
|
||||
}
|
||||
};
|
||||
// Project current list of speakers
|
||||
// same logic as in core/base.js
|
||||
$scope.projectCurrentLoS = function (projectorId) {
|
||||
var isCurrentLoSProjectedIds = $scope.isCurrentLoSProjected($scope.mainListTree);
|
||||
_.forEach(isCurrentLoSProjectedIds, function (id) {
|
||||
$http.post('/rest/core/projector/' + id + '/clear_elements/');
|
||||
});
|
||||
if (_.indexOf(isCurrentLoSProjectedIds, projectorId) == -1) {
|
||||
$http.post('/rest/core/projector/' + projectorId + '/prune_elements/',
|
||||
[{name: 'agenda/current-list-of-speakers'}]);
|
||||
}
|
||||
};
|
||||
// same logic as in core/base.js
|
||||
$scope.isCurrentLoSProjected = function () {
|
||||
// Returns the ids of all projectors with an element with the name
|
||||
// 'agenda/current-list-of-speakers'. Elsewise returns an empty list.
|
||||
var projectorIds = [];
|
||||
$scope.projectors.forEach(function (projector) {
|
||||
var key = _.findKey(projector.elements, function (element) {
|
||||
return element.name == 'agenda/current-list-of-speakers';
|
||||
});
|
||||
if (typeof key === 'string') {
|
||||
projectorIds.push(projector.id);
|
||||
}
|
||||
});
|
||||
return projectorIds;
|
||||
$scope.agendaItem = CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference);
|
||||
};
|
||||
|
||||
// go to the list of speakers (management) of the currently
|
||||
// displayed projector slide
|
||||
$scope.goToListOfSpeakers = function() {
|
||||
$state.go('agenda.item.detail', {id: $scope.AgendaItem.id});
|
||||
if ($scope.agendaItem) {
|
||||
$state.go('agenda.item.detail', {id: $scope.agendaItem.id});
|
||||
}
|
||||
};
|
||||
$scope.currentListOfSpeakers = CurrentListOfSpeakersSlide;
|
||||
// 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.currentListOfSpeakersItem = function () {
|
||||
return CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference);
|
||||
};
|
||||
$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);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
|
@ -7,41 +7,59 @@
|
||||
</a>
|
||||
<!-- manage list of speakers -->
|
||||
<button os-perms="agenda.can_manage"
|
||||
ng-disabled="!currentListOfSpeakersItem()"
|
||||
ng-click="goToListOfSpeakers()"
|
||||
class="btn btn-sm btn-default">
|
||||
<i class="fa fa-microphone"></i>
|
||||
<translate>Manage list</translate>
|
||||
</button>
|
||||
<!-- project -->
|
||||
<div os-perms="core.can_manage_projector" class="btn-group" uib-dropdown
|
||||
uib-tooltip="{{ 'Projector' | translate }} {{ isCurrentLoSProjected()[0] || '' }}"
|
||||
tooltip-enable="isCurrentLoSProjected().length">
|
||||
|
||||
<!-- Current list of speakers projector button -->
|
||||
<div class="btn-group button" uib-dropdown
|
||||
uib-tooltip="{{ 'Project the current list of speakers' | translate }}"
|
||||
os-perms="core.can_manage_projector">
|
||||
<button type="button" class="btn btn-default btn-sm"
|
||||
title="{{ 'Project current list of speakers' | translate }}"
|
||||
ng-click="projectCurrentLoS(defaultProjectorId)"
|
||||
ng-class="{ 'btn-primary': isCurrentLoSProjected().length && inArray(isCurrentLoSProjected(), defaultProjectorId) }">
|
||||
ng-click="currentListOfSpeakers.project(listOfSpeakersDefaultProjectorId, currentListOfSpeakersAsOverlay)"
|
||||
ng-class="{ 'btn-primary': currentListOfSpeakers.isProjected().length && inArray(currentListOfSpeakers.isProjected(), listOfSpeakersDefaultProjectorId)}">
|
||||
<i class="fa fa-video-camera"></i>
|
||||
<translate>Current list of speakers</translate>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" uib-dropdown-toggle
|
||||
ng-class="{ 'btn-primary': isCurrentLoSProjected().length && !inArray(isCurrentLoSProjected(), defaultProjectorId) }">
|
||||
<button type="button" class="btn btn-default btn-sm"
|
||||
ng-if="projectors.length > 1"
|
||||
uib-dropdown-toggle
|
||||
ng-class="{ 'btn-primary': currentListOfSpeakers.isProjected().length && !inArray(currentListOfSpeakers.isProjected(), listOfSpeakersDefaultProjectorId)}">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="split-button">
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="split-button" ng-if="projectors.length > 1">
|
||||
<li role="menuitem">
|
||||
<a href="" ng-click="setOverlay(false); $event.stopPropagation();">
|
||||
<i class="fa" ng-class="currentListOfSpeakersAsOverlay ? 'fa-circle-o' : 'fa-check-circle-o'"></i>
|
||||
<translate>Project as slide</translate>
|
||||
</a>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<a href="" ng-click="setOverlay(true); $event.stopPropagation();">
|
||||
<i class="fa" ng-class="currentListOfSpeakersAsOverlay ? 'fa-check-circle-o' : 'fa-circle-o'"></i>
|
||||
<translate>Project as overlay</translate>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li role="menuitem" ng-repeat="projector in projectors | orderBy:'id'">
|
||||
<a href="" ng-click="projectCurrentLoS(projector.id)"
|
||||
ng-class="{ 'projected': inArray(isCurrentLoSProjected(), projector.id) }">
|
||||
<i class="fa fa-video-camera" ng-show="inArray(isCurrentLoSProjected(), projector.id) "></i>
|
||||
<a href="" ng-click="currentListOfSpeakers.project(projector.id, currentListOfSpeakersAsOverlay)"
|
||||
ng-class="{ 'projected': inArray(currentListOfSpeakers.isProjected(), projector.id) }">
|
||||
<i class="fa fa-video-camera" ng-show="inArray(currentListOfSpeakers.isProjected(), projector.id)"></i>
|
||||
{{ projector.name | translate }}
|
||||
<span ng-if="projector.id == defaultProjectorId">(<translate>Default</translate>)</span>
|
||||
<span ng-if="projector.id == listOfSpeakersDefaultProjectorId">(<translate>Default</translate>)</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1 translate>Current list of speakers</h1>
|
||||
<h2> {{ AgendaItem.getTitle() }}
|
||||
<span class="slimlabel label label-danger ng-scope" style="" ng-if="AgendaItem.speaker_list_closed" translate>
|
||||
<h2> {{ agendaItem.getTitle() }}
|
||||
<span class="slimlabel label label-danger ng-scope" style="" ng-if="agendaItem.speaker_list_closed" translate>
|
||||
Closed
|
||||
</span>
|
||||
</h2>
|
||||
@ -50,16 +68,16 @@
|
||||
|
||||
<div class="details">
|
||||
<!-- Last speakers -->
|
||||
<p ng-repeat="speaker in lastSpeakers = (AgendaItem.speakers | filter: {end_time: '!!', begin_time: '!!'}) |
|
||||
<p ng-repeat="speaker in lastSpeakers = (agendaItem.speakers | filter: {end_time: '!!', begin_time: '!!'}) |
|
||||
limitTo: config('agenda_show_last_speakers') : (lastSpeakers.length - config('agenda_show_last_speakers'))" class="lastSpeakers">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
<!-- Current speaker -->
|
||||
<p ng-repeat="speaker in currentspeakers = (AgendaItem.speakers| filter: {end_time: null, begin_time: '!!'})"
|
||||
<p ng-repeat="speaker in currentspeakers = (agendaItem.speakers| filter: {end_time: null, begin_time: '!!'})"
|
||||
class="currentSpeaker">
|
||||
<i class="fa fa-microphone fa-lg"></i> {{ speaker.user.get_full_name() }}
|
||||
<!-- Next speakers -->
|
||||
<ol class="nextSpeakers">
|
||||
<li ng-repeat="speaker in AgendaItem.speakers | filter: {begin_time: null} | orderBy:'weight'">
|
||||
<li ng-repeat="speaker in agendaItem.speakers | filter: {begin_time: null} | orderBy:'weight'">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
</ol>
|
||||
</div>
|
||||
|
@ -0,0 +1,30 @@
|
||||
<div id="speakerbox">
|
||||
<h3 translate>List of speakers</h3>
|
||||
|
||||
<!-- Last speakers -->
|
||||
<p ng-repeat="speaker in lastSpeakers = (agendaItem.speakers
|
||||
| filter: {end_time: '!!', begin_time: '!!'})
|
||||
| limitTo: config('agenda_show_last_speakers') : (lastSpeakers.length - config('agenda_show_last_speakers'))"
|
||||
class="lastSpeakers">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
</p>
|
||||
|
||||
<!-- Current speaker -->
|
||||
<p ng-repeat="speaker in agendaItem.speakers | filter: {end_time: null, begin_time: '!!'} "
|
||||
class="currentSpeaker">
|
||||
<i class="fa fa-microphone fa-lg"></i> {{ speaker.user.get_full_name() }}
|
||||
</p>
|
||||
|
||||
<!-- Next speakers -->
|
||||
<ol class="nextSpeakers">
|
||||
<li ng-repeat="speaker in nextSpeakers = (agendaItem.speakers
|
||||
| filter: {begin_time: null})
|
||||
| orderBy:'weight'
|
||||
| limitTo: 3">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
</li>
|
||||
</ol>
|
||||
<p ng-if="nextSpeakers.length > 3" class="lastSpeakers">
|
||||
<i>+ {{ nextSpeakers.length - 3 }}</i>
|
||||
</p>
|
||||
</div>
|
@ -0,0 +1,33 @@
|
||||
<div class="content scrollcontent">
|
||||
<div class="title">
|
||||
<h1 translate>Current list of speakers</h1>
|
||||
<h2> {{ agendaItem.getTitle() }}
|
||||
<span class="slimlabel label label-danger ng-scope"
|
||||
ng-if="agendaItem.speaker_list_closed" translate>Closed</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<!-- Last speakers -->
|
||||
<p ng-repeat="speaker in lastSpeakers = (agendaItem.speakers
|
||||
| filter: {end_time: '!!', begin_time: '!!'})
|
||||
| limitTo: config('agenda_show_last_speakers') : (lastSpeakers.length - config('agenda_show_last_speakers'))"
|
||||
class="lastSpeakers">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
</p>
|
||||
|
||||
<!-- Current speaker -->
|
||||
<p ng-repeat="speaker in currentspeakers = (agendaItem.speakers
|
||||
| filter: {end_time: null, begin_time: '!!'})"
|
||||
class="currentSpeaker">
|
||||
<i class="fa fa-microphone fa-lg"></i> {{ speaker.user.get_full_name() }}
|
||||
</p>
|
||||
|
||||
<!-- Next speakers -->
|
||||
<ol class="nextSpeakers">
|
||||
<li ng-repeat="speaker in agendaItem.speakers
|
||||
| filter: {begin_time: null}
|
||||
| orderBy:'weight'">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
@ -1,19 +0,0 @@
|
||||
<div ng-controller="SlideCurrentListOfSpeakersCtrl">
|
||||
<div ng-if="agendaItem.speakers && agendaItem.speakers.length">
|
||||
<div id="speakerbox">
|
||||
<h3 translate>List of speakers</h3>
|
||||
<p ng-repeat="speaker in lastSpeakers = (agendaItem.speakers | filter: {end_time: '!!', begin_time: '!!'}) |
|
||||
limitTo: config('agenda_show_last_speakers') : (lastSpeakers.length - config('agenda_show_last_speakers'))"
|
||||
class="lastSpeakers">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
<p ng-repeat="speaker in agendaItem.speakers | filter: {end_time: null, begin_time: '!!'} "
|
||||
class="currentSpeaker">
|
||||
<i class="fa fa-microphone fa-lg"></i> {{ speaker.user.get_full_name() }}
|
||||
<ol class="nextSpeakers">
|
||||
<li ng-repeat="speaker in nextSpeakers = (agendaItem.speakers | filter: {begin_time: null}) | orderBy:'weight' | limitTo: 3">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
</ol>
|
||||
<p ng-if="nextSpeakers.length > 3" class="lastSpeakers">
|
||||
<i>+ {{ nextSpeakers.length - 3 }}</i>
|
||||
</div>
|
||||
</div>
|
@ -1,23 +1,8 @@
|
||||
<div ng-controller="SlideCurrentListOfSpeakersCtrl" class="content scrollcontent">
|
||||
<div class="title">
|
||||
<h1 translate>Current list of speakers</h1>
|
||||
<h2> {{ agendaItem.getTitle() }}
|
||||
<span class="slimlabel label label-danger ng-scope" style=""
|
||||
ng-if="agendaItem.speaker_list_closed" translate>Closed</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div ng-controller="SlideCurrentListOfSpeakersCtrl">
|
||||
|
||||
<ng-include src="'static/templates/agenda/partial-slide-current-list-of-speakers.html'"
|
||||
ng-if="!overlay"></ng-include>
|
||||
<ng-include src="'static/templates/agenda/partial-slide-current-list-of-speakers-overlay.html'"
|
||||
ng-if="overlay"></ng-include>
|
||||
|
||||
<!-- Last speakers -->
|
||||
<p ng-repeat="speaker in lastSpeakers = (agendaItem.speakers | filter: {end_time: '!!', begin_time: '!!'}) |
|
||||
limitTo: config('agenda_show_last_speakers') : (lastSpeakers.length - config('agenda_show_last_speakers'))" class="lastSpeakers">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
<!-- Current speaker -->
|
||||
<p ng-repeat="speaker in currentspeakers = (agendaItem.speakers| filter: {end_time: null, begin_time: '!!'})"
|
||||
class="currentSpeaker">
|
||||
<i class="fa fa-microphone fa-lg"></i> {{ speaker.user.get_full_name() }}
|
||||
<!-- Next speakers -->
|
||||
<ol class="nextSpeakers">
|
||||
<li ng-repeat="speaker in agendaItem.speakers | filter: {begin_time: null} | orderBy:'weight'">
|
||||
{{ speaker.user.get_full_name() }}
|
||||
</ol>
|
||||
</div>
|
||||
|
@ -230,9 +230,10 @@ h3 {
|
||||
position: absolute;
|
||||
background: #d3d3d3;
|
||||
border-radius: 7px;
|
||||
border: 1px solid;
|
||||
padding: 3px 7px 10px 19px;
|
||||
border: 1px solid #999;
|
||||
padding: 0px 7px 10px 19px;
|
||||
z-index: 99;
|
||||
box-shadow: 3px 3px 10px 1px rgba(0,0,0,0.5);
|
||||
}
|
||||
ul, ol {
|
||||
margin: 0 0 10px 2em;
|
||||
|
@ -712,7 +712,8 @@ angular.module('OpenSlidesApp.core', [
|
||||
value.name != 'agenda/item-list' &&
|
||||
value.name != 'core/clock' &&
|
||||
value.name != 'core/countdown' &&
|
||||
value.name != 'core/message' ) {
|
||||
value.name != 'core/message' &&
|
||||
value.name != 'agenda/current-list-of-speakers' ) {
|
||||
return_dict = {
|
||||
'state': value.name.replace('/', '.')+'.detail.update',
|
||||
'param': {id: value.id}
|
||||
|
@ -1036,7 +1036,7 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
'Config',
|
||||
'Projector',
|
||||
'CurrentListOfSpeakersItem',
|
||||
'ListOfSpeakersOverlay',
|
||||
'CurrentListOfSpeakersSlide',
|
||||
'ProjectionDefault',
|
||||
'ProjectorMessage',
|
||||
'Countdown',
|
||||
@ -1044,7 +1044,7 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
'ngDialog',
|
||||
'ProjectorMessageForm',
|
||||
function($scope, $http, $interval, $state, $q, $filter, Config, Projector, CurrentListOfSpeakersItem,
|
||||
ListOfSpeakersOverlay, ProjectionDefault, ProjectorMessage, Countdown, gettextCatalog,
|
||||
CurrentListOfSpeakersSlide, ProjectionDefault, ProjectorMessage, Countdown, gettextCatalog,
|
||||
ngDialog, ProjectorMessageForm) {
|
||||
ProjectorMessage.bindAll({}, $scope, 'messages');
|
||||
|
||||
@ -1078,7 +1078,6 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
cancelIntervalTimers();
|
||||
});
|
||||
|
||||
$scope.listofspeakers = ListOfSpeakersOverlay;
|
||||
$scope.$watch(function () {
|
||||
return Projector.lastModified();
|
||||
}, function () {
|
||||
@ -1086,20 +1085,14 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
if (!$scope.active_projector) {
|
||||
$scope.changeProjector($filter('orderBy')($scope.projectors, 'id')[0]);
|
||||
}
|
||||
if ($scope.projectors.length === 1) {
|
||||
$scope.currentListOfSpeakersAsOverlay = true;
|
||||
}
|
||||
|
||||
$scope.messageDefaultProjectorId = ProjectionDefault.filter({name: 'messages'})[0].projector_id;
|
||||
$scope.countdownDefaultProjectorId = ProjectionDefault.filter({name: 'countdowns'})[0].projector_id;
|
||||
$scope.getDefaultOverlayProjector();
|
||||
$scope.listOfSpeakersDefaultProjectorId = ProjectionDefault.filter({name: 'agenda_current_list_of_speakers'})[0].projector_id;
|
||||
});
|
||||
// gets the default projector where the current list of speakers overlay will be displayed
|
||||
$scope.getDefaultOverlayProjector = function () {
|
||||
var projectiondefault = ProjectionDefault.filter({name: 'agenda_current_list_of_speakers'})[0];
|
||||
if (projectiondefault) {
|
||||
$scope.listofSpeakersDefaultProjectorId = projectiondefault.projector_id;
|
||||
} else {
|
||||
$scope.listOfSpeakersDefaultProjectorId = 1;
|
||||
}
|
||||
};
|
||||
// watch for changes in projector_broadcast and currentListOfSpeakersReference
|
||||
var last_broadcast;
|
||||
$scope.$watch(function () {
|
||||
@ -1172,11 +1165,35 @@ angular.module('OpenSlidesApp.core.site', [
|
||||
ProjectorMessage.destroy(message.id);
|
||||
};
|
||||
|
||||
/* Current list of speakers */
|
||||
$scope.currentListOfSpeakers = CurrentListOfSpeakersSlide;
|
||||
// Set the current overlay status
|
||||
if ($scope.currentListOfSpeakers.isProjected().length) {
|
||||
var isProjected = $scope.currentListOfSpeakers.isProjectedWithOverlayStatus();
|
||||
$scope.currentListOfSpeakersAsOverlay = isProjected[0].overlay;
|
||||
} else {
|
||||
$scope.currentListOfSpeakersAsOverlay = true;
|
||||
}
|
||||
// go to the list of speakers(management) of the currently displayed list of speakers reference slide
|
||||
$scope.goToListOfSpeakers = function() {
|
||||
CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference).then(function (success) {
|
||||
$state.go('agenda.item.detail', {id: success.id});
|
||||
var item = $scope.currentListOfSpeakersItem();
|
||||
if (item) {
|
||||
$state.go('agenda.item.detail', {id: item.id});
|
||||
}
|
||||
};
|
||||
$scope.currentListOfSpeakersItem = function () {
|
||||
return CurrentListOfSpeakersItem.getItem($scope.currentListOfSpeakersReference);
|
||||
};
|
||||
$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);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
])
|
||||
|
@ -268,14 +268,55 @@
|
||||
<h4 translate>List of speakers</h4>
|
||||
</a>
|
||||
<div uib-collapse="!isSpeakerList" ng-cloak>
|
||||
<projector-button model="listofspeakers" default-projector-id="listOfSpeakersDefaultProjectorId">
|
||||
</projector-button>
|
||||
<div class="btn-group" os-perms="agenda.can_manage">
|
||||
<a ng-click="goToListOfSpeakers()" class="btn btn-default btn-sm"
|
||||
title="{{ 'Manage current list of speakers' | translate}}">
|
||||
<i class="fa fa-microphone"></i>
|
||||
|
||||
<!-- Current list of speakers projector button -->
|
||||
<div class="btn-group button" uib-dropdown
|
||||
uib-tooltip="{{ 'Project the current list of speakers' | translate }}"
|
||||
os-perms="core.can_manage_projector">
|
||||
<button type="button" class="btn btn-default btn-sm"
|
||||
title="{{ 'Project current list of speakers' | translate }}"
|
||||
ng-click="currentListOfSpeakers.project(listOfSpeakersDefaultProjectorId, currentListOfSpeakersAsOverlay)"
|
||||
ng-class="{ 'btn-primary': currentListOfSpeakers.isProjected().length && inArray(currentListOfSpeakers.isProjected(), listOfSpeakersDefaultProjectorId)}">
|
||||
<i class="fa fa-video-camera"></i>
|
||||
<translate>Current list of speakers</translate>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm slimDropDown"
|
||||
ng-if="projectors.length > 1"
|
||||
uib-dropdown-toggle
|
||||
ng-class="{ 'btn-primary': currentListOfSpeakers.isProjected().length && !inArray(currentListOfSpeakers.isProjected(), listOfSpeakersDefaultProjectorId)}">
|
||||
<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="split-button" ng-if="projectors.length > 1">
|
||||
<li role="menuitem">
|
||||
<a href="" ng-click="setOverlay(false); $event.stopPropagation();">
|
||||
<i class="fa" ng-class="currentListOfSpeakersAsOverlay ? 'fa-circle-o' : 'fa-check-circle-o'"></i>
|
||||
<translate>Project as slide</translate>
|
||||
</a>
|
||||
</li>
|
||||
<li role="menuitem">
|
||||
<a href="" ng-click="setOverlay(true); $event.stopPropagation();">
|
||||
<i class="fa" ng-class="currentListOfSpeakersAsOverlay ? 'fa-check-circle-o' : 'fa-circle-o'"></i>
|
||||
<translate>Project as overlay</translate>
|
||||
</a>
|
||||
</li>
|
||||
<li class="divider"></li>
|
||||
<li role="menuitem" ng-repeat="projector in projectors | orderBy:'id'">
|
||||
<a href="" ng-click="currentListOfSpeakers.project(projector.id, currentListOfSpeakersAsOverlay)"
|
||||
ng-class="{ 'projected': inArray(currentListOfSpeakers.isProjected(), projector.id) }">
|
||||
<i class="fa fa-video-camera" ng-show="inArray(currentListOfSpeakers.isProjected(), projector.id)"></i>
|
||||
{{ projector.name | translate }}
|
||||
<span ng-if="projector.id == listOfSpeakersDefaultProjectorId">(<translate>Default</translate>)</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button os-perms="agenda.can_manage"
|
||||
ng-disabled="!currentListOfSpeakersItem()"
|
||||
ng-click="goToListOfSpeakers()" class="btn btn-default btn-sm"
|
||||
uib-tooltip="{{ 'Manage the current list of speakers' | translate}}">
|
||||
<i class="fa fa-microphone"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- end div ProjectorControlCtrl -->
|
||||
|
Loading…
Reference in New Issue
Block a user