(function () { 'use strict'; angular .module("SportlogiqWebApp.services") .service("playlistCreator", PlaylistCreator); PlaylistCreator.$inject = ["$rootScope", "$filter", "$http", "apiEndpoint", "usersPlaylists", "userCompany", "companies", "mixpanelAPI"]; function PlaylistCreator($rootScope, $filter, $http, apiEndpoint, usersPlaylists, userCompany, companies, mixpanelAPI) { var that = this; // Private Members var ENDPOINT = apiEndpoint + "playlists"; // Public Members this.isPlaylistCreatorActive = false; this.isShareByURLDialogOpen = false; this.description = undefined; this.events = []; this.removedEvents = []; this.selectedPlaylistToShare = {}; this.userToSharePlaylistWith = undefined; this.newlyCreatedPlaylistId = undefined; // Public Methods this.createEventPlaylist = createEventPlaylist; this.addEventToPlaylist = addEventToPlaylist; this.removeEventFromPlaylist = removeEventFromPlaylist; this.closePlaylistCreator = closePlaylistCreator; this.saveAndSharePlaylist = saveAndSharePlaylist; this.sharePlaylistWithUser = sharePlaylistWithUser; this.openShareByURLDialog = openShareByURLDialog; this.resetShareDialogFields = resetShareDialogFields; // Event handlers // When the eventPlayer is opened, reset the removed events // This was done to resolve a circular dep conflict. $rootScope.$on('eventSelection::Reset', function () { that.removedEvents = []; }); //////////////// /** * Opens playlist creation dialog and creates * Array of events on playlistCreator.events * @param {Array} eventData - The filtered event data that needs to be used */ function createEventPlaylist(eventData, context) { // if eventData is empty; exit if (eventData.length < 1) { return; } // Make sure description is empty this.description = undefined; that.events = eventData; if (this.removedEvents.length > 0) { // Build the events array by filtering out the removed events this.removedEvents.forEach(function (removedEvent) { that.events = that.events.filter(function (event) { // Coerce removedEvent to number return +removedEvent !== +event.id; }); }); } if (!userCompany.companyUsers) { // Get the users associated to the current company // and open the playlist creator modal userCompany.getCompanyUsers().then(function (response) { that.isPlaylistCreatorActive = true; return response; }); } that.isPlaylistCreatorActive = true; mixpanelAPI.send('openCreatePlaylistDialog', context); } /** * Adds event to that.removedEvents (marking it as removed) * @param {object} eventList - the current events being viewed * @param {number} currentItemIndex - The current index in the eventList */ function removeEventFromPlaylist(eventList, currentItemIndex, context) { var currentItem = eventList[currentItemIndex]; context.itemToRemove = { name: currentItem.name, outcome: currentItem.outcome, shorthand: currentItem.shorthand, zone: currentItem.zone, manpowerSituation: currentItem.manpowerSituation, period: currentItem.period, playerInfo: currentItem.playerInfo }; delete context.itemToAdd; // Loop over the eventList passed in; if the values match // set the isRemoved prop to true and push to the removedEvents array eventList.map(function (value) { if (currentItem.id === value.id && !currentItem.isRemoved) { currentItem.isRemoved = true; that.removedEvents.push(value.id); } }); mixpanelAPI.send('removeEventFromSelection', context); } /** * Removed event from that.removedEvents (putting in the user playlist) * @param {object} eventList - the current events being viewed * @param {number} currentItemIndex - The current index in the eventList */ function addEventToPlaylist(eventList, currentItemIndex, context) { var currentItem = eventList[currentItemIndex]; delete context.itemToRemove; context.itemToAdd = { name: currentItem.name, outcome: currentItem.outcome, shorthand: currentItem.shorthand, zone: currentItem.zone, manpowerSituation: currentItem.manpowerSituation, period: currentItem.period, playerInfo: currentItem.playerInfo }; // Loop over the removedEvents; if the values match // set the isRemoved prop to false and remove the item from // the array that.removedEvents.map(function (value, index) { if (currentItem.id === value && currentItem.isRemoved) { currentItem.isRemoved = false; that.removedEvents.splice(index, 1); } }); mixpanelAPI.send('addEventToSelection', context); } /** * Closes and resets the playlist creation dialog */ function closePlaylistCreator(context) { this.isPlaylistCreatorActive = false; // Reset all fields this.resetShareDialogFields(); mixpanelAPI.send('closeCreatePlaylistDialog', context); } /** * Saves playlist and shares it with user(s) if any have been selected */ function saveAndSharePlaylist(context) { // Make sure the description is filled before submitting if (angular.isUndefined(this.description) || this.description.length < 1 || this.events.length < 1) { return; } var playbackOffsets = { default: { pre: 5.0, post: 10.0 }, shot: { pre: 5.0, post: 7.5 }, carry: { pre: 5.0, post: 10.0 }, dumpout: { pre: 5.0, post: 5.5 }, dumpin: { pre: 5.0, post: 10.0 }, lpr: { pre: 5.0, post: 12.0 }, controlledbreakout: { pre: 5.0, post: 15.0 } } var payload = { baseUrl: window.location.protocol + '//' + window.location.host + '/videos/', label: this.description, segments: this.events.map(function (event) { var video = context.videos.filter(function (vid) { return vid.period === event.period })[0]; return { start: event.frame / event.framerate - playbackOffsets[event.name].pre, duration: playbackOffsets[event.name].pre + playbackOffsets[event.name].post, label: event.shorthand, playerEventId: event.id, videoId: video && video.id, data: "" } }) }; // Setup context for mixpanel context.description = this.description; context.numOfPlayerEvents = this.events.length; context.sharedWithEveryone = this.shareWithEveryone; // IMPORTANT: On promise success close window. On promise error, throw $http.post(ENDPOINT, payload) .success(function (data) { that.isPlaylistCreatorActive = false; if (that.shareWithEveryone || that.userToSharePlaylistWith) { // data returned is the id of the playlist just created that.selectedPlaylistToShare.id = +(data); // Coerce to {number} // Then call the sharePlaylistWithUser method that.sharePlaylistWithUser(context); } mixpanelAPI.send('saveEventPlaylist', context); that.openShareByURLDialog(data); that.resetShareDialogFields(); }) .error(function (data, status) { alert("Oops! Couldn't save playlist"); return status; }); } /** * Shares the playlist with user selected in the dialog */ function sharePlaylistWithUser(context) { var PAYLOAD = { "isEveryone": false, "targetId": +(this.userToSharePlaylistWith) // Coerce value to {number} }; if (this.shareWithEveryone) { PAYLOAD.isEveryone = true; PAYLOAD.targetId = 0; } // Setup context for mixpanel context.sharedWithEveryone = this.shareWithEveryone; context.playlist = this.selectedPlaylistToShare; return $http.post( ENDPOINT + "/" + this.selectedPlaylistToShare.id + "/shares", PAYLOAD ) .success(function (data) { usersPlaylists.getPlaylists(); mixpanelAPI.send('sharePlaylistWithUser', context); }) .error(function (data, status) { console.error(data); if (status >= 400 && status < 500) { window.alert("Playlist shared with everyone already.") } return status; }); } function openShareByURLDialog(playlistId) { if (this.isShareByURLDialogOpen) { this.isShareByURLDialogOpen = false; this.resetShareDialogFields(); return; } this.newlyCreatedPlaylistId = playlistId; this.isShareByURLDialogOpen = true; } /** * Resets all dialog fields to undefined || false */ function resetShareDialogFields() { this.selectedPlaylistToShare = {}; this.userToSharePlaylistWith = undefined; this.shareWithEveryone = false; } } })();