mirror of
https://github.com/chenasraf/snpr.git
synced 2026-05-17 17:38:07 +00:00
remove all of fitbit (#482)
* remove all of fitbit * try fixing migration * add new structure sql * 🐶 * add first test for das * 🐶 * fix structure.sql
This commit is contained in:
committed by
GitHub
parent
293926c199
commit
44184dda33
@@ -1,19 +0,0 @@
|
||||
.fitbit__download-button
|
||||
width: 175px
|
||||
margin-bottom: 10px
|
||||
|
||||
.fitbit__download-text
|
||||
font-size: 10px
|
||||
|
||||
.fitbit__download-container
|
||||
margin-top: 30px
|
||||
|
||||
.fitbit__table
|
||||
clear: both
|
||||
margin-top: 30px
|
||||
|
||||
.fitbit__form
|
||||
margin: 30px 0
|
||||
|
||||
.fitbit__form-submit-button
|
||||
margin-top: 20px
|
||||
@@ -1,138 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
class FitbitProfilesController < ApplicationController
|
||||
before_action :require_user, except: [:show, :index]
|
||||
helper_method :sort_column, :sort_direction
|
||||
|
||||
def index
|
||||
@title = 'Listing all connected Fitbit accounts'
|
||||
@fitbit_profiles = FitbitProfile
|
||||
.includes(:user)
|
||||
.order("#{sort_column} #{sort_direction}")
|
||||
.paginate(page: params[:page], per_page: 15)
|
||||
end
|
||||
|
||||
def show
|
||||
@fitbit_profile = FitbitProfile.find_by_id(params[:id]) || not_found
|
||||
@title = 'Fitbit profile'
|
||||
|
||||
#grab activity measures for graphs
|
||||
if @fitbit_profile.activities
|
||||
@activity = FitbitActivity
|
||||
.where(fitbit_profile_id: @fitbit_profile.id)
|
||||
.order(:date_logged)
|
||||
@total_length = 0 # sum of all steps which are not 0 and not nil
|
||||
|
||||
@total_floors = []
|
||||
@total_steps = []
|
||||
@floors = []
|
||||
@steps = []
|
||||
@floor_counter = 0
|
||||
@step_counter = 0
|
||||
|
||||
@activity.each do |a|
|
||||
# Sometimes, floors is nil and not a number - API problem?
|
||||
# Dismiss these entries
|
||||
if a.steps.nil? or a.floors.nil?
|
||||
next
|
||||
end
|
||||
|
||||
if a.steps != 0
|
||||
@total_length += 1
|
||||
end
|
||||
|
||||
@total_floors << [a.date_logged, @floor_counter += a.floors]
|
||||
@floors << [a.date_logged, a.floors]
|
||||
@steps << [a.date_logged, a.steps]
|
||||
@total_steps << [a.date_logged, @step_counter += a.steps]
|
||||
end
|
||||
|
||||
if not @total_steps.empty?
|
||||
begin
|
||||
@mean_steps = @total_steps[-1][-1] / @total_length #@activity.length
|
||||
rescue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#grab body measurements for graphs
|
||||
if @fitbit_profile.body
|
||||
@body = FitbitBody
|
||||
.where(fitbit_profile_id: @fitbit_profile.id)
|
||||
.order(:date_logged)
|
||||
@bmi = @body.map {|fa| [fa.date_logged, fa.bmi]}
|
||||
end
|
||||
|
||||
#grab sleep measurements for graphs
|
||||
if @fitbit_profile.sleep
|
||||
@sleep = FitbitSleep
|
||||
.where(fitbit_profile_id: @fitbit_profile.id)
|
||||
.order(:date_logged)
|
||||
|
||||
@total_minutes_asleep = []
|
||||
@total_minutes_to_sleep = []
|
||||
@minutes_asleep = []
|
||||
@minutes_to_sleep = []
|
||||
@awakenings = []
|
||||
@total_to_sleep_counter = 0
|
||||
@total_asleep_counter = 0
|
||||
@no_sleep = 0
|
||||
|
||||
@sleep.each do |s|
|
||||
# Here again, some have nils
|
||||
# Skip these
|
||||
if s.minutes_to_sleep.nil? or s.minutes_asleep.nil?
|
||||
next
|
||||
end
|
||||
|
||||
if s.minutes_asleep == 0
|
||||
@no_sleep += 1
|
||||
end
|
||||
|
||||
@total_minutes_to_sleep << [s.date_logged, @total_to_sleep_counter += s.minutes_to_sleep]
|
||||
@total_minutes_asleep << [s.date_logged, @total_asleep_counter += s.minutes_asleep]
|
||||
@minutes_asleep << [s.date_logged, s.minutes_asleep]
|
||||
@minutes_to_sleep << [s.date_logged, s.minutes_to_sleep]
|
||||
@awakenings << [s.date_logged, s.number_awakenings]
|
||||
end
|
||||
|
||||
if not @total_minutes_asleep.empty?
|
||||
begin
|
||||
@mean_sleep = @total_minutes_asleep[-1][-1] / (@sleep.length - @no_sleep)
|
||||
rescue
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def dump
|
||||
@fitbit_profile = FitbitProfile.find_by_id(params[:id]) || not_found
|
||||
FitbitDump.perform_async(@fitbit_profile.id,current_user.id)
|
||||
end
|
||||
|
||||
def info
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def require_owner
|
||||
unless current_user == FitbitProfile.find(params[:fitbit_profile][:id]).user.id
|
||||
store_location
|
||||
if current_user
|
||||
return true
|
||||
else
|
||||
flash[:notice] = 'You need to be logged in'
|
||||
redirect_to '/signin'
|
||||
end
|
||||
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
|
||||
@@ -127,7 +127,7 @@ class UsersController < ApplicationController
|
||||
@user = User.find(params[:id])
|
||||
|
||||
if params[:user][:user_phenotypes_attributes].present?
|
||||
params[:user][:user_phenotypes_attributes].each do |p|
|
||||
params[:user][:user_phenotypes_attributes].each do |p|
|
||||
@phenotype = UserPhenotype.find(p[1]["id"]).phenotype
|
||||
@old_variation = UserPhenotype.find_by_id(p[1]["id"]).variation
|
||||
end
|
||||
@@ -186,10 +186,6 @@ class UsersController < ApplicationController
|
||||
|
||||
flash[:notice] = 'Thank you for using openSNP. Goodbye!'
|
||||
|
||||
# disconnect from fitbit if needed
|
||||
if @user.fitbit_profile != nil
|
||||
Sidekiq::Client.enqueue(FitbitEndSubscription, @user.fitbit_profile.id)
|
||||
end
|
||||
|
||||
@user.destroy
|
||||
|
||||
|
||||
@@ -114,13 +114,6 @@ class UserMailer < ActionMailer::Base
|
||||
mail(subject: 'openSNP.org: Sorry, there is no data to be dumped', to: target_address)
|
||||
end
|
||||
|
||||
def fitbit_dump(link, user_id)
|
||||
@link = link
|
||||
@user = User.find(user_id)
|
||||
mail(subject: 'openSNP.org: The Fitbit-data you requested is now ready for download',
|
||||
to: @user.email)
|
||||
end
|
||||
|
||||
def finished_parsing(genotype_id, stats)
|
||||
genotype = Genotype.find(genotype_id)
|
||||
@user = genotype.user
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
class FitbitActivity < ActiveRecord::Base
|
||||
belongs_to :fitbit_profile
|
||||
|
||||
def self.find_or_create_by_fitbit_profile_id_and_date_logged(fitbit_profile_id, date_logged)
|
||||
obj = self.find_by_fitbit_profile_id_and_date_logged( fitbit_profile_id, date_logged ) || self.new(fitbit_profile_id: fitbit_profile_id, date_logged: date_logged)
|
||||
obj
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,10 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
class FitbitBody < ActiveRecord::Base
|
||||
belongs_to :fitbit_profile
|
||||
|
||||
def self.find_or_create_by_fitbit_profile_id_and_date_logged(fitbit_profile_id, date_logged)
|
||||
obj = self.find_by_fitbit_profile_id_and_date_logged( fitbit_profile_id, date_logged ) || self.new(fitbit_profile_id: fitbit_profile_id, date_logged: date_logged)
|
||||
obj
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
class FitbitProfile < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
has_many :fitbit_bodies, dependent: :destroy
|
||||
has_many :fitbit_activities, dependent: :destroy
|
||||
has_many :fitbit_sleeps, dependent: :destroy
|
||||
end
|
||||
@@ -1,10 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
class FitbitSleep < ActiveRecord::Base
|
||||
belongs_to :fitbit_profile
|
||||
|
||||
def self.find_or_create_by_fitbit_profile_id_and_date_logged(fitbit_profile_id, date_logged)
|
||||
obj = self.find_by_fitbit_profile_id_and_date_logged( fitbit_profile_id, date_logged ) || self.new(fitbit_profile_id: fitbit_profile_id, date_logged: date_logged)
|
||||
obj
|
||||
end
|
||||
|
||||
end
|
||||
@@ -35,7 +35,6 @@ class User < ActiveRecord::Base
|
||||
has_many :snp_comments # these shouldn't be deleted, but orphaned
|
||||
has_many :phenotype_comments, dependent: :destroy
|
||||
has_many :picture_phenotype_comments, dependent: :destroy
|
||||
has_one :fitbit_profile, dependent: :destroy
|
||||
has_one :open_humans_profile, dependent: :destroy
|
||||
|
||||
# needed to edit several user_phenotypes at once, add and delete, and not empty
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<div class="general__container">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h3><%=image_tag("fitbit-icon.png")%> Listing all connected <em>Fitbit</em> accounts </h3>
|
||||
<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>
|
||||
</div>
|
||||
<div class="fitbit__download-container col-md-6 ">
|
||||
<%= link_to Zipfulldata.public_path, title: "Request download", class: "btn btn-default center-block fitbit__download-button" do %>
|
||||
Download dump
|
||||
<% end %>
|
||||
<p class="text-center fitbit__text-download">Includes all genotyping files plus a CSV with all phenotypes of those users</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover snps__table" id="all_fitbit">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>User</th>
|
||||
<th>#</th>
|
||||
<th><%= sortable "fitbit_user_id", "Fitbit ID"%></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>
|
||||
</thead>
|
||||
<% @fitbit_profiles.each_with_index do |fitbit_profile, i| %>
|
||||
<tr>
|
||||
<td class="table-cell vertical-centered"><%= link_to(image_tag(fitbit_profile.user.avatar.url(:head), :class => "img-circle", :width => "50px") + " #{fitbit_profile.user.name}", fitbit_profile.user) %></td>
|
||||
<td class="table-cell vertical-centered"><%= table_row_sequence_number(@fitbit_profiles, i) %></td>
|
||||
<td class="table-cell vertical-centered"><%= link_to(fitbit_profile.fitbit_user_id, {:controller => "fitbit_profiles", :action => "show", :id => fitbit_profile.id}) %></td>
|
||||
<td class="table-cell vertical-centered"><%if fitbit_profile.activities == true%><i class="icon-ok"></i><%else%><i class="icon-remove"></i><%end%></td>
|
||||
<td class="table-cell vertical-centered"><%if fitbit_profile.body == true%><i class="icon-ok"></i><%else%><i class="icon-remove"></i><%end%></td>
|
||||
<td class="table-cell vertical-centered"><%if fitbit_profile.sleep == true%><i class="icon-ok"></i><%else%><i class="icon-remove"></i><%end%></td>
|
||||
<td class="table-cell vertical-centered"><%= link_to("View", {:controller => "fitbit_profiles", :action => "show", :id => fitbit_profile.id}, class: "btn btn-default")%></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
<div class="text-center">
|
||||
<%= page_navigation_links @fitbit_profiles%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,231 +0,0 @@
|
||||
<div class="general__container">
|
||||
<h3 class="general__title"><%=image_tag("fitbit-icon.png")%> <em>"Fitbit"</em> profile for <%= link_to(@fitbit_profile.user.name, @fitbit_profile.user)%></h3>
|
||||
<%if current_user%>
|
||||
<p class="lead"><%=link_to("Download dump",{:controller => "fitbit_profiles", :action => "dump", :id => @fitbit_profile.id}, class: "btn btn-default")%></p>
|
||||
<%else%>
|
||||
<p class="lead">If you log in to <em>openSNP</em>, you can download a CSV file with all the data.</p>
|
||||
<%end%>
|
||||
|
||||
<%if @activity != nil%>
|
||||
<legend>Activity Measurements</legend>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
// Activity Graph
|
||||
var steps=<%=raw(@steps.to_json)%>;
|
||||
var floors=<%=raw(@floors.to_json)%>;
|
||||
var plot1 = $.jqplot('chart1', [floors,steps], {
|
||||
title:'Activity per Day (Mean steps/day: <%=@mean_steps%>)',
|
||||
series:[{label:'Floors' ,yaxis:'y2axis',fill: true,fillAlpha: 0.8,highlightMouseOver: false}, {label:'Steps'}],
|
||||
axes:{
|
||||
xaxis:{
|
||||
renderer:$.jqplot.DateAxisRenderer,
|
||||
tickOptions:{
|
||||
formatString:'%b %#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
|
||||
}
|
||||
});
|
||||
// Sum Activity Graph
|
||||
var total_steps=<%=raw(@total_steps.to_json)%>;
|
||||
var total_floors=<%=raw(@total_floors.to_json)%>;
|
||||
var plot2 = $.jqplot('chart2', [total_floors,total_steps], {
|
||||
title:'Sum of Activity',
|
||||
series:[{label:"Floors",yaxis:'y2axis',fill:true,fillAlpha:0.5},{label:'Steps',fill:true,fillAlpha:0.5}],
|
||||
axes:{
|
||||
xaxis:{
|
||||
renderer:$.jqplot.DateAxisRenderer,
|
||||
tickOptions:{
|
||||
formatString:'%b %#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>
|
||||
<div id="chart1"></div>
|
||||
<div id="chart2"></div>
|
||||
<%end%>
|
||||
|
||||
<%if @body and @body != [] %>
|
||||
<legend>Body Measurements</legend>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
// BMI Graph
|
||||
var bmi=<%=raw(@bmi.to_json)%>;
|
||||
var plot3 = $.jqplot('chart3', [bmi], {
|
||||
title:'BMI per Day',
|
||||
series:[{label:'Body Mass Index',fill:true}],
|
||||
axes:{
|
||||
xaxis:{
|
||||
renderer:$.jqplot.DateAxisRenderer,
|
||||
tickOptions:{
|
||||
formatString:'%b %#d'
|
||||
}
|
||||
},
|
||||
yaxis:{
|
||||
tickOptions:{
|
||||
formatString:'%.2f BMI'
|
||||
}
|
||||
},
|
||||
},
|
||||
axesDefaults: {
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
placement: 'outsideGrid'
|
||||
},
|
||||
highlighter: {
|
||||
show: true,
|
||||
sizeAdjust: 7.5
|
||||
},
|
||||
cursor: {
|
||||
show: false
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div id="chart3"></div>
|
||||
<%end%>
|
||||
|
||||
<%if @sleep and @sleep != [] %>
|
||||
<legend>Sleep Measurements</legend>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
// Activity Graph
|
||||
var minutes_asleep=<%=raw(@minutes_asleep.to_json)%>;
|
||||
var minutes_to_sleep=<%=raw(@minutes_to_sleep.to_json)%>;
|
||||
var awakenings=<%=raw(@awakenings.to_json)%>;
|
||||
var plot4 = $.jqplot('chart4', [awakenings,minutes_asleep,minutes_to_sleep], {
|
||||
title:'Sleep per Day (Mean sleep/day: <%=@mean_sleep%> minutes)',
|
||||
series:[{label:'# awaken' ,yaxis:'y2axis',fill: true,highlightMouseOver: false}, {label:'Minutes asleep'},{label: 'Minutes awake',fill:true}],
|
||||
axes:{
|
||||
xaxis:{
|
||||
renderer:$.jqplot.DateAxisRenderer,
|
||||
tickOptions:{
|
||||
formatString:'%b %#d'
|
||||
}
|
||||
},
|
||||
yaxis:{
|
||||
tickOptions:{
|
||||
formatString:'%i minutes'
|
||||
}
|
||||
},
|
||||
y2axis:{
|
||||
tickOptions:{
|
||||
formatString:'%i times awoken'
|
||||
},
|
||||
},
|
||||
},
|
||||
axesDefaults: {
|
||||
pad: 0
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
placement: 'outsideGrid'
|
||||
},
|
||||
highlighter: {
|
||||
show: true,
|
||||
sizeAdjust: 7.5
|
||||
},
|
||||
cursor: {
|
||||
show: false
|
||||
}
|
||||
});
|
||||
// Sum Activity Graph
|
||||
var total_minutes_asleep=<%=raw(@total_minutes_asleep.to_json)%>;
|
||||
var total_minutes_to_sleep=<%=raw(@total_minutes_to_sleep.to_json)%>;
|
||||
var plot5 = $.jqplot('chart5', [total_minutes_asleep,total_minutes_to_sleep], {
|
||||
title:'Sum of Sleep',
|
||||
series:[{label:'minutes asleep',fill:true,fillAlpha:0.5},{label:"minutes falling asleep",yaxis:'y2axis',fill:true,fillAlpha:0.6}],
|
||||
axes:{
|
||||
xaxis:{
|
||||
renderer:$.jqplot.DateAxisRenderer,
|
||||
tickOptions:{
|
||||
formatString:'%b %#d'
|
||||
}
|
||||
},
|
||||
yaxis:{
|
||||
tickOptions:{
|
||||
formatString:'%i min (asleep)'
|
||||
}
|
||||
},
|
||||
y2axis:{
|
||||
tickOptions:{
|
||||
formatString:'%i min (falling asleep)'
|
||||
},
|
||||
},
|
||||
},
|
||||
axesDefaults: {
|
||||
pad: 0
|
||||
},
|
||||
legend: {
|
||||
show: true,
|
||||
placement: 'outsideGrid'
|
||||
},
|
||||
highlighter: {
|
||||
show: true,
|
||||
sizeAdjust: 7.5
|
||||
},
|
||||
cursor: {
|
||||
show: false
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div id="chart4"></div>
|
||||
<div id="chart5"></div>
|
||||
<%end%>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$("[rel=tooltip]").tooltip({placement:'right'});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
@@ -20,7 +20,6 @@
|
||||
<li><%= link_to "Phenotypes Pictures", {:controller => "picture_phenotypes", :action => "index"}, class: "navbar-menu__options"%></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><%= link_to "Open Humans Connections", {:controller => "open_humans_profiles", :action => "index"}, class: "navbar-menu__options"%></li>
|
||||
<li><%= link_to "Fitbit Connections", {:controller => "fitbit_profiles", :action => "index"}, class: "navbar-menu__options"%></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><%= link_to "Latest Data", "/updates", class: "navbar-menu__options"%></li>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if ["phenotypes", "picture_phenotypes", "fitbit_profiles", "open_humans_profiles"].include? params[:controller] %>
|
||||
<% if ["phenotypes", "picture_phenotypes", "open_humans_profiles"].include? params[:controller] %>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-xs-6 col-xs-offset-2 col-md-offset-0">
|
||||
@@ -87,9 +87,6 @@
|
||||
<li <% if params[:controller] == "open_humans_profiles" %>class="active"<% end %>>
|
||||
<a class="phenotype__side-menu-item" href="/openhumans">Open Humans</a>
|
||||
</li>
|
||||
<li <% if params[:controller] == "fitbit_profiles" %>class="active"<% end %>>
|
||||
<a class="phenotype__side-menu-item" href="/fitbit">Fitbit phenotypes</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<ul class="nav nav-tabs faq__questions-tabs" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#updating-data" aria-controls="home" role="tab" data-toggle="tab">Uploading data</a></li>
|
||||
<li role="presentation"><a href="#downloading-data" aria-controls="profile" role="tab" data-toggle="tab">Downloading data</a></li>
|
||||
<li role="presentation"><a href="#phenotype-fitbit" aria-controls="messages" role="tab" data-toggle="tab">Phenotypes & Fitbit</a></li>
|
||||
<li role="presentation"><a href="#phenotype-fitbit" aria-controls="messages" role="tab" data-toggle="tab">Phenotypes</a></li>
|
||||
<li role="presentation"><a href="#filetypes" aria-controls="settings" role="tab" data-toggle="tab">Filetypes</a></li>
|
||||
<li role="presentation"><a href="#json-api" aria-controls="settings" role="tab" data-toggle="tab">JSON-API</a></li>
|
||||
<li role="presentation"><a href="#distributed-system" aria-controls="settings" role="tab" data-toggle="tab">Distributed Annotation System</a></li>
|
||||
@@ -391,96 +391,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="faq__single-question ">
|
||||
<div class='panel panel-default faq__single-question-div'>
|
||||
<div class='panel-heading faq__single-question-panel'>
|
||||
<h4 class="panel-title clearfix faq__question-title">
|
||||
<a data-toggle='collapse' data-target='#question21' href='#question21' class="pull-left faq__title-content" data-js="panel-header">What is <em>Fitbit</em>?</a>
|
||||
<a data-toggle='collapse' data-target='#question21' href='#question21' class="hidden-xs faq__title-extend pull-right" data-js="extend-button">+</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id='question21' class='panel-collapse collapse'>
|
||||
<div class='panel-body'>
|
||||
<p>
|
||||
<em>Fitbit</em> is a wearable gadget which allows you to track your activities (How many steps have you taken? How many floors have you climbed?) and your sleep (How long did you sleep? How often have you awoken at night?). The tracker displays this information on the <em>Fitbit</em> website and calculates how efficient you sleep and many calories you have burned. Their website also allows you to track your body-development (i.e. your weight/BMI) and how much food you have eaten.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="faq__single-question ">
|
||||
<div class='panel panel-default faq__single-question-div'>
|
||||
<div class='panel-heading faq__single-question-panel'>
|
||||
<h4 class="panel-title clearfix faq__question-title">
|
||||
<a data-toggle='collapse' data-target='#question22' href='#question22' class="pull-left faq__title-content" data-js="panel-header">Which data will <em>openSNP</em> save from <em>Fitbit</em>? And will it be public?</a>
|
||||
<a data-toggle='collapse' data-target='#question22' href='#question22' class="hidden-xs faq__title-extend pull-right" data-js="extend-button">+</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id='question22' class='panel-collapse collapse'>
|
||||
<div class='panel-body'>
|
||||
<p>
|
||||
If you connect your <em>Fitbit</em> account with <em>openSNP</em> we will save data for up to three different categories: Activities, Body and Sleep. In the activity category we will save your step-count and the number of floors you've climbed for each day. For the body category we will save your Body Mass Index and your weight for each day. In the sleep category we will save how many minutes you have slept, how many minutes you were awake while you tried to sleep, how long it took you to fall asleep and the number of times you awoke for each night.<br/><br/>If you connect your <em>Fitbit</em> account we will also save as much data of past days as it's possible to get through the API of <em>Fitbit</em>. This data is as public as are the genotyping datasets or all standard phenotypes which are entered into openSNP. So please be sure you want the world to be able to see this data.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="faq__single-question ">
|
||||
<div class='panel panel-default faq__single-question-div'>
|
||||
<div class='panel-heading faq__single-question-panel'>
|
||||
<h4 class="panel-title clearfix faq__question-title">
|
||||
<a data-toggle='collapse' data-target='#question23' href='#question23' class="pull-left faq__title-content" data-js="panel-header">Can I choose which data <em>openSNP</em> should save and which not?</a>
|
||||
<a data-toggle='collapse' data-target='#question23' href='#question23' class="hidden-xs faq__title-extend pull-right" data-js="extend-button">+</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id='question23' class='panel-collapse collapse'>
|
||||
<div class='panel-body'>
|
||||
<p>
|
||||
Yes, you can choose which for which categories we should save the data. For example you can share our activity-data, so people can see the number of steps you have taken for each day, along with the floors you have climbed, but keep your body and sleep data on <em>FitBit</em>.Two things you should keep in mind: You can (de)activate the saving of data for different categories at any time. <br/><br/>1. If you deactivate a category we will delete all of your data of this category from <em>openSNP</em> (but of course not on <em>Fitbit</em>).<br/>2. If activate a category we will try to save as many data from the past as possible. So if there is past data you don't want to share you probably should not activate it (or delete the data from <em>Fitbit</em>).
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="faq__single-question ">
|
||||
<div class='panel panel-default faq__single-question-div'>
|
||||
<div class='panel-heading faq__single-question-panel'>
|
||||
<h4 class="panel-title clearfix faq__question-title">
|
||||
<a data-toggle='collapse' data-target='#question24' href='#question24' class="pull-left faq__title-content" data-js="panel-header">Do you get write-access to my <em>Fitbit</em> account?</a>
|
||||
<a data-toggle='collapse' data-target='#question24' href='#question24' class="hidden-xs faq__title-extend pull-right" data-js="extend-button">+</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id='question24' class='panel-collapse collapse'>
|
||||
<div class='panel-body'>
|
||||
<p>
|
||||
No, if you connect your <em>Fitbit</em> account with <em>openSNP</em> we only have read-access. The read-access gives us access to all data you have in your <em>Fitbit</em> account, but we will only read and save the data for which you have given us permission. We're sorry that you have to trust us in this point but the <em>Fitbit</em> API currently doesn't allow for a more granular setting.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="faq__single-question ">
|
||||
<div class='panel panel-default faq__single-question-div'>
|
||||
<div class='panel-heading faq__single-question-panel'>
|
||||
<h4 class="panel-title clearfix faq__question-title">
|
||||
<a data-toggle='collapse' data-target='#question25' href='#question25' class="pull-left faq__title-content" data-js="panel-header">Does <em>openSNP</em> automatically get the latest data from <em>Fitbit</em>?</a>
|
||||
<a data-toggle='collapse' data-target='#question25' href='#question25' class="hidden-xs faq__title-extend pull-right" data-js="extend-button">+</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id='question25' class='panel-collapse collapse'>
|
||||
<div class='panel-body'>
|
||||
<p>
|
||||
Yes, once your <em>Fitbit</em> account is connected and set up we will get an notification from <em>Fitbit</em> each time you enter or change any data in their system. So each time your tracker uploads new data to <em>Fitbit</em> we will get those changes as well. This also works for past records. So if you change or delete entries on the <em>Fitbit</em> website those changes will be reflected on <em>openSNP</em> as well.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<p>
|
||||
the Fitbit data you requested for
|
||||
<a href="<%="http://"+ActionMailer::Base.default_url_options[:host]+@link%>">
|
||||
download from openSNP is now available as a CSV (Comma-separated value) file.
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Have fun with it!
|
||||
</p>
|
||||
@@ -1,4 +0,0 @@
|
||||
the Fitbit data you requested for download from openSNP is now available as a
|
||||
CSV (Comma-separated value) file. To download them just visit:
|
||||
|
||||
<%="http://"+ActionMailer::Base.default_url_options[:host]+@link%>
|
||||
@@ -3,9 +3,6 @@
|
||||
<%= image_tag @user.avatar.url(:thumb), class: "hidden-xs pull-left userpage__profile-picture"%>
|
||||
<h3>
|
||||
<%= @user.name %>'s page
|
||||
<%if @user.fitbit_profile != nil%>
|
||||
<%=link_to(image_tag("fitbit-icon.png"), {:controller => "fitbit_profiles", :action => "show", :id => @user.fitbit_profile.id}, :data => {toggle:"tooltip", placement:"bottom"}, :title => "See Fitbit data")%>
|
||||
<%end%>
|
||||
<%if @user.open_humans_profile != nil%>
|
||||
<%=link_to(image_tag("open_humans_logo.png",size: '32x32'), {:controller => "open_humans_profiles", :action => "index"}, :data => {toggle:"tooltip", placement:"bottom"}, :title => "Linked to an Open Humans Account")%>
|
||||
<%end%>
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
<div class="col-md-10 col-xs-12 clearfix">
|
||||
<%= image_tag @user.avatar.url(:thumb), class: "hidden-xs pull-left userpage__profile-picture"%>
|
||||
<h2>Hello, <%= @first_name %>
|
||||
<%if @user.fitbit_profile != nil%>
|
||||
<%=link_to(image_tag("fitbit-icon.png"), {:controller => "fitbit_profiles", :action => "show", :id => @user.fitbit_profile.id}, :data => {toggle:"tooltip", placement:"bottom"}, :title => "See your Fitbit data")%>
|
||||
<%end%>
|
||||
<%if @user.open_humans_profile != nil%>
|
||||
<%=link_to(image_tag("open_humans_logo.png", size: '32x32'), {:controller => "open_humans_profiles", :action => "index"}, :data => {toggle:"tooltip", placement:"bottom"}, :title => "Linked to an Open Humans Account")%>
|
||||
<%end%>
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
|
||||
# frozen_string_literal: true
|
||||
class FitbitDump
|
||||
include Sidekiq::Worker
|
||||
sidekiq_options queue: :fitbit, retry: 5, unique: true
|
||||
|
||||
def perform(fitbit_profile_id,user_id)
|
||||
fp = FitbitProfile.find_by_id(fitbit_profile_id)
|
||||
# open handle
|
||||
|
||||
@time = Time.now.utc
|
||||
@time_str = @time.strftime("%Y%m%d%H%M")
|
||||
@time = @time.to_s.gsub(":","_")
|
||||
|
||||
@fitbit_handle = File.new(::Rails.root.to_s+"/public/data/fitbit/user"+fp.user.id.to_s+"_fitbit_data_"+@time_str.to_s+".csv","w")
|
||||
@fitbit_handle.puts("date;steps;floors;weight;bmi;minutes asleep;minutes awake; times awaken; minutes until fell asleep")
|
||||
|
||||
# get all dates which have to be included in the csv
|
||||
@time_array = []
|
||||
fp.fitbit_bodies.each do |fb|
|
||||
@time_array << fb.date_logged
|
||||
end
|
||||
fp.fitbit_sleeps.each do |fs|
|
||||
@time_array << fs.date_logged
|
||||
end
|
||||
fp.fitbit_activities.each do |fa|
|
||||
@time_array << fa.date_logged
|
||||
end
|
||||
|
||||
@time_array = @time_array.uniq.sort
|
||||
|
||||
@time_array.each do |d|
|
||||
@line = d.to_s + ";"
|
||||
@activity = fp.fitbit_activities.find_by_date_logged(d)
|
||||
if @activity == nil
|
||||
@line = @line + "-;-;"
|
||||
else
|
||||
@line = @line + @activity.steps.to_s + ";" + @activity.floors.to_s+ ";"
|
||||
end
|
||||
|
||||
@body = fp.fitbit_bodies.find_by_date_logged(d)
|
||||
if @body == nil
|
||||
@line = @line + "-;-;"
|
||||
else
|
||||
@line = @line + @body.weight.to_s + ";" + @body.bmi.to_s + ";"
|
||||
end
|
||||
|
||||
@sleep = fp.fitbit_sleeps.find_by_date_logged(d)
|
||||
if @sleep == nil
|
||||
@line = @line + "-;-;-;-;"
|
||||
else
|
||||
@line = @line + @sleep.minutes_asleep.to_s+";"+@sleep.minutes_awake.to_s+";"+@sleep.number_awakenings.to_s+";"+@sleep.minutes_to_sleep.to_s+";"
|
||||
end
|
||||
@fitbit_handle.puts(@line)
|
||||
end
|
||||
@fitbit_handle.close
|
||||
puts "Saved fibit-date for "
|
||||
system("chmod 777 "+::Rails.root.to_s+"/public/data/fitbit/user"+fp.user.id.to_s+"_fitbit_data_"+@time_str.to_s+".csv")
|
||||
UserMailer.fitbit_dump("/data/fitbit/user#{fp.user.id.to_s}_fitbit_data_#{@time_str.to_s}.csv",user_id).deliver_later
|
||||
end
|
||||
end
|
||||
@@ -47,7 +47,6 @@ class Zipfulldata
|
||||
logger.info("Starting zipfile #{zip_fs_path}")
|
||||
Zip::File.open(zip_fs_path, Zip::File::CREATE) do |zipfile|
|
||||
create_user_csv(genotypes, zipfile)
|
||||
create_fitbit_csv(zipfile)
|
||||
list_of_pics = create_picture_phenotype_csv(zipfile)
|
||||
create_picture_zip(list_of_pics, zipfile)
|
||||
create_readme(zipfile)
|
||||
@@ -100,64 +99,6 @@ class Zipfulldata
|
||||
zipfile.add("phenotypes_#{time_str}.csv", csv_file_name)
|
||||
end
|
||||
|
||||
def create_fitbit_csv(zipfile)
|
||||
# Create a file of fitbit-data for each user with fitbit-data
|
||||
fitbit_profiles = FitbitProfile.
|
||||
includes(:fitbit_activities, :fitbit_bodies, :fitbit_sleeps)
|
||||
fitbit_profiles.each do |fp|
|
||||
csv_file_name =
|
||||
"#{tmp_dir}/dump_user#{fp.user.id}_fitbit_data_#{time_str}.csv"
|
||||
csv_header = ['date', 'steps', 'floors', 'weight', 'bmi',
|
||||
'minutes asleep', 'minutes awake', 'times awaken',
|
||||
'minutes until fell asleep']
|
||||
CSV.open(csv_file_name, "w", csv_options) do |csv|
|
||||
csv << csv_header
|
||||
bodies = fp.fitbit_bodies.group_by(&:date_logged)
|
||||
sleeps = fp.fitbit_sleeps.group_by(&:date_logged)
|
||||
activities = fp.fitbit_activities.group_by(&:date_logged)
|
||||
|
||||
# get all dates which have to be included in the csv
|
||||
time_array = []
|
||||
time_array.concat(bodies.keys)
|
||||
time_array.concat(sleeps.keys)
|
||||
time_array.concat(activities.keys)
|
||||
time_array = time_array.uniq.sort
|
||||
|
||||
time_array.each do |d|
|
||||
row = [d]
|
||||
|
||||
activity = activities[d]
|
||||
if activity.present?
|
||||
activity = activity.first
|
||||
row.concat([activity.steps, activity.floors])
|
||||
else
|
||||
row.concat(%w(- -))
|
||||
end
|
||||
|
||||
body = bodies[d]
|
||||
if body.present?
|
||||
body = body.first
|
||||
row.concat([body.weight, body.bmi])
|
||||
else
|
||||
row.concat(%w(- -))
|
||||
end
|
||||
|
||||
sleep = sleeps[d]
|
||||
if sleep.present?
|
||||
sleep = sleep.first
|
||||
row.concat([sleep.minutes_asleep, sleep.minutes_awake,
|
||||
sleep.number_awakenings, sleep.minutes_to_sleep])
|
||||
else
|
||||
row.concat(%w(- - - -))
|
||||
end
|
||||
csv << row
|
||||
end
|
||||
end
|
||||
zipfile.add("user#{fp.user.id}_fitbit_data_#{time_str}.csv", csv_file_name)
|
||||
logger.info('Saved fibit-date for ')
|
||||
end
|
||||
end
|
||||
|
||||
# make a CSV describing all of them - which filename is for which user's phenotype
|
||||
def create_picture_phenotype_csv(zipfile)
|
||||
file_name = "#{tmp_dir}/picture_dump#{time_str}.csv"
|
||||
|
||||
@@ -33,8 +33,6 @@ docker run -d \
|
||||
-e POSTGRES_URL='postgres://postgres@postgres/postgres' \
|
||||
-e SECRET_KEY_BASE=foo \
|
||||
-e SECRET_TOKEN=bar \
|
||||
-e FITBIT_CONSUMER_KEY=foo \
|
||||
-e FITBIT_CONSUMER_SECRET=bar \
|
||||
-e PLOS_API_KEY=foo \
|
||||
-e RECAPTCHA_PRIVATE_KEY=foo \
|
||||
-e RECAPTCHA_PUBLIC_KEY=bar \
|
||||
|
||||
@@ -39,9 +39,6 @@ Snpr::Application.routes.draw do
|
||||
get '/openhumans/new', to: 'open_humans_profiles#start_auth'
|
||||
get '/openhumans/authorize', to: 'open_humans_profiles#authorize', as: :openhumans_authorize
|
||||
get '/openhumans/destroy/:id', to: 'open_humans_profiles#destroy'
|
||||
get '/fitbit/show/:id', to: 'fitbit_profiles#show', as: :fitbit_show
|
||||
get '/fitbit/dump/:id', to: 'fitbit_profiles#dump', as: :fitbit_dump
|
||||
get '/fitbit/', to: 'fitbit_profiles#index', as: :fitbit_index
|
||||
get '/phenotypesets/enter/:id', to: 'phenotype_sets#enter_userphenotypes'
|
||||
get '/phenotypesets/user_phenotypes/save', to: 'phenotype_sets#save_user_phenotypes'
|
||||
get '/users/:id/changepassword', to: 'users#changepassword'
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
- [zipgenotyping,5]
|
||||
- [zipfulldata,5]
|
||||
- [recommend,5]
|
||||
- [fitbit,3]
|
||||
- [frequency,1]
|
||||
- [fixphenotypes,1]
|
||||
- [default, 1]
|
||||
@@ -29,7 +28,6 @@
|
||||
recommend: 1
|
||||
zipgenotyping: 1
|
||||
zipfulldata: 1
|
||||
fitbit: 3
|
||||
frequency: 1
|
||||
fixphenotypes: 1
|
||||
mailnewgenotype: 1
|
||||
|
||||
14
db/migrate/20180118100003_remove_fitbit.rb
Normal file
14
db/migrate/20180118100003_remove_fitbit.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RemoveFitbit < ActiveRecord::Migration
|
||||
def self.up
|
||||
drop_table :fitbit_activities
|
||||
drop_table :fitbit_sleeps
|
||||
drop_table :fitbit_bodies
|
||||
drop_table :fitbit_profiles
|
||||
end
|
||||
|
||||
def self.down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
214
db/structure.sql
214
db/structure.sql
@@ -272,150 +272,6 @@ CREATE SEQUENCE file_links_id_seq
|
||||
ALTER SEQUENCE file_links_id_seq OWNED BY file_links.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_activities; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE fitbit_activities (
|
||||
id integer NOT NULL,
|
||||
fitbit_profile_id integer,
|
||||
steps integer,
|
||||
floors integer,
|
||||
date_logged date,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_activities_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE fitbit_activities_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_activities_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE fitbit_activities_id_seq OWNED BY fitbit_activities.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_bodies; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE fitbit_bodies (
|
||||
id integer NOT NULL,
|
||||
fitbit_profile_id integer,
|
||||
date_logged date,
|
||||
weight double precision,
|
||||
bmi double precision,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_bodies_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE fitbit_bodies_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_bodies_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE fitbit_bodies_id_seq OWNED BY fitbit_bodies.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_profiles; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE fitbit_profiles (
|
||||
id integer NOT NULL,
|
||||
fitbit_user_id character varying(255),
|
||||
user_id integer,
|
||||
request_token character varying(255),
|
||||
request_secret character varying(255),
|
||||
access_token character varying(255),
|
||||
access_secret character varying(255),
|
||||
verifier character varying(255),
|
||||
body boolean DEFAULT true,
|
||||
activities boolean DEFAULT true,
|
||||
sleep boolean DEFAULT true,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_profiles_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE fitbit_profiles_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_profiles_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE fitbit_profiles_id_seq OWNED BY fitbit_profiles.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_sleeps; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE fitbit_sleeps (
|
||||
id integer NOT NULL,
|
||||
fitbit_profile_id integer,
|
||||
minutes_asleep integer,
|
||||
minutes_awake integer,
|
||||
number_awakenings integer,
|
||||
minutes_to_sleep integer,
|
||||
date_logged date,
|
||||
created_at timestamp without time zone,
|
||||
updated_at timestamp without time zone
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_sleeps_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE fitbit_sleeps_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_sleeps_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE fitbit_sleeps_id_seq OWNED BY fitbit_sleeps.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: friendly_id_slugs; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1264,34 +1120,6 @@ ALTER TABLE ONLY admin_users ALTER COLUMN id SET DEFAULT nextval('admin_users_id
|
||||
ALTER TABLE ONLY file_links ALTER COLUMN id SET DEFAULT nextval('file_links_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_activities id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_activities ALTER COLUMN id SET DEFAULT nextval('fitbit_activities_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_bodies id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_bodies ALTER COLUMN id SET DEFAULT nextval('fitbit_bodies_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_profiles id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_profiles ALTER COLUMN id SET DEFAULT nextval('fitbit_profiles_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_sleeps id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_sleeps ALTER COLUMN id SET DEFAULT nextval('fitbit_sleeps_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: friendly_id_slugs id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1471,38 +1299,6 @@ ALTER TABLE ONLY file_links
|
||||
ADD CONSTRAINT file_links_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_activities fitbit_activities_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_activities
|
||||
ADD CONSTRAINT fitbit_activities_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_bodies fitbit_bodies_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_bodies
|
||||
ADD CONSTRAINT fitbit_bodies_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_profiles fitbit_profiles_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_profiles
|
||||
ADD CONSTRAINT fitbit_profiles_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_sleeps fitbit_sleeps_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_sleeps
|
||||
ADD CONSTRAINT fitbit_sleeps_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: friendly_id_slugs friendly_id_slugs_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -1819,14 +1615,6 @@ CREATE UNIQUE INDEX index_users_on_persistence_token ON users USING btree (persi
|
||||
CREATE INDEX snps_position_idx ON snps USING btree ("position");
|
||||
|
||||
|
||||
--
|
||||
-- Name: fitbit_profiles fitbit_profiles_user_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY fitbit_profiles
|
||||
ADD CONSTRAINT fitbit_profiles_user_id_fk FOREIGN KEY (user_id) REFERENCES users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: genotypes genotypes_user_id_fk; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -2169,3 +1957,5 @@ INSERT INTO schema_migrations (version) VALUES ('20161226175703');
|
||||
|
||||
INSERT INTO schema_migrations (version) VALUES ('20171113104813');
|
||||
|
||||
INSERT INTO schema_migrations (version) VALUES ('20180118100003');
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
RSpec.feature 'Fitbit profiles' do
|
||||
let!(:user) { create(:user) }
|
||||
let!(:fitbit_profile) { create(:fitbit_profile, user: user) }
|
||||
|
||||
scenario 'are shown' do
|
||||
visit '/fitbit'
|
||||
|
||||
expect(page).to have_content('Listing all connected Fitbit accounts')
|
||||
end
|
||||
end
|
||||
21
spec/requests/das_spec.rb
Normal file
21
spec/requests/das_spec.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'DAS-API', type: :request do
|
||||
let!(:user) { create(:user, name: 'API-Hacker', id: 1) }
|
||||
let!(:genotype) { create(:genotype,id: 1, user: user) }
|
||||
let!(:snp) { create(:snp, name: 'rs2345', chromosome: 1, position: 10) }
|
||||
let!(:snp_two) { create(:snp, name: 'rs1234', chromosome: 1, position: 12) }
|
||||
let!(:user_snp) { create(:user_snp, user: user, snp: snp, genotype: genotype) }
|
||||
let!(:user_snp_two) { create(:user_snp, user: user, snp: snp_two, genotype: genotype) }
|
||||
|
||||
it 'GET /das/:id/' do
|
||||
get "/das/#{user.id}/features?segment=1:10,11",
|
||||
nil,
|
||||
'SERVER_SOFTWARE' => 'faked for test'
|
||||
assert_response :success
|
||||
expect(response.body).to include('rs2345')
|
||||
expect(response.body).not_to include('rs1234')
|
||||
end
|
||||
end
|
||||
@@ -48,29 +48,6 @@ describe Zipfulldata do
|
||||
expect(csv).to eq([exp_header, exp_row1, exp_row2])
|
||||
end
|
||||
|
||||
it "creates fitbit CSVs" do
|
||||
file_name =
|
||||
"#{job.tmp_dir}/dump_user#{user.id}_fitbit_data_#{job.time_str}.csv"
|
||||
fp = create(:fitbit_profile, user: user)
|
||||
expect(zipfile).to receive(:add).
|
||||
with("user#{fp.user.id}_fitbit_data_#{job.time_str}.csv", file_name)
|
||||
job.create_fitbit_csv(zipfile)
|
||||
csv = CSV.read(file_name, job.csv_options)
|
||||
exp_header = ["date", "steps", "floors", "weight", "bmi",
|
||||
"minutes asleep", "minutes awake", "times awaken",
|
||||
"minutes until fell asleep"]
|
||||
exp_row = [fp.fitbit_activities.first.date_logged.to_s,
|
||||
fp.fitbit_activities.first.steps.to_s,
|
||||
fp.fitbit_activities.first.floors.to_s,
|
||||
fp.fitbit_bodies.first.weight.to_s,
|
||||
fp.fitbit_bodies.first.bmi.to_s,
|
||||
fp.fitbit_sleeps.first.minutes_asleep.to_s,
|
||||
fp.fitbit_sleeps.first.minutes_awake.to_s,
|
||||
fp.fitbit_sleeps.first.number_awakenings.to_s,
|
||||
fp.fitbit_sleeps.first.minutes_to_sleep.to_s]
|
||||
expect(csv).to eq([exp_header, exp_row])
|
||||
end
|
||||
|
||||
it "creates picture phenotype CSVs" do
|
||||
user2 = create(:user)
|
||||
pp = create(:picture_phenotype)
|
||||
@@ -122,7 +99,6 @@ Thanks for using openSNP!
|
||||
expect(Zip::File).to receive(:open).with(job.zip_fs_path, Zip::File::CREATE).
|
||||
and_yield(zipfile)
|
||||
expect(job).to receive(:create_user_csv).with([genotype], zipfile)
|
||||
expect(job).to receive(:create_fitbit_csv).with(zipfile)
|
||||
expect(job).to receive(:create_picture_phenotype_csv).with(zipfile).and_return([upp])
|
||||
expect(job).to receive(:create_picture_zip).with([upp], zipfile)
|
||||
expect(job).to receive(:create_readme).with(zipfile)
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
require_relative '../test_helper'
|
||||
|
||||
class FitbitProfilesControllerTest < ActionController::TestCase
|
||||
context "Fitbit profiles" do
|
||||
setup do
|
||||
@user = FactoryGirl.create(:user)
|
||||
@fitbit_profile = FactoryGirl.create(:fitbit_profile, user: @user)
|
||||
end
|
||||
|
||||
should "show up" do
|
||||
get 'show', id: @fitbit_profile.id
|
||||
assert_response :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user