* VRFS-778, VRFS-777, VRFS-788, VRFS-787-to create new downloads page, I needed to add a new layout 'web', and make user dropdown more reusable

This commit is contained in:
Seth Call 2013-10-19 14:46:06 -05:00
parent 33ce8f2959
commit 481514e301
69 changed files with 1108 additions and 607 deletions

View File

@ -27,7 +27,7 @@ describe InvitedUser do
end
it { should have_selector('#main_content .panel:first-child h3', text: "Invited Users Details" ); }
it { should have_selector('#main_content .panel:first-child h3', text: "Invited Users nDetails" ); }
it { UserMailer.deliveries.length.should == 1 }
end
end

View File

@ -95,7 +95,7 @@ end
gem 'rack-test'
# gem 'rb-fsevent', '0.9.1', :require => false
# gem 'growl', '1.0.3'
gem 'poltergeist' , '1.4.1' # can't go to 1.4.0 until this is fixed https://github.com/jonleighton/poltergeist/issues/385
gem 'poltergeist'
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 542 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -92,7 +92,7 @@
function deleteAvatarSuccess(response) {
renderAvatar(null, null);
JK.Header.loadMe();
JK.UserDropdown.loadMe();
rest.getUserDetail()
.done(function(userDetail) {
@ -361,7 +361,7 @@
self.userDetail = response;
// notify any listeners that the avatar changed
JK.Header.loadMe();
JK.UserDropdown.loadMe();
// $('.avatar_large img').trigger('avatar_changed', [self.userDetail.photo_url]);
app.notify(

View File

@ -1,7 +1,7 @@
(function(context,$) {
/**
* Javascript for managing the header (account dropdown) as well
* Javascript for managing the header as well
* as any dialogs reachable from there. Account settings dialog.
*/
@ -17,8 +17,7 @@
var instrumentIds = [];
var instrumentNames = [];
var instrumentPopularities = {}; // id -> popularity
var invitationDialog = new context.JK.InvitationDialog(app);
var rest = new JK.Rest();
function loadInstruments() {
// TODO: This won't work in the long-term. We'll need to provide
@ -98,45 +97,10 @@
context.location = '#/home';
});
$('.userinfo').on('click', function() {
$('ul.shortcuts', this).toggle();
});
$('.userinfo .invite-friends .menuheader').on('click', function(e) {
$(this).closest('li').css('height', 'auto').find('ul').toggle();
e.stopPropagation();
return false;
});
/**
$('.userinfo .sign-out a').on('click', function(e) {
e.stopPropagation();
/** rest.signout()
.done(function() {
})
}); */
$('.invite-friends .google-invite a').on('click', function(e) {
invitationDialog.showGoogleDialog();
});
$('.invite-friends .email-invite a').on('click', function(e) {
invitationDialog.showEmailDialog();
})
$('#account-identity-form').submit(handleIdentitySubmit);
$('#account-profile-form').submit(handleProfileSubmit);
// Remove added instruments when 'X' is clicked
$('#added-profile-instruments').on("click", ".instrument span", removeInvitation);
$('#header-avatar').on('avatar_changed', function(event, newAvatarUrl) {
updateAvatar(newAvatarUrl);
event.preventDefault();
return false;
})
}
function handleIdentitySubmit(evt) {
@ -194,52 +158,12 @@
return false;
}
function loadMe() {
$.ajax({
url: '/api/users/' + context.JK.currentUserId
}).done(function(r) {
userMe = r;
// TODO - Setting global variable for local user.
context.JK.userMe = r;
updateHeader();
}).fail(app.ajaxError);
}
function updateHeader() {
$('#user').html(userMe.name);
showAvatar();
}
// initially show avatar
function showAvatar() {
var photoUrl = context.JK.resolveAvatarUrl(userMe.photo_url);
$('#header-avatar').attr('src', photoUrl);
}
// handle update avatar event
function updateAvatar(avatar_url) {
var photoUrl = context.JK.resolveAvatarUrl(avatar_url);
var avatar = $(new Image());
avatar.attr('src', photoUrl + '?cache_bust=' + new Date().getTime());
avatar.attr('alt', "Avatar");
avatar.attr('id', 'header-avatar');
$('#header-avatar').replaceWith(avatar);
}
this.initialize = function() {
events();
loadInstruments();
loadMe();
invitationDialog.initialize();
//searcher = new context.JK.Searcher(app);
//searcher.initialize();
};
this.loadMe = loadMe;
};
})(window,jQuery);

View File

@ -28,7 +28,10 @@
var heartbeatAckCheckInterval = null;
var opts = {
layoutOpts: {}
inClient: true, // specify false if you want the app object but none of the client-oriented features
layoutOpts: {
layoutFilter: true // specify false if you want footer to be left alone
}
};
/**
@ -279,14 +282,17 @@
this.opts = $.extend(opts, inOpts);
this.layout = new context.JK.Layout();
this.layout.initialize(this.opts.layoutOpts);
registerLoginAck();
registerHeartbeatAck();
registerBadStateRecovered();
registerBadStateError();
registerSocketClosed();
events();
context.JK.FaderHelpers.initialize();
context.window.onunload = this.unloadFunction;
if(opts.inClient) {
registerLoginAck();
registerHeartbeatAck();
registerBadStateRecovered();
registerBadStateError();
registerSocketClosed();
context.JK.FaderHelpers.initialize();
context.window.onunload = this.unloadFunction;
}
};

View File

@ -1,106 +1,115 @@
/**
* hoverIntent is similar to jQuery's built-in "hover" function except that
* instead of firing the onMouseOver event immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the onMouseOver event.
*
* hoverIntent r6 // 2011.02.26 // jQuery 1.5.1+
* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
*
* hoverIntent is currently available for use in all personal or commercial
* projects under both MIT and GPL licenses. This means that you can choose
* the license that best suits your project, and use it accordingly.
*
* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
* $("ul li").hoverIntent( showNav , hideNav );
*
* // advanced usage receives configuration object only
* $("ul li").hoverIntent({
* sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
* interval: 100, // number = milliseconds of polling interval
* over: showNav, // function = onMouseOver callback (required)
* timeout: 0, // number = milliseconds delay before onMouseOut function call
* out: hideNav // function = onMouseOut callback (required)
* });
*
* @param f onMouseOver function || An object with configuration options
* @param g onMouseOut function || Nothing (use configuration options object)
* @author Brian Cherne brian(at)cherne(dot)net
*/
/*!
* hoverIntent r7 // 2013.03.11 // jQuery 1.9.1+
* http://cherne.net/brian/resources/jquery.hoverIntent.html
*
* You may use hoverIntent under the terms of the MIT license. Basically that
* means you are free to use hoverIntent as long as this header is left intact.
* Copyright 2007, 2013 Brian Cherne
*/
/* hoverIntent is similar to jQuery's built-in "hover" method except that
* instead of firing the handlerIn function immediately, hoverIntent checks
* to see if the user's mouse has slowed down (beneath the sensitivity
* threshold) before firing the event. The handlerOut function is only
* called after a matching handlerIn.
*
* // basic usage ... just like .hover()
* .hoverIntent( handlerIn, handlerOut )
* .hoverIntent( handlerInOut )
*
* // basic usage ... with event delegation!
* .hoverIntent( handlerIn, handlerOut, selector )
* .hoverIntent( handlerInOut, selector )
*
* // using a basic configuration object
* .hoverIntent( config )
*
* @param handlerIn function OR configuration object
* @param handlerOut function OR selector for delegation OR undefined
* @param selector selector OR undefined
* @author Brian Cherne <brian(at)cherne(dot)net>
*/
(function($) {
$.fn.hoverIntent = function(f,g) {
// default configuration options
var cfg = {
sensitivity: 7,
interval: 100,
timeout: 0
};
// override configuration options with user supplied object
cfg = $.extend(cfg, g ? { over: f, out: g } : f );
$.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
// instantiate variables
// cX, cY = current X and Y position of mouse, updated by mousemove event
// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
var cX, cY, pX, pY;
// default configuration values
var cfg = {
interval: 100,
sensitivity: 7,
timeout: 0
};
// A private function for getting mouse position
var track = function(ev) {
cX = ev.pageX;
cY = ev.pageY;
};
if ( typeof handlerIn === "object" ) {
cfg = $.extend(cfg, handlerIn );
} else if ($.isFunction(handlerOut)) {
cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
} else {
cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
}
// A private function for comparing current and previous mouse position
var compare = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
// compare mouse positions to see if they've crossed the threshold
if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
$(ob).unbind("mousemove",track);
// set hoverIntent state to true (so mouseOut can be called)
ob.hoverIntent_s = 1;
return cfg.over.apply(ob,[ev]);
} else {
// set previous coordinates for next time
pX = cX; pY = cY;
// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
}
};
// instantiate variables
// cX, cY = current X and Y position of mouse, updated by mousemove event
// pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
var cX, cY, pX, pY;
// A private function for delaying the mouseOut function
var delay = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
ob.hoverIntent_s = 0;
return cfg.out.apply(ob,[ev]);
};
// A private function for getting mouse position
var track = function(ev) {
cX = ev.pageX;
cY = ev.pageY;
};
// A private function for handling mouse 'hovering'
var handleHover = function(e) {
// copy objects to be passed into t (required for event object to be passed in IE)
var ev = jQuery.extend({},e);
var ob = this;
// A private function for comparing current and previous mouse position
var compare = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
// compare mouse positions to see if they've crossed the threshold
if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
$(ob).off("mousemove.hoverIntent",track);
// set hoverIntent state to true (so mouseOut can be called)
ob.hoverIntent_s = 1;
return cfg.over.apply(ob,[ev]);
} else {
// set previous coordinates for next time
pX = cX; pY = cY;
// use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
}
};
// cancel hoverIntent timer if it exists
if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
// A private function for delaying the mouseOut function
var delay = function(ev,ob) {
ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
ob.hoverIntent_s = 0;
return cfg.out.apply(ob,[ev]);
};
// if e.type == "mouseenter"
if (e.type == "mouseenter") {
// set "previous" X and Y position based on initial entry point
pX = ev.pageX; pY = ev.pageY;
// update "current" X and Y position based on mousemove
$(ob).bind("mousemove",track);
// start polling interval (self-calling timeout) to compare mouse coordinates over time
if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
// A private function for handling mouse 'hovering'
var handleHover = function(e) {
// copy objects to be passed into t (required for event object to be passed in IE)
var ev = jQuery.extend({},e);
var ob = this;
// else e.type == "mouseleave"
} else {
// unbind expensive mousemove event
$(ob).unbind("mousemove",track);
// if hoverIntent state is true, then call the mouseOut function after the specified delay
if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
}
};
// cancel hoverIntent timer if it exists
if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
// bind the function to the two event listeners
return this.bind('mouseenter',handleHover).bind('mouseleave',handleHover);
};
// if e.type == "mouseenter"
if (e.type == "mouseenter") {
// set "previous" X and Y position based on initial entry point
pX = ev.pageX; pY = ev.pageY;
// update "current" X and Y position based on mousemove
$(ob).on("mousemove.hoverIntent",track);
// start polling interval (self-calling timeout) to compare mouse coordinates over time
if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
// else e.type == "mouseleave"
} else {
// unbind expensive mousemove event
$(ob).off("mousemove.hoverIntent",track);
// if hoverIntent state is true, then call the mouseOut function after the specified delay
if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
}
};
// listen for mouseenter and mouseleave
return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
};
})(jQuery);

