Skip to content

Commit 96ed240

Browse files
committed
Add csv export for Pressensor import
Resolves #102
1 parent 1c5f575 commit 96ed240

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

app/controllers/api/shots_controller.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ def show
3030

3131
def profile
3232
with_shot do |shot|
33-
if params[:format] == "json" && shot.information&.json_profile_fields.present?
33+
if params[:format] == "csv"
34+
send_data shot.information&.csv_profile, filename: "#{shot.profile_title} from Visualizer.csv", type: "text/csv", disposition: "attachment"
35+
elsif params[:format] == "json" && shot.information&.json_profile_fields.present?
3436
render json: shot.information&.json_profile
3537
elsif shot.information&.tcl_profile_fields.present?
3638
send_data shot.information.tcl_profile, filename: "#{shot.profile_title} from Visualizer.tcl", type: "application/x-tcl", disposition: "attachment"

app/models/shot_information/profile.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module ShotInformation::Profile
22
JSON_PROFILE_KEYS = %w[title author notes beverage_type steps tank_temperature target_weight target_volume target_volume_count_start legacy_profile_type type lang hidden reference_file changes_since_last_espresso version].freeze
3+
CSV_PROFILE_HEADERS = %w[information_type elapsed pressure current_total_shot_weight flow_in flow_out water_temperature_boiler water_temperature_in water_temperature_basket metatype metadata comment].freeze
34

45
def tcl_profile_fields
56
@tcl_profile_fields ||= profile_fields.except("json")
@@ -35,4 +36,30 @@ def json_profile
3536

3637
JSON.pretty_generate(json)
3738
end
39+
40+
def csv_profile
41+
CSV.generate do |csv|
42+
csv << CSV_PROFILE_HEADERS
43+
44+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, "Name", shot.profile_title, "text"]
45+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, "Date", shot.start_time.iso8601, "ISO8601 formatted date"]
46+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, "Roasting Date", Date.parse(shot.roast_date)&.iso8601, "ISO8601 formatted date"] if shot.roast_date.present?
47+
48+
Parsers::SepCsv::MAPPING.each do |key, value|
49+
metadata_value = extra[value]
50+
next if metadata_value.blank?
51+
52+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, key, metadata_value, "text"]
53+
end
54+
55+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, "Attribution", "Visualizer", nil]
56+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, "Software", "Visualizer", nil]
57+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, "Url", "https://visualizer.coffee/shots/#{shot.id}", nil]
58+
csv << ["meta", nil, nil, nil, nil, nil, nil, nil, nil, "Export version", "1.0.0", nil]
59+
60+
timeframe.each.with_index do |time, i|
61+
csv << ["moment", time, data.dig("espresso_pressure", i), data.dig("espresso_weight", i), data.dig("espresso_flow", i), data.dig("espresso_flow_weight", i), nil, data.dig("espresso_temperature_mix", i), data.dig("espresso_temperature_basket", i), nil, nil, "Visualizer"]
62+
end
63+
end
64+
end
3865
end

app/views/shots/_share.html.erb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
<div class="mr-3">
2+
<a class="inline-flex px-4 py-2 text-sm bg-white border rounded-md shadow-sm cursor-pointer border-neutral-300 dark:border-neutral-600 dark:bg-neutral-800 hover:bg-neutral-50 dark:hover:bg-neutral-900" href="<%= api_shot_profile_path(@shot, format: :csv) %>" title="Download CSV profile" target="_blank">
3+
<svg class="w-4 h-4 -ml-1 -mr-1 text-neutral-500 dark:text-neutral-300" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor">
4+
<path fill-rule="evenodd" d="M15 11a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v6ZM7.25 7.5a.5.5 0 0 0-.5-.5H3a.5.5 0 0 0-.5.5V8a.5.5 0 0 0 .5.5h3.75a.5.5 0 0 0 .5-.5v-.5Zm1.5 3a.5.5 0 0 1 .5-.5H13a.5.5 0 0 1 .5.5v.5a.5.5 0 0 1-.5.5H9.25a.5.5 0 0 1-.5-.5v-.5ZM13.5 8v-.5A.5.5 0 0 0 13 7H9.25a.5.5 0 0 0-.5.5V8a.5.5 0 0 0 .5.5H13a.5.5 0 0 0 .5-.5Zm-6.75 3.5a.5.5 0 0 0 .5-.5v-.5a.5.5 0 0 0-.5-.5H3a.5.5 0 0 0-.5.5v.5a.5.5 0 0 0 .5.5h3.75Z" clip-rule="evenodd" />
5+
</svg>
6+
</a>
7+
</div>
18
<% if @shot.information&.tcl_profile_fields.present? %>
29
<div class="mr-3">
310
<a class="inline-flex px-4 py-2 text-sm bg-white border rounded-md shadow-sm cursor-pointer border-neutral-300 dark:border-neutral-600 dark:bg-neutral-800 hover:bg-neutral-50 dark:hover:bg-neutral-900" href="<%= api_shot_profile_path(@shot) %>" title="Download this profile" target="_blank">

0 commit comments

Comments
 (0)