first graphs for fitbit & fixed achievements for user-not-user

This commit is contained in:
Bastian Greshake
2012-09-06 23:55:16 +02:00
parent 526d65a8de
commit 973829128b
14 changed files with 341 additions and 37 deletions

View File

@@ -1,12 +1,28 @@
class FitbitProfilesController < ApplicationController
before_filter :require_user, except: [:new_notification]
before_filter :require_user, except: [:new_notification, :show, :index]
before_filter :require_user, only: [:update,:destroy,:init,:edit,:start_auth,:verify_auth,:dump]
protect_from_forgery :except => :new_notification
helper_method :sort_column, :sort_direction
def index
@title = "Listing all connected Fitbit accounts"
@fitbit = FitbitProfile.order(sort_column + " " + sort_direction)
@fitbit_paginate = @fitbit.paginate(:page => params[:page],:per_page => 20)
respond_to do |format|
format.html
format.xml
end
end
def show
@fitbit_profile = FitbitProfile.find_by_id(params[:id]) || not_found
@activity = FitbitActivity.find_all_by_fitbit_profile_id(@fitbit_profile.id,:order => "date_logged")
@step_counter = 0
@floor_counter = 0
@steps = @activity.map {|fa| [fa.date_logged,fa.steps.to_i]}.inspect
@total_steps = @activity.map {|fa| [fa.date_logged,@step_counter = @step_counter += fa.steps.to_i]}.inspect
@total_floors = @activity.map {|fa| [fa.date_logged,@floor_counter = @floor_counter += fa.floors.to_i]}.inspect
@floors = @activity.map {|fa| [fa.date_logged,fa.floors.to_i]}.inspect
respond_to do |format|
format.html
end
@@ -129,5 +145,13 @@ class FitbitProfilesController < ApplicationController
return false
end
end
def sort_column
Genotype.column_names.include?(params[:sort]) ? params[:sort] : "created_at"
end
def sort_direction
%w[desc asc].include?(params[:direction]) ? params[:direction] : "desc"
end
end

View File

