jam-cloud/web/app/assets/javascripts/sessionList.js

383 lines
15 KiB
JavaScript

(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 = '', rsvpUsersHtml = '', openSlotsHtml = '', latencyHtml = '', 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];
latencyHtml += 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 {
latencyHtml += "<div style='height:15px;'>&nbsp;</div>";
}
// render users who have approved RSVPs
if (session.approved_rsvps) {
for (i=0; i < session.approved_rsvps.length; 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);
rsvpUsersHtml += rsvpUserInfo[0];
latencyHtml += rsvpUserInfo[1];
}
else {
showJoinLink = true;
}
}
}
// render if anyone interested
if(session['is_unstructured_rsvp?']) {
openSlotsHtml += sessionUtils.createOpenSlot($openSlotsTemplate, {description: 'Any Instrument'})
}
// render open slots
if (session.open_slots) {
for (i=0; i < session.open_slots.length; i++) {
openSlotsHtml += sessionUtils.createOpenSlot($openSlotsTemplate, session.open_slots[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, rsvpUsersHtml, openSlotsHtml, latencyHtml);
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 $latencyBadge = $row.find('.latency-value');
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);
if (showJoinLink) {
// wire up the Join Link to the T&Cs dialog
var $parentRow = $('tr[data-session-id=' + session.id + ']', tbGroup);
$('.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 rsvpUsersHtml = '', openSlotsHtml = '', latencyHtml = '', 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) {
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);
rsvpUsersHtml += rsvpUserInfo[0];
latencyHtml += rsvpUserInfo[1];
});
}
// this provides a buffer at the top to shift the first latency tag down in the event there are NO RSVP musicians
else {
latencyHtml += "<div style='height:15px;'>&nbsp;</div>";
}
if(session['is_unstructured_rsvp?']) {
openSlots = true; // unstructured RSVP means there are always open slots
openSlotsHtml += sessionUtils.createOpenSlot($openSlotsTemplate, {description: 'Any Instrument'})
}
// render open slots
if (session.open_slots) {
for (i=0; i < session.open_slots.length; i++) {
openSlots = true;
openSlotsHtml += sessionUtils.createOpenSlot($openSlotsTemplate, session.open_slots[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, rsvpUsersHtml, openSlotsHtml, latencyHtml);
sessionVals.scheduled_start = session.pretty_scheduled_start_with_timezone;
var $row = $(context.JK.fillTemplate($inactiveSessionTemplate.html(), sessionVals));
var $offsetParent = $(tbGroup).closest('.content');
var $latencyBadge = $row.find('.latency-value');
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);
var showRsvpLink = true;
var noLinkText = '';
if (approvedRsvpId) {
showRsvpLink = false;
noLinkText = $('<span class="text">You have been confirmed for this session. <a href="#">Cancel</a></span>');
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 = $('<span class="text">You have RSVP\'ed to this session. <a href="#">Cancel</a></span>');
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 = '<span class="text">No more openings in this session.</span>';
}
else if (!openRsvps && !hasInvitation) {
showRsvpLink = false;
noLinkText = '<span class="text">You need an invitation to RSVP to this session.</span>';
}
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, rsvpUsersHtml, openSlotsHtml, latencyHtml) {
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: rsvpUsersHtml.length > 0 ? rsvpUsersHtml : 'N/A',
open_slots: openSlotsHtml.length > 0 ? openSlotsHtml : 'No slots available',
latency: latencyHtml,
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 += '<img src="' + inst + '" width="24" height="24" />&nbsp;';
}
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
};
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) {
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 += '<img src="' + inst + '" width="24" height="24" />&nbsp;';
}
}
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
};
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);
}
this.renderActiveSession = renderActiveSession;
this.renderInactiveSession = renderInactiveSession;
return this;
}})(window,jQuery);