View File

@ -7,6 +7,4 @@
//= require ga
//= require jam_rest
//= require landing/init
//= require landing/signup
//= require landing/downloads
//= require landing/congratulations
//= require landing/signup

View File

@ -281,6 +281,8 @@
}
function layoutFooter(screenWidth, screenHeight) {
if(!opts.layoutFooter) { return; }
var $footer = $('#footer');
var nHeight = $footer.height();
var footerStyle = {
@ -291,17 +293,7 @@
$footer.animate({ "left" : opts.gutter, "width" : width, "top": (screenHeight - 78) + "px"}, opts.animationDuration);
}
function requiredStyles() {
var bodyStyle = {
margin: '0px',
padding: '0px',
overflow: 'hidden'
};
if (opts.allowBodyOverflow) {
delete bodyStyle.overflow;
}
$('body').css(bodyStyle);
function requiredLayoutStyles() {
var layoutStyle = {
position: 'absolute',
margin: '0px',
@ -321,6 +313,21 @@
$('[layout-grid]').children().css({
position: "absolute"
});
}
function requiredStyles() {
var bodyStyle = {
margin: '0px',
padding: '0px',
overflow: 'hidden'
};
if (opts.allowBodyOverflow) {
delete bodyStyle.overflow;
}
$('body').css(bodyStyle);
requiredLayoutStyles();
var curtainStyle = {
position: "absolute",
margin: '0px',

View File

@ -0,0 +1,85 @@
(function(context,$) {
/** Javascript for managing the (account dropdown) */
"use strict";
context.JK = context.JK || {};
context.JK.UserDropdown = function(app) {
var logger = context.JK.logger;
var rest = new JK.Rest();
var userMe = null;
var invitationDialog = new context.JK.InvitationDialog(app);
function menuHoverIn() {
$('ul.shortcuts', this).show();
}
function menuHoverOut() {
$('ul.shortcuts', this).hide();
}
function events() {
$('.userinfo').hoverIntent(menuHoverIn, menuHoverOut);
$('.userinfo .invite-friends .menuheader').on('click', function(e) {
$(this).closest('li').css('height', 'auto').find('ul').toggle();
e.stopPropagation();
return false;
});
$('.invite-friends .google-invite a').on('click', function(e) {
invitationDialog.showGoogleDialog();
});
$('.invite-friends .email-invite a').on('click', function(e) {
invitationDialog.showEmailDialog();
});
$('#header-avatar').on('avatar_changed', function(event, newAvatarUrl) {
updateAvatar(newAvatarUrl);
event.preventDefault();
return false;
})
}
function loadMe() {
$.ajax({
url: '/api/users/' + context.JK.currentUserId
}).done(function(r) {
userMe = r;
// TODO - Setting global variable for local user.
context.JK.userMe = r;
updateHeader();
}).fail(app.ajaxError);
}
function updateHeader() {
$('#user').html(userMe.name);
showAvatar();
}
// initially show avatar
function showAvatar() {
var photoUrl = context.JK.resolveAvatarUrl(userMe.photo_url);
$('#header-avatar').attr('src', photoUrl);
}
// handle update avatar event
function updateAvatar(avatar_url) {
var photoUrl = context.JK.resolveAvatarUrl(avatar_url);
var avatar = $(new Image());
avatar.attr('src', photoUrl + '?cache_bust=' + new Date().getTime());
avatar.attr('alt', "Avatar");
avatar.attr('id', 'header-avatar');
$('#header-avatar').replaceWith(avatar);
}
this.initialize = function() {
events();
invitationDialog.initialize();
loadMe();
}
}
})(window,jQuery);

View File

@ -297,7 +297,7 @@
context.JK.popExternalLinks = function() {
// Allow any a link with a rel="external" attribute to launch
// the link in the default browser, using jamClient:
$('a[rel="external"]').click(function(evt) {
$('body').on('click', 'a[rel="external"]', function(evt) {
if(!context.jamClient) {
return;

View File

@ -6,7 +6,7 @@
congratulations.initialize = function initialize(musician, registrationType) {
if(musician) {
context.JK.Downloads.listClients();
context.JK.Downloads.listClients(true);
}
if(registrationType) {

View File

@ -5,66 +5,121 @@
context.JK = context.JK || {};
var downloads = {};
var isCongratulations;
var downloadUris = {}; // map of platform > uri
var rest = context.JK.Rest();
function selectPlatform(selectedPlatform) {
var platformName; // mac, windows, linux
var platformDisplay; // Mac, Windows, Linux
var platform = selectedPlatform; //MacOSX, Win32, Unix
var platformName1, platformName2, platform1, platform2;
var uri = downloadUris[selectedPlatform];
// prepare template varaibles
if (selectedPlatform == "Unix") {
platformName = "linux";
platformDisplay = "Linux"
platformName1 = "mac";
platformName2 = "windows";
platform1 = "MacOSX";
platform2 = "Win32"
} else if(selectedPlatform == "Win32") {
platformName = "windows";
platformDisplay = "Windows";
platformName1 = "mac";
platformName2 = "linux"
platform1 = "MacOSX";
platform2 = "Unix";
} else if(selectedPlatform == "MacOSX") {
platformName = "mac";
platformDisplay = "Mac";
platformName1 = "windows";
platformName2 = "linux";
platform1 = "Win32";
platform2 = "Unix";
}
else {
alert("unknown platform: " + selectedPlatform);
}
var options = {
platform : platform,
platformName : platformName,
platformDisplay : platformDisplay,
platformName1 : platformName1,
platformName2 : platformName2,
platform1: platform1,
platform2: platform2,
uri : uri ? uri : '#',
isCongratulations : isCongratulations
};
var blurb = $(context._.template($('#client-download-blurb-contents').html(), options, { variable: 'data' }));
var selectOthers = $(context._.template($('#client-download-select-others').html(), options, { variable: 'data' }));
// install click handler for change selection
$('a', selectOthers).click(function() {
var platform = $(this).attr('data-platform');
selectPlatform(platform);
return false;
});
$('a', blurb).click(function() {
var clicked = $(this);
var href = clicked.attr('href');
if(href != "#") {
rest.userDownloadedClient().always(function() {
$('body').append('<iframe class="downloading" src="' + clicked.attr('href') + '" style="display:none"/>')
});
}
else {
context.JK.GA.trackDownload(clicked.attr('data-platform'));
// if there is no download available, apologize to the user
alert("Sorry, this download is not currently available.");
return false;
}
return false;
});
// update blurb
$('body.web .downloads-blurb').empty().append(blurb);
// update the 'download other platforms' buttons
$('body.web .downloads-container').empty().append(selectOthers);
// update system requirements
$('body.web .system-requirements ul').hide();
$('body.web .system-requirements ul.' + platformName + '-requirements').show();
$('body.web .system-requirements').show();
}
function removeSpinner() {
$('body.web .spinner-large').remove();
}
function listClients(congratulations) {
isCongratulations = congratulations;
function listClients() {
var rest = context.JK.Rest();
var currentOS = context.JK.detectOS();
var downloads = $('.downloads');
rest.getClientDownloads()
.done(function(data) {
downloads.removeClass('spinner-large');
removeSpinner();
var count = 0;
for ( var property in data ) count++;
$.each(data, function(key, item) {
var platform = key.substring('JamClient/'.length);
if(count == 0) {
alert("Currently unable to list client software downloads.");
}
else {
$.each(data, function(key, item) {
// if the currentOS we detect from browser is found within the product of an available client
// we flag it with this boolean
var matchesUserOS = currentOS != null && key.toLowerCase().indexOf(currentOS.toLowerCase()) > -1;
var platform = key.substring('JamClient/'.length);
var options = {
emphasis: matchesUserOS ? "currentOS" : "",
uri: item.uri,
platform: platform
}
var download = $(context._.template($('#client-download-link').html(), options, { variable: 'data' }));
download.find('a').data('platform', platform).click(function() {
var clicked = $(this);
rest.userDownloadedClient().always(function() {
$('body').append('<iframe class="downloading" src="' + clicked.attr('href') + '" style="display:none"/>')
})
context.JK.GA.trackDownload($(this).data('platform'));
return false;
});
if(matchesUserOS) {
// make sure the current user OS is at the top
downloads.prepend(download);
}
else {
downloads.append(download)
}
});
}
downloadUris[platform] = item.uri;
});
})
.fail(function() {
downloads.removeClass('spinner-large');
removeSpinner();
alert("Currently unable to list client software downloads due to error.");
})
.always(function() {
selectPlatform(currentOS == null ? 'Win32' : currentOS);
});
}
downloads.listClients = listClients;

View File

@ -0,0 +1,18 @@
//= require jquery
//= require jquery_ujs
//= require jquery.queryparams
//= require jquery.hoverIntent
//= require AAA_Log
//= require AAC_underscore
//= require globals
//= require invitationDialog
//= require layout
//= require user_dropdown
//= require jamkazam
//= require utils
//= require ga
//= require jam_rest
//= require landing/init
//= require landing/signup
//= require web/downloads
//= require web/congratulations

View File

@ -14,6 +14,7 @@
*= require ./content
*= require ./faders
*= require ./header
#= require ./user_dropdown
*= require ./footer
*= require ./screen_common
*= require ./notify

View File

@ -338,8 +338,15 @@ ul.shortcuts {
}
}
}
.tagline {
font-size:30px;
margin-top:55px;
color:#ed3718;
font-weight:300;
width:345px;
clear:left;
white-space:normal;
}

View File

@ -1,6 +1,5 @@
@charset "UTF-8";
@import "compass/utilities/text/replacement";
@import "client/common.css.scss";
.header {
height: 55px;
@ -15,123 +14,3 @@ div[layout="header"] h1 {
@include replace-text(image-url("header/logo.png"));
float:left;
}
#logo {
float:left;
width:247px;
}
#profile {
width:auto;
float:right;
height:54px;
}
.avatar_large {
float:left;
padding:2px;
width:54px;
height:54px;
background-color: $ColorScreenPrimary;
-webkit-border-radius:28px;
-moz-border-radius:28px;
border-radius:28px;
}
.avatar_large img {
width:54px;
height:54px;
-webkit-border-radius:26px;
-moz-border-radius:26px;
border-radius:26px;
}
#user {
margin:18px 0px 0px 10px;
font-size:20px;
font-weight:200;
color:#ccc;
float:left;
}
.arrow-down {
float:left;
cursor:pointer;
margin-left:16px;
margin-top:26px;
width: 0;
height: 0;
border-left: 8px solid transparent;
border-right: 8px solid transparent;
border-top: 8px solid #fff;
}
.userinfo {
cursor:pointer;
}
.userinfo ul {
clear:both;
background: scale-lightness($ColorUIBackground, 10%);
display:none;
}
.userinfo li {
display:block;
margin: 2px;
padding: 2px;
background: scale-lightness($ColorUIBackground, 20%);
}
/*
div[layout="header"] h1 {
width: 252px;
height:47px;
@include replace-text(image-url("logo.png"));
}
*/
/*.header h1 {*/
/*margin:22px;*/
/*font-size:300%;*/
/*font-family: 'LatoLight', Arial, sans-serif;*/
/*}*/
/*
.userinfo {
position:absolute;
right:0px;
top:0px;
width: 266px;
z-index:5;
}
.userinfo img.avatar {
float:left;
}
.userinfo .username {
float:left;
margin-top: 18px;
cursor: pointer;
}
.userinfo h2 {
font-size:120%;
font-weight: bold;
float:left;
margin-right:4px;
}
.userinfo .profile-toggle {
display:inline-block;
}
.userinfo ul {
clear:both;
background: $color7;
display:none;
}
.userinfo li {
display:block;
margin: 2px;
padding: 2px;
background: scale-lightness($color7, 10%);
}
*/

View File

@ -1,3 +1,5 @@
@import "client/common.css.scss";
#logo {
float:left;
@ -7,7 +9,11 @@
#profile {
width:auto;
float:right;
height:54px;
height:64px;
.signin {
position:relative;
margin-top:40px;
}
}
.avatar_large {
@ -57,7 +63,9 @@
clear:both;
background: scale-lightness($ColorUIBackground, 10%);
display:none;
position:relative;
}
.userinfo li {
display:block;
margin: 2px;

View File

@ -0,0 +1,42 @@
@charset "UTF-8";
#footer-container {
position:relative;
width:1100px;
top:20px;
height:13px;
}
#footer {
padding-top: 10px;
border-top:solid 1px #444;
}
#copyright {
float:left;
font-size:11px;
color:#ccc;
}
#footer-links {
float:right;
font-size:11px;
color:#ccc;
}
#footer-links a {
color:#ccc;
text-decoration:none;
}
#footer-links a:hover {
color:#fff;
text-decoration:underline;
}
#version {
font-size:11px;
color:#ccc;
text-align: center;
}

View File

@ -0,0 +1,308 @@
html {
height:100%;
}
body.web {
background-image: url(../web/bkg_home.gif);
background-repeat: repeat-x;
margin:0 !important;
padding:0 !important;
position:relative !important;
overflow: visible !important;
width:auto !important;
#web-container {
padding:3% 6%;
}
div.wrapper {
width: 1100px;
margin: 0 auto;
white-space: nowrap;
}
.logo-home {
width: 298px;
margin-top: 30px;
display: inline-block;
float:left;
}
#profile {
margin-top: 25px;
}
#landing-inner {
p, ul {
color:#999;
line-height:160%;
margin-bottom:20px;
width:90%;
white-space:normal;
font-size:16px;
}
}
ul {
list-style: none outside none;
}
h3 {
font-size:20px;
font-weight:normal;
}
.download-box {
padding:15px;
color:#fff;
text-align:center;
font-size:20px;
-webkit-border-radius: 8px;
border-radius: 8px;
background:#383838;
margin-top:100px;
}
.system-requirements {
margin-top:75px;
display:none;
ul {
display:none;
list-style:disc outside none;
padding-left:40px;
}
}
div.proceed {
margin:40px 0 250px 5px;
}
.downloads {
ul {
list-style:disc outside none;
padding-left:40px;
}
}
}
#landing-container {
padding: 3% 0;
position:relative;
text-align: center;
}
.signin-overlay {
position:relative;
top:0;
}
strong {
font-weight: 600;
}
.logo-message {
display: block;
margin: 0 auto;
width: 247px;
}
.message-wrapper {
margin: 0 auto;
width: 480px;
}
.message-wrapper .left {
display: block;
overflow: visible;
}
.message {
display: block;
float: left;
margin-left: 20px;
overflow: visible;
width: 320px;
}
.message h2 {
border-bottom: 1px solid #FFFFFF;
color: #FFFFFF;
display: block;
font-weight: 200;
margin-bottom: 10px;
font-size:21px;
}
.spinner-large {
vertical-align:middle;
text-align: center;
margin: 125px auto;
}
.client-download {
margin-bottom:20px;
}
.currentOS {
span.platform {
font-size:18px;
}
}
// all custom CSS for the sign-in page goes here
.signin-page {
.ftue-inner {
line-height:18px;
}
.ftue-left, .ftue-right {
}
fieldset[name=text-input]{
float:right;
margin-right:18px;
}
fieldset[name=signin-options] {
float:left;
margin:10px 0 0 10px;
small {
float:left;
}
}
fieldset[name=actions] {
float:right;
margin: 10px 19px 0 0;
}
.field {
right:0;
}
.email {
float:left;
margin-right:10px;
}
.password {
float:left;
}
label {
margin:27px 0 10px;
}
.already-member {
}
.keep-logged-in {
}
.forgot-password {
font-size:11px;
float:right;
margin:15px 19px 0 0;
a {
text-decoration: underline;
}
}
.login-error {
background-color: #330000;
border: 1px solid #990000;
padding:4px;
}
.login-error-msg {
display:none;
margin-top:10px;
text-align:center;
color:#F00;
font-size:11px;
}
fieldset.login-error .login-error-msg {
display:block;
}
}
// all custom CSS for the register page goes here
.register-page {
.register-container {
padding:10px;
}
input.register-musician {
}
.error {
padding: 5px 12px 5px 5px;
margin-left:-5px;
margin-right:-12px;
}
input.register-fan {
margin-left:20px;
}
input[type=text], input[type=password] {
margin-top:1px;
width:100%;
}
select {
width:100%;
}
.right-side {
margin-left:25px;
}
.ftue-left {
margin-bottom:30px;
select {
width:104%;
}
div.field {
margin-top:31px;
width:43%;
float:left;
}
}
.ftue-right {
table {
border-collapse:separate;
border-spacing:6px;
}
label.instruments {
margin-bottom:2px;
}
div.field {
margin-top:15px;
}
a.tos {
text-decoration: underline;
}
input[type=submit] {
margin-top:20px;
}
}
}

