(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', 'gettextCatalog', 'gettext', 'CamelCase', 'EditForm', function($http, DS, Speaker, jsDataModel, Projector, 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; }, 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; } } }); }, getListViewTitle: function () { var title; try { title = this.getContentObject().getAgendaListViewTitle(); } catch (e) { // when the content object is not in the DS store title = this.list_view_title; } 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); _.forEach(isProjectedIds, function (id) { $http.post('/rest/core/projector/' + id + '/clear_elements/'); }); // Activate, if the projector_id is a new projector. if (_.indexOf(isProjectedIds, projectorId) == -1) { return $http.post( '/rest/core/projector/' + projectorId + '/prune_elements/', [{ name: 'agenda/item-list', tree: true, id: this.id }] ); } } else { // Project the content object var contentObject = DS.get(this.content_object.collection, this.content_object.id); 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(); _.forEach(isProjectedIds, function (id) { $http.post('/rest/core/projector/' + id + '/clear_elements/'); }); if (_.indexOf(isProjectedIds, projectorId) == -1) { return $http.post( '/rest/core/projector/' + projectorId + '/prune_elements/', [{name: 'agenda/list-of-speakers', id: this.id}] ); } }, // 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) {}]); }());