@@ -25,7 +25,7 @@
</div>
<div class="span6">
<p>We will save data from three different categories: <strong>Body</strong>, <strong>Activities</strong> and <strong>Sleep</strong>.</p>
<p>For the <strong>Body</strong> category we will save your Body Mass Index (BMI) and your weight (Unfortunately there's currently no option to get your height through <em>Fitbit</em>).</p>
<p>For the <strong>Body</strong> category we will save your Body Mass Index (BMI) and your weight (Unfortunately there's currently no option to get your height through <em>Fitbit</em> but you can calculate it through BMI and weight).</p>
<p>For <strong>Sleep</strong> we will save how long you have slept and how often you have awoke, how long you've been awake and how long it took you to fall asleep.</p>
<p>For the <strong>Activities</strong> we will save how many steps you have taken and how many floors you have climbed.</p><p>We will try to save the data you have uploaded to <em>Fitbit</em> up to now as well. You can decide which categories we should save. So if you feel comfortable to share your activities but neither weight nor sleep information that's no problem.</p>

View File

@@ -1,2 +1,2 @@
<legend>Dumping <em>Fitbit</em> data for <%=@fitbit_profile.user.name%></legend>
<legend><%=image_tag("/images/fitbit-icon.png")%> Dumping <em>Fitbit</em> data for <%=@fitbit_profile.user.name%></legend>
<p class="lead">You have requested <em>Fitbit</em> data for the user <%= link_to(@fitbit_profile.user.name, @fitbit_profile.user)%>. The data is currently prepared and you will receive an email as soon as the data is ready to be downloaded. <%=link_to("Return to the Fitbit Profile" ,{:controller => "fitbit_profiles", :action => "show", :id => @fitbit_profile.id})%>.</p>

View File

@@ -0,0 +1,41 @@
<legend><%=image_tag("/images/fitbit-icon.png")%> Listing all connected <em>Fitbit</em> accounts </legend>
<%if current_user%>
<h4>
<%=link_to(image_tag("/images/filedownload_small.png",:style => "vertical-align:middle"),{:controller => "genotypes", :action => "get_dump"})%> <%=link_to("Download the dump: Includes all Fitbit data with all other phenotypes & genotyping files",{:controller => "genotypes", :action => "get_dump"}, :title => "Request download")%>
</h4>
<% end %>
<br/>
<% if not current_user and @filelink != nil%>
<h4>
<%= link_to(image_tag("/images/filedownload_small.png", :style => "vertical-align:middle"), {:controller => "genotypes",:action => "dump_download"})%> <%= link_to("Download the dump: Includes all Fitbit data with all other phenotypes & genotyping files",{:controller => "genotypes", :action => "dump_download"}, :title => "Download the dump") %>
</h4>
<%end%>
<h4><a href="https://github.com/superbobry/snpy">Python-library to parse the provided files</a>, courtesy of <a href="https://github.com/superbobry/">Sergei Lebedev</a></h4>
<br/>
<table class="table table-striped" id="all_fitbit">
<tr>
<th>#</th>
<th><%= sortable "fitbit_user_id", "Fitbit ID"%></th>
<th>User</th>
<th><%= sortable "activities", "Shares Activities"%></th>
<th><%= sortable "body", "Shares Body Data"%></th>
<th><%= sortable "sleep", "Shares Sleep Data"%></th>
<th>View Profile</th>
</tr>
<% @fitbit_paginate.each do |g| %>
<tr>
<td><%= FitbitProfile.all.sort! { |a,b| a.id <=> b.id }.index(g) + 1 %></td>
<td><%= link_to(g.fitbit_user_id, {:controller => "fitbit_profiles", :action => "show", :id => g.id}) %></td>
<td><%=image_tag g.user.avatar.url(:head),:style => "vertical-align:middle"%><%= link_to(g.user.name, g.user)%></td>
<td><%if g.activities == true%><i class="icon-ok"></i><%else%><i class="icon-remove"></i><%end%></td>
<td><%if g.body == true%><i class="icon-ok"></i><%else%><i class="icon-remove"></i><%end%></td>
<td><%if g.sleep == true%><i class="icon-ok"></i><%else%><i class="icon-remove"></i><%end%></td>
<td><%= link_to("view", {:controller => "fitbit_profiles", :action => "show", :id => g.id})%></td>
</tr>
<% end %>
</table>
<div class="pagination">
<%= will_paginate(@fitbit_paginate) %>
</div>

View File

@@ -3,4 +3,92 @@
<p class="lead">Some graphs go here. This is FitbitProfile #<%=link_to(@fitbit_profile.id ,{:controller => "fitbit_profiles", :action => "show", :id => @fitbit_profile.id})%> for user <%= link_to(@fitbit_profile.user.name, @fitbit_profile.user)%>.</p>
<%if current_user%>
<p class="lead"><%=link_to(image_tag("/images/filedownload_small.png",:style => "vertical-align:middle"),{:controller => "fitbit_profiles", :action => "dump", :id => @fitbit_profile.id})%> <%=link_to("Download a dump of the data",{:controller => "fitbit_profiles", :action => "dump", :id => @fitbit_profile.id})%></p>
<%end%>
<%end%>
<div id="chart1"></div>
<div id="chart2"></div>
<script class="include" language="javascript" type="text/javascript" src="/javascripts/jqplot.highlighter.min.js"></script>
<script class="include" language="javascript" type="text/javascript" src="/javascripts/jqplot.dateAxisRenderer.min.js"></script>
<script class="include" language="javascript" type="text/javascript" src="/javascripts/jqplot.cursor.min.js"></script>
<script class="include" language="javascript" type="text/javascript" src="/javascripts/jqplot.barRenderer.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var steps=<%=raw(@steps)%>;
var floors=<%=raw(@floors)%>;
var plot1 = $.jqplot('chart1', [floors,steps], {
title:'Activity per Day',
series:[{label:'Floors' ,yaxis:'y2axis',fill: true,highlightMouseOver: false}, {label:'Steps'}],
axes:{
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
tickOptions:{
formatString:'%b&nbsp;%#d'
}
},
yaxis:{
tickOptions:{
formatString:'%i steps'
}
},
y2axis:{
tickOptions:{
formatString:'%i floors'
},
},
},
axesDefaults: {
pad: 0
},
legend: {
show: true,
placement: 'outsideGrid'
},
highlighter: {
show: true,
sizeAdjust: 7.5
},
cursor: {
show: false
}
});
var total_steps=<%=raw(@total_steps)%>;
var total_floors=<%=raw(@total_floors)%>;
var plot2 = $.jqplot('chart2', [total_floors,total_steps], {
title:'Sum of Activity',
series:[{label:"Floors",yaxis:'y2axis',fill:true},{label:'Steps',fill:true}],
axes:{
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
tickOptions:{
formatString:'%b&nbsp;%#d'
}
},
yaxis:{
tickOptions:{
formatString:'%i steps'
}
},
y2axis:{
tickOptions:{
formatString:'%i floors'
},
},
},
axesDefaults: {
pad: 0
},
legend: {
show: true,
placement: 'outsideGrid'
},
highlighter: {
show: true,
sizeAdjust: 7.5
},
cursor: {
show: false
}
});
});
</script>