View File

@ -0,0 +1,12 @@
/**
*= require client/ie
*= require client/jamkazam
*= require client/screen_common
*= require client/content
*= require client/ftue
*= require client/user_dropdown
*= require client/dialog
*= require client/invitationDialog
*= require web/main
*= require web/footer
*/

View File

@ -102,15 +102,15 @@ class UsersController < ApplicationController
end
def congratulations_fan
render :layout => "landing"
render :layout => "web"
end
def congratulations_musician
render :layout => "landing"
render :layout => "web"
end
def downloads
render :layout => "landing"
render :layout => "web"
end
def signup_confirm

View File

@ -22,10 +22,10 @@
<div class="left mt35">
<div class="left w5 ml10 mr10">
<div>
<img id="img-add-track2-input-add" style="cursor:pointer;" src="assets/content/arrow_right_24.png" width="24" height="24" />
<img id="img-add-track2-input-add" style="cursor:pointer;" src="/assets/content/arrow_right_24.png" width="24" height="24" />
</div>
<div class="mt10">
<img id="img-add-track2-input-remove" style="cursor:pointer;" src="assets/content/arrow_left_24.png" width="24" height="24" />
<img id="img-add-track2-input-remove" style="cursor:pointer;" src="/assets/content/arrow_left_24.png" width="24" height="24" />
</div>
</div>
</div>

