VRFS-201 create session screen

This commit is contained in:
Brian Smith 2013-01-13 20:43:48 -05:00
parent 6dab346305
commit 55f5053a4a
7 changed files with 224 additions and 158 deletions

View File

@ -84,42 +84,63 @@ Message from Seth on sequence for creating/joining sessions:
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 = $('#description').val();
if (!description) {
errors.push(['#description', "Please enter a description."]);
}
// Description can't be empty
var description = $('textarea[name="description"]').val();
if (!description) {
errors.push(['textarea[name="description"]', "Please enter a description."]);
var genres = getSelectedGenres();
if (genres.length == 0) {
errors.push(['#genre-list-items', "Please select a genre."]);
}
if (genres.length > 3) {
errors.push(['#genre-list-items', "No more than 3 genres are allowed."]);
}
return (errors.length) ? errors : null;
}
function getSelectedGenres() {
var selectedGenres = [];
$('#genre-list-items :checked').each(function() {
selectedGenres.push($(this).val());
});
return selectedGenres;
}
function submitForm(evt) {
evt.preventDefault();
evt.preventDefault();
var formErrors = validateForm();
if (formErrors) {
app.notify({
title: "Form Problems",
title: "Validation Errors",
text: JSON.stringify(formErrors)
});
return false;
}
var $this = $(evt.currentTarget);
logger.debug($this.length);
var data = $this.formToObject();
var data = {};
data.client_id = app.clientId;
data.description = $('#description').val()
data.as_musician = true;
data.legal_terms = true; // this overrides the default of 'on', which isn't satisfying our concept of boolean
if (typeof(data.genres) === "string") {
data.genres = [data.genres];
data.legal_terms = true; // this overrides the default of 'on', which isn't satisfying our concept of boolean
data.genres = getSelectedGenres();
data.musician_access = $('#musician-access option:selected').val() === "true" ? true : false;
data.approval_required = $("input[name='musician-access-option']:checked").val() === "true" ? true : false;
data.fan_access = $('#fan-access option:selected').val() === "true" ? true : false;
data.fan_chat = $("input[name='fan-chat-option']:checked").val() === "true" ? true : false;
if ($('#band-list option:selected').val() != '') {
data.band = $('#band-list option:selected').val();
}
// FIXME: Hard-code tracks for now. Needs to default to:
@ -131,20 +152,7 @@ Message from Seth on sequence for creating/joining sessions:
{ 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 jsonData = JSON.stringify(data);
var url = "/api/sessions";
$.ajax({
@ -199,36 +207,68 @@ Message from Seth on sequence for creating/joining sessions:
$('#added-invitations').on("click", ".invitation span", removeInvitation);
$('#genre-list-header').on("click", toggleGenreBox);
$('#genre-list-arrow').on("click", toggleGenreBox);
$('#genre-list-items input[type=checkbox]').each(function() {
$(this).on("click", updateGenreCount);
});
$('#musician-access').change(toggleMusicianAccess);
$('#fan-access').change(toggleFanAccess);
}
// Used to disable checkboxes once 3 genres are selected.
function updateGenreCount() {
var genreCount = parseInt($('#genre-count').val());
if ($(this).attr('checked')) {
genreCount++;
}
else {
genreCount--;
}
$('#genre-count').val(genreCount);
var disabled = false;
if (genreCount == 3) {
disabled = true;
}
$('#genre-list-items input[type=checkbox]').each(function() {
if (!$(this).attr('checked')) {
if (disabled) {
$(this).attr('disabled', 'disabled');
}
else {
$(this).removeAttr('disabled');
}
}
});
}
function removeInvitation(evt) {
$(evt.currentTarget).closest('.invitation').remove();
}
function toggleMusicianAccess() {
var value = $("#musician-access option:selected").val();
if (value == "private") {
$("[name='musician-access-option']").attr('disabled', 'disabled');
$("[name='musician-access-option']").parent().addClass("op50");
if (value == "false") {
$("input[name='musician-access-option']").attr('disabled', 'disabled');
$("input[name='musician-access-option']").parent().addClass("op50");
}
else {
$("[name='musician-access-option']").removeAttr('disabled');
$("[name='musician-access-option']").parent().removeClass("op50");
$("input[name='musician-access-option']").removeAttr('disabled');
$("input[name='musician-access-option']").parent().removeClass("op50");
}
}
function toggleFanAccess() {
var value = $("#fan-access option:selected").val();
if (value == "private") {
$("[name='fan-chat-option']").attr('disabled', 'disabled');
$("[name='fan-chat-option']").parent().addClass("op50");
if (value == "false") {
$("input[name='fan-chat-option']").attr('disabled', 'disabled');
$("input[name='fan-chat-option']").parent().addClass("op50");
}
else {
$("[name='fan-chat-option']").removeAttr('disabled');
$("[name='fan-chat-option']").parent().removeClass("op50");
$("input[name='fan-chat-option']").removeAttr('disabled');
$("input[name='fan-chat-option']").parent().removeClass("op50");
}
}
@ -237,6 +277,7 @@ Message from Seth on sequence for creating/joining sessions:
$.ajax({
type: "GET",
url: url,
async: false, // do this synchronously so the event handlers in events() can be wired up
success: genresLoaded
});
}
@ -246,7 +287,6 @@ Message from Seth on sequence for creating/joining sessions:
var template = $('#template-genre-option').html();
var genreOptionHtml = context.JK.fillTemplate(template, {value: this.id, label: this.description});
$('#genre-list-items').append(genreOptionHtml);
//$('#genre-list-items').append("<div class='list-item-text'><input type='checkbox' name='" + this.id + "'>" + this.description + "</div>");
});
}
@ -281,8 +321,24 @@ Message from Seth on sequence for creating/joining sessions:
});
}
function loadFriends() {
var url = "/api/users/" + context.JK.currentUserId + "/friends";
$.ajax({
type: "GET",
url: url,
success: friendsLoaded
});
}
function friendsLoaded(response) {
$.each(response, function() {
$('#hdn-friends').append();
$('#band-list').append(bandOptionHtml);
});
}
function enterText(div,v) {
cv = $(div).value;
cv = $(dcreateSessioniv).value;
if (cv != v && v != '' && cv != '') {
$(div).value = cv;
}
@ -292,8 +348,8 @@ Message from Seth on sequence for creating/joining sessions:
}
function initialize() {
events();
loadGenres();
events();
loadBands();
var screenBindings = { 'afterShow': afterShow, 'beforeShow': beforeShow };
app.bindScreen('createSession', screenBindings);
@ -303,10 +359,10 @@ Message from Seth on sequence for creating/joining sessions:
this.initialize = initialize;
this.resetForm = resetForm;
this.submitForm = submitForm;
this.validateForm = validateForm;
this.loadGenres = loadGenres;
this.loadBands = loadBands;
this.validateForm = validateForm;
this.toggleGenreBox = toggleGenreBox;
this.loadFriends = loadFriends;
return this;
};

