* VRFS-315; profile page is working except for avatar, and does not do error visualization yet

This commit is contained in:
Seth Call 2013-05-18 13:04:04 -05:00
parent 4633f0fa08
commit fef9d3ad19
10 changed files with 281 additions and 115 deletions

View File

@ -42,7 +42,7 @@ gem 'omniauth-facebook', '1.4.1'
gem 'fb_graph', '2.5.9'
gem 'sendgrid', '1.1.0'
gem 'recaptcha', '0.3.4'
gem 'filepicker-rails', '0.0.2'
gem 'filepicker-rails', '0.1.0'
gem 'aws-sdk', '1.8.0'
gem 'aasm', '3.0.16'
gem 'carrierwave'

View File

@ -8,6 +8,8 @@
var api = context.JK.API(app);
var userId;
var user = {};
var recentUserDetail = null;
var loadingLocationData = false;
function beforeShow(data) {
userId = data.id;
@ -24,61 +26,139 @@
$('#account-profile-content-scroller form .error').removeClass("error")
}
function getUserDetail() {
var url = "/api/users/" + context.JK.currentUserId;
return $.ajax({
type: "GET",
dataType: "json",
url: url,
async: true,
processData: false
});
}
function populateAccountProfile(userDetail, instruments, isps, regions, cities) {
function populateAccountProfile(userDetail, instruments) {
var template = context.JK.fillTemplate($('#template-account-profile').html(), {
country: userDetail.country,
state: userDetail.state,
region: userDetail.state,
first_name: userDetail.first_name,
last_name: userDetail.last_name,
user_instruments: userDetail.instruments,
birth_date : userDetail.birth_date,
isp : userDetail.isp,
gender: userDetail.gender,
instruments: instruments,
cities: cities["cities"],
regions: regions["regions"],
isps: isps["isps"]
gender: userDetail.gender
});
$('#account-profile-content-scroller').html(template);
var content_root = $('#account-profile-content-scroller')
content_root.html(template);
// now use javascript to fix up values too hard to do with templating
// set gender
$('select[name=gender]', content_root).val(userDetail.gender)
// set birth_date
if(userDetail.birth_date) {
var birthDateFields = userDetail.birth_date.split('-')
var birthDateYear = birthDateFields[0];
var birthDateMonth = birthDateFields[1];
var birthDateDay = birthDateFields[2];
$('select#user_birth_date_1i', content_root).val(parseInt(birthDateYear));
$('select#user_birth_date_2i', content_root).val(parseInt(birthDateMonth));
$('select#user_birth_date_3i', content_root).val(parseInt(birthDateDay));
}
// update instruments
$.each(instruments, function(index, instrument) {
var template = context.JK.fillTemplate($('#account-profile-instrument').html(), {
checked : isUserInstrument(instrument, userDetail.instruments) ? "checked=\"checked\"" :"",
description : instrument.description,
id : instrument.id
})
$('.instrument_selector', content_root).append(template)
})
// and fill in the proficiency for the instruments that the user can play
$.each(userDetail.instruments, function(index, userInstrument) {
$('tr[data-instrument-id="' + userInstrument.instrument_id + '"] select.proficiency_selector', content_root).val(userInstrument.proficiency_level)
})
}
function isUserInstrument(instrument, userInstruments) {
var isUserInstrument = false;
$.each(userInstruments, function(index, userInstrument) {
if(instrument.id == userInstrument.instrument_id) {
isUserInstrument = true;
return false;
}
})
return isUserInstrument;
}
function populateAccountProfileLocation(userDetail, regions, cities) {
populateRegions(regions, userDetail.state);
populateCities(cities, userDetail.city);
}
function populateRegions(regions, userRegion) {
var regionSelect = getRegionElement()
regionSelect.children().remove()
$.each(regions, function(index, region) {
if(!region) return;
var option = $('<option></option>')
option.text(region)
option.attr("value", region)
regionSelect.append(option)
})
regionSelect.val(userRegion)
regionSelect.attr("disabled", null)
}
function populateCities(cities, userCity) {
var citySelect = getCityElement();
citySelect.children().remove()
$.each(cities, function(index, city) {
if(!city) return;
var option = $('<option></option>')
option.text(city)
option.attr("value", city)
citySelect.append(option)
})
citySelect.val(userCity)
citySelect.attr("disabled", null)
}
/****************** MAIN PORTION OF SCREEN *****************/
// events for main screen
function events() {
$('#account-profile-content-scroller').on('click', '#account-edit-email-cancel', function(evt) { evt.stopPropagation(); navToAccount(); return false; } );
$('#account-profile-content-scroller').on('click', '#account-edit-email-submit', function(evt) { evt.stopPropagation(); handleUpdateProfile(); return false; } );
$('#account-profile-content-scroller').on('click', '#account-edit-profile-cancel', function(evt) { evt.stopPropagation(); navToAccount(); return false; } );
$('#account-profile-content-scroller').on('click', '#account-edit-profile-submit', function(evt) { evt.stopPropagation(); handleUpdateProfile(); return false; } );
$('#account-profile-content-scroller').on('submit', '#account-edit-email-form', function(evt) { evt.stopPropagation(); handleUpdateProfile(); return false; } );
$('#account-profile-content-scroller').on('click', '#account-edit-password-cancel', function(evt) { evt.stopPropagation(); navToAccount(); return false; } );
$('#account-profile-content-scroller').on('change', 'select[name=region]', function(evt) { evt.stopPropagation(); handleRegionChanged(); return false; } );
}
function renderAccountProfile() {
$.when( api.getUserDetail(),
api.getInstruments())
.done(function(userDetail, instruments) {
.done(function(userDetailResponse, instrumentsResponse) {
var userDetail = userDetailResponse[0];
recentUserDetail = userDetail // store userDetail for later
var instruments = instrumentsResponse[0];
// show page; which can be done quickly at this point
populateAccountProfile(userDetail, instruments);
// now that we have the user's country and region, we can query further
loadingLocationData = true;
// make the 3 slower requests, which only matter if the user wants to affect their ISP or location
$.when(
api.getIsps( { country: userDetail.country } ),
api.getRegions( { country: userDetail.country } ),
api.getCities( { country: userDetail.country, region: userDetail.state }))
.done(function(isps, regions, cities) {
populateAccountProfile(userDetail, instruments, isps, regions, cities)
.done(function(regionsResponse, citiesResponse) {
var regions = regionsResponse[0];
var cities = citiesResponse[0];
populateAccountProfileLocation(userDetail, regions["regions"], cities["cities"])
})
.fail(app.ajaxError)
.always(function() {loadingLocationData = false;})
})
.fail(app.ajaxError);
}
@ -89,15 +169,32 @@
}
function handleUpdateProfile() {
if (loadingLocationData) return;
resetForm();
var currentPassword = $('#account-edit-password-form input[name=current_password]').val()
var password = $('#account-edit-password-form input[name=password]').val()
var passwordConfirmation = $('#account-edit-password-form input[name=password_confirmation]').val()
var country = getCountryElement().val();
var region = getRegionElement().val();
var city = getCityElement().val();
var firstName = getFirstNameElement().val();
var lastName = getLastNameElement().val();
var gender = getGenderElement().val()
var birthDate = getBirthDate();
var instruments = getInstrumentsValue();
postUpdatePassword(currentPassword, password, passwordConfirmation)
.done(postUpdatePasswordSuccess)
.fail(postUpdatePasswordFailure)
postUpdateProfile({
country: country,
state: region,
city: city,
first_name: firstName,
last_name: lastName,
gender: gender,
birth_date: birthDate,
instruments: instruments
})
.done(postUpdateProfileSuccess)
.fail(postUpdateProfileFailure)
}
function postUpdateProfile(options) {
@ -146,6 +243,91 @@
}
}
function handleRegionChanged() {
var selectedCountry = getCountryElement().val()
var selectedRegion = getRegionElement().val()
var cityElement = getCityElement();
// only update
if(selectedCountry && selectedRegion) {
// set city disabled while updating
cityElement.attr('disabled', true);
loadingLocationData = false;
cityElement.children().remove()
cityElement.append($('<option></option>').text('loading...'))
api.getCities( { country: selectedCountry, region: selectedRegion })
.done(getCitiesDone)
.fail(app.ajaxError)
.always(function() { loadingLocationData = false; })
}
}
function getCitiesDone(data) {
populateCities(data['cities'], recentUserDetail.city)
}
function getCountryElement() {
return $('#account-profile-content-scroller select[name=country]')
}
function getRegionElement() {
return $('#account-profile-content-scroller select[name=region]')
}
function getCityElement() {
return $('#account-profile-content-scroller select[name=city]')
}
function getFirstNameElement() {
return $('#account-profile-content-scroller input[name=first_name]')
}
function getLastNameElement() {
return $('#account-profile-content-scroller input[name=last_name]')
}
function getGenderElement() {
return $('#account-profile-content-scroller select[name=gender]')
}
function getBirthDate() {
var month = $('#account-profile-content-scroller select#user_birth_date_2i').val()
var day = $('#account-profile-content-scroller select#user_birth_date_3i').val()
var year = $('#account-profile-content-scroller select#user_birth_date_1i').val()
if(month != null && month.length > 0 && day != null && day.length > 0 && year != null && year.length > 0) {
return month + "-" + day + "-" + year;
}
else {
return null;
}
}
// looks in instrument_selector parent element, and gathers up all
// selected elements, and the proficiency level declared
function getInstrumentsValue() {
var instrumentsParentElement = $(".instrument_selector")
var instruments = []
$('input[type=checkbox]:checked', instrumentsParentElement).each(function(i) {
var instrumentElement = $(this).closest('tr');
// traverse up to common parent of this instrument, and pick out proficiency selector
var proficiency = $('select.proficiency_selector', instrumentElement).val()
instruments.push({
instrument_id: instrumentElement.attr('data-instrument-id'),
proficiency_level: proficiency,
priority : i
})
});
return instruments;
}
function initialize() {
var screenBindings = {
'beforeShow': beforeShow,

View File

@ -59,7 +59,7 @@
}
function getInstruments(options) {
return $.ajax('/api/isps', {
return $.ajax('/api/instruments', {
data : { },
dataType : 'json'
});

View File

@ -68,6 +68,11 @@
margin-bottom:27px;
}
div.profile-instrumentlist table {
border-collapse: separate;
border-spacing: 6px;
}
}

View File

@ -57,7 +57,7 @@ class ApiUsersController < ApiController
current_user.id,
params[:first_name],
params[:last_name],
params[:email],
nil, # Don't allow changing email here, since updating email is something that must be done through it's own API
nil, # Don't allow changing password here, since we want to prompt again for the old password
nil,
params[:musician],

View File

@ -235,7 +235,7 @@ class UsersController < ApplicationController
@location = MaxMindManager.lookup(remote_ip)
end
@location[:country] = "United States" if @location[:country].nil?
@location[:country] = "US" if @location[:country].nil?
# right now we only accept US signups for beta
@countries = MaxMindManager.countries()

View File

@ -33,98 +33,77 @@
<div class="content-wrapper account-profile">
<br />
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<form id="account-edit-profile-form">
<table width="100%" cellpadding="0" cellspacing="0">
<tr>
<td valign="top" width="33%">
<div class="right mr30"><a href="#" class="avatar_large ml10"><img src="images/shared/avatar_jonathon.png" width="246" height="246" /></a><br clear="left" />
<a href="#" class="small">Change Avatar</a></div>
<h2>profile:</h2>
<td valign="top" width="33%">
<div class="right mr30"><a href="#" class="avatar_large ml10"><img src="images/shared/avatar_jonathon.png" width="246" height="246" /></a><br clear="left" />
<a href="#" class="small">Change Avatar</a></div>
<h2>profile:</h2>
</td>
</td>
<td valign="top" width="33%">First Name:<br />
<input type="text" value="Jonathon" class="w80"><br />
</td>
<td valign="top" width="33%">Last Name:<br />
<input type="text" value="Wilson" class="w80"></td>
</tr>
<td valign="top" width="33%">First Name:<br />
<input type="text" name="first_name" value="{first_name}" class="w80"><br />
</td>
<td valign="top" width="33%">Last Name:<br />
<input type="text" name="last_name" value="{last_name}" class="w80"></td>
</tr>
<tr>
<td valign="top">Country:<br />
<select class="w80"><option>United States</option></select><br /><br />
<tr>
<td valign="top">Country:<br />
<select name='country' class="w80"><option value='US'>United States</option></select><br /><br />
</td>
<td valign="top">Gender:<br />
<select class="w80"><option>Male</option></select><br />
<br />
</td>
<td valign="top">Birth Date:<br />
<select><option>Feb</option></select>&nbsp;&nbsp;<select><option>15</option></select>&nbsp;&nbsp;<select><option>1970</option></select>
</td>
</td>
<td valign="top">Gender:<br />
<select name="gender" data-value="{gender}" class="w80"><option value='M'>Male</option><option value='F'>Female</option><option value="">-</option></select><br />
<br />
</td>
<td valign="top">Birth Date:<br />
<%= date_select("user", "birth_date", :use_short_month => true, :start_year => 1900, :end_year => Time.now.year - 18, :order => [:month, :day, :year], :default => -25.years.from_now ) %>
</td>
</tr>
</tr>
<tr>
<td valign="top">State/Province:<br />
<select class="w80"><option>Texas</option></select><br /><br />
<tr>
<td valign="top">State/Province:<br />
<select name='region' class="w80" disabled='disabled'><option>loading...</option></select><br /><br />
<td rowspan=3 colspan=2 valign="top"> What instruments can you play?
<td rowspan=3 colspan=2 valign="top"> What instruments can you play?
<div class="profile-instrumentlist w90">
<table width="100%" cellpadding="0" cellspacing="6">
<tr>
<td><input type="checkbox" checked="checked" /> Acoustic Guitar</td>
<td align="right" width="50%"><select><option>Beginner</option><option>Intermediate</option><option>Expert</option></select></td>
</tr>
<tr>
<td><input type="checkbox" /> Bass Guitar</td>
<td align="right" width="50%"><select disabled="disabled"><option>Beginner</option><option>Intermediate</option><option>Expert</option></select></td>
</tr>
<tr>
<td><input type="checkbox" checked="checked" /> Electric Guitar</td>
<td align="right" width="50%"><select><option>Beginner</option><option selected="selected">Intermediate</option><option>Expert</option></select></td>
</tr>
<tr>
<td><input type="checkbox" /> Drums/Percussion</td>
<td align="right" width="50%"><select disabled="disabled"><option>Beginner</option><option>Intermediate</option><option>Expert</option></select></td>
</tr>
<tr>
<td><input type="checkbox" /> Computer</td>
<td align="right" width="50%"><select disabled="disabled"><option>Beginner</option><option>Intermediate</option><option>Expert</option></select></td>
</tr>
<tr>
<td><input type="checkbox" checked="checked" /> Keyboard/Piano</td>
<td align="right" width="50%"><select><option>Beginner</option><option>Intermediate</option><option selected="selected">Expert</option></select></td>
</tr>
<tr>
<td><input type="checkbox" /> Violin</td>
<td align="right" width="50%"><select disabled="disabled"><option>Beginner</option><option>Intermediate</option><option>Expert</option></select></td>
</tr>
</table>
</div></td>
</tr>
<div class="profile-instrumentlist w90">
<table class="instrument_selector" width="100%" cellpadding="0" cellspacing="6">
<tr>
<td valign="top">City:<br />
<select class="w80"><option>Austin</option></select><br /><br />
</table>
</div></td>
</tr>
</td>
</tr>
<tr>
<td valign="top">City:<br />
<select name='city' class="w80" disabled='disabled'><option>loading...</option></select><br /><br />
<tr>
<td valign="top">Internet Provider:<br />
<select class="w80"><option>AT&amp;T Uverse</option></select></td>
</tr>
</table>
</td>
</tr>
</table>
</form>
<br clear="all" />
<div class="right"><a href="account.shtml" class="button-grey">CANCEL</a>&nbsp;&nbsp;<a href="account.shtml" class="button-orange">UPDATE PROFILE</a></div>
<div class="right"><a id="account-edit-profile-cancel" href="#" class="button-grey">CANCEL</a>&nbsp;&nbsp;<a id="account-edit-profile-submit" href="#" class="button-orange">UPDATE PROFILE</a></div>
</div>
<!-- end content wrapper -->
</script>
<script type="text/template" id="account-profile-instrument">
<tr data-instrument-id='{id}'>
<td><input type="checkbox" {checked} />{description}</td>
<td align="right" width="50%"><select name="proficiency" class='proficiency_selector'><option value="1">Beginner</option><option value="2">Intermediate</option><option value="3">Expert</option></select></td>
</tr>
</script>

View File

@ -52,7 +52,7 @@
<select id="country_select" name="jam_ruby_user[country]" autocomplete="off">
<option value="">Select Country</option>
<% @countries.each do |country| %>
<option value="<%= country %>" <%= @location[:country] == "United States" ? "selected" : "" %>><%= country %></option>
<option value="<%= country %>" <%= @location[:country] == "US" ? "selected" : "" %>><%= country %></option>
<% end %>
</select>

View File

@ -40,7 +40,7 @@
<%= f.text_field :email, :disabled => true %></td>
<td>Country:<br />
<select id="jam_ruby_user_country" name="jam_ruby_user_country"><option value="United States">United States</option></select>
<select id="jam_ruby_user_country" name="jam_ruby_user_country"><option value="US">United States</option></select>
</td>
</tr>

View File

@ -86,7 +86,7 @@ class MaxMindManager < BaseManager
ActiveRecord::Base.connection_pool.with_connection do |connection|
pg_conn = connection.instance_variable_get("@connection")
pg_conn.exec("SELECT DISTINCT isp FROM max_mind_isp WHERE country = $1 ORDER BY isp ASC", [country]).map do |tuple|
tuple["country"]
tuple["isp"]
end
end
end