View File

@ -46,19 +46,19 @@
<div class="left">
<div id="track1-input-buttons" class="left w5 ml10 mr10">
<div>
<img id="img-track1-input-add" style="cursor:pointer;" src="assets/content/arrow_right_24.png" width="24" height="24" />
<img id="img-track1-input-add" style="cursor:pointer;" src="/assets/content/arrow_right_24.png" width="24" height="24" />
</div>
<div class="mt10">
<img id="img-track1-input-remove" style="cursor:pointer;" src="assets/content/arrow_left_24.png" width="24" height="24" />
<img id="img-track1-input-remove" style="cursor:pointer;" src="/assets/content/arrow_left_24.png" width="24" height="24" />
</div>
</div>
<div class="clearall"></div>
<div id="track2-input-buttons" class="left w5 ml10 mr10 mt45">
<div>
<img id="img-track2-input-add" style="cursor:pointer;" src="assets/content/arrow_right_24.png" width="24" height="24" />
<img id="img-track2-input-add" style="cursor:pointer;" src="/assets/content/arrow_right_24.png" width="24" height="24" />
</div>
<div class="mt10">
<img id="img-track2-input-remove" style="cursor:pointer;" src="assets/content/arrow_left_24.png" width="24" height="24" />
<img id="img-track2-input-remove" style="cursor:pointer;" src="/assets/content/arrow_left_24.png" width="24" height="24" />
</div>
</div>
</div>
@ -114,10 +114,10 @@
</div>
<div class="left ml10 mr10 mt25">
<div>
<img id="img-audio-output-add" style="cursor:pointer;" src="assets/content/arrow_right_24.png" width="24" height="24" />
<img id="img-audio-output-add" style="cursor:pointer;" src="/assets/content/arrow_right_24.png" width="24" height="24" />
</div>
<div class="mt10">
<img id="img-audio-output-remove" style="cursor:pointer;" src="assets/content/arrow_left_24.png" width="24" height="24" />
<img id="img-audio-output-remove" style="cursor:pointer;" src="/assets/content/arrow_left_24.png" width="24" height="24" />
</div>
</div>
<div class="left w27">
@ -154,10 +154,10 @@
<div class="left mt55">
<div class="left ml10 mr10">
<div>
<img id="img-voice-input-add" style="cursor:pointer;" src="assets/content/arrow_right_24.png" width="24" height="24" />
<img id="img-voice-input-add" style="cursor:pointer;" src="/assets/content/arrow_right_24.png" width="24" height="24" />
</div>
<div class="mt10">
<img id="img-voice-input-remove" style="cursor:pointer;" src="assets/content/arrow_left_24.png" width="24" height="24" />
<img id="img-voice-input-remove" style="cursor:pointer;" src="/assets/content/arrow_left_24.png" width="24" height="24" />
</div>
</div>
</div>

