(function(context,$) { "use strict"; context.JK = context.JK || {}; context.JK.SessionList = function(app) { var EVENTS = context.JK.EVENTS; var gearUtils = context.JK.GearUtils; var sessionUtils = context.JK.SessionUtils; var helpBubble = context.JK.HelpBubbleHelper; var logger = context.JK.logger; var rest = context.JK.Rest(); var ui = new context.JK.UIHelper(app); var $activeSessionTemplate = $('#template-active-session-row'); var $inactiveSessionTemplate = $('#template-inactive-session-row'); var $notationFileTemplate = $('#template-notation-files'); var $openSlotsTemplate = $('#template-open-slots'); var $latencyTemplate = $('#template-latency'); var $musicianTemplate = $('#template-musician-info'); var showJoinLink = true; var showRsvpLink = true; function renderActiveSession(session, tbGroup, myAudioLatency) { $('#actionHeader', tbGroup).html('JOIN'); var i = 0; var inSessionUsersHtml = '', rsvpFirst3UsersHtml = '', rsvpRemainingUsersHtml = '', openSlotsFirst3Html = '', openSlotsRemainingHtml = '', latencyInSessionHtml = '', latencyFirst3Html = '', latencyRemainingHtml = '', notationFileHtml = ''; // this is used to track which users are already in the session so we can exclude them from the // "RSVPs" section var inSessionUsers = []; showJoinLink = session.musician_access; // render musicians who are already in the session if (session.active_music_session && "participants" in session.active_music_session && session.active_music_session.participants.length > 0) { for (i=0; i < session.active_music_session.participants.length; i++) { inSessionUsers.push(session.active_music_session.participants[i].user.id); var inSessionUserInfo = createInSessionUser(session.active_music_session.participants[i]); inSessionUsersHtml += inSessionUserInfo[0]; latencyInSessionHtml += inSessionUserInfo[1]; } } // this provides a buffer at the top to shift the first latency tag down in the event there are NO in-session musicians else { latencyInSessionHtml += "
 
"; } // render users who have approved RSVPs if (session.approved_rsvps) { var approvedRsvpCount = session.approved_rsvps.length; for (i=0; i < approvedRsvpCount; i++) { // do not show the user in this section if he is already in the session if ($.inArray(session.approved_rsvps[i].id, inSessionUsers) === -1) { if (session.approved_rsvps[i].id === context.JK.currentUserId) { showJoinLink = true; } var rsvpUserInfo = createRsvpUser(session.approved_rsvps[i], session, approvedRsvpCount, i); if (i < 3) { rsvpFirst3UsersHtml += rsvpUserInfo[0]; latencyFirst3Html += rsvpUserInfo[1]; } else { rsvpRemainingUsersHtml += rsvpUserInfo[0]; latencyRemainingHtml += rsvpUserInfo[1]; } } else { showJoinLink = true; } } } // render if anyone interested if(session['is_unstructured_rsvp?']) { openSlotsFirst3Html += sessionUtils.createOpenSlot($openSlotsTemplate, {description: 'Any Instrument'}); } // render open slots if (session.open_slots) { var openSlotCount = session.open_slots.length; for (i=0; i < openSlotCount; i++) { if (i < 3) { openSlotsFirst3Html += sessionUtils.createOpenSlot($openSlotsTemplate, session.open_slots[i], openSlotCount, i); } else { openSlotsRemainingHtml += sessionUtils.createOpenSlot($openSlotsTemplate, session.open_slots[i], openSlotCount, i); } } } // notation files if (session.music_notations) { for (i=0; i < session.music_notations.length; i++) { notationFileHtml += createNotationFile(session.music_notations[i]); } } var sessionVals = buildSessionObject(session, notationFileHtml, rsvpFirst3UsersHtml, rsvpRemainingUsersHtml, openSlotsFirst3Html, openSlotsRemainingHtml, latencyFirst3Html, latencyRemainingHtml, latencyInSessionHtml); sessionVals.in_session_musicians = inSessionUsersHtml.length > 0 ? inSessionUsersHtml : 'N/A'; sessionVals.join_link_display_style = showJoinLink ? "block" : "none"; var $row = $(context.JK.fillTemplate($activeSessionTemplate.html(), sessionVals)); var $offsetParent = $(tbGroup).closest('.content'); var $latencyBadges = $row.find('.latency-value'); context._.each($latencyBadges, function(latencyBadge) { var $latencyBadge = $(latencyBadge); var full_score = $latencyBadge.attr('data-full-score') || null; var internet_score = $latencyBadge.attr('data-internet-score') || null; var audio_latency = $latencyBadge.attr('data-audio-latency') || null; var latencyBadgeUserId = $latencyBadge.attr('data-user-id'); var scoreOptions = {offsetParent: $offsetParent}; helpBubble.scoreBreakdown($latencyBadge, context.JK.currentUserId == latencyBadgeUserId, full_score, myAudioLatency, audio_latency, internet_score, scoreOptions); }); $(tbGroup).append($row); var $parentRow = $('tr[data-session-id=' + session.id + ']', tbGroup); // wire up "more" links $('a.more.slots', $parentRow).click(toggleSlots); $('a.more.rsvps', $parentRow).click(toggleRsvps); if (showJoinLink) { // wire up the Join Link to the T&Cs dialog $('.join-link', $parentRow).click(function(evt) { if(!context.JK.guardAgainstBrowser(app)) { return false; } if (!context.JK.JamServer.connected) { app.notifyAlert("Not Connected", 'To create or join a session, you must be connected to the server.'); return false; } gearUtils.guardAgainstInvalidConfiguration(app) .fail(function() { app.notify( { title: "Unable to Join Session", text: "You can only join a session once you have working audio gear and a tested internet connection." }) }) .done(function(){ sessionUtils.joinSession(session.id); }) return false; }); } } function renderInactiveSession(session, tbGroup, $rowToUpdate, myAudioLatency) { var openSlots = false; var hasInvitation = false; var approvedRsvpId = null; // if set, the user has an accepted RSVP var pendingRsvpId = null; // if set, the user has a pending RSVP var hasPendingOrDeclinedRsvp = false; var openRsvps = session.open_rsvps; $('#actionHeader', tbGroup).html('RSVP'); var i = 0; var rsvpFirst3UsersHtml = '', rsvpRemainingUsersHtml = '', openSlotsFirst3Html = '', openSlotsRemainingHtml = '', latencyFirst3Html = '', latencyRemainingHtml = '', notationFileHtml = ''; context._.each(session.pending_rsvp_requests, function(pending_rsvp_request) { if(pending_rsvp_request.user_id === context.JK.currentUserId) { pendingRsvpId = pending_rsvp_request.id; } }); // render users who have approved RSVPs if (session.approved_rsvps && session.approved_rsvps.length > 0) { var approvedRsvpCount = session.approved_rsvps.length; context._.each(session.approved_rsvps, function(approved_rsvp) { if (approved_rsvp.id === context.JK.currentUserId) { approvedRsvpId = approved_rsvp.rsvp_request_id; } var rsvpUserInfo = createRsvpUser(approved_rsvp, session, approvedRsvpCount, i); if (i < 3) { rsvpFirst3UsersHtml += rsvpUserInfo[0]; latencyFirst3Html += rsvpUserInfo[1]; } else { rsvpRemainingUsersHtml += rsvpUserInfo[0]; latencyRemainingHtml += rsvpUserInfo[1]; } i++; }); } // this provides a buffer at the top to shift the first latency tag down in the event there are NO RSVP musicians else { latencyFirst3Html += "
 
"; } if(session['is_unstructured_rsvp?']) { openSlots = true; // unstructured RSVP means there are always open slots openSlotsFirst3Html += sessionUtils.createOpenSlot($openSlotsTemplate, {description: 'Any Instrument'}); } // render open slots if (session.open_slots) { var openSlotCount = session.open_slots.length; for (i=0; i < openSlotCount; i++) { openSlots = true; if (i < 3) { openSlotsFirst3Html += sessionUtils.createOpenSlot($openSlotsTemplate, session.open_slots[i], openSlotCount, i); } else { openSlotsRemainingHtml += sessionUtils.createOpenSlot($openSlotsTemplate, session.open_slots[i], openSlotCount, i); } } } // render pending invitations if (session.pending_invitations) { for (i=0; i < session.pending_invitations.length; i++) { if (session.pending_invitations[i].id === context.JK.currentUserId) { hasInvitation = true; } } } // notation files if (session.music_notations) { for (i=0; i < session.music_notations.length; i++) { notationFileHtml += createNotationFile(session.music_notations[i]); } } var sessionVals = buildSessionObject(session, notationFileHtml, rsvpFirst3UsersHtml, rsvpRemainingUsersHtml, openSlotsFirst3Html, openSlotsRemainingHtml, latencyFirst3Html, latencyRemainingHtml, ''); sessionVals.scheduled_start = session.pretty_scheduled_start_with_timezone; var $row = $(context.JK.fillTemplate($inactiveSessionTemplate.html(), sessionVals)); var $offsetParent = $(tbGroup).closest('.content'); var $latencyBadges = $row.find('.latency-value'); context._.each($latencyBadges, function(latencyBadge) { var $latencyBadge = $(latencyBadge); var full_score = $latencyBadge.attr('data-full-score') || null; var internet_score = $latencyBadge.attr('data-internet-score') || null; var audio_latency = $latencyBadge.attr('data-audio-latency') || null; var latencyBadgeUserId = $latencyBadge.attr('data-user-id'); var scoreOptions = {offsetParent: $offsetParent}; helpBubble.scoreBreakdown($latencyBadge, context.JK.currentUserId == latencyBadgeUserId, full_score, myAudioLatency, audio_latency, internet_score, scoreOptions); }) // initial page load if (!$rowToUpdate) { $(tbGroup).append($row); } // inline update after an RSVP submission / cancellation else { $rowToUpdate.replaceWith($row); } var $parentRow = $('tr[data-session-id=' + session.id + ']', tbGroup); // wire up "more" links $('a.more.slots', $parentRow).click(toggleSlots); $('a.more.rsvps', $parentRow).click(toggleRsvps); var showRsvpLink = true; var noLinkText = ''; if (approvedRsvpId) { showRsvpLink = false; noLinkText = $('You have been confirmed for this session. Cancel'); noLinkText.find('a').click(function() { ui.launchRsvpCancelDialog(session.id, approvedRsvpId) .one(EVENTS.RSVP_CANCELED, function() { rest.getSessionHistory(session.id) .done(function(response) { renderInactiveSession(response, tbGroup, $parentRow, myAudioLatency); }); }) .one(EVENTS.DIALOG_CLOSED, function() { $(this).unbind(EVENTS.RSVP_CANCELED); }); return false; }); } else if (pendingRsvpId) { showRsvpLink = false; noLinkText = $('You have RSVP\'ed to this session. Cancel'); noLinkText.find('a').click(function() { ui.launchRsvpCancelDialog(session.id, pendingRsvpId) .one(EVENTS.RSVP_CANCELED, function() { rest.getSessionHistory(session.id) .done(function(response) { renderInactiveSession(response, tbGroup, $parentRow, myAudioLatency); }); }) .one(EVENTS.DIALOG_CLOSED, function() { $(this).unbind(EVENTS.RSVP_CANCELED); }); return false; }); } else if (!openSlots) { showRsvpLink = false; noLinkText = 'No more openings in this session.'; } else if (!openRsvps && !hasInvitation) { showRsvpLink = false; noLinkText = 'You need an invitation to RSVP to this session.'; } if (showRsvpLink) { $('.rsvp-msg', $parentRow).hide(); $('.rsvp-link', $parentRow).show(); $('.rsvp-link', $parentRow).click(function(evt) { ui.launchRsvpSubmitDialog(session.id) .one(EVENTS.RSVP_SUBMITTED, function() { rest.getSessionHistory(session.id) .done(function(response) { renderInactiveSession(response, tbGroup, $parentRow, myAudioLatency); }); }) .one(EVENTS.DIALOG_CLOSED, function() { $(this).unbind(EVENTS.RSVP_SUBMITTED); }); return false; }); } else { $('.rsvp-msg', $parentRow).html(noLinkText).show(); $('.rsvp-link', $parentRow).hide(); } } function buildSessionObject(session, notationFileHtml, rsvpFirst3UsersHtml, rsvpRemainingUsersHtml, openSlotsFirst3Html, openSlotsRemainingHtml, latencyFirst3Html, latencyRemainingHtml, latencyInSessionHtml) { return { id: session.id, name: session.name, description: session.description || "(No description)", notation_files: notationFileHtml.length > 0 ? notationFileHtml : 'N/A', genres: session.genres.join (', '), rsvp_musicians_first_3: rsvpFirst3UsersHtml.length > 0 ? rsvpFirst3UsersHtml : 'N/A', rsvp_musicians_remaining: rsvpRemainingUsersHtml.length > 0 ? rsvpRemainingUsersHtml : 'N/A', open_slots_first_3: openSlotsFirst3Html.length > 0 ? openSlotsFirst3Html : 'No slots available', open_slots_remaining: openSlotsRemainingHtml.length > 0 ? openSlotsRemainingHtml : 'No slots available', latency_first_3: latencyFirst3Html, latency_remaining: latencyRemainingHtml, latency_in_session: latencyInSessionHtml, language: session.language_description, musician_access: session.musician_access_description, fan_access: session.fan_access_description, legal_policy: session.legal_policy }; } function createInSessionUser(participant) { var instrumentLogoHtml = ''; var j; // loop through the tracks to get the instruments for (j=0; j < participant.tracks.length; j++) { var track = participant.tracks[j]; logger.debug("Find:Finding instruments. Participant tracks:", participant.tracks); var inst = context.JK.getInstrumentIcon24(track.instrument_id); instrumentLogoHtml += ' '; } var id = participant.user.id; var name = participant.user.name; var musicianVals = { userId: id, avatar_url: context.JK.resolveAvatarUrl(participant.user.photo_url), profile_url: "/client#/profile/" + id, musician_name: name, instruments: instrumentLogoHtml, more_link: '' }; var musicianHtml = context.JK.fillTemplate($musicianTemplate.html(), musicianVals); var latencyHtml = context._.template($latencyTemplate.html(), $.extend(sessionUtils.createLatency(participant.user), participant.user), { variable: 'data' }); return [musicianHtml, latencyHtml]; } function createRsvpUser(user, session, rsvpCount, currentIndex) { var instrumentLogoHtml = ''; var j; // loop through the tracks to get the instruments if ("instrument_list" in user) { for (j=0; j < user.instrument_list.length; j++) { var instrument = user.instrument_list[j]; var inst = context.JK.getInstrumentIcon24(instrument.id); instrumentLogoHtml += ' '; } } var moreLinkHtml = ''; if (rsvpCount > 3 && currentIndex === 2) { moreLinkHtml = 'more'; } var id = user.id; var name = user.name; var musicianVals = { userId: id, avatar_url: context.JK.resolveAvatarUrl(user.photo_url), profile_url: "/client#/profile/" + id, musician_name: name, instruments: instrumentLogoHtml, more_link: moreLinkHtml }; var musicianHtml = context.JK.fillTemplate($musicianTemplate.html(), musicianVals); var latencyHtml = context._.template($latencyTemplate.html(), $.extend(sessionUtils.createLatency(user), user), { variable: 'data' }); return [musicianHtml, latencyHtml]; } function createNotationFile(notation) { var notationVals = { notation_id: notation.id, file_url: notation.file_url, file_name: notation.file_name }; return context.JK.fillTemplate($notationFileTemplate.html(), notationVals); } function toggleSlots() { var $div = $(this).closest('table').next(); var $arrow = $(this).next(); if ($div.is(":visible")) { $(this).text('more'); $arrow.removeClass('arrow-up-orange'); $arrow.addClass('arrow-down-orange'); $div.hide(); } else { $(this).text('less'); $arrow.addClass('arrow-up-orange'); $arrow.removeClass('arrow-down-orange'); $div.show(); } } function toggleRsvps() { var sessionId = $(this).closest('tr[data-session-id]').attr('data-session-id'); // musicians var $musicians = $(this).closest('table').next(); // latency indicators that need expanding / collapsing var $extraLatencies = $("#latency-extra-" + sessionId); var $arrow = $(this).next(); if ($musicians.is(":visible")) { $(this).text('more'); $arrow.removeClass('arrow-up-orange'); $arrow.addClass('arrow-down-orange'); $musicians.hide(); $extraLatencies.hide(); } else { $(this).text('less'); $arrow.addClass('arrow-up-orange'); $arrow.removeClass('arrow-down-orange'); $musicians.show(); $extraLatencies.show(); } } this.renderActiveSession = renderActiveSession; this.renderInactiveSession = renderInactiveSession; return this; }})(window,jQuery);