jam-cloud/app/assets/javascripts/createSession.js

240 lines
8.6 KiB
JavaScript

(function(context,$) {
context.JK = context.JK || {};
context.JK.CreateSessionScreen = function(app) {
var logger = context.JK.logger;
var realtimeMessaging = context.JK.JamServer;
var autoComplete = null;
var usernames = [];
var userids = [];
/*
Message from Seth on sequence for creating/joining sessions:
02:31:46 PM) Seth Call: sequence:
(02:31:53 PM) Seth Call: LOGIN websocket (get your client_id)
(02:32:02 PM) Seth Call: CRETAE SESSION
(02:32:09 PM) Seth Call: CREATE PARTICIPANT (pass in client_id)
(02:32:12 PM) Seth Call: that's it for client 1
(02:32:13 PM) Seth Call: client 2
(02:32:20 PM) Seth Call: LOGIN WEBSOCKET (get your client_id)
(02:32:29 PM) Seth Call: CREATE PARTICIPANT(pass in client_id for client2)
(02:32:31 PM) Seth Call: that's it
(02:32:43 PM) Seth Call: USER_JOINED_MUSIC_SESSION is an event from the server
(02:32:52 PM) Seth Call: and LOGIN_MUSIC_SESSION is deprecated/junk
*/
function beforeShow(data) {
usernames = [];
userids = [];
resetForm();
}
/**
* Reset form to initial state.
*/
function resetForm() {
$form = $('#create-session-form');
$('textarea[name="description"]', $form).val('');
}
function afterShow(data) {
// TODO: This won't work in the long-term. We'll need to provide
// a handlers which accepts some characters and only returns users
// who are musicians who match that input string. Once we get there,
// we could just use the ajax functionality of the autocomplete plugin.
//
// But for now:
// Load the users list into our local array for autocomplete.
$.ajax({
type: "GET",
url: "/api/users"
}).done(function(response) {
$.each(response, function() {
usernames.push(this.name);
userids.push(this.id);
});
// Hook up the autocomplete.
autoCompleteOptions = {
lookup: {suggestions:usernames, data: userids},
onSelect: addInvitation
};
if (!(autoComplete)) {
autoComplete = $('#invitations').autocomplete(autoCompleteOptions);
} else {
autoComplete.setOptions(autoCompleteOptions);
}
});
}
function addInvitation(value, data) {
var username = value;
var userid = data;
var template = $('#template-added-invitation').html(); // TODO: cache this
var inviteHtml = JK.fillTemplate(template, {userId: userid, userName: username});
$('#added-invitations').append(inviteHtml);
$('#invitations').select();
}
/**
* Validate the form, returning a list of errors.
*/
function validateForm() {
var errors = [];
var $form = $('#create-session-form');
// Genres
var genresCount = $('select[name="genres"]', $form).find(':selected').length;
if (genresCount === 0) {
errors.push(['select[name="genres"]', "Please select at least one genre."]);
}
if (genresCount > 3) {
errors.push(['select[name="genres"]', "Please select no more than three genres."]);
}
// Description can't be empty
var description = $('textarea[name="description"]').val();
if (!description) {
errors.push(['textarea[name="description"]', "Please enter a description."]);
}
return (errors.length) ? errors : null;
}
function submitForm(evt) {
evt.preventDefault();
var formErrors = validateForm();
if (formErrors) {
app.notify({
title: "Form Problems",
text: JSON.stringify(formErrors)
});
return false;
}
var $this = $(this);
var data = $this.formToObject();
data.client_id = app.clientId;
if (typeof(data.genres) === "string") {
data.genres = [data.genres];
}
// FIXME: Hard-code tracks for now. Needs to default to:
// 1. If no previous session data, a single stereo track with the
// top instrument in the user's profile.
// 2. Otherwise, use the tracks from the last created session.
data.tracks = [
{ instrument_id: "electric guitar", sound: "mono" },
{ instrument_id: "keyboard", sound: "mono" }
];
// music_session["musician_access"].should be_true
// music_session["invitations"].should == []
// music_session["fan_invitations"].should == []
// music_session["approval_required"].should be_false
// music_session["fan_chat"].should be_true
// music_session["fan_access"].should be_true
// music_session["participants"].length.should == 1
// participant = music_session["participants"][0]
// participant["ip_address"].should == client.ip_address
// participant["client_id"].should == client.client_id
// participant["tracks"].length.should == 1
// track = participant["tracks"][0]
// track["instrument_id"].should == "electric guitar"
// track["sound"].should == "mono"
var url = "/api/sessions";
$.ajax({
type: "POST",
dataType: "json",
contentType: 'application/json',
url: url,
processData:false,
data: JSON.stringify(data),
success: function(response) {
var newSessionId = response.id;
createInvitations(newSessionId, function() {
self.location = '#/session/' + newSessionId;
});
},
error: app.ajaxError
});
return false;
}
function createInvitations(sessionId, onComplete) {
var callCount = 0;
$('#added-invitations .invitation').each(function() {
callCount++;
var invite_id = $(this).attr('user-id');
var invite = {
music_session: sessionId,
receiver: invite_id
};
$.ajax({
type: "POST",
url: "/api/invitations",
data: invite
}).done(function(response) {
callCount--;
}).fail(app.ajaxError);
});
// TODO - this is the second time I've used this pattern.
// refactor to make a common utility for this.
function checker() {
if (callCount === 0) {
onComplete();
} else {
setTimeout(checker, 10);
}
}
checker();
}
function events() {
$('#create-session-form').submit(submitForm);
$('#added-invitations').on("click", ".invitation span", removeInvitation);
}
function removeInvitation(evt) {
$(this).closest('.invitation').remove();
}
function genresLoaded(response) {
var options = [];
var optionTemplate = $('#template-genre-option').html();
$.each(response, function() {
var d = {value: this.id, label: this.description};
var opt = context.JK.fillTemplate(optionTemplate, d);
options.push(opt);
});
$('#create-session-form select[name="genres"]').html(options.join(''));
}
function loadGenres() {
var url = "/api/genres";
$.ajax({
type: "GET",
url: url,
success: genresLoaded
});
}
function initialize() {
events();
loadGenres();
screenBindings = { 'afterShow': afterShow, 'beforeShow': beforeShow };
app.bindScreen('createSession', screenBindings);
}
// Expose publics
this.initialize = initialize;
this.resetForm = resetForm;
this.submitForm = submitForm;
this.loadGenres = loadGenres;
this.validateForm = validateForm;
return this;
};
})(window,jQuery);