View File

@ -8,40 +8,8 @@
<a onclick="jamClient.FTUESetStatus(true);">No FTUE</a> |
<a layout-link="session-settings">SS</a>
-->
<!-- profile area -->
<div id="profile" class="userinfo">
<!-- avatar -->
<div class="avatar_large">
<img id="header-avatar" />
</div>
<!-- user name -->
<div id="user"></div>
<div class="arrow-down"></div>
<ul class="shortcuts">
<!-- <li><a layout-link="account">Profile</a></li> -->
<li class="account-home"><%= link_to "Account Home", '#/account' %></li>
<li class="identity"><%= link_to "Identity", '#/account/identity' %></li>
<li class="profile"><%= link_to "Profile", '#/account/profile' %></li>
<!--<li class="subscriptions"><%= link_to "Subscriptions", '#/account/subscriptions' %></li> -->
<!-- <li class="payments"><%= link_to "Payments", '#/account/payments' %></li> -->
<li class="audio"><%= link_to "Audio Gear", '#/account/audio' %></li>
<li class="invite-friends"><span class='menuheader'><span class="arrow-right"></span><%= link_to "Invite Friends", '#' %></span>
<ul class="shortcuts-submenu">
<li class="google-invite"><%= link_to "Google", '#' %></li>
<li class="email-invite"><%= link_to "Email", '#' %></li>
</ul>
</li>
<li class="download-app"><%= link_to "Download App", downloads_path, :rel => "external" %></li>
<li class="get-help"><%= link_to "Get Help", 'https://jamkazam.desk.com/', :rel => "external" %></li>
<li class="sign-out"><%= link_to "Sign Out", signout_path, method: "delete" %></li>
</ul>
</div>
<!-- end profile area -->
<%= render "users/user_dropdown" %>
<!-- Templates -->
<script type="text/template" id="template-search-section">

View File

