diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb index 9fdefc388..bba983b6c 100644 --- a/app/controllers/plantings_controller.rb +++ b/app/controllers/plantings_controller.rb @@ -71,6 +71,7 @@ class PlantingsController < ApplicationController respond_to do |format| if @planting.save + @planting.update_attribute(:days_before_maturity, update_days_before_maturity(@planting, planting_params[:crop_id])) format.html { redirect_to @planting, notice: 'Planting was successfully created.' } format.json { render json: @planting, status: :created, location: @planting } expire_fragment("homepage_stats") @@ -89,6 +90,7 @@ class PlantingsController < ApplicationController respond_to do |format| if @planting.update(planting_params) + @planting.update_attribute(:days_before_maturity, update_days_before_maturity(@planting, planting_params[:crop_id])) format.html { redirect_to @planting, notice: 'Planting was successfully updated.' } format.json { head :no_content } else @@ -119,4 +121,12 @@ class PlantingsController < ApplicationController :quantity, :sunniness, :planted_from, :owner_id, :finished, :finished_at) end + + def update_days_before_maturity(planting, crop_id) + if planting.finished_at.nil? + planting.calculate_days_before_maturity(planting, crop_id) + else + (planting.finished_at - planting.planted_at).to_i + end + end end diff --git a/app/helpers/plantings_helper.rb b/app/helpers/plantings_helper.rb new file mode 100644 index 000000000..1eb220481 --- /dev/null +++ b/app/helpers/plantings_helper.rb @@ -0,0 +1,36 @@ +module PlantingsHelper + + def display_days_before_maturity(planting) + if planting.finished? + 0 + elsif !planting.finished_at.nil? + ((p = planting.finished_at - DateTime.now).to_i) <= 0 ? 0 : p.to_i + elsif planting.days_before_maturity.nil? + "unknown" + else + ((p = (planting.planted_at + planting.days_before_maturity) - DateTime.now).to_i <= 0) ? 0 : p.to_i + end + end + + def display_finished(planting) + if !planting.finished_at.nil? + planting.finished_at + elsif planting.finished + "Yes (no date specified)" + else + "(no date specified)" + end + end + + def display_sunniness(planting) + !planting.sunniness.blank? ? planting.sunniness : "not specified" + end + + def display_planted_from(planting) + !planting.planted_from.blank? ? planting.planted_from : "not specified" + end + + def display_planting_quantity(planting) + !planting.quantity.blank? ? planting.quantity : "not specified" + end +end \ No newline at end of file diff --git a/app/models/planting.rb b/app/models/planting.rb index ea9faf0d0..f06ccf9ac 100644 --- a/app/models/planting.rb +++ b/app/models/planting.rb @@ -94,6 +94,21 @@ class Planting < ActiveRecord::Base return photos.present? end + def calculate_days_before_maturity(planting, crop) + p_crop = Planting.where(:crop_id => crop).where.not(:id => planting) + differences = p_crop.collect do |p| + if p.finished and !p.finished_at.nil? + (p.finished_at - p.planted_at).to_i + end + end + + if differences.compact.empty? + nil + else + differences.compact.sum/differences.compact.length + end + end + # return a list of interesting plantings, for the homepage etc. # we can't do this via a scope (as far as we know) so sadly we have to # do it this way. diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml index 0ca1f3cfb..cef4c95f8 100644 --- a/app/views/gardens/show.html.haml +++ b/app/views/gardens/show.html.haml @@ -43,22 +43,37 @@ %p{:style => 'text-align: center; padding-top: 50px'} = link_to "Add photo", new_photo_path(:type => "garden", :id => @garden.id), :class => 'btn btn-primary' - - %h3 - What's planted here? - + %h3 What's planted here? - if @garden.plantings.current.size > 0 - - @garden.plantings.current.each do |p| - = render :partial => "plantings/thumbnail", :locals => { :planting => p } + .container + .row + .col-md-1 + %b # + .col-md-3 + %b Photo + .col-md-6 + %b Planting Details + .col-md-2 + - @garden.plantings.current.each.with_index do |planting_current, index_current| + = render partial: "plantings/thumbnail", locals: {:planting => planting_current, :index => index_current} - else %p Nothing is currently planted here. + %h3 Previously planted in this garden - if @garden.plantings.finished.size > 0 - %h3 Previously planted in this garden - - @garden.plantings.finished.each do |p| - = render :partial => "plantings/thumbnail", :locals => { :planting => p } - + .container + .row + .col-md-1 + %b # + .col-md-3 + %b Photo + .col-md-6 + %b Planting Details + .col-md-2 + - @garden.plantings.finished.each.with_index do |planting_finished, index_finished| + = render partial: "plantings/thumbnail", locals: {:planting => planting_finished, :index => index_finished} + .col-md-3 %h4 About this garden %p diff --git a/app/views/members/_gardens.html.haml b/app/views/members/_gardens.html.haml index cca8ca5b1..7f5d4de2b 100644 --- a/app/views/members/_gardens.html.haml +++ b/app/views/members/_gardens.html.haml @@ -34,8 +34,18 @@ = link_to "Add photo", new_photo_path(:type => "garden", :id => g.id), :class => 'btn btn-primary' %h3 What's planted here? - - g.featured_plantings.each do |p| - = render :partial => "plantings/thumbnail", :locals => { :planting => p, :hide_description => true } + - if g.featured_plantings.size > 0 + .container + .row + .col-md-1 + %b # + .col-md-3 + %b Photo + .col-md-6 + %b Planting Details + .col-md-2 + - g.featured_plantings.each.with_index do |planting, index| + = render partial: "plantings/thumbnail", locals: {:planting => planting, :index => index} %p = link_to "More about this garden...", url_for(g) diff --git a/app/views/plantings/_planting_progress.html.haml b/app/views/plantings/_planting_progress.html.haml new file mode 100644 index 000000000..86ba5d1a5 --- /dev/null +++ b/app/views/plantings/_planting_progress.html.haml @@ -0,0 +1,14 @@ +- if DateTime.now.to_date < planting.planted_at + = "Progress: 0% - not planted yet" + = render partial: "plantings/progress_bar", locals: {status: "warning", progress: "100%"} +- elsif planting.finished? + = "Progress: 100%" + = render partial: "plantings/progress_bar", locals: {status: "success", progress: "100%"} +- elsif planting.days_before_maturity.nil? + = "Progress: 0% - Days before maturity unknown" + = render partial: "plantings/progress_bar", locals: {status: "danger", progress: "100%"} +- else + - if (percent = (((DateTime.now - planting.planted_at)/planting.days_before_maturity*100).to_i)) >= 100 + - percent = 100 + = "Progress: #{percent}%" + = render partial: "plantings/progress_bar", locals: {status: "success", progress: "#{percent}%"} \ No newline at end of file diff --git a/app/views/plantings/_progress_bar.html.haml b/app/views/plantings/_progress_bar.html.haml new file mode 100644 index 000000000..4b13c3338 --- /dev/null +++ b/app/views/plantings/_progress_bar.html.haml @@ -0,0 +1,2 @@ +.progress + %div{:class => "progress-bar progress-bar-#{status}", :role => "progressbar", :style => "width: #{progress}"} diff --git a/app/views/plantings/_thumbnail.html.haml b/app/views/plantings/_thumbnail.html.haml index f1b67c2cb..2cebfcbd7 100644 --- a/app/views/plantings/_thumbnail.html.haml +++ b/app/views/plantings/_thumbnail.html.haml @@ -1,47 +1,44 @@ -.well - .row - .col-md-3 - = link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img'), planting +.row + .col-md-1 + = "##{index+1}" + .col-md-3 + = link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => planting.crop_id, :class => 'img'), planting + .col-md-6 + %dl.dl-horizontal + %dt Owner: + %dd= link_to planting.owner.login_name, planting.owner + %dt Garden: + %dd= link_to planting.garden.name, planting.garden + %dt Planted on: + %dd= planting.planted_at + %dt Quantity: + %dd= "#{display_planting_quantity(planting)}" + %dt Finished on: + %dd= "#{display_finished(planting)}" + %dt Sun/shade?: + %dd= "#{display_sunniness(planting)}" + %dt Planted from: + %dd= "#{display_planted_from(planting)}" + .col-md-2 + %ul{:style => "list-style-type:none"} + %li= link_to 'Details', planting, :class => 'btn btn-default btn-xs' + - if can? :edit, planting + %li= link_to 'Edit', edit_planting_path(planting), :class => 'btn btn-default btn-xs' + - if ! planting.finished + %li= link_to "Mark as finished", planting_path(planting, :planting => {:finished => 1}), :method => :put, :class => 'btn btn-default btn-xs append-date' + - if can? :destroy, planting + %li= link_to 'Delete', planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' +.row + .col-md-1 + .col-md-3 + %ul{:style => "list-style-type:none"} + %li + %b Crop name: + = link_to planting.crop.name, planting.crop + %li + %b Days until maturity: + = "#{display_days_before_maturity(planting)}" - .col-md-9 - %h4 - - if defined?(title) && title == 'owner' - = link_to planting.owner, planting.owner - - else - = link_to planting.crop.name, planting - - %p - Planted - - if planting.planted_at - = planting.planted_at - in - = link_to planting.location, planting.garden - - %p - - if planting.quantity - Quantity: - = planting.quantity - - else -   - - - if planting.description && ! defined?(hide_description) - %div - :growstuff_markdown - #{ planting.description } - - - if planting.finished - %p - Finished: - - if planting.finished_at - = planting.finished_at - - else - Yes (no date specified) - - - if can? :edit, planting or can? :destroy, planting - %p - - if can? :edit, planting - =link_to 'Edit', edit_planting_path(planting), :class => 'btn btn-default btn-xs' - - if ! planting.finished - = link_to "Mark as finished", planting_path(planting, :planting => {:finished => 1}), :method => :put, :class => 'btn btn-default btn-xs append-date' - - if can? :destroy, planting - =link_to 'Delete', planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' + .col-md-8 + %ul{:style => "list-style-type:none"} + %li= render partial: 'plantings/planting_progress', locals: {:planting => planting} \ No newline at end of file diff --git a/app/views/plantings/index.html.haml b/app/views/plantings/index.html.haml index 25b52ee2d..aa01c9129 100644 --- a/app/views/plantings/index.html.haml +++ b/app/views/plantings/index.html.haml @@ -19,43 +19,16 @@ = will_paginate @plantings - if @plantings.size > 0 - - %table.table.table-striped - %tr - - unless @owner - %th Owner - %th Crop - %th Garden - %th Quantity - %th Planted on - %th Finished - %th Sun/shade? - %th Planted from - %th - - - @plantings.each do |planting| - %tr - - unless @owner - %td= link_to planting.owner.login_name, planting.owner - %td= link_to planting.crop.name, planting.crop - %td= link_to planting.garden.name, planting.garden - %td= planting.quantity - %td= planting.planted_at - %td - - if planting.finished and planting.finished_at - = planting.finished_at - - elsif planting.finished - Yes (no date specified) - %td= planting.sunniness - %td= planting.planted_from - %td - = link_to 'Details', planting, :class => 'btn btn-default btn-xs' - - if can? :edit, planting - =link_to 'Edit', edit_planting_path(planting), :class => 'btn btn-default btn-xs' - - if ! planting.finished - = link_to "Mark as finished", planting_path(planting, :planting => {:finished => 1}), :method => :put, :class => 'btn btn-default btn-xs append-date' - - if can? :destroy, planting - =link_to 'Delete', planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-default btn-xs' + .row + .col-md-1 + %b # + .col-md-3 + %b Photo + .col-md-6 + %b Planting Details + .col-md-2 + - @plantings.each.with_index do |planting, index| + = render partial: "plantings/thumbnail", locals: {:planting => planting, :index => index} %div.pagination = page_entries_info @plantings, :model => "plantings" diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index 93cc2a910..127507104 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -8,7 +8,7 @@ — = link_to "view all #{@planting.owner}'s plantings", plantings_by_owner_path(:owner => @planting.owner.slug) %p - %b Planted: + %b Planted on: = @planting.planted_at ? @planting.planted_at : "not specified" %p @@ -18,28 +18,32 @@ - if ! @planting.owner.location.blank? = "(#{@planting.owner.location})" %p - %b Quantity: - = @planting.quantity.blank? ? "not specified" : @planting.quantity - - - if ! @planting.planted_from.blank? + %b + = "Quantity: " + = "#{display_planting_quantity(@planting)}" + + - if !@planting.planted_from.blank? %p - %b Planted from: - = @planting.planted_from - - - if ! @planting.sunniness.blank? + %b + = "Planted from: " + = "#{display_planted_from(@planting)}" + + - if !@planting.sunniness.blank? %p - %b Sun or shade? - = @planting.sunniness - - - if @planting.finished - %p - %b Finished: - - if @planting.finished_at - = @planting.finished_at - - else - Yes (no date specified) - + %b + = "Sun or shade?: " + = "#{display_sunniness(@planting)}" + %p + %b + = "Days until maturity: " + = "#{display_days_before_maturity(@planting)}" + %p + %b + = "Finished: " + = "#{display_finished(@planting)}" + %p + %b= render 'planting_progress', planting: @planting - if can? :edit, @planting or can? :destroy, @planting %p diff --git a/db/migrate/20150625224805_add_days_before_maturity_to_plantings.rb b/db/migrate/20150625224805_add_days_before_maturity_to_plantings.rb new file mode 100644 index 000000000..0ddf5acb5 --- /dev/null +++ b/db/migrate/20150625224805_add_days_before_maturity_to_plantings.rb @@ -0,0 +1,5 @@ +class AddDaysBeforeMaturityToPlantings < ActiveRecord::Migration + def change + add_column :plantings, :days_before_maturity, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 7f8c479ce..be45fa333 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150209105410) do +ActiveRecord::Schema.define(version: 20150625224805) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -380,8 +380,8 @@ ActiveRecord::Schema.define(version: 20150209105410) do end create_table "plantings", force: true do |t| - t.integer "garden_id", null: false - t.integer "crop_id", null: false + t.integer "garden_id", null: false + t.integer "crop_id", null: false t.date "planted_at" t.integer "quantity" t.text "description" @@ -391,8 +391,9 @@ ActiveRecord::Schema.define(version: 20150209105410) do t.string "sunniness" t.string "planted_from" t.integer "owner_id" - t.boolean "finished", default: false + t.boolean "finished", default: false t.date "finished_at" + t.integer "days_before_maturity" end add_index "plantings", ["slug"], name: "index_plantings_on_slug", unique: true, using: :btree diff --git a/spec/features/gardens_spec.rb b/spec/features/gardens_spec.rb index 31626d06f..889fdd220 100644 --- a/spec/features/gardens_spec.rb +++ b/spec/features/gardens_spec.rb @@ -69,7 +69,6 @@ feature "Planting a crop", :js => true do describe "Making a planting inactive from garden show" do let(:path) { garden_path(garden) } let(:link_text) { "Mark as finished" } - it_behaves_like "append date" end diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 1becf895d..0a6663b30 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -27,6 +27,104 @@ feature "Planting a crop", :js => true do end expect(page).to have_content "Planting was successfully created" + expect(page).to have_content "Progress: 0% - Days before maturity unknown" + end + + describe "Progress bar status on planting creation" do + before(:each) do + DateTime.stub(:now){DateTime.new(2015, 10, 20, 10, 34)} + login_as(member) + visit new_planting_path + sync_elasticsearch([maize]) + end + + it "should show that it is not planted yet" do + fill_autocomplete "crop", :with => "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + fill_in "When", :with => "2015-12-15" + fill_in "How many?", :with => 42 + select "cutting", :from => "Planted from:" + select "semi-shade", :from => "Sun or shade?" + fill_in "Tell us more about it", :with => "It's rad." + click_button "Save" + end + + expect(page).to have_content "Planting was successfully created" + expect(page).to have_content "Progress: 0% - not planted yet" + end + + it "should show that days before maturity is unknown" do + fill_autocomplete "crop", :with => "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + fill_in "When", :with => "2015-9-15" + fill_in "How many?", :with => 42 + select "cutting", :from => "Planted from:" + select "semi-shade", :from => "Sun or shade?" + fill_in "Tell us more about it", :with => "It's rad." + click_button "Save" + end + + expect(page).to have_content "Planting was successfully created" + expect(page).to have_content "Progress: 0% - Days before maturity unknown" + expect(page).to have_content "Days until maturity: unknown" + end + + it "should show that planting is in progress" do + fill_autocomplete "crop", :with => "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + fill_in "When", :with => "2015-10-15" + fill_in "How many?", :with => 42 + select "cutting", :from => "Planted from:" + select "semi-shade", :from => "Sun or shade?" + fill_in "Tell us more about it", :with => "It's rad." + fill_in "Finished date", :with => "2015-10-30" + click_button "Save" + end + + expect(page).to have_content "Planting was successfully created" + expect(page).to_not have_content "Progress: 0% - not planted yet" + expect(page).to_not have_content "Progress: 0% - Days before maturity unknown" + end + + it "should show that planting is 100% complete (no date specified)" do + fill_autocomplete "crop", :with => "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + fill_in "When", :with => "2015-10-15" + fill_in "How many?", :with => 42 + select "cutting", :from => "Planted from:" + select "semi-shade", :from => "Sun or shade?" + fill_in "Tell us more about it", :with => "It's rad." + check "Mark as finished" + click_button "Save" + end + + expect(page).to have_content "Planting was successfully created" + expect(page).to have_content "Progress: 100%" + expect(page).to have_content "Yes (no date specified)" + expect(page).to have_content "Days until maturity: 0" + end + + it "should show that planting is 100% complete (date specified)" do + fill_autocomplete "crop", :with => "mai" + select_from_autocomplete "maize" + within "form#new_planting" do + fill_in "When", :with => "2015-10-15" + fill_in "How many?", :with => 42 + select "cutting", :from => "Planted from:" + select "semi-shade", :from => "Sun or shade?" + fill_in "Tell us more about it", :with => "It's rad." + fill_in "Finished date", :with => "2015-10-19" + click_button "Save" + end + + expect(page).to have_content "Planting was successfully created" + expect(page).to have_content "Progress: 100%" + expect(page).to have_content "Days until maturity: 0" + end end scenario "Planting from crop page" do @@ -49,6 +147,17 @@ feature "Planting a crop", :js => true do expect(page).to have_content "Planting was successfully updated" end + scenario "Editing a planting to fill in the finished date" do + visit planting_path(planting) + expect(page).to have_content "Progress: 0% - Days before maturity unknown" + click_link "Edit" + check "finished" + fill_in "Finished date", :with => "2015-06-25" + click_button "Save" + expect(page).to have_content "Planting was successfully updated" + expect(page).to_not have_content "Progress: 0% - Days before maturity unknown" + end + scenario "Marking a planting as finished" do fill_autocomplete "crop", :with => "mai" select_from_autocomplete "maize" @@ -94,6 +203,7 @@ feature "Planting a crop", :js => true do end expect(page).to have_content "Planting was successfully created" expect(page).to have_content "Finished: Yes (no date specified)" + expect(page).to have_content "Progress: 100%" end describe "Marking a planting as finished from the show page" do diff --git a/spec/views/plantings/_thumbnail.html.haml_spec.rb b/spec/views/plantings/_thumbnail.html.haml_spec.rb deleted file mode 100644 index 279dfda56..000000000 --- a/spec/views/plantings/_thumbnail.html.haml_spec.rb +++ /dev/null @@ -1,69 +0,0 @@ -## DEPRECATION NOTICE: Do not add new tests to this file! -## -## View and controller tests are deprecated in the Growstuff project. -## We no longer write new view and controller tests, but instead write -## feature tests (in spec/features) using Capybara (https://github.com/jnicklas/capybara). -## These test the full stack, behaving as a browser, and require less complicated setup -## to run. Please feel free to delete old view/controller tests as they are reimplemented -## in feature tests. -## -## If you submit a pull request containing new view or controller tests, it will not be -## merged. - - - - - -require 'rails_helper' - -describe "plantings/_thumbnail" do - before(:each) do - controller.stub(:current_user) { nil } - @member = FactoryGirl.create(:member) - @garden = FactoryGirl.create(:garden, :owner => @member) - @crop = FactoryGirl.create(:tomato) - - @planting = FactoryGirl.create(:planting, - :garden => @garden, - :crop => @crop - ) - end - - context "simple view" do - before(:each) do - render :partial => "thumbnail", :locals => { - :planting => @planting, - } - end - - it "renders the quantity planted" do - rendered.should have_content "33" - end - - it "renders the date planted" do - rendered.should have_content @planting.planted_at.to_s(:default) - end - - it "shows the name of the crop" do - rendered.should have_content @crop.name - end - - it "shows the description by default" do - rendered.should have_content "This is a" - end - end - - context "with complicated args" do - before(:each) do - render :partial => "thumbnail", :locals => { - :planting => @planting, - :hide_description => true - } - end - - it "hides the description if asked" do - rendered.should_not have_content "This is a" - end - end - -end