View File

@@ -21,9 +21,16 @@
<ul class="nav">
<li class=""><%= link_to("News", '/news') %></li>
<li class=""><%= link_to("Genotypes", :controller => "genotypes", :action => "index")%></li>
<li class=""><%= link_to("Phenotypes", :controller => "phenotypes", :action => "index")%></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Phenotypes <b class="caret"></b></a>
<ul class="dropdown-menu">
<li class=""><%= link_to("Normal Phenotypes", :controller => "phenotypes", :action => "index")%></li>
<li class=""><%= link_to("Fitbit Connections", :controller => "fitbit_profiles", :action => "index")%></li>
</ul>
</li>
<li class=""><%= link_to("SNPs", :controller => "snps", :action => "index") %></li>
<li class=""><%= link_to("Users", '/user_index') %></li>
<li class=""><%= link_to("User", '/user_index') %></li>
</ul>
<%= form_tag "/search", :method => "get",:class => "navbar-search pull-left", :authenticity_token => true do %>
<%= text_field_tag :search, nil, :placeholder => "Search here", :class => "search-query" %>
@@ -38,6 +45,7 @@
<ul class="dropdown-menu">
<li><%= link_to("Settings", :controller => "users", :action => "edit",:id => current_user) %></li>
<li><%= link_to("Edit Your Phenotypes", "/users/"+current_user.id.to_s+"/edit#phenotypes")%></li>
<%if current_user.fitbit_profile != nil%><li><%=link_to("Edit Fitbit settings" ,{:controller => "fitbit_profiles", :action => "edit"})%></li><%end%>
<li class="divider"></li>
<li><%= link_to("Messages ("+current_user.messages.where(:user_has_seen => false).length.to_s+")","/users/" + current_user.id.to_s + "#messages")%></li>
<li class="divider"></li>

View File

@@ -7,6 +7,7 @@
<li><a href="#general">General</a></li>
<li><a href="#phenotypes">Phenotypes</a></li>
<li><a href="#details">Details</a></li>
<li><a href="#fitbit">Fitbit</a></li>
<li><a href="#notifications">Notifications</a></li>
<li><a href="#deleting">Deleting</a></li>
</ul>
@@ -107,7 +108,17 @@
<p><%= link_to "Delete this account", @user, :method => "delete", :confirm => "Are you sure you want to delete your account?" %></p>
</div>
</div>
<div id="fitbit">
<div class="well">
<h2><%=image_tag("/images/fitbit-icon.png")%> <em>Fitbit</em> Settings</h2>
<%if @user.fitbit_profile != nil%>
<p class="lead">You have connected your <em>Fitbit</em> account with <em>openSNP</em></p>
<p class="lead"><%=link_to("Edit your Fitbit connection" ,{:controller => "fitbit_profiles", :action => "edit"})%></p>
<%else%>
<p class="lead">You haven't connected a <em>Fitbit</em> account with <em>openSNP</em> yet. <%=link_to("Do you want to learn more about how to do this?" ,{:controller => "fitbit_profiles", :action => "info"})%></p>
<%end%>
</div>
</div>
<div class="actions">
<%= f.submit "Update Information", :class => "btn btn-primary", :id => "update_user" %>