@ -1,10 +1,10 @@
<div class="curtain" style="width:100%; height:100%; z-index:9999;">
<div class="splash">
<img src="assets/header/logo.png"/>
<img src="/assets/header/logo.png"/>
<p>Connecting...</p>
</div>
</div>
<div class="dialog-overlay op70" style="display:none; width:100%; height:100%; z-index:99;"></div>
<div class="dialog-overlay op70" style="display:none; width:100%; height:100%; z-index:99;"></div>
<%= render "header" %>
<%= render "home" %>
@ -86,6 +86,10 @@
// Some things can't be initialized until we're connected. Put them here.
function _initAfterConnect() {
var userDropdown = new JK.UserDropdown(JK.app);
JK.UserDropdown = userDropdown;
userDropdown.initialize();
var header = new JK.Header(JK.app);
JK.Header = header;
header.initialize();

View File

@ -1,43 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<title><%= full_title(yield(:title)) %></title>
<head>
<title><%= full_title(yield(:title)) %></title>
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="css/ie.css" media="screen, projection"/>
<![endif]-->
<link href='http://fonts.googleapis.com/css?family=Raleway:100,200,300,400,500,600,700' rel='stylesheet' type='text/css'>
<%= stylesheet_link_tag "landing/landing", media: "all" %>
<% if bugsnag? %>
<!-- THIS NEEDS TO BE IN FRONT OF ANY OTHER JAVASCRIPT INCLUDES ACCORDING TO BUGSNAG -->
<script src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-1.0.9.min.js" data-apikey="<%= Rails.application.config.bugsnag_key %>"></script>
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="css/ie.css" media="screen, projection"/>
<![endif]-->
<link href='http://fonts.googleapis.com/css?family=Raleway:100,200,300,400,500,600,700' rel='stylesheet' type='text/css'>
<%= stylesheet_link_tag "web/web", media: "all" %>
<% if bugsnag? %>
<!-- THIS NEEDS TO BE IN FRONT OF ANY OTHER JAVASCRIPT INCLUDES ACCORDING TO BUGSNAG -->
<script src="//d2wy8f7a9ursnm.cloudfront.net/bugsnag-1.0.9.min.js" data-apikey="<%= Rails.application.config.bugsnag_key %>"></script>
<% end %>
<%= include_gon %>
<%= csrf_meta_tags %>
</head>
<body class="web">
<%= javascript_include_tag "web/web" %>
<div class="dialog-overlay op70" style="display:none; width:100%; height:100%; z-index:99;"></div>
<div id="web-container">
<div class="wrapper">
<div class="logo-home">
<%= link_to root_path do %>
<%= image_tag("web/logo_home.png", :alt => "JamKazam logo", :size => "298x54") %>
<% end %>
</div>
<%= render "users/user_dropdown" %>
<br clear="all">
<div id="landing-inner">
<%= yield %>
</div>
<div id="footer-container">
<%= render "clients/footer" %>
</div>
</div>
<%= render "clients/invitationDialog" %>
<script type="text/javascript">
$(function () {
JK = JK || {};
<% if current_user %>
JK.currentUserId = '<%= current_user.id %>';
<% else %>
JK.currentUserId = null;
<% end %>
<%= include_gon %>
<%= csrf_meta_tags %>
</head>
<body>
<div id="landing-container">
<%= javascript_include_tag "landing/landing" %>
<div class="logo-message">
<%= link_to root_path do %>
<%= image_tag("header/logo.png", :alt => "JamKazam logo", :size => "247x45") %>
<% end %>
</div>
if (JK.currentUserId) {
JK.app = JK.JamKazam();
JK.app.initialize({inClient: false, layoutOpts: {layoutFooter:false}});
<br />
<br />
var userDropdown = new JK.UserDropdown(JK.app);
userDropdown.initialize();
}
})
</script>
<div id="landing-inner">
<%= yield %>
</div>
</div>
</div>
<div id="footer-container">
<%= render "clients/footer" %>
</div>
<%= render "shared/ga" %>
<!-- version info: <%= version %> -->
</body>
<%= render "shared/ga" %>
<!-- version info: <%= version %> -->
</body>
</html>

View File

@ -66,7 +66,7 @@
<br>
<div align="center"><span class="white"><strong>Not a member?</strong></span> Join JamKazam for free:<br>
<br>
<a href="/signup" class="button-orange">REGISTER NOW</a>
<a href="/signup" rel="external" class="button-orange">REGISTER NOW</a>
</div>
<!-- end right column -->

View File

@ -1,3 +1,36 @@
<script type="text/template" id="client-download-link">
<div align="center" class="client-download {{data.emphasis}}"><a href="{{data.uri}}" class="button-orange m0">DOWNLOAD JAMKAZAM SOFTWARE<br/><span class="platform" platform="{{data.platform}}">{{data.platform}}</span></a></div>
<script type="text/template" id="client-download-blurb-contents">
<div class="downloads">
{% if(data.isCongratulations) { %}
<div class="tagline">Congratulations!</div>
<br>
<p>You have successfully registered as a JamKazam musician. To get started playing with others, use the button below to download the JamKazam application through your browser. When the download is complete, open the downloaded file, and follow the on-screen instructions to install the application on your computer.</p>
<br>
{% } else { %}
<div class="tagline">JamKazam for {{data.platformDisplay}}</div><br>
<p>Here are a few of the great things you can do with JamKazam:</p>
<ul>
<li>Play with other musicians from your homes across the Internet as if you were in the same room</li>
<li>Record performances from your online sessions and share them over Facebook, Twitter, email, and more</li>
<li>Live broadcast your sessions so that family, friends, and fans can listen from anywhere</li>
</ul>
<br>
{% } %}
<a href="{{data.uri}}" class="current-os-download" data-platform="{{data.platform}}"><%= image_tag("content/button_download_{{data.platformName}}.png", :alt => "download {{data.platformName}}", :size => "348x92") %></a>
</div>
</script>
<script type="text/template" id="client-download-select-others"> 2 1 31 2
<div class="download-box">
NEED A DIFFERENT VERSION?
<br><br>
<div class="download-others">
<a href="#" data-platform="{{data.platform1}}"><%= image_tag("content/button_download_other_{{data.platformName1}}.png", :alt => "show download for {{data.platformName1}}", :size => "300x79") %></a><br><br>
<a href="#" data-platform="{{data.platform2}}"><%= image_tag("content/button_download_other_{{data.platformName2}}.png", :alt => "show download for {{data.platformName2}}", :size => "300x79") %></a>
</div>
</div>
</script>

View File

@ -0,0 +1,35 @@
<!-- used by congrats_musician, and downloads -->
<div class="w100 ">
<div class="spinner-large"></div>
<div class="w70 left downloads-blurb">
</div>
</div>
<div class="w30 left downloads-container">
</div>
<br clear="all">
<div class="system-requirements w100">
<h3>SYSTEM REQUIREMENTS:</h3><br>
<p>A short summary of requirements follows. For a more detailed explanation of system requirements, please review our <a href="https://jamkazam.desk.com/customer/portal/articles/1288274-minimum-system-requirements">Minimum System Requirements</a> knowledgebase article.</p>
<ul class="windows-requirements">
<li>Windows 64-bit operating system (Win 7 &amp; 8 tested, Win XP and Vista like to work but not officially supported</li>
<li>Dual-core processor or higher</li>
<li>Ethernet port for Internet (we strongly advise that you not use Wi-Fi)</li>
<li>74MB hard disk space for app, plus any space needed for recordings</li>
<li>Audio interface (best to use an audio interface device that gets your music into your computer, else can use built-in mic &amp; headphones on your computer to get started)</li>
<li>Broadband Internet services with 1Mbps uplink bandwidth</li>
</ul>
<ul class="mac-requirements">
<li>Mac</li>
</ul>
<ul class="linux-requirements">
<li>Linux is not yet supported</li>
</ul>
</div>
<%= render "users/download_templates" %>

View File

@ -0,0 +1,39 @@
<div id="profile" class="userinfo">
<% if signed_in? %>
<!-- profile area -->
<!-- avatar -->
<div class="avatar_large">
<img id="header-avatar" />
</div>
<!-- user name -->
<div id="user"></div>
<div class="arrow-down"></div>
<ul class="shortcuts">
<!-- <li><a layout-link="account">Profile</a></li> -->
<li class="account-home"><%= link_to "Account Home", '/client/#/account' %></li>
<li class="identity"><%= link_to "Identity", '/client/#/account/identity' %></li>
<li class="profile"><%= link_to "Profile", '/client/#/account/profile' %></li>
<!--<li class="subscriptions"><%= link_to "Subscriptions", '/client/#/account/subscriptions' %></li> -->
<!-- <li class="payments"><%= link_to "Payments", '/client/#/account/payments' %></li> -->
<li class="audio"><%= link_to "Audio Gear", '/client/#/account/audio' %></li>
<li class="invite-friends"><span class='menuheader'><span class="arrow-right"></span><%= link_to "Invite Friends", '#' %></span>
<ul class="shortcuts-submenu">
<li class="google-invite"><%= link_to "Google", '#' %></li>
<li class="email-invite"><%= link_to "Email", '#' %></li>
</ul>
</li>
<li class="download-app"><%= link_to "Download App", downloads_path, :rel => "external" %></li>
<li class="get-help"><%= link_to "Get Help", 'https://jamkazam.desk.com/', :rel => "external" %></li>
<li class="sign-out"><%= link_to "Sign Out", signout_path, method: "delete" %></li>
</ul>
<!-- end profile area -->
<% else %>
<a class="signin" href="/signin">Sign In</a>
<% end %>
</div>

View File

@ -1,23 +1,8 @@
<% provide(:title, 'Congratulations') %>
<div class="overlay-small">
<!-- header -->
<div class="content-head">
<h1>congratulations</h1>
</div>
<div class="tagline">Congratulations!</div>
<!-- inner wrapper -->
<div class="overlay-inner">
You have successfully registered as a JamKazam fan.
<br />
<br />
<div align="center"><%= link_to "PROCEED TO JAMKAZAM SITE", root_path, :class =>"button-orange m0" %></div>
</div>
<!-- end inner -->
</div>
<div class="proceed"><%= link_to "PROCEED TO JAMKAZAM SITE", root_path, :class =>"button-orange m0" %></div>
<script type="text/javascript">
window.congratulations.initialize(false, jQuery.QueryString["type"]);

View File

@ -1,30 +1,7 @@
<% provide(:title, 'Congratulations') %>
<div class="overlay-small">
<!-- header -->
<div class="content-head">
<h1>congratulations</h1>
</div>
<!-- inner wrapper -->
<div class="overlay-inner">
You have successfully registered as a JamKazam musician.
To get started playing with others, use the button below to download the JamKazam software, then click to open the download and follow the on-screen instructions to install the application on your computer.<br />
<br />
<div align="center" class="downloads spinner-large">
</div>
</div>
<!-- end inner -->
</div>
<%= render "users/downloads" %>
<script type="text/javascript">
window.congratulations.initialize(true, jQuery.QueryString["type"]);
</script>
<%= render "users/download_templates" %>

View File

@ -1,28 +1,7 @@
<% provide(:title, 'Downloads') %>
<div class="overlay-small">
<!-- header -->
<div class="content-head">
<h1>Downloads</h1>
</div>
<!-- inner wrapper -->
<div class="overlay-inner">
To get started playing with others, use the button below to download the JamKazam software, then click to open the download and follow the on-screen instructions to install the application on your computer.<br />
<br />
<div align="center" class="downloads spinner-large">
</div>
</div>
<!-- end inner -->
</div>
<%= render "users/download_templates" %>
<%= render "users/downloads" %>
<script type="text/javascript">
window.JK.Downloads.listClients();
window.JK.Downloads.listClients(false);
</script>

View File

@ -77,6 +77,7 @@ if defined?(Bundler)
config.assets.precompile += %w( client/client.css )
config.assets.precompile += %w( landing/landing.js landing/landing.css )
config.assets.precompile += %w( corp/corporate.js corp/corporate.css )
config.assets.precompile += %w( web/web.js web/web.css )
# where is rabbitmq?

View File

@ -51,7 +51,7 @@ describe "Authentication", :js => true, :type => :feature, :capybara_feature =>
should have_selector('h2', text: "musicians")
# open menu
find('.userinfo').trigger(:click)
find('.userinfo').hover
# click signout link
find('.userinfo .sign-out a').trigger(:click)

View File

@ -0,0 +1,51 @@
require 'spec_helper'
# these test will verify all of the user progression cases that rely on a javascript event (not bothering with instrumented models)
describe "User Progression", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
before(:all) do
Capybara.javascript_driver = :poltergeist
Capybara.current_driver = Capybara.javascript_driver
Capybara.default_wait_time = 10
end
let(:user) { FactoryGirl.create(:user) }
describe "downloaded client" do
before(:each) do
FactoryGirl.create(:artifact_update, :product => 'JamClient/Win32')
FactoryGirl.create(:artifact_update, :product => 'JamClient/MacOSX')
end
describe "downloads-page" do
# there is also a generic download pages
before(:each) do
sign_in_poltergeist user
visit '/downloads'
# put the user on Windows to start
detected_os = find("a.current-os-download")['data-platform']
if detected_os != "Win32"
find(".download-others a[data-platform='Win32']").trigger(:click)
end
end
it "toggle active download" do
find(".download-others a[data-platform='Unix']").trigger(:click)
find("a.current-os-download")['data-platform'].should == "Unix"
find(".download-others a[data-platform='MacOSX']").trigger(:click)
find("a.current-os-download")['data-platform'].should == "MacOSX"
find(".download-others a[data-platform='Win32']").trigger(:click)
find("a.current-os-download")['data-platform'].should == "Win32"
end
end
end
end

View File

@ -19,7 +19,7 @@ describe "Landing", :js => true, :type => :feature, :capybara_feature => true do
UserMailer.deliveries.clear
visit "/downloads" # this is just a good, generic page that uses the landing layout
find('#landing-container')
find('div.tagline')
end
it "footer links work" do

View File

@ -13,79 +13,105 @@ describe "Profile Menu", :js => true, :type => :feature, :capybara_feature => tr
let(:user) { FactoryGirl.create(:user) }
before(:each) do
UserMailer.deliveries.clear
sign_in_poltergeist user
visit "/"
find('h2', text: 'musicians')
# open menu
find('.userinfo').trigger(:click)
end
shared_examples_for "Profile Menu Assertions" do |pops_external|
describe "Account Home link" do
describe "Account Home link" do
before(:each) do
click_link 'Account Home'
end
it { should have_selector('h1', text: 'my account') }
end
describe "Identity link" do
before(:each) do
click_link 'Identity'
end
it { should have_selector('h2', text: 'identity:') }
end
describe "Profile link" do
before(:each) do
click_link 'Profile'
end
it { should have_selector('h2', text: 'profile:') }
end
describe "Audio Gear link" do
before(:each) do
click_link 'Audio Gear'
end
it { should have_selector('h2', text: 'audio profiles:') }
end
describe "Download App link" do
before(:each) do
click_link 'Download App'
end
it {
# the download app link opens a new window
page.driver.window_handles.last
page.within_window page.driver.window_handles.last do
should have_selector('h1', text: 'Downloads')
end
}
end
describe "invite submenu" do
before(:each) do
click_link "Invite Friends"
end
describe "Email" do
before(:each) do
click_link "Email"
click_link 'Account Home'
end
it {should have_selector('label', text: 'Enter email address(es). If multiple addresses, separate with commas.')}
it { should have_selector('h1', text: 'my account') }
end
describe "Identity link" do
before(:each) do
click_link 'Identity'
end
it { should have_selector('h2', text: 'identity:') }
end
describe "Profile link" do
before(:each) do
click_link 'Profile'
end
it { should have_selector('h2', text: 'profile:') }
end
describe "Audio Gear link" do
before(:each) do
click_link 'Audio Gear'
end
it { should have_selector('h2', text: 'audio profiles:') }
end
describe "Download App link" do
before(:each) do
click_link 'Download App'
end
it {
# the download app link opens a new window in the client, but not non-client areas of the site
if pops_external
page.driver.window_handles.last
page.within_window page.driver.window_handles.last do
should have_content('Here are a few of the great things you can do with JamKazam:')
end
else
should have_selector("a.current-os-download")
end
}
end
describe "invite submenu" do
before(:each) do
click_link "Invite Friends"
end
describe "Email" do
before(:each) do
click_link "Email"
end
it {should have_selector('label', text: 'Enter email address(es). If multiple addresses, separate with commas.')}
end
end
end
describe "Profile Menu while in Client" do
before(:each) do
UserMailer.deliveries.clear
sign_in_poltergeist user
visit "/"
find('h2', text: 'musicians')
# open menu
find('.userinfo').hover()
end
it_behaves_like "Profile Menu Assertions", true
end
describe "Profile Menu while in Web" do
before(:each) do
UserMailer.deliveries.clear
sign_in_poltergeist user
visit "/downloads"
find('div.tagline')
# open menu
find('.userinfo').hover()
end
it_behaves_like "Profile Menu Assertions", false
end
end

View File

@ -1,6 +1,6 @@
require 'spec_helper'
describe "Signup" do
describe "Signup", :js => true, :type => :feature, :capybara_feature => true do
subject { page }
@ -28,7 +28,7 @@ describe "Signup" do
# Successful signup with no invitation tells you to go sign up
it { page.should have_title("JamKazam | Congratulations") }
it { should have_selector('.overlay-inner', text: "You have successfully registered as a JamKazam musician.") }
it { should have_content("You have successfully registered as a JamKazam musician.") }
it { User.find_by_email('noone@jamkazam.com').musician_instruments.length.should == 1 }
# an email is sent on no-invite signup
it { UserMailer.deliveries.length.should == 1 }
@ -64,7 +64,7 @@ describe "Signup" do
# Successful signup with no invitation tells you to go sign up
it { page.should have_title("JamKazam | Congratulations") }
it { should have_selector('.overlay-inner', text: "You have successfully registered as a JamKazam fan.") }
it { should have_selector('div.tagline', text: "Congratulations!") }
it { should have_selector('a.button-orange.m0', text: 'PROCEED TO JAMKAZAM SITE') }
it { User.find_by_email('somefan@jamkazam.com').musician_instruments.length.should == 0 }
# an email is sent on no-invite signup
@ -90,7 +90,7 @@ describe "Signup" do
# Successful sign-in goes to the client
it { page.should have_title("JamKazam") }
it { should have_selector('h1', text: "congratulations") }
it { should have_selector('div.tagline', text: "Congratulations!") }
it { UserMailer.deliveries.length.should == 1 }
it {uri = URI.parse(current_url); "#{uri.path}?#{uri.query}".should == congratulations_musician_path(:type => 'Native')}
@ -114,7 +114,7 @@ describe "Signup" do
# Successful sign-in goes to the client
it { page.should have_title("JamKazam") }
it { should have_selector('h1', text: "congratulations") }
it { should have_selector('div.tagline', text: "Congratulations!") }
it { @user.friends?(User.find_by_email("noone@jamkazam.com")) }
it { User.find_by_email("noone@jamkazam.com").friends?(@user) }
it {uri = URI.parse(current_url); "#{uri.path}?#{uri.query}".should == congratulations_musician_path(:type => 'Native')}
@ -134,7 +134,7 @@ describe "Signup" do
check("jam_ruby_user[terms_of_service]")
click_button "CREATE ACCOUNT"
page.should have_title("JamKazam")
should have_selector('h1', text: "congratulations")
should have_selector('div.tagline', text: "Congratulations!")
visit "#{signup_path}?invitation_code=#{@invited_user.invitation_code}"
end
@ -160,7 +160,7 @@ describe "Signup" do
end
it { page.should have_title("JamKazam | Congratulations") }
it { should have_selector('.overlay-inner', text: "You have successfully registered as a JamKazam musician.") }
it { should have_content("You have successfully registered as a JamKazam musician.") }
it { User.find_by_email('noone@jamkazam.com').musician_instruments.length.should == 1 }
it { User.find_by_email('what@jamkazam.com').should be_nil }
# an email is sent when you invite but use a different email than the one used to invite

View File

@ -34,13 +34,19 @@ describe "User Progression", :js => true, :type => :feature, :capybara_feature
check("jam_ruby_user[terms_of_service]")
click_button "CREATE ACCOUNT"
should have_selector('.overlay-inner', text: "You have successfully registered as a JamKazam musician.")
first("div.client-download a").trigger(:click)
#find("body iframe.downloading")
sleep 1
should have_content("You have successfully registered as a JamKazam musician.")
detected_os = find("a.current-os-download")['data-platform']
if detected_os != "Win32"
find(".download-others a[data-platform='Win32']").trigger(:click)
end
find("a.current-os-download").trigger(:click)
sleep 1 # it's really hard to know if the rest API completed after the click
end
it {User.find_by_email('noone@jamkazam.com').reload(); User.find_by_email('noone@jamkazam.com').first_downloaded_client_at.should_not be_nil }
it {
User.find_by_email('noone@jamkazam.com').reload();
User.find_by_email('noone@jamkazam.com').first_downloaded_client_at.should_not be_nil
}
end
describe "downloads-page" do
@ -48,10 +54,14 @@ describe "User Progression", :js => true, :type => :feature, :capybara_feature
# there is also a generic download pages
before(:each) do
sign_in_poltergeist user
visit '/downloads'
first("div.client-download a").trigger(:click)
#find("body iframe.downloading")
sleep 1
detected_os = find("a.current-os-download")['data-platform']
if detected_os != "Win32"
find(".download-others a[data-platform='Win32']").trigger(:click)
end
find("a.current-os-download").trigger(:click)
sleep 1 # it's really hard to know if the rest API completed after the click
end
it {user.reload(); user.first_downloaded_client_at.should_not be_nil }

View File

@ -40,7 +40,7 @@ Spork.prefork do
require 'capybara-screenshot/rspec'
require 'capybara/poltergeist'
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, { debug: false, phantomjs_logger: File.open('log/phantomjs.out', 'w') })
driver = Capybara::Poltergeist::Driver.new(app, { debug: false, phantomjs_logger: File.open('log/phantomjs.out', 'w') })
end
Capybara.javascript_driver = :poltergeist
Capybara.default_wait_time = 10
@ -102,6 +102,7 @@ Spork.prefork do
if example.metadata[:js]
page.driver.resize(1920, 1080)
page.driver.headers = { 'User-Agent' => 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:25.0) Gecko/20100101 Firefox/25.0' }
end
end