View File

@ -1,23 +1,3 @@
.content-scroller {
height:inherit;
position:relative;
display:block;
overflow:auto;
}
.content-wrapper {
padding:20px 30px 20px 36px;
font-size:15px;
color:#ccc;
border-bottom: dotted 1px #444;
}
.content-wrapper h2 {
color:#fff;
font-weight:600;
font-size:24px;
}
.session-left {
width:50%;
float:left;
@ -55,18 +35,6 @@
display:block;
}
.invite-friend {
margin:0px 4px 4px 4px;
float:left;
display:block;
background-color:#666;
color:#fff;
font-size:12px;
-webkit-border-radius: 7px;
border-radius: 7px;
padding:2px 2px 2px 4px;
}
div.friendbox {
background-color:#c5c5c5;
border:none;
@ -80,4 +48,16 @@ div.friendbox input[type=text] {
box-shadow: inset 0px 0px 0px 0px #888;
color:#666;
font-style:italic;
}
.invite-friend {
margin:0px 4px 4px 4px;
float:left;
display:block;
background-color:#666;
color:#fff;
font-size:12px;
-webkit-border-radius: 7px;
border-radius: 7px;
padding:2px 2px 2px 4px;
}

View File

@ -250,4 +250,12 @@ input[type="text"] {
.op50 {
opacity: .5;
-ms-filter: "alpha(opacity=50)";
}
.left {
float:left;
}
.right {
float:right;
}

View File

@ -8,16 +8,75 @@
.screen.secondary {
border: 1px solid $ColorScreenPrimary;
background-color:$ColorScreenBackground;
.footer button {
margin:1em 0em 1em 1em;
}
.breadcrumb {
margin-bottom:3em;
}
.breadcrumb p {
float:left;
}
p {
margin: 1em;
cursor: pointer;
font-size: 120%;
line-height: 150%;
}
ul {
margin-left: 2em;
list-style: disc;
}
li {
margin-bottom:1.5em;
}
p.current {
font-weight: bold;
}
}
.content {
background-color: #353535;
clear: both;
float: left;
height: auto;
width: auto;
position:relative;
}
.content-scroller {
height:inherit;
position:relative;
display:block;
overflow:auto;
}
.content-wrapper {
padding:20px 30px 20px 36px;
font-size:15px;
color:#ccc;
border-bottom: dotted 1px #444;
}
.content-wrapper h2 {
color:#fff;
font-weight:600;
font-size:24px;
}
.content-head {
height:21px;
padding:4px;
background-color:#ED3618;
h1 {
margin: -6px 0px 0px 0px;
margin: -3px 0px 0px 0px;
padding:0;
float:left;
font-weight:100;
@ -72,36 +131,6 @@
z-index:5;
background-color:$translucent1;
width:100%;
/*text-align:right;*/
}
.screen.secondary .footer button {
margin:1em 0em 1em 1em;
}
.screen.secondary .breadcrumb {
margin-bottom:3em;
}
.screen.secondary .breadcrumb p {
float:left;
}
.screen.secondary p {
margin: .5em;
cursor: pointer;
font-size: 120%;
}
.screen.secondary p.current {
font-weight: bold;
}
.left {
float:left;
}
.right {
float:right;
}
textarea {

View File

@ -18,7 +18,7 @@
<h2>session info</h2>
<br />
Description:<br />
<textarea rows=4 class="session-description"></textarea>
<textarea rows=4 id="description" name="description" class="session-description"></textarea>
<br />
<br />
<div class="left mr20">
@ -29,13 +29,14 @@
</div>
<a class="arrow-down" id="genre-list-arrow"></a>
<div id="genre-list-items" class="list-items">
</div>
</div>
<input id="genre-count" type="hidden" value="0" />
</div>
</div>
<div class="left">
Band:<br />
<select id="band-list">
<option>Not a Band Session</option>
<option value="">Not a Band Session</option>
</select>
</div>
@ -44,24 +45,24 @@
Musician Access:<br />
<select id="musician-access" class="left mr20">
<option selected="selected" value="public">Public</option>
<option value="private">Private</option>
<option selected="selected" value="true">Public</option>
<option value="false">Private</option>
</select>
<div class="left">
<input type="radio" name="musician-access-option" checked="checked" />&nbsp;Open&nbsp;&nbsp;
<input type="radio" name="musician-access-option" />&nbsp;By Approval
<input type="radio" name="musician-access-option" checked="checked" value="false" />&nbsp;Open&nbsp;&nbsp;
<input type="radio" name="musician-access-option" value="true" />&nbsp;By Approval
</div>
<br clear="all" /><br />
Fan Access:<br />
<select id="fan-access" class="left mr20">
<option value="public">Public</option>
<option selected="selected" value="private">Private</option>
<option value="true">Public</option>
<option selected="selected" value="false">Private</option>
</select>
<div class="left op50">
<input type="radio" name="fan-chat-option" disabled="disabled" />&nbsp;Chat&nbsp;&nbsp;
<input type="radio" name="fan-chat-option" disabled="disabled" />&nbsp;No Fan Chat
<input type="radio" name="fan-chat-option" value="true" disabled="disabled" />&nbsp;Chat&nbsp;&nbsp;
<input type="radio" name="fan-chat-option" checked="checked" value="false" disabled="disabled" />&nbsp;No Fan Chat
</div>
</div>
<!-- right column -->
@ -72,9 +73,16 @@
<br />
<!-- friend invitation box -->
<div class="friendbox">
<div class="invite-friend">Brian Smith
<a href="#">
<%= image_tag "shared/icon_delete_sm.png", :size => "13x13", :align => "texttop" %>
</a>
</div>
<input id="friend-input" type="text" value="Type a friend's name" onfocus="enterText(this.id,'')" onblur="enterText(this.id,'Type a friend\'s name')" />
<div class="clearall"></div>
</div>
<input id="hdn-friends" type="hidden" />
<input id="hdn-selected-friends" type="hidden" />
<br />
Invite friends and contacts to join you on JamKazam from:<br /><br />
<div class="left mr20">
@ -104,34 +112,22 @@
<br clear="all" />
</div>
</div>
<!--<div class="body">
<div class="formrow">
<div id="added-invitations"></div>
<div id="invitation-controls">
<label>Musician Invitations
<input id="invitations" type="text"/>
</label>
</div>
</div>
</div>
<div class="footer">
<input type="submit" id="btn-create-session" value="JAM!"/>
<button layout-link="home">CANCEL</button>
</div>-->
</form>
</div>
</div>
<!-- Added Invitation Template -->
<script type="text/template" id="template-added-invitation">
<div class="invitation" user-id="{userId}">{userName} <span>X</span></div>
<div class="invite-friend">{name}
<a href="#">
<%= image_tag "shared/icon_delete_sm.png", :size => "13x13", :align => "texttop" %>
</a>
</div>
</script>
<!-- Genre option template -->
<script type="text/template" id="template-genre-option">
<div class="list-item-text"><input type="checkbox" name="{value}"> {label}</div>
<div class="list-item-text"><input type="checkbox" value="{value}"> {label}</div>
</script>
<!-- Band option template -->

View File

@ -20,15 +20,13 @@ When /^I create a public music session$/ do
page.find("[layout-link='createSession']").click
sleep 1
# fill out minimially required elements of the form
page.choose 'music_access_true' # public session
# pick a genre, any genre
page.select 'African', :from => 'genres'
page.find("input[value='african']").click
#page.select 'african', :from => 'genre-list-items'
page.fill_in 'description', :with => @session_description
# create the session
click_button 'Create Session'
click_button 'btn-create-session'
# verify that the 'in-session' page is showing, with our description showing
page.find("#session-info").should have_content @session_description

View File

@ -13,13 +13,13 @@
var selectors = {
form: '#create-session-form',
genres: '#create-session-form select[name="genres"]',
description: '#create-session-form textarea[name="description"]'
genres: '#genre-list-items',
description: '#description'
};
function makeValid() {
var genre = '<option selected="selected" value="1">1</option>';
$(selectors.genres).html(genre);
var genre = '<div class="list-item-text"><input type="checkbox" checked="checked" value="1">1</div>';
$(selectors.genres).append(genre);
$(selectors.description).val('XYZ');
}
@ -47,7 +47,7 @@
});
it("should populate genres select", function() {
css.loadGenres();
expect($(selectors.genres + ' option').length).toEqual(2);
expect($(selectors.genres + ' .list-item-text').length).toEqual(2);
});
});
@ -111,7 +111,6 @@
describe("validateForm", function() {
beforeEach(function() {
makeValid();
});
@ -122,18 +121,18 @@
});
it("should fail with > 3 genres", function() {
var htm = '<option selected="selected" value="1">1</option>' +
'<option selected="selected" value="2">2</option>' +
'<option selected="selected" value="3">3</option>' +
'<option selected="selected" value="4">4</option>';
$(selectors.genres).html(htm);
var htm = '<div class="list-item-text"><input type="checkbox" checked="checked" value="2">2</div>' +
'<div class="list-item-text"><input type="checkbox" checked="checked" value="3">3</div>' +
'<div class="list-item-text"><input type="checkbox" checked="checked" value="4">4</div>' +
'<div class="list-item-text"><input type="checkbox" checked="checked" value="5">5</div>';
$(selectors.genres).append(htm);
var errs = css.validateForm();
// Verify that we have an error.
expect(errs).toBeTruthy();
// Verify that the error is a two-part list
expect(errs[0].length).toEqual(2);
// Verify that the first part is a selector for the problem.
expect(errs[0][0]).toEqual('select[name="genres"]');
expect(errs[0][0]).toEqual('#genre-list-items');
});
it("should fail with 0 genres", function() {
@ -142,7 +141,7 @@
// Verify that we have an error.
expect(errs).toBeTruthy();
// Verify that the first part is a selector for the problem.
expect(errs[0][0]).toEqual('select[name="genres"]');
expect(errs[0][0]).toEqual('#genre-list-items');
});
it("should fail with empty description", function() {
@ -151,7 +150,7 @@
// Verify that we have an error.
expect(errs).toBeTruthy();
// Verify that the first part is a selector for the problem.
expect(errs[0][0]).toEqual('textarea[name="description"]');
expect(errs[0][0]).toEqual('#description');
});
});