437 lines
18 KiB
JavaScript
437 lines
18 KiB
JavaScript
(function () {
|
|
|
|
'use strict';
|
|
|
|
angular.module('OpenSlidesApp.agenda', ['OpenSlidesApp.users'])
|
|
|
|
.factory('Speaker', [
|
|
'DS',
|
|
function(DS) {
|
|
return DS.defineResource({
|
|
name: 'agenda/speaker',
|
|
relations: {
|
|
belongsTo: {
|
|
'users/user': {
|
|
localField: 'user',
|
|
localKey: 'user_id',
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
])
|
|
|
|
.factory('Agenda', [
|
|
'$http',
|
|
'DS',
|
|
'Speaker',
|
|
'jsDataModel',
|
|
'Projector',
|
|
'ProjectHelper',
|
|
'gettextCatalog',
|
|
'gettext',
|
|
'CamelCase',
|
|
'EditForm',
|
|
function($http, DS, Speaker, jsDataModel, Projector, ProjectHelper, gettextCatalog,
|
|
gettext, CamelCase, EditForm) {
|
|
var name = 'agenda/item';
|
|
return DS.defineResource({
|
|
name: name,
|
|
useClass: jsDataModel,
|
|
verboseName: gettext('Agenda'),
|
|
methods: {
|
|
getResourceName: function () {
|
|
return name;
|
|
},
|
|
getContentObject: function () {
|
|
return DS.get(this.content_object.collection, this.content_object.id);
|
|
},
|
|
getContentObjectDetailState: function () {
|
|
return CamelCase(this.content_object.collection).replace('/', '.') +
|
|
'.detail({id: ' + this.content_object.id + '})';
|
|
},
|
|
getContentObjectForm: function () {
|
|
return EditForm.fromCollectionString(this.content_object.collection);
|
|
},
|
|
getContentResource: function () {
|
|
return DS.definitions[this.content_object.collection];
|
|
},
|
|
getTitle: function () {
|
|
var title;
|
|
try {
|
|
title = this.getContentObject().getAgendaTitle();
|
|
} catch (e) {
|
|
// when the content object is not in the DS store.
|
|
title = this.title;
|
|
}
|
|
if (this.item_number) {
|
|
title = this.item_number + ' · ' + title;
|
|
}
|
|
return title;
|
|
},
|
|
getListOfSpeakersTitle: function () {
|
|
var title;
|
|
try {
|
|
title = this.getContentObject().getListOfSpeakersTitle();
|
|
if (this.item_number) {
|
|
title = this.item_number + ' · ' + title;
|
|
}
|
|
} catch (e) {
|
|
title = this.getTitle();
|
|
}
|
|
return title;
|
|
},
|
|
getAgendaTitle: function () {
|
|
return this.title;
|
|
},
|
|
getCSVExportText: function () {
|
|
var text;
|
|
try {
|
|
text = this.getContentObject().getCSVExportText();
|
|
} catch (e) {
|
|
// when the content object is not in the DS store
|
|
// or 'getCSVExportText' is not defined return nothing.
|
|
}
|
|
return text;
|
|
},
|
|
// link name which is shown in search result
|
|
getSearchResultName: function () {
|
|
return this.getAgendaTitle();
|
|
},
|
|
// return true if a specific relation matches for given searchquery
|
|
// (here: speakers)
|
|
hasSearchResult: function (results) {
|
|
var item = this;
|
|
// search for speakers (check if any user.id from already found users matches)
|
|
return _.some(results, function(result) {
|
|
if (result.getResourceName() === "users/user") {
|
|
if (_.some(item.speakers, {'user_id': result.id})) {
|
|
return true;
|
|
}
|
|
}
|
|
});
|
|
},
|
|
getProjectorTitle: function () {
|
|
try {
|
|
return this.getContentObject().getAgendaListViewTitle();
|
|
} catch (e) {
|
|
// when the content object is not in the DS store
|
|
return this.list_view_title;
|
|
}
|
|
},
|
|
getListViewTitle: function () {
|
|
var title = this.getProjectorTitle();
|
|
if (this.item_number) {
|
|
title = this.item_number + ' · ' + title;
|
|
}
|
|
return title;
|
|
},
|
|
getItemNumberWithAncestors: function (agendaId) {
|
|
if (!agendaId) {
|
|
agendaId = this.id;
|
|
}
|
|
var agendaItem = DS.get(name, agendaId);
|
|
if (!agendaItem) {
|
|
return '';
|
|
} else if (agendaItem.item_number) {
|
|
return agendaItem.item_number;
|
|
} else if (agendaItem.parent_id) {
|
|
return this.getItemNumberWithAncestors(agendaItem.parent_id);
|
|
} else {
|
|
return '';
|
|
}
|
|
},
|
|
// override project function of jsDataModel factory
|
|
project: function (projectorId, tree) {
|
|
if (tree) {
|
|
var isProjectedIds = this.isProjected(tree);
|
|
var requestData = {
|
|
clear_ids: isProjectedIds,
|
|
};
|
|
// Activate, if the projector_id is a new projector.
|
|
if (_.indexOf(isProjectedIds, projectorId) == -1) {
|
|
requestData.prune = {
|
|
id: projectorId,
|
|
element: {
|
|
name: 'agenda/item-list',
|
|
tree: true,
|
|
id: this.id,
|
|
},
|
|
};
|
|
}
|
|
return ProjectHelper.project(requestData);
|
|
} else { // Project the content object
|
|
var contentObject = DS.get(this.content_object.collection, this.content_object.id);
|
|
return contentObject.project(projectorId);
|
|
}
|
|
},
|
|
// override isProjected function of jsDataModel factory
|
|
isProjected: function (tree) {
|
|
// Returns all ids of all projectors with an agenda-item element. Otherwise an empty list.
|
|
if (typeof tree === 'undefined') {
|
|
tree = false;
|
|
}
|
|
var self = this;
|
|
var predicate = function (element) {
|
|
var value;
|
|
if (tree) {
|
|
// Item tree slide for sub tree
|
|
value = element.name == 'agenda/item-list' &&
|
|
typeof element.id !== 'undefined' &&
|
|
element.id == self.id;
|
|
} else {
|
|
// Releated item detail slide
|
|
value = element.name == self.content_object.collection &&
|
|
typeof element.id !== 'undefined' &&
|
|
element.id == self.content_object.id;
|
|
}
|
|
return value;
|
|
};
|
|
var isProjectedIds = [];
|
|
Projector.getAll().forEach(function (projector) {
|
|
if (typeof _.findKey(projector.elements, predicate) === 'string') {
|
|
isProjectedIds.push(projector.id);
|
|
}
|
|
});
|
|
return isProjectedIds;
|
|
},
|
|
isRelatedProjected: function () {
|
|
// related objects for agenda items: list of speakers slide.
|
|
return this.isListOfSpeakersProjected();
|
|
},
|
|
// project list of speakers
|
|
projectListOfSpeakers: function(projectorId) {
|
|
var isProjectedIds = this.isListOfSpeakersProjected();
|
|
var requestData = {
|
|
clear_ids: isProjectedIds,
|
|
};
|
|
if (_.indexOf(isProjectedIds, projectorId) == -1) {
|
|
requestData.prune = {
|
|
id: projectorId,
|
|
element: {
|
|
name: 'agenda/list-of-speakers',
|
|
id: this.id,
|
|
},
|
|
};
|
|
}
|
|
return ProjectHelper.project(requestData);
|
|
},
|
|
// check if list of speakers is projected
|
|
isListOfSpeakersProjected: function () {
|
|
// Returns all ids of all projectors with an element with the
|
|
// name 'agenda/list-of-speakers' and the same id. Else returns an empty list.
|
|
var self = this;
|
|
var predicate = function (element) {
|
|
return element.name == 'agenda/list-of-speakers' &&
|
|
typeof element.id !== 'undefined' &&
|
|
element.id == self.id;
|
|
};
|
|
var isProjecteds = [];
|
|
Projector.getAll().forEach(function (projector) {
|
|
if (typeof _.findKey(projector.elements, predicate) === 'string') {
|
|
isProjecteds.push(projector.id);
|
|
}
|
|
});
|
|
return isProjecteds;
|
|
},
|
|
hasSubitems: function(items) {
|
|
var self = this;
|
|
var hasChild = false;
|
|
// Returns true if the item has at least one child item.
|
|
_.each(items, function (item) {
|
|
if (item.parent_id == self.id) {
|
|
hasChild = true;
|
|
}
|
|
});
|
|
return hasChild;
|
|
}
|
|
},
|
|
relations: {
|
|
hasMany: {
|
|
'core/tag': {
|
|
localField: 'tags',
|
|
localKeys: 'tags_id',
|
|
},
|
|
'agenda/speaker': {
|
|
localField: 'speakers',
|
|
foreignKey: 'item_id',
|
|
}
|
|
}
|
|
},
|
|
beforeInject: function (resource, instance) {
|
|
Speaker.ejectAll({where: {item_id: {'==': instance.id}}});
|
|
}
|
|
});
|
|
}
|
|
])
|
|
|
|
.factory('AgendaTree', [
|
|
function () {
|
|
return {
|
|
getTree: function (items) {
|
|
// Sort items after there weight
|
|
items.sort(function(itemA, itemB) {
|
|
return itemA.weight - itemB.weight;
|
|
});
|
|
|
|
// Build a dict with all children (dict-value) to a specific
|
|
// item id (dict-key).
|
|
var itemChildren = {};
|
|
|
|
_.each(items, function (item) {
|
|
if (item.parent_id) {
|
|
// Add item to his parent. If it is the first child, then
|
|
// create a new list.
|
|
try {
|
|
itemChildren[item.parent_id].push(item);
|
|
} catch (error) {
|
|
itemChildren[item.parent_id] = [item];
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
// Recursive function that generates a nested list with all
|
|
// items with there children
|
|
function getChildren(items) {
|
|
var returnItems = [];
|
|
_.each(items, function (item) {
|
|
returnItems.push({
|
|
item: item,
|
|
children: getChildren(itemChildren[item.id]),
|
|
id: item.id,
|
|
});
|
|
});
|
|
return returnItems;
|
|
}
|
|
|
|
// Generates the list of root items (with no parents)
|
|
var parentItems = items.filter(function (item) {
|
|
return !item.parent_id;
|
|
});
|
|
return getChildren(parentItems);
|
|
},
|
|
|
|
// Returns a list of all items as a flat tree
|
|
getFlatTree: function(items) {
|
|
var tree = this.getTree(items);
|
|
var flatItems = [];
|
|
|
|
function generateFlatTree(tree, parentCount) {
|
|
_.each(tree, function (item) {
|
|
item.item.childrenCount = item.children.length;
|
|
item.item.parentCount = parentCount;
|
|
flatItems.push(item.item);
|
|
generateFlatTree(item.children, parentCount + 1);
|
|
});
|
|
}
|
|
generateFlatTree(tree, 0);
|
|
return flatItems;
|
|
}
|
|
};
|
|
}
|
|
])
|
|
|
|
.factory('CurrentListOfSpeakersItem', [
|
|
'Projector',
|
|
'Agenda',
|
|
function (Projector, Agenda) {
|
|
return {
|
|
getItem: function (projectorId) {
|
|
var projector = Projector.get(projectorId), item;
|
|
if (projector) {
|
|
_.forEach(projector.elements, function(element) {
|
|
if (element.agenda_item_id) {
|
|
item = Agenda.get(element.agenda_item_id);
|
|
}
|
|
});
|
|
}
|
|
return item;
|
|
}
|
|
};
|
|
}
|
|
])
|
|
|
|
.factory('CurrentListOfSpeakersSlide', [
|
|
'$http',
|
|
'Projector',
|
|
function($http, Projector) {
|
|
var name = 'agenda/current-list-of-speakers';
|
|
return {
|
|
project: function (projectorId, overlay) {
|
|
var isProjected = this.isProjectedWithOverlayStatus();
|
|
_.forEach(isProjected, function (mapping) {
|
|
$http.post('/rest/core/projector/' + mapping.projectorId + '/deactivate_elements/',
|
|
[mapping.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);
|
|
}
|
|
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: 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) {
|
|
return element.name === name;
|
|
};
|
|
var isProjectedIds = [];
|
|
Projector.getAll().forEach(function (projector) {
|
|
if (typeof _.findKey(projector.elements, predicate) === 'string') {
|
|
isProjectedIds.push(projector.id);
|
|
}
|
|
});
|
|
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;
|
|
},
|
|
};
|
|
}
|
|
])
|
|
|
|
|
|
|
|
// Make sure that the Agenda resource is loaded.
|
|
.run(['Agenda', function(Agenda) {}]);
|
|
|
|
}());
|