View File

@@ -3,15 +3,12 @@
<%= image_tag @user.avatar.url(:thumb),:style => "vertical-align:middle" %>
</div>
<div class="span6 columns"><legend><%= @user.name %>'s page</legend>
<% @user.achievements.each do |a|%>
<div id="<%=a.short_name%>" class="tooltip">
Achievement: <%=a.award%>.
</div>
<a onmouseover="showWMTT('<%=a.short_name%>')" onmouseout="hideWMTT()" href="/achievements/<%=a.id%>"><%=image_tag("/images/achievements/"+a.short_name+"_32px.png",:style => "vertical-align:middle",:height=>"20",:alt => a.award)%></a>
<%if @user.fitbit_profile != nil%>
<%=link_to(image_tag("/images/fitbit-icon.png"),{:controller => "fitbit_profiles", :action => "show", :id => @user.fitbit_profile.id},:rel =>"tooltip",:title => "See Fitbit data for this user")%>
<%end%>
<% @user.achievements.each do |a|%>
<a href="/achievements/<%= a.id %>" rel="tooltip" title="Achievement: <%=a.award%>"><%=image_tag("/images/achievements/"+a.short_name+"_32px.png",:height=>"20px",:alt => a.award)%></a>
<%end%>
</div>
<%if current_user%><div class="span3"><h5><%=link_to(image_tag("/images/sendmessage_small.png",:style => "vertical-align:middle" ), :controller => "messages", :action => "new", :user_to_send => @user.id)%> <%= link_to("Send "+ @first_name + " a message", :controller => "messages", :action => "new", :user_to_send => @user.id) %></h5></div><%end%>
</div>
@@ -54,24 +51,8 @@
</div>
<% end %>
<script type="text/javascript">
<!--
wmtt = null;
document.onmousemove = updateWMTT;
function updateWMTT(e) {
if (wmtt != null && wmtt.style.display == 'block') {
x = (e.pageX ? e.pageX : window.event.x);
y = (e.pageY ? e.pageY : window.event.y);
wmtt.style.left = x + "px";
wmtt.style.top = (y - wmtt.offsetHeight) + "px";
}
}
function showWMTT(id) {
wmtt = document.getElementById(id);
wmtt.style.display = "block";
}
function hideWMTT() {
wmtt.style.display = "none";
}
-->
</script>
<script type="text/javascript">
$(document).ready(function () {
$("[rel=tooltip]").tooltip({placement:'bottom'});
});
</script>

View File

@@ -5,6 +5,9 @@
<div class="span3"><h1>Hello <%= @first_name %>!</h1></div>
<br/>
<div class="span4">
<%if @user.fitbit_profile != nil%>
<%=link_to(image_tag("/images/fitbit-icon.png"),{:controller => "fitbit_profiles", :action => "show", :id => @user.fitbit_profile.id},:rel =>"tooltip",:title => "See Fitbit data for this user")%>
<%end%>
<% current_user.achievements.each do |a|%>
<a href="/achievements/<%= a.id %>" rel="tooltip" title="Achievement: <%=a.award%>"><%=image_tag("/images/achievements/"+a.short_name+"_32px.png",:height=>"20px",:alt => a.award)%></a>
<%end%>

View File

@@ -32,6 +32,7 @@ Snpr::Application.routes.draw do
match '/fitbit/delete/', :to => 'fitbit_profiles#destroy'
match '/fitbit/show/:id', :to => 'fitbit_profiles#show', :as => :fitbit_show
match '/fitbit/dump/:id', :to => 'fitbit_profiles#dump', :as => :fitbit_dump
match '/fitbit/', :to => 'fitbit_profiles#index', :as => :fitbit_index
match '/users/:id/changepassword', :to => 'users#changepassword'
match '/signup', :to => 'users#new'
match '/signin', :to => 'user_sessions#new', :as => :login

File diff suppressed because one or more lines are too long

30
public/javascripts/jqplot.cursor.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long