VRFS-212 Find Session work

This commit is contained in:
Brian Smith 2013-01-21 00:52:28 -05:00
parent c8f0695a54
commit bf7e16abee
26 changed files with 580 additions and 382 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -6,24 +6,11 @@
context.JK.CreateSessionScreen = function(app) {
var logger = context.JK.logger;
var realtimeMessaging = context.JK.JamServer;
var genreSelector;
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
*/
var MAX_GENRES = 3;
function beforeShow(data) {
usernames = [];
@ -31,55 +18,12 @@ Message from Seth on sequence for creating/joining sessions:
resetForm();
}
/**
* Reset form to initial state.
*/
function resetForm() {
var $form = $('#create-session-form');
$('textarea[name="description"]', $form).val('');
genreSelector.reset();
}
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.
var 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 = context.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');
@ -90,28 +34,19 @@ Message from Seth on sequence for creating/joining sessions:
errors.push(['#description', "Please enter a description."]);
}
var genres = getSelectedGenres();
var genres = genreSelector.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."]);
if (genres.length > MAX_GENRES) {
errors.push(['#genre-list-items', "No more than " + MAX_GENRES + "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();
@ -131,7 +66,7 @@ Message from Seth on sequence for creating/joining sessions:
data.as_musician = true;
data.legal_terms = true; // this overrides the default of 'on', which isn't satisfying our concept of boolean
data.genres = getSelectedGenres();
data.genres = genreSelector.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;
@ -204,43 +139,33 @@ Message from Seth on sequence for creating/joining sessions:
function events() {
$('#create-session-form').submit(submitForm);
$('#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);
});
//$('#added-invitations').on("click", ".invitation span", removeInvitation);
$('#musician-access').change(toggleMusicianAccess);
$('#fan-access').change(toggleFanAccess);
// friend input focus
$('#friend-input').focus(function() {
$(this).val('');
});
// friend input blur
// $('#friend-input').blur(function() {
// $(this).val('Type a friend\'s name');
// $('#friend-search-results').attr('style', 'display:none');
// });
// friend input change
$('#friend-input').keyup(function() {
//<span onclick="addFriend(this);">
searchFriends($(this).val());
});
}
// 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 addInvitation() {
alert(target);
var template = $('#template-added-invitation').html();
var inviteHtml = context.JK.fillTemplate(template, {userId: this.id, userName: 'Text'});
$('#friend-input').prepend(inviteHtml);
}
function removeInvitation(evt) {
@ -271,38 +196,6 @@ Message from Seth on sequence for creating/joining sessions:
}
}
function loadGenres() {
var url = "/api/genres";
$.ajax({
type: "GET",
url: url,
async: false, // do this synchronously so the event handlers in events() can be wired up
success: genresLoaded
});
}
function genresLoaded(response) {
$.each(response, function() {
var template = $('#template-genre-option').html();
var genreOptionHtml = context.JK.fillTemplate(template, {value: this.id, label: this.description});
$('#genre-list-items').append(genreOptionHtml);
});
}
function toggleGenreBox() {
var boxHeight = $('#genre-list').css("height");
// TODO: clean this up (check class name of arrow to determine current state)
if (boxHeight == "20px") {
$('#genre-list').css({height: "auto"});
$('#genre-list-arrow').removeClass("arrow-down").addClass("arrow-up");
}
else {
$('#genre-list').css({height: "20px"});
$('#genre-list-arrow').removeClass("arrow-up").addClass("arrow-down");
}
}
function loadBands() {
var url = "/api/users/" + context.JK.currentUserId + "/bands";
$.ajax({
@ -320,37 +213,42 @@ Message from Seth on sequence for creating/joining sessions:
});
}
function loadFriends() {
var url = "/api/users/" + context.JK.currentUserId + "/friends";
function searchFriends(query) {
if (query.length < 2) {
$('#friend-search-results').empty();
return;
}
var url = "/api/search?query=" + query + "&userId=" + context.JK.currentUserId;
$.ajax({
type: "GET",
url: url,
success: friendsLoaded
success: friendSearchComplete
});
}
function friendsLoaded(response) {
$.each(response, function() {
$('#hdn-friends').append();
$('#band-list').append(bandOptionHtml);
});
}
function friendSearchComplete(response) {
// reset search results each time
$('#friend-search-results').empty();
function enterText(div,v) {
cv = $(dcreateSessioniv).value;
if (cv != v && v != '' && cv != '') {
$(div).value = cv;
}
else {
$(div).value = v;
}
// loop through each
$.each(response.friends, function() {
// only show friends who are musicians
if (this.musician === true) {
var template = $('#template-friend-search-results').html();
var searchResultHtml = context.JK.fillTemplate(template, {userId: this.id, name: this.first_name + ' ' + this.last_name});
$('#friend-search-results').append(searchResultHtml);
$('#friend-search-results').attr('style', 'display:block');
}
});
}
function initialize() {
loadGenres();
genreSelector = new context.JK.GenreSelector(app);
genreSelector.initialize('Choose up to ' + MAX_GENRES + ' genres', MAX_GENRES, $('#create-session-form'));
events();
loadBands();
var screenBindings = { 'afterShow': afterShow, 'beforeShow': beforeShow };
var screenBindings = { 'beforeShow': beforeShow };
app.bindScreen('createSession', screenBindings);
}
@ -359,9 +257,9 @@ Message from Seth on sequence for creating/joining sessions:
this.resetForm = resetForm;
this.submitForm = submitForm;
this.validateForm = validateForm;
this.loadGenres = loadGenres;
this.loadBands = loadBands;
this.loadFriends = loadFriends;
this.searchFriends = searchFriends;
this.addInvitation = addInvitation;
return this;
};

View File

@ -4,9 +4,17 @@
context.JK = context.JK || {};
context.JK.FindSessionScreen = function(app) {
var CATEGORY = {
INVITATION : {index:0, id:"sessions-invitations"},
FRIENDS : {index:1, id:"sessions-friends"},
OTHER : {index:2, id:"sessions-other"}
};
var logger = context.JK.logger;
var sessionLatency;
var genreSelector;
var sessions = {};
var sessionList
var selectors = {
TABLE_BODY: '#findSession-tableBody'
};
@ -45,7 +53,7 @@
*/
function renderSession(sessionId) {
var $tb = $(selectors.TABLE_BODY);
var rowTemplate = $('#template-findSession-row').html();
var rowTemplate = $('#template-session-row').html();
var session = sessions[sessionId];
var latencyInfo = sessionLatency.sessionInfo(sessionId);
var audience = "Open to Fans";
@ -101,6 +109,9 @@
* Initialize, providing an instance of the SessionLatency class.
*/
function initialize(_sessionLatency) {
genreSelector = new context.JK.GenreSelector(app);
genreSelector.initialize('Any genre', 0, $('#find-session-form'));
if (_sessionLatency) {
sessionLatency = _sessionLatency;
} else {
@ -114,13 +125,13 @@
}
this.initialize = initialize;
this.afterShow = afterShow;
this.renderSession = renderSession;
// Following exposed for easier testing.
this.setSession = setSession;
this.selectors = selectors;
return this;
};
})(window,jQuery);

View File

@ -0,0 +1,114 @@
(function(context,$) {
/**
* Javascript for managing the genre selector.
*/
"use strict";
context.JK = context.JK || {};
context.JK.GenreSelector = function(app) {
var _logger = context.JK.logger;
var _maxSelections = 0;
var _form; // identifies the form containing the genre selector
function loadGenres() {
var url = "/api/genres";
$.ajax({
type: "GET",
url: url,
async: false, // do this synchronously so the event handlers in events() can be wired up
success: genresLoaded
});
}
function reset() {
$('#genre-list-items input[type=checkbox]', _form).removeAttr('checked');
$('#genre-list-items input[type=checkbox]', _form).removeAttr('disabled');
}
function genresLoaded(response) {
$.each(response, function(index) {
var template = $('#template-genre-option', _form).html();
var genreOptionHtml = context.JK.fillTemplate(template, {value: this.id, label: this.description});
$('#genre-list-items', _form).append(genreOptionHtml);
});
}
function toggleGenreBox() {
var boxHeight = $('#genre-list', _form).css("height");
// TODO: clean this up (check class name of arrow to determine current state)
if (boxHeight == "20px") {
$('#genre-list', _form).css({height: "auto"});
$('#genre-list-arrow', _form).removeClass("arrow-down").addClass("arrow-up");
}
else {
$('#genre-list', _form).css({height: "20px"});
$('#genre-list-arrow', _form).removeClass("arrow-up").addClass("arrow-down");
}
}
// Used to disable checkboxes once _maxSelections are selected.
function updateGenreCount() {
var genreCount = parseInt($('#genre-count', _form).val());
if ($(this).attr('checked')) {
genreCount++;
}
else {
genreCount--;
}
$('#genre-count', _form).val(genreCount);
var disabled = false;
if (_maxSelections != 0 && genreCount == _maxSelections) {
disabled = true;
}
$('#genre-list-items input[type=checkbox]', _form).each(function() {
if (!$(this).attr('checked')) {
if (disabled) {
$(this).attr('disabled', 'disabled');
}
else {
$(this).removeAttr('disabled');
}
}
});
}
function getSelectedGenres() {
var selectedGenres = [];
$('#genre-list-items :checked', _form).each(function() {
selectedGenres.push($(this).val());
});
return selectedGenres;
}
function events() {
$('#genre-list-header', _form).on("click", toggleGenreBox);
$('#genre-list-arrow', _form).on("click", toggleGenreBox);
$('#genre-list-items input[type=checkbox]', _form).each(function() {
$(this).on("click", updateGenreCount);
});
}
function initialize(title, maxSelections, form) {
_form = form;
_maxSelections = maxSelections;
$('#genre-list-header', _form).text(title);
loadGenres();
events();
};
this.initialize = initialize;
this.getSelectedGenres = getSelectedGenres;
this.reset = reset;
return this;
};
})(window,jQuery);

View File

View File

@ -1,24 +1,28 @@
.session-left {
width:50%;
width:45%;
float:left;
padding-top:10px;
margin-left:35px;
}
.session-right {
width:45%;
float:right;
font-size:13px;
padding-top:10px;
margin-right:10px;
}
.session-description {
padding:5px;
width:100%;
width:80%;
height:80px;
}
.friendbox {
padding:5px;
width:100%;
height:60px;
width:75%;
}
.terms-checkbox {

View File

@ -3,3 +3,90 @@ div[layout-id="findSession"] {
th, td { margin: 4px; padding:4px; }
}
.session-filter {
width:100%;
padding:11px 0px 11px 0px;
background-color:#4c4c4c;
min-height:20px;
overflow-x:hidden;
}
table.findsession-table {
margin-top:6px;
width:100%;
font-size:11px;
color:#fff;
background-color:#262626;
border:solid 1px #4d4d4d;
}
.findsession-table th {
font-weight:300;
background-color:#4d4d4d;
padding:6px;
border-right:solid 1px #333;
}
.findsession-table td {
padding:9px 5px 5px 5px;
border-right:solid 1px #333;
border-top:solid 1px #333;
vertical-align:top;
white-space:normal;
}
.findsession-table .noborder {
border-right:none;
}
.findsession-table .musicians {
margin-top:-3px;
}
.findsession-table .musicians td {
border-right:none;
border-top:none;
padding:3px;
vertical-align:middle;
}
.findsession-table a {
color:#fff;
text-decoration:none;
}
.findsession-table a:hover {
color:#227985;
}
.latency-green {
width: 50px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:9px;
text-align:center;
background-color:#72a43b;
}
.latency-yellow {
width: 50px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:9px;
text-align:center;
background-color:#cc9900;
}
.latency-red {
width: 50px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:9px;
text-align:center;
text-align:center;
background-color:#980006;
}

View File

@ -57,11 +57,6 @@ a.arrow-down {
border-top: 7px solid #333;
}
form {
clear:both;
margin: 1em;
}
form .body {
/* TODO - size with layout */
width: 100%;
@ -70,18 +65,6 @@ form .body {
overflow:auto;
}
fieldset {
/*border: 1px solid #555;*/
/*padding: 1em;*/
/*margin: 2em 1em;*/
/*width:auto;*/
/*float:left;*/
}
fieldset.unstyled {
border: 1px solid #f00;
}
.formrow {
margin: 1em;
padding: 1em;
@ -222,6 +205,24 @@ input[type="button"] {
width:135px;
}
.search-box {
float:left;
width:140px;
margin-left: 10px;
-webkit-border-radius: 6px;
border-radius: 6px;
background-color:#C5C5C5;
border: none;
color:#333;
font-weight:400;
padding:0px 0px 0px 8px;
height:20px;
line-height:20px;
overflow:hidden;
-webkit-box-shadow: inset 2px 2px 3px 0px #888;
box-shadow: inset 2px 2px 3px 0px #888;
}
input[type="text"] {
background-color: $ColorTextBoxBackground;
}
@ -250,6 +251,10 @@ input[type="text"] {
margin-left:30px;
}
.ml35 {
margin-left:35px;
}
.op50 {
opacity: .5;
-ms-filter: "alpha(opacity=50)";

View File

@ -43,34 +43,13 @@
}
.content {
background-color: #353535;
clear: both;
float: left;
height: auto;
width: auto;
height: 100%;
width: 100%;
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;
@ -121,10 +100,29 @@
border-bottom: 7px solid transparent;
border-right:7px solid #FFF;
}
}
}
.content-scroller {
height:inherit;
position:relative;
display:block;
overflow:auto;
}
.content-wrapper {
padding: 0px 0px 0px 0px;
font-size: 15px;
color: #ccc;
border-bottom: dotted 1px #444;
}
.content-wrapper h2 {
color:#fff;
font-weight:600;
font-size:24px;
}
.buttonrow, .screen.secondary .footer {
position: absolute;
bottom:0px;

View File

@ -0,0 +1,97 @@
table.findsession-table {
margin-top:6px;
width:100%;
font-size:11px;
color:#fff;
background-color:#262626;
border:solid 1px #4d4d4d;
}
.findsession-table th {
font-weight:300;
background-color:#4d4d4d;
padding:6px;
border-right:solid 1px #333;
}
.findsession-table td {
padding:9px 5px 5px 5px;
border-right:solid 1px #333;
border-top:solid 1px #333;
vertical-align:top;
white-space:normal;
}
.findsession-table .noborder {
border-right:none;
}
.findsession-table .musicians {
margin-top:-3px;
}
.findsession-table .musicians td {
border-right:none;
border-top:none;
padding:3px;
vertical-align:middle;
}
.findsession-table a {
color:#fff;
text-decoration:none;
}
.findsession-table a:hover {
color:#227985;
}
.latency-green {
width: 50px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:9px;
text-align:center;
background-color:#72a43b;
}
.latency-yellow {
width: 50px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:9px;
text-align:center;
background-color:#cc9900;
}
.latency-red {
width: 50px;
height: 10px;
font-family:Arial, Helvetica, sans-serif;
font-weight:200;
font-size:9px;
text-align:center;
text-align:center;
background-color:#980006;
}
.avatar-tiny {
float:left;
padding:1px;
width:24px;
height:24px;
background-color:#ed3618;
-webkit-border-radius:12px;
-moz-border-radius:12px;
border-radius:12px;
}
.avatar-tiny img {
width: 24px;
height: 24px;
-webkit-border-radius:12px;
-moz-border-radius:12px;
border-radius:12px;
}

View File

@ -6,7 +6,12 @@ class ApiSearchController < ApiController
respond_to :json
def index
@search = Search.search(params[:query])
if (params[:userId] == nil)
@search = Search.search(params[:query])
# TODO: fix this hack to accommodate friend searches
else
@search = Search.search(params[:query], params[:userId])
end
end
end

View File

@ -1,17 +1,31 @@
object @search
child(:bands => :bands) {
attributes :id, :name, :location, :photo_url, :logo_url
}
unless @search.bands.nil? || @search.bands.size == 0
child(:bands => :bands) {
attributes :id, :name, :location, :photo_url, :logo_url
}
end
child(:musicians => :musicians) {
attributes :id, :first_name, :last_name, :location, :photo_url
}
unless @search.musicians.nil? || @search.musicians.size == 0
child(:musicians => :musicians) {
attributes :id, :first_name, :last_name, :location, :photo_url
}
end
child(:fans => :fans) {
attributes :id, :first_name, :last_name, :location, :photo_url
}
unless @search.fans.nil? || @search.fans.size == 0
child(:fans => :fans) {
attributes :id, :first_name, :last_name, :location, :photo_url
}
end
child(:recordings => :recordings) {
attributes :id, :name
}
unless @search.recordings.nil? || @search.recordings.size == 0
child(:recordings => :recordings) {
attributes :id, :name
}
end
unless @search.friends.nil? || @search.friends.size == 0
child(:friends => :friends) {
attributes :id, :first_name, :last_name, :city, :state, :country, :email, :online, :photo_url, :musician
}
end

View File

@ -23,15 +23,7 @@
<br />
<div class="left mr20">
Genre:<br />
<div id="genre-list" class="multiselect-dropdown">
<div class="list-item-text">
<a id="genre-list-header">Choose up to 3 genres</a>
</div>
<a class="arrow-down" id="genre-list-arrow"></a>
<div id="genre-list-items" class="list-items">
</div>
<input id="genre-count" type="hidden" value="0" />
</div>
<%= render "genreSelector" %>
</div>
<div class="left">
Band:<br />
@ -73,15 +65,11 @@
<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>
<input id="friend-input" type="text" value="Type a friend's name" /><br />
<div id="friend-search-results">
</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 />
@ -119,143 +107,20 @@
<!-- Added Invitation Template -->
<script type="text/template" id="template-added-invitation">
<div class="invite-friend">{name}
<a href="#">
<a href="#" id="{userId}" onclick="removeInvitation();">
<%= 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" value="{value}"> {label}</div>
<!-- Friend Search Result Template -->
<script type="text/template" id="template-friend-search-results">
<div>
<a href="#" id="{userId}" onclick="addInvitation();">{name}</a>
</div>
</script>
<!-- Band option template -->
<script type="text/template" id="template-band-option">
<option value="{value}">{label}</option>
</script>
<!-- Create Session:Audio Screen -->
<!-- Keeping as this will move into a user settings dialog... -->
<div layout="screen" layout-id="createSessionAudio" class="screen secondary">
<div class="breadcrumb">
<p layout-link="home">Home &gt; </p>
<p class="current">Create a Session (3/3): Audio</p>
</div>
<form>
<p>Configure your instruments, headphones or speakers, and voice chat settings. Then play your instrument and sing or speak into your microphone, and ensure you hear everything correctly before entering the session.</p>
<fieldset>
<legend>Audio Settings</legend>
<fieldset>
<legend>Instrument 1</legend>
<label>
Sound Card
<select>
<option>Internal Intel Audio</option>
<option>Tascam US-800</option>
</select>
</label>
<label>
Driver
<select>
<option>These will be tied to the sound card</option>
</select>
</label>
<label>
Input
<select>
<option>Input 1</option>
<option>Input 2</option>
<option>Input 3</option>
<option>Input 4</option>
<option>Input 5</option>
<option>Input 6</option>
</select>
</label>
<label>
Instrument
<select>
<optgroup label="High Popular">
<option>Acoustic Guitar</option>
<option>Bass Guitar</option>
<option>Computer</option>
<option>Drums</option>
<option>Electric Guitar</option>
<option>Keyboard</option>
<option>Voice</option>
</optgroup>
<optgroup label="Mid Popular">
<option>Flute</option>
<option>Clarinet</option>
<option>Saxophone</option>
<option>Trumpet</option>
<option>Violin</option>
<option>Trombone</option>
<option>Banjo</option>
<option>Harmonica</option>
<option>Accordian</option>
</optgroup>
<optgroup label="Low Popular">
<option>French Horn</option>
<option>Euphonium</option>
<option>Tuba</option>
<option>Oboe</option>
<option>Ukulele</option>
<option>Cello</option>
<option>Viola</option>
<option>Mandolin</option>
</optgroup>
</select>
</label>
<label>Other <input type="text"/></label>
<label>Gain Slider goes here</label>
<label>VU Meter goes here</label>
</fieldset>
</fieldset>
<fieldset>
<legend>Headphone/Speaker Settings</legend>
<label>
Sound Card
<select>
<option>Internal Intel Audio</option>
<option>Tascam US-800</option>
</select>
</label>
<label>
Driver
<select>
<option>These will be tied to the sound card</option>
</select>
</label>
<label>
Output
<select>
<option>Output 1</option>
<option>Output 2</option>
<option>Output 3</option>
<option>Output 4</option>
<option>Output 5</option>
<option>Output 6</option>
</select>
</label>
</fieldset>
<fieldset>
<legend>Voice Chat Settings</legend>
<label>
Sound Card
<select>
<option>Internal Intel Audio</option>
<option>Tascam US-800</option>
</select>
</label>
<label>Gain Slider goes here</label>
<label>VU Meter goes here</label>
</fieldset>
<div class="footer">
<button layout-link="createSessionInvite">Back</button>
<button layout-link="session">Jam</button>
<button layout-link="home">Cancel</button>
</div>
</form>
</div>
</script>

View File

@ -1,25 +1,55 @@
<!-- Find Session Screen -->
<div layout="screen" layout-id="findSession" class="screen secondary">
<div class="content-head">
<h1>Find a Session</h1>
<%= render "screen_navigation" %>
<div class="content">
<div class="content-head">
<div class="content-icon">
<a href="#"><%= image_tag "content/icon_search.png", :size => "19x19" %></a>
</div>
<h1>find a session</h1>
<%= render "screen_navigation" %>
</div>
<form id="find-session-form">
<div class="session-filter">
<div style="min-width:770px">
<div class="left ml35">Filter Session List:</div>
<!-- musician filter -->
<div class="ml10 left">
<div id="musician-list" class="multiselect-dropdown">
<div class="list-item-text">
<a id="musician-list-header">All musicians</a>
</div>
<a class="arrow-down" id="musician-list-arrow"></a>
<div id="musician-list-items" class="list-items">
</div>
</div>
</div>
<!-- genre filter -->
<div class="left ml10">
<%= render "genreSelector" %>
</div>
<!-- keyword filter -->
<div class="search-box">
<input id="search-session-input" type="text" name="search" value="Search by Keyword" onfocus="enterText(this.id,'')" onblur="enterText(this.id,'Search by Keyword')" />
</div>
</div>
</div>
<div class="content-scroller">
<div class="content-wrapper" style="padding-left:35px;padding-top:10px;">
<%= render :partial => "sessionList", :locals => {:title => "sessions you're invited to", :category => "sessions-invitations"} %>
<%= render :partial => "sessionList", :locals => {:title => "sessions with friends or bandmates", :category => "sessions-friends"} %>
<%= render :partial => "sessionList", :locals => {:title => "other sessions", :category => "sessions-other"} %>
</div>
</div>
</form>
</div>
<table>
<tr>
<th>Genre</th>
<th>Description</th>
<th>Musicians</th>
<th>Audience</th>
<th>Latency</th>
<th>Listen</th>
<th>Join</th>
</tr>
<tbody id="findSession-tableBody">
</tbody>
</table>
</div>
<script type="text/template" id="template-findSession-row">
<script type="text/template" id="template-session-row">
<tr data-sortScore="{sortScore}">
<td>{genres}</td>
<td>{description}</td>

View File

@ -1,3 +1,4 @@
<!-- Footer -->
<div class="footer">
<p class="left">
Copyright &copy; <%= Time.now.year %> JamKazam, Inc. All Rights Reserved.

View File

@ -0,0 +1,14 @@
<div id="genre-list" class="multiselect-dropdown">
<div class="list-item-text">
<a id="genre-list-header"></a>
</div>
<a id="genre-list-arrow" class="arrow-down" ></a>
<div id="genre-list-items" class="list-items">
</div>
<input id="genre-count" type="hidden" value="0" />
</div>
<!-- Genre option template -->
<script type="text/template" id="template-genre-option">
<div class="list-item-text"><input type="checkbox" value="{value}"> {label}</div>
</script>

View File

@ -1,3 +1,4 @@
<!-- Header -->
<div layout="header" class="header" style="display:none;">
<!-- logo -->

View File

@ -0,0 +1,52 @@
<h2><%= title %></h2>
<table id="<%= category %>" class="findsession-table" cellspacing="0" cellpadding="0" border="0">
<!-- header -->
<tr>
<th align="left" width="40">GENRE</th>
<th align="left" width="25%">DESCRIPTION</th>
<th align="left">MUSICIANS</th>
<th align="left">AUDIENCE</th>
<th width="60" align="center">LATENCY</th>
<th width="50" align="center">LISTEN</th>
<th class="noborder" width="30" align="center">JOIN</th>
</tr>
<!-- sessions -->
<tr>
<td>{genres}</td>
<td>{description}</td>
<td>
<!-- sub-table of musicians -->
<table class="musicians" cellpadding="0" cellspacing="0">
<tr>
<td width="24">
<a href="#" class="avatar-tiny">
<img src="{avatar_url}" />
</a>
</td>
<td>
<a href="{profile_url}">{musician_name}</a>
</td>
<td>
<div class="nowrap">
<img src="{instrument_logo_url}" width="24" height="24" />
</div>
</td>
</tr>
</table>
</td>
<td>{audience}</td>
<td align="center">
<div class="{latency_style}">{latency_text}</div>
</td>
<td align="center">
<a id="play-link" href="{play_url}">
<%= image_tag "content/icon_playbutton.png", :size => "20x20" %>
</a>
</td>
<td class="noborder" align="center">
<a id="join-link" href="{join_url}">
<%= image_tag "content/icon_join.png", :size => "19x22" %>
</a>
</td>
</tr>
</table>

View File

@ -1,12 +1,11 @@
<div class="curtain" style="width:100%; height:100%; z-index:9999; background-color:#ffffff;"></div>
<%= render "landing" %>
<%= render "footer" %>
<%= render "header" %>
<%= render "home" %>
<%= render "landing" %>
<%= render "ftue1" %>
<%= render "ftue2" %>
<%= render "ftue3" %>
<%= render "home" %>
<%= render "sidebar" %>
<%= render "createSession" %>
<%= render "session" %>
@ -17,6 +16,7 @@
<%= render "testBridge" %>
<%= render "account" %>
<%= render "notify" %>
<%= render "footer" %>
<script type="text/javascript">
$(function() {

View File

@ -21,6 +21,8 @@
<%= stylesheet_link_tag "client/ftue", media: "all" %>
<%= stylesheet_link_tag "client/lato", media: "all" %>
<%= stylesheet_link_tag "client/createSession", media: "all" %>
<%= stylesheet_link_tag "client/genreSelector", media: "all" %>
<%= stylesheet_link_tag "client/sessionList", media: "all" %>
<%= include_gon %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>