diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 2a92cebba..b66986240 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -48,4 +48,6 @@ submit the change with your pull request. - Maki Sugita / [macckii](https:://github.com/macckii) - Shiho Takagi / [oshiho3](https://github.com/oshiho3) - Emma Winston / [emmawinston](https://github.com/emmawinston) +- Kevin Rio / [krio](https://github.com/krio) - Yoong Kang Lim / [yoongkang](https://github.com/yoongkang) + diff --git a/Gemfile b/Gemfile index d034f2789..451b2d3fc 100644 --- a/Gemfile +++ b/Gemfile @@ -78,7 +78,6 @@ gem 'flickraw' # Use unicorn as the app server # gem 'unicorn' -# To use debugger group :development do # A debugger and irb alternative. Pry doesn't play nice # with unicorn, so start a Webrick server when debugging @@ -120,6 +119,7 @@ gem 'omniauth-flickr', '>= 0.0.15' gem 'rake', '>= 10.0.0' group :development, :test do + gem 'byebug' # debugging gem 'haml-rails' # HTML templating language gem 'rspec-rails', '~> 2.12.1' # unit testing framework gem 'database_cleaner', '~> 1.3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 34b5f136a..8c7328269 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,7 +49,7 @@ GEM multi_json (~> 1.0) addressable (2.3.6) arel (3.0.3) - bcrypt (3.1.7) + bcrypt (3.1.9) better_errors (2.0.0) coderay (>= 1.0.0) erubis (>= 2.6.6) @@ -60,6 +60,10 @@ GEM bootstrap-datepicker-rails (1.3.0.2) railties (>= 3.0) builder (3.0.4) + byebug (3.5.1) + columnize (~> 0.8) + debugger-linecache (~> 1.2) + slop (~> 3.6) cancan (1.6.10) capybara (2.4.4) mime-types (>= 1.16) @@ -70,7 +74,7 @@ GEM capybara-email (2.4.0) capybara (~> 2.4) mail - chunky_png (1.3.2) + chunky_png (1.3.3) cliver (0.3.2) coderay (1.1.0) coffee-rails (3.2.2) @@ -80,6 +84,7 @@ GEM coffee-script-source execjs coffee-script-source (1.8.0) + columnize (0.8.9) commonjs (0.2.7) compass (0.12.7) chunky_png (~> 1.2) @@ -93,11 +98,12 @@ GEM simplecov (>= 0.7) term-ansicolor thor - csv_shaper (1.0.0) + csv_shaper (1.1.1) activesupport (>= 3.0.0) dalli (2.7.2) database_cleaner (1.3.0) debug_inspector (0.0.2) + debugger-linecache (1.2.0) devise (3.2.4) bcrypt (~> 3.0) orm_adapter (~> 0.1) @@ -123,7 +129,7 @@ GEM friendly_id (4.0.10.1) activerecord (>= 3.0, < 4.0) fssm (0.2.10) - gibbon (1.1.3) + gibbon (1.1.4) httparty multi_json (>= 1.3.4) gravatar-ultimate (2.0.0) @@ -143,7 +149,7 @@ GEM multi_json (~> 1.0) multi_xml (>= 0.5.2) i18n (0.6.1) - i18n-tasks (0.7.7) + i18n-tasks (0.7.8) activesupport easy_translate (>= 0.5.0) erubis @@ -163,7 +169,7 @@ GEM sprockets-rails json (1.7.7) kgio (2.9.2) - launchy (2.4.2) + launchy (2.4.3) addressable (~> 2.3) leaflet-markercluster-rails (0.7.0) railties (>= 3.1) @@ -184,13 +190,13 @@ GEM memcachier (0.0.2) method_source (0.8.2) mime-types (1.25.1) - mini_portile (0.6.0) + mini_portile (0.6.1) multi_json (1.10.1) multi_xml (0.5.5) netrc (0.8.0) - newrelic_rpm (3.9.5.251) - nokogiri (1.6.3.1) - mini_portile (= 0.6.0) + newrelic_rpm (3.9.6.257) + nokogiri (1.6.4.1) + mini_portile (~> 0.6.0) oauth (0.4.7) omniauth (1.2.2) hashie (>= 1.2, < 4) @@ -272,7 +278,7 @@ GEM simplecov-html (~> 0.8.0) simplecov-html (0.8.0) slop (3.6.0) - sprockets (2.2.2) + sprockets (2.2.3) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) @@ -293,7 +299,7 @@ GEM treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (0.3.41) + tzinfo (0.3.42) uglifier (2.2.1) execjs (>= 0.3.0) multi_json (~> 1.0, >= 1.0.2) @@ -307,7 +313,7 @@ GEM nokogiri (>= 1.2.0) rack (>= 1.0) rack-test (>= 0.5.3) - websocket-driver (0.3.5) + websocket-driver (0.4.0) will_paginate (3.0.7) xpath (2.0.0) nokogiri (~> 1.3) @@ -323,6 +329,7 @@ DEPENDENCIES bluecloth bootstrap-datepicker-rails bundler (>= 1.1.5) + byebug cancan capybara capybara-email diff --git a/app/assets/javascripts/append_date.js.coffee b/app/assets/javascripts/append_date.js.coffee index cf54f4654..8fc31de9d 100644 --- a/app/assets/javascripts/append_date.js.coffee +++ b/app/assets/javascripts/append_date.js.coffee @@ -8,12 +8,28 @@ jQuery -> el.datepicker({'format': 'yyyy-mm-dd'}) + href = el.attr('href') + + originalText = el.text() + el.click (e) -> e.stopPropagation() e.preventDefault() + $(this).text('Confirm without date') + + $(this).bind('click.confirm', (e) -> + link = $("") + $('body').append(link) + $(link).click() + ) + + $(this).blur (e) -> + $(this).text(originalText) + $(this).unbind('click.confirm') + + el.one 'changeDate', -> - href = $(this).attr('href') date = $(this).datepicker('getDate') url = "#{href}&planting[finished_at]=#{date}" diff --git a/app/models/photo.rb b/app/models/photo.rb index 32679eeed..862b9d28b 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -14,7 +14,7 @@ class Photo < ActiveRecord::Base # remove photos that aren't used by anything def destroy_if_unused - unless plantings.size > 0 and harvests.size > 0 + unless plantings.size > 0 or harvests.size > 0 self.destroy end end diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index edf4d0b68..afb10d932 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -22,5 +22,5 @@ .col-md-3 = render :partial => "avatar", :locals => { :member => @member } = render :partial => "account", :locals => { :member => @member } - = render :partial => "contact", :locals => { :member => @member, :twitter_auth => @twitter_auth, :flickr_auth => @flickr_auth } = render :partial => "stats", :locals => { :member => @member } + = render :partial => "contact", :locals => { :member => @member, :twitter_auth => @twitter_auth, :flickr_auth => @flickr_auth } diff --git a/app/views/plantings/_thumbnail.html.haml b/app/views/plantings/_thumbnail.html.haml index c8588abf5..fd34b0703 100644 --- a/app/views/plantings/_thumbnail.html.haml +++ b/app/views/plantings/_thumbnail.html.haml @@ -17,14 +17,6 @@ in = link_to planting.location, planting.garden - - if planting.finished - %p - Finished: - - if planting.finished_at - = planting.finished_at - - else - Yes (no date specified) - %p - if planting.quantity Quantity: @@ -37,11 +29,19 @@ :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' + = 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' diff --git a/app/views/plantings/index.html.haml b/app/views/plantings/index.html.haml index eb1e017dc..1d27df4e8 100644 --- a/app/views/plantings/index.html.haml +++ b/app/views/plantings/index.html.haml @@ -43,7 +43,7 @@ %td= planting.planted_at %td - if planting.finished and planting.finished_at - = planting.planted_at + = planting.finished_at - elsif planting.finished Yes (no date specified) %td= planting.sunniness @@ -53,7 +53,7 @@ - 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' + = 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' diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml index cc3d58bae..72819f7ac 100644 --- a/app/views/plantings/show.html.haml +++ b/app/views/plantings/show.html.haml @@ -11,14 +11,6 @@ %b Planted: = @planting.planted_at ? @planting.planted_at : "not specified" - - if @planting.finished - %p - %b Finished: - - if @planting.finished_at - = @planting.finished_at - - else - Yes (no date specified) - %p %b Where: =link_to "#{@planting.owner}'s", @planting.owner @@ -39,6 +31,15 @@ %b Sun or shade? = @planting.sunniness + - if @planting.finished + %p + %b Finished: + - if @planting.finished_at + = @planting.finished_at + - else + Yes (no date specified) + + - if can? :edit, @planting or can? :destroy, @planting %p diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake index c1043963d..0cf0a50f7 100644 --- a/lib/tasks/growstuff.rake +++ b/lib/tasks/growstuff.rake @@ -47,8 +47,8 @@ namespace :growstuff do send_on_day = 3 # wednesday every_n_weeks = 2 # send fortnightly - if Date.today.cwday == send_on_day and Date.today.cw_week % every_n_weeks == 0 - Member.find_each do |m| + if Date.today.cwday == send_on_day and Date.today.cweek % every_n_weeks == 0 + Member.confirmed.find_each do |m| Notifier.planting_reminder(m).deliver! end end diff --git a/spec/features/gardens_spec.rb b/spec/features/gardens_spec.rb index 1b803a41e..2b4c22d8b 100644 --- a/spec/features/gardens_spec.rb +++ b/spec/features/gardens_spec.rb @@ -2,6 +2,8 @@ require 'spec_helper' feature "Planting a crop", :js => true do let!(:garden) { FactoryGirl.create(:garden) } + let!(:planting) { FactoryGirl.create(:planting, garden: garden, planted_at: Date.parse("2013-3-10")) } + background do login_as(garden.owner) @@ -54,4 +56,11 @@ feature "Planting a crop", :js => true do expect(page).to have_content "#{garden.owner}'s gardens" end + 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 + end diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index ab120fa48..82d180d84 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -4,14 +4,14 @@ feature "Planting a crop", :js => true do let(:member) { FactoryGirl.create(:member) } let!(:maize) { FactoryGirl.create(:maize) } let(:garden) { FactoryGirl.create(:garden, owner: member) } - let(:planting) { FactoryGirl.create(:planting, garden: garden, planted_at: Date.parse("2013-3-10")) } + let!(:planting) { FactoryGirl.create(:planting, garden: garden, planted_at: Date.parse("2013-3-10")) } background do login_as(member) visit new_planting_path end - it_behaves_like "crop suggest", "planting", "crop" + it_behaves_like "crop suggest", "planting" scenario "Creating a new planting" do fill_autocomplete "crop", :with => "m" @@ -71,6 +71,9 @@ feature "Planting a crop", :js => true do end expect(page).to have_content "Planting was successfully created" expect(page).to have_content "Finished: August 30, 2014" + + visit plantings_path + expect(page).to have_content "August 30, 2014" end scenario "Marking a planting as finished without a date" do @@ -84,16 +87,16 @@ feature "Planting a crop", :js => true do expect(page).to have_content "Finished: Yes (no date specified)" end - scenario "Marking a planting as finished from the show page" do - this_month = Date.today.strftime("%B") - this_year = Date.today.strftime("%Y") - visit planting_path(planting) - click_link "Mark as finished" - within "div.datepicker" do - expect(page).to have_content "#{this_month}" - page.find(".datepicker-days td.day", text: "21").click - end - expect(page).to have_content "Finished: #{this_month} 21, #{this_year}" + describe "Marking a planting as finished from the show page" do + let(:path) { planting_path(planting) } + let(:link_text) { "Mark as finished" } + it_behaves_like "append date" + end + + describe "Marking a planting as finished from the list page" do + let(:path) { plantings_path } + let(:link_text) { "Mark as finished" } + it_behaves_like "append date" end end diff --git a/spec/features/shared_examples/append_date_spec.rb b/spec/features/shared_examples/append_date_spec.rb new file mode 100644 index 000000000..089680ff9 --- /dev/null +++ b/spec/features/shared_examples/append_date_spec.rb @@ -0,0 +1,22 @@ +shared_examples "append date" do + + scenario "Selecting a date with datepicker" do + this_month = Date.today.strftime("%B") + this_year = Date.today.strftime("%Y") + visit path + click_link link_text + within "div.datepicker" do + expect(page).to have_content "#{this_month}" + page.find(".datepicker-days td.day", text: "21").click + end + expect(page).to have_content "Finished: #{this_month} 21, #{this_year}" + end + + scenario "Confirming without selecting date" do + visit path + click_link link_text + click_link "Confirm without date" + expect(page).to have_content("Finished: Yes (no date specified) ") + end + +end \ No newline at end of file diff --git a/spec/features/shared_examples/crop_suggest.rb b/spec/features/shared_examples/crop_suggest.rb index 499bab891..da10072a3 100644 --- a/spec/features/shared_examples/crop_suggest.rb +++ b/spec/features/shared_examples/crop_suggest.rb @@ -1,5 +1,3 @@ -require 'spec_helper' - shared_examples "crop suggest" do |resource| let!(:popcorn) { FactoryGirl.create(:popcorn) } let!(:pear) { FactoryGirl.create(:pear) } diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 2a0b1d5ff..f17127301 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -39,16 +39,20 @@ describe Photo do expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound end - it 'they are no longer used by plantings' do + it 'they are used by plantings but not harvests' do + harvest.photos << photo planting.photos << photo - planting.destroy # photo is now no longer used by anything - expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound + harvest.destroy # photo is now used by harvest but not planting + photo.destroy_if_unused + expect(lambda { photo.reload }).not_to raise_error ActiveRecord::RecordNotFound end - it 'they are no longer used by harvests' do + it 'they are used by harvests but not plantings' do harvest.photos << photo - harvest.destroy # photo is now no longer used by anything - expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound + planting.photos << photo + planting.destroy # photo is now used by harvest but not planting + photo.destroy_if_unused + expect(lambda { photo.reload }).not_to raise_error ActiveRecord::RecordNotFound end it 'they are no longer used by anything' do @@ -59,11 +63,14 @@ describe Photo do planting.destroy # photo is still used by harvest photo.reload - expect(photo).to be_an_instance_of Photo expect(photo.plantings.size).to eq 0 expect(photo.harvests.size).to eq 1 harvest.destroy # photo is now no longer used by anything + photo.reload + expect(photo.plantings.size).to eq 0 + expect(photo.harvests.size).to eq 0 + photo.destroy_if_unused expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound end diff --git a/spec/views/plantings/index.html.haml_spec.rb b/spec/views/plantings/index.html.haml_spec.rb index d46b4e003..f80331117 100644 --- a/spec/views/plantings/index.html.haml_spec.rb +++ b/spec/views/plantings/index.html.haml_spec.rb @@ -8,8 +8,8 @@ describe "plantings/index" do @tomato = FactoryGirl.create(:tomato) @maize = FactoryGirl.create(:maize) page = 1 - per_page = 2 - total_entries = 2 + per_page = 3 + total_entries = 3 plantings = WillPaginate::Collection.create(page, per_page, total_entries) do |pager| pager.replace([ FactoryGirl.create(:planting, @@ -22,6 +22,13 @@ describe "plantings/index" do :crop => @maize, :description => '', :planted_at => Time.local(2013, 1, 13) + ), + FactoryGirl.create(:planting, + :garden => @garden, + :crop => @tomato, + :planted_at => Time.local(2013, 1, 13), + :finished_at => Time.local(2013, 1, 20), + :finished => true ) ]) end @@ -40,6 +47,10 @@ describe "plantings/index" do rendered.should contain 'January 13, 2013' end + it "displays finished time" do + rendered.should contain 'January 20, 2013' + end + it "provides data links" do render rendered.should contain "The data on this page is available in the following formats:"