diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index a9f784ac3..2dcbb1842 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -87,6 +87,7 @@ submit the change with your pull request. - Christopher Bazin / [RobotScissors](https://github.com/robotscissors) - Ahmed Shahin / [codeminator](https://www.github.com/codeminator) - Brandon Baker / [brandonbaker40](https://github.com/brandonbaker40) +- Alex Darr / [apdarr](https://github.com/apdarr) ## Bots diff --git a/app/assets/stylesheets/overrides.sass b/app/assets/stylesheets/overrides.sass index b255536ea..1e9374184 100644 --- a/app/assets/stylesheets/overrides.sass +++ b/app/assets/stylesheets/overrides.sass @@ -132,11 +132,13 @@ p.stats padding: 0 border: 1px solid darken($beige, 10%) border-radius: 4px - .planting-actions - top: -8em .planting-name position: relative top: -1em + .planting-quick-actions + position: absolute + top: 0 + right: 2em dl.planting-attributes dt diff --git a/app/helpers/buttons_helper.rb b/app/helpers/buttons_helper.rb new file mode 100644 index 000000000..7ae28247e --- /dev/null +++ b/app/helpers/buttons_helper.rb @@ -0,0 +1,101 @@ +module ButtonsHelper + include IconsHelper + def garden_plant_something_button(garden) + link_to new_planting_path(garden_id: garden.id), class: "btn btn-default btn-xs btn-primary" do + planting_icon + ' ' + t('buttons.plant_something_here') + end + end + + def garden_mark_active_button(garden) + link_to t('buttons.mark_as_active'), + garden_path(garden, garden: { active: 1 }), + method: :put, class: 'btn btn-default btn-xs' + end + + def garden_mark_inactive_button(garden) + link_to t('buttons.mark_as_inactive'), + garden_path(garden, garden: { active: 0 }), + method: :put, class: 'btn btn-default btn-xs', + data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' } + end + + def crop_edit_button(crop) + edit_button(edit_crop_path(crop)) + end + + def seed_edit_button(seed) + edit_button(edit_seed_path(seed)) + end + + def harvest_edit_button(harvest) + edit_button(edit_harvest_path(harvest)) + end + + def garden_edit_button(garden) + edit_button(edit_garden_path(garden)) + end + + def planting_edit_button(planting) + edit_button(edit_planting_path(planting)) + end + + def planting_finish_button(planting) + return unless can?(:edit, planting) || planting.finished + + link_to planting_path(planting, planting: { finished: 1 }), + method: :put, class: 'btn btn-default btn-xs append-date' do + finished_icon + ' ' + t('buttons.mark_as_finished') + end + end + + def planting_harvest_button(planting) + return unless planting.active? && can?(:create, Harvest) && can?(:edit, planting) + + link_to new_planting_harvest_path(planting), class: "btn btn-default btn-xs" do + harvest_icon + ' ' + t('buttons.harvest') + end + end + + def planting_save_seeds_button(planting) + return unless can?(:edit, planting) + + link_to new_planting_seed_path(planting), class: "btn btn-default btn-xs" do + seed_icon + ' ' + t('buttons.save_seeds') + end + end + + def add_photo_button(model) + return unless can?(:edit, model) && can?(:create, Photo) + + link_to new_photo_path(id: model.id, type: model_type_for_photo(model)), + class: "btn btn-default btn-xs" do + photo_icon + ' ' + t('buttons.add_photo') + end + end + + def edit_button(path) + link_to path, class: "btn btn-default btn-xs" do + edit_icon + ' ' + t('buttons.edit') + end + end + + def delete_button(model, message: 'are_you_sure') + return unless can? :destroy, model + + link_to model, method: :delete, data: { confirm: t(message) }, class: 'btn btn-default btn-xs' do + delete_icon + ' ' + t('buttons.delete') + end + end + + private + + def model_type_for_photo(model) + ActiveModel::Name.new(model.class).to_s.downcase + end + + def button(path, button_title, icon, size = 'btn-xs') + link_to path, class: "btn btn-default #{size}" do + icon + ' ' + button_title + end + end +end diff --git a/app/helpers/icons_helper.rb b/app/helpers/icons_helper.rb new file mode 100644 index 000000000..a42aaf5d8 --- /dev/null +++ b/app/helpers/icons_helper.rb @@ -0,0 +1,34 @@ +module IconsHelper + include FontAwesome::Sass::Rails::ViewHelpers + def garden_icon + icon('far', 'square') + end + + def planting_icon + icon('fas', 'seedling') + end + + def harvest_icon + icon('fas', 'carrot') + end + + def seed_icon + icon('fas', 'heart') + end + + def finished_icon + icon('fas', 'calendar') + end + + def edit_icon + icon('far', 'edit') + end + + def delete_icon + icon('fas', 'trash-alt') + end + + def photo_icon + icon('fas', 'camera-retro') + end +end diff --git a/app/views/crops/_actions.html.haml b/app/views/crops/_actions.html.haml index e15979f61..92ae2b00f 100644 --- a/app/views/crops/_actions.html.haml +++ b/app/views/crops/_actions.html.haml @@ -1,9 +1,16 @@ .crop-actions - - if can? :create, Planting - = link_to "Plant this", new_planting_path(crop_id: crop.id), class: 'btn btn-default' + .btn-group + - if can? :create, Planting + = link_to new_planting_path(crop_id: crop.id), class: 'btn btn-default' do + = planting_icon + = t('buttons.plant_crop', crop_name: crop.name) - - if can? :create, Harvest - = link_to "Harvest this", new_harvest_path(crop_id: crop.id), class: 'btn btn-default' - - - if can? :create, Seed - = link_to 'Add seeds to stash', new_seed_path(params: { crop_id: crop.id }), class: 'btn btn-default' + - if can? :create, Harvest + = link_to new_harvest_path(crop_id: crop.id), class: 'btn btn-default' do + = harvest_icon + = t('buttons.harvest_crop', crop_name: crop.name) + + - if can? :create, Seed + = link_to new_seed_path(crop_id: crop.id), class: 'btn btn-default' do + = seed_icon + = t('buttons.add_seed_to_stash', crop_name: crop.name) diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml index 99b4a1a7e..1c94573cf 100644 --- a/app/views/crops/_index_card.html.haml +++ b/app/views/crops/_index_card.html.haml @@ -31,6 +31,6 @@ days after planting - if can? :create, Planting - = link_to 'Plant this', new_planting_path(params: { crop_id: crop.id }), class: 'btn btn-primary' + = link_to "Plant #{crop.name}", new_planting_path(params: { crop_id: crop.id }), class: 'btn btn-primary' - if can? :create, Seed - = link_to 'Add seeds to stash', new_seed_path(params: { crop_id: crop.id }), class: 'btn btn-primary' + = link_to "Add #{crop.name} seeds to stash", new_seed_path(params: { crop_id: crop.id }), class: 'btn btn-primary' diff --git a/app/views/crops/_search_bar.haml b/app/views/crops/_search_bar.haml new file mode 100644 index 000000000..390c32390 --- /dev/null +++ b/app/views/crops/_search_bar.haml @@ -0,0 +1,9 @@ += form_tag crops_search_path, method: :get, id: 'navbar-search' do + = label_tag :term, "Search crop database:", class: 'sr-only' + .input + .input-group + = text_field_tag 'term', nil, class: 'search-query input-medium form-control', placeholder: 'Search crops' + .input-group-btn + %button.btn.btn-default{ style: "height: 34px;" } + = submit_tag "Search", class: 'btn sr-only' + %span.glyphicon.glyphicon-search diff --git a/app/views/crops/_wrangle.html.haml b/app/views/crops/_wrangle.html.haml index 8e8f87558..4260bbfe2 100644 --- a/app/views/crops/_wrangle.html.haml +++ b/app/views/crops/_wrangle.html.haml @@ -4,11 +4,6 @@ You are a = succeed "." do %strong CROP WRANGLER - %p - - if can? :edit, crop - = link_to 'Edit crop', edit_crop_path(crop), class: 'btn btn-default btn-xs' - - if can? :destroy, crop - = link_to 'Delete crop', crop, - method: :delete, - data: { confirm: 'Are you sure?' }, - class: 'btn btn-default btn-xs' + + %p= crop_edit_button(crop) if can? :edit, crop + %p= delete_button(crop) if can? :destroy, crop diff --git a/app/views/gardens/_actions.html.haml b/app/views/gardens/_actions.html.haml index a5187991e..ea97a3931 100644 --- a/app/views/gardens/_actions.html.haml +++ b/app/views/gardens/_actions.html.haml @@ -1,29 +1,14 @@ .garden-actions - if can?(:edit, garden) + = garden_plant_something_button(garden) if garden.active .btn-group - if garden.active - = link_to new_planting_path(garden_id: garden.id), class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-grain{ title: "Plant" } - Plant something - = link_to "Mark as inactive", garden_path(garden, garden: { active: 0 }), - method: :put, class: 'btn btn-default btn-xs', - data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' } + = garden_mark_inactive_button(garden) - else - = link_to "Mark as active", garden_path(garden, garden: { active: 1 }), - method: :put - = render 'shared/buttons/edit', path: edit_garden_path(garden) + = garden_mark_active_button(garden) - - if can?(:edit, garden) && can?(:create, Photo) - = link_to new_photo_path(type: "garden", id: garden.id), - class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-camera{ title: "Add photo" } - Add photo + = garden_edit_button(garden) + = add_photo_button(garden) - if can?(:destroy, garden) - .pull-right - = link_to garden_path(garden), - method: :delete, - data: { confirm: 'All plantings associated with this garden will also be deleted. Are you sure?' }, - class: 'btn btn-default btn-xs', id: 'delete_garden_link' do - %span.glyphicon.glyphicon-trash{ title: "Delete" } - Delete + = delete_button(garden, message: 'All plantings associated with this garden will also be deleted. Are you sure?') diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml index 8b45b0b16..2c8ec76d6 100644 --- a/app/views/gardens/show.html.haml +++ b/app/views/gardens/show.html.haml @@ -14,11 +14,11 @@ = javascript_include_tag "charts" = javascript_include_tag "https://www.gstatic.com/charts/loader.js" +-content_for(:buttonbar) do + = render 'gardens/actions', garden: @garden + .row .col-md-9 - = render 'gardens/actions', garden: @garden - - - unless @garden.active .alert.alert-warning This garden is inactive. @@ -57,7 +57,7 @@ - if @finished_plantings.size.positive? - @finished_plantings.each do |planting| .col-xs-6.col-md-2 - = render partial: "plantings/thumbnail", locals: { planting: planting } + = render "plantings/thumbnail", planting: planting - else %p Nothing has been planted here. .col-md-3 diff --git a/app/views/harvests/_actions.html.haml b/app/views/harvests/_actions.html.haml index 2ebfbc8f9..28a9aee77 100644 --- a/app/views/harvests/_actions.html.haml +++ b/app/views/harvests/_actions.html.haml @@ -1,7 +1,5 @@ .harvest-actions - - if can?(:edit, harvest) || can?(:destroy, harvest) - .btn-group - - if can? :edit, harvest - = render 'shared/buttons/edit', path: edit_harvest_path(harvest) - - if can? :destroy, harvest - .pull-right= render 'shared/buttons/delete', path: harvest_path(harvest) + .btn-group + = harvest_edit_button(harvest) if can? :edit, harvest + = add_photo_button(harvest) + = delete_button(harvest) diff --git a/app/views/harvests/new.html.haml b/app/views/harvests/new.html.haml index 5b5004622..f3a9dbe75 100644 --- a/app/views/harvests/new.html.haml +++ b/app/views/harvests/new.html.haml @@ -1,3 +1,3 @@ -- content_for :title, "New Harvest" +- content_for :title, t('harvests.harvest_something') = render 'form' diff --git a/app/views/harvests/show.html.haml b/app/views/harvests/show.html.haml index a584389fe..c2c773819 100644 --- a/app/views/harvests/show.html.haml +++ b/app/views/harvests/show.html.haml @@ -8,6 +8,9 @@ = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) +-content_for(:buttonbar) do + = render 'harvests/actions', harvest: @harvest + .row .col-md-6 %p @@ -32,7 +35,6 @@ %b Quantity: = display_quantity(@harvest) - = render 'harvests/actions', harvest: @harvest .col-md-6 = render partial: "crops/index_card", locals: { crop: @harvest.crop } diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml index d05d6a37a..be274c930 100644 --- a/app/views/home/index.html.haml +++ b/app/views/home/index.html.haml @@ -1,16 +1,9 @@ .homepage.row .col-md-12 - if member_signed_in? - %h1= t('.welcome', site_name: ENV['GROWSTUFF_SITE_NAME'], member_name: current_member) + - content_for :title, t('.welcome', site_name: ENV['GROWSTUFF_SITE_NAME'], member_name: current_member) = render 'stats' - %p - .btn-group - = link_to t('.plant'), new_planting_path, class: 'btn btn-default' - = link_to t('.harvest'), new_harvest_path, class: 'btn btn-default' - = link_to t('.add_seeds'), new_seed_path, class: 'btn btn-default' - = link_to t('.post'), new_post_path, class: 'btn btn-default' - - else .hidden-xs .jumbotron diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index d2b8fd01c..ff4086c2e 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -17,15 +17,7 @@ alt: ENV['GROWSTUFF_SITE_NAME']) .form.navbar-form.pull-left - = form_tag crops_search_path, method: :get, id: 'navbar-search' do - = label_tag :term, "Search crop database:", class: 'sr-only' - .input - .input-group - = text_field_tag 'term', nil, class: 'search-query input-medium form-control', placeholder: 'Search crops' - .input-group-btn - %button.btn.btn-default{ style: "height: 34px;" } - = submit_tag "Search", class: 'btn sr-only' - %span.glyphicon.glyphicon-search + = render 'crops/search_bar' .navbar-collapse.collapse#navbar-collapse %ul.nav.navbar-nav.navbar-right diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 070ed73db..d36f217b8 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -7,20 +7,28 @@ #maincontainer .row - .col-md-12 + .col-md-12= render partial: "shared/flash_messages", flash: flash + .row + .col-md-6 - if content_for?(:title) %h1#title = yield(:title) - if content_for?(:subtitle) %small= yield(:subtitle) - + - if content_for?(:buttonbar) - .btn-group.layout-actions= yield(:buttonbar) - = render partial: "shared/flash_messages", flash: flash + .btn-group.layout-actions + = yield(:buttonbar) + + .col-md-6 + = render 'shared/global_actions' + + .row + .col-md-12 = yield %footer - = render partial: "layouts/footer" + = render "layouts/footer" / Javascripts \================================================== diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml index 621f35c51..a786b8077 100644 --- a/app/views/members/show.html.haml +++ b/app/views/members/show.html.haml @@ -7,11 +7,17 @@ = tag("meta", property: "og:type", content: "profile") = tag("meta", property: "og:url", content: request.original_url) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) + + - content_for :buttonbar do - - if can? :update, @member - = link_to 'Edit profile', edit_member_registration_path, class: 'btn btn-default pull-right' - - if can?(:create, Notification) && current_member != @member - = link_to 'Send message', new_notification_path(recipient_id: @member.id), class: 'btn btn-default pull-right' + %p.btn-group + - if can? :update, @member + = link_to edit_member_registration_path, class: 'btn btn-default pull-right' do + = edit_icon + = t('members.edit_profile') + + - if can?(:create, Notification) && current_member != @member + = link_to 'Send message', new_notification_path(recipient_id: @member.id), class: 'btn btn-default' - if current_member && current_member != @member # must be logged in, can't follow yourself - follow = current_member.get_follow(@member) diff --git a/app/views/plantings/_actions.html.haml b/app/views/plantings/_actions.html.haml index 6f5b1b93d..3de6ce339 100644 --- a/app/views/plantings/_actions.html.haml +++ b/app/views/plantings/_actions.html.haml @@ -1,12 +1,13 @@ - if can?(:edit, planting) - .btn-group.planting-actions - = render 'shared/buttons/edit', path: edit_planting_path(planting) - = render 'shared/buttons/add_photo', path: new_photo_path(id: planting.id, type: 'planting') + .planting-actions + .btn-group + = planting_edit_button(planting) + = add_photo_button(planting) - - if planting.active? - = render 'shared/buttons/finish_planting', planting: planting - = render 'shared/buttons/harvest_planting', planting: planting - = render 'shared/buttons/save_seeds', planting: planting + - if planting.active? + = planting_finish_button(planting) + = planting_harvest_button(planting) + = planting_save_seeds_button(planting) - if can? :destroy, planting - = render 'shared/buttons/delete', path: planting + = delete_button(planting) diff --git a/app/views/plantings/_badges.html.haml b/app/views/plantings/_badges.html.haml index 2d690b914..acd244da4 100644 --- a/app/views/plantings/_badges.html.haml +++ b/app/views/plantings/_badges.html.haml @@ -1,20 +1,21 @@ -// Finish times -- if planting.finish_is_predicatable? - - if planting.super_late? - %span.badge.badge-super-late= t('.super_late') - = render 'shared/buttons/finish_planting', planting: planting - - elsif planting.late? - %span.badge.badge-late= t('.late_finishing') - - else - %span.badge - = days_from_now_to_finished(planting) - = t('.days_until_finished') +- unless planting.finished? + // Finish times + - if planting.finish_is_predicatable? + - if planting.super_late? + %span.badge.badge-super-late= t('.super_late') + = planting_finish_button(planting) + - elsif planting.late? + %span.badge.badge-late= t('.late_finishing') + - else + %span.badge + = days_from_now_to_finished(planting) + = t('.days_until_finished') -// Harvest times -- unless planting.super_late? - - if planting.harvest_time? - %span.badge.badge-harvest= t('.harvesting_now') - - elsif planting.before_harvest_time? - %span.badge - = days_from_now_to_first_harvest(planting) - = t('.days_until_harvest') + // Harvest times + - unless planting.super_late? + - if planting.harvest_time? + %span.badge.badge-harvest= t('.harvesting_now') + - elsif planting.before_harvest_time? + %span.badge + = days_from_now_to_first_harvest(planting) + = t('.days_until_harvest') diff --git a/app/views/plantings/_thumbnail.html.haml b/app/views/plantings/_thumbnail.html.haml index a6b8349b8..bfe4892a8 100644 --- a/app/views/plantings/_thumbnail.html.haml +++ b/app/views/plantings/_thumbnail.html.haml @@ -1,13 +1,20 @@ .planting .planting-badges = render 'plantings/badges', planting: planting - .hover-wrapper - .thumbnail - .planting-thumbnail{ class: planting_classes(planting) } - = link_to image_tag(planting_image_path(planting), - alt: planting.crop.name, class: 'img'), planting_path(planting) - = render 'plantings/progress', planting: planting, show_explanation: false - .planting-name - = link_to planting.crop.name, planting - .text - .planting-actions= render 'plantings/actions', planting: planting + + .planting-quick-actions.pull-right + %a.btn.btn-default.btn-xs#actionsMenu.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#"} + =icon('fas', 'bars') + .dropdown-menu{"aria-labelledby" => "actionsMenu"} + %p= render 'plantings/actions', planting: planting + + .thumbnail + + .planting-thumbnail{ class: planting_classes(planting) } + = link_to image_tag(planting_image_path(planting), + alt: planting.crop.name, class: 'img'), planting_path(planting) + = render 'plantings/progress', planting: planting, show_explanation: false + + .planting-name + = link_to planting.crop.name, planting + diff --git a/app/views/plantings/new.html.haml b/app/views/plantings/new.html.haml index f28af6b19..c509e5646 100644 --- a/app/views/plantings/new.html.haml +++ b/app/views/plantings/new.html.haml @@ -1,3 +1,3 @@ -= content_for :title, "Plant something" += content_for :title, t('plantings.plant_something') = render 'form' diff --git a/app/views/posts/new.html.haml b/app/views/posts/new.html.haml index 75b111f6e..748c290b8 100644 --- a/app/views/posts/new.html.haml +++ b/app/views/posts/new.html.haml @@ -1,3 +1,3 @@ -= content_for :title, @forum ? "Post in #{@forum.name}" : "Post something" += content_for :title, @forum ? "Post in #{@forum.name}" : t('posts.write_blog_post') = render 'form' diff --git a/app/views/seeds/_actions.html.haml b/app/views/seeds/_actions.html.haml index 6e1cef334..c801142a4 100644 --- a/app/views/seeds/_actions.html.haml +++ b/app/views/seeds/_actions.html.haml @@ -1,8 +1,8 @@ .seed-actions - if can? :edit, seed .btn-group - = render 'shared/buttons/edit', path: edit_seed_path(seed) - = render 'shared/buttons/add_photo', path: new_photo_path(id: seed.id, type: 'seed') + = seed_edit_button(seed) + = add_photo_button(seed) - if can?(:create, Planting) && seed.active? = link_to new_planting_path(seed_id: seed), class: 'btn btn-default btn-xs' do @@ -11,5 +11,4 @@ = render 'shared/buttons/finish_seeds', seed: seed - - if can? :destroy, seed - = render 'shared/buttons/delete', path: seed + = delete_button(seed) if can? :destroy, seed diff --git a/app/views/seeds/new.html.haml b/app/views/seeds/new.html.haml index 834c958d8..6a59b7050 100644 --- a/app/views/seeds/new.html.haml +++ b/app/views/seeds/new.html.haml @@ -1,3 +1,3 @@ -- content_for :title, "Add seeds" +- content_for :title, t('seeds.save_seeds') = render 'form' diff --git a/app/views/shared/_global_actions.html.haml b/app/views/shared/_global_actions.html.haml new file mode 100644 index 000000000..638ce87d0 --- /dev/null +++ b/app/views/shared/_global_actions.html.haml @@ -0,0 +1,22 @@ +- if signed_in? + .global-actions.pull-right + .btn-group + = link_to gardens_by_owner_path(owner: current_member.slug), class: 'btn btn-default' do + = garden_icon + = t('links.my_gardens') + + .btn-group + = link_to new_planting_path, class: 'btn btn-default' do + = planting_icon + = t('plantings.plant_something') + + = link_to new_harvest_path, class: 'btn btn-default' do + = harvest_icon + = t('harvests.harvest_something') + + = link_to new_seed_path, class: 'btn btn-default' do + = seed_icon + = t('buttons.save_seeds') + + .btn-group + = link_to t('posts.write_blog_post'), new_post_path, class: 'btn btn-default' diff --git a/app/views/shared/_glyphicon.html.haml b/app/views/shared/_glyphicon.html.haml new file mode 100644 index 000000000..65cba2bdd --- /dev/null +++ b/app/views/shared/_glyphicon.html.haml @@ -0,0 +1,2 @@ +%span.glyphicon{class: "glyphicon-#{icon}", title: t(title) } +=t(title) \ No newline at end of file diff --git a/app/views/shared/buttons/_add_photo.haml b/app/views/shared/buttons/_add_photo.haml deleted file mode 100644 index 71e97c0e9..000000000 --- a/app/views/shared/buttons/_add_photo.haml +++ /dev/null @@ -1,4 +0,0 @@ -- if can?(:create, Photo) - = link_to path, class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-camera{ title: "Add photo" } - Add photo diff --git a/app/views/shared/buttons/_delete.haml b/app/views/shared/buttons/_delete.haml index b7490837b..8be23926a 100644 --- a/app/views/shared/buttons/_delete.haml +++ b/app/views/shared/buttons/_delete.haml @@ -1,4 +1,4 @@ = link_to path, method: :delete, - data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-trash{ title: "Delete" } - Delete + data: { confirm: t(:are_you_sure?) }, class: 'btn btn-default btn-xs' do + = render 'shared/glyphicon', icon: 'trash', title: 'buttons.delete' + =t('buttons.delete') diff --git a/app/views/shared/buttons/_edit.haml b/app/views/shared/buttons/_edit.haml index 87d464023..f80cdf917 100644 --- a/app/views/shared/buttons/_edit.haml +++ b/app/views/shared/buttons/_edit.haml @@ -1,3 +1,3 @@ -= link_to path, class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-pencil{ title: "Edit" } - Edit += link_to path, class: 'btn btn-default' do + = render 'shared/glyphicon', icon: 'pencil', title: 'buttons.edit' + =t('buttons.edit') diff --git a/app/views/shared/buttons/_finish_planting.html.haml b/app/views/shared/buttons/_finish_planting.html.haml deleted file mode 100644 index 7b1ba8319..000000000 --- a/app/views/shared/buttons/_finish_planting.html.haml +++ /dev/null @@ -1,5 +0,0 @@ -- if can?(:edit, planting) && !planting.finished - = link_to planting_path(planting, planting: { finished: 1 }), - method: :put, class: 'btn btn-default btn-xs append-date' do - %span.glyphicon.glyphicon-ok{ title: "Finished" } - Mark as finished diff --git a/app/views/shared/buttons/_finish_seeds.haml b/app/views/shared/buttons/_finish_seeds.haml index 211e3ec8b..23316d861 100644 --- a/app/views/shared/buttons/_finish_seeds.haml +++ b/app/views/shared/buttons/_finish_seeds.haml @@ -1,5 +1,5 @@ - unless seed.finished = link_to seed_path(seed, seed: { finished: 1 }), method: :put, class: 'btn btn-default btn-xs append-date' do - %span.glyphicon.glyphicon-ok{ title: "Finished" } - Mark as finished + = render 'shared/glyphicon', icon: 'ok', title: 'buttons.finished' + =t('buttons.mark_as_finished') diff --git a/app/views/shared/buttons/_harvest_planting.haml b/app/views/shared/buttons/_harvest_planting.haml deleted file mode 100644 index c90e163ad..000000000 --- a/app/views/shared/buttons/_harvest_planting.haml +++ /dev/null @@ -1,4 +0,0 @@ -- planting.active? && if can?(:create, Harvest) && can?(:edit, planting) - = link_to new_planting_harvest_path(planting), class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-leaf{ title: "Harvest" } - Harvest diff --git a/app/views/shared/buttons/_save_seeds.haml b/app/views/shared/buttons/_save_seeds.haml deleted file mode 100644 index 00d5febb0..000000000 --- a/app/views/shared/buttons/_save_seeds.haml +++ /dev/null @@ -1,4 +0,0 @@ -- if planting.active? - = link_to new_planting_seed_path(planting), class: 'btn btn-default btn-xs' do - %span.glyphicon.glyphicon-heart{ title: "Save seeds" } - Save seeds diff --git a/config/locales/en.yml b/config/locales/en.yml index 879d7c51c..12942554f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -63,6 +63,27 @@ en: seed: one: seed other: seeds + application_helper: + title: + title: + default: Default + are_you_sure: Are you sure? + buttons: + add: Add + add_photo: Add photo + add_seed_to_stash: Add %{crop_name} seeds to stash + delete: Delete + edit: Edit + harvest: Harvest + harvest_crop: Harvest %{crop_name} + mark_as_active: Mark as active + mark_as_finished: Mark as finished + mark_as_inactive: Mark as inactive + plant: Plant + plant_crop: Plant %{crop_name} + plant_something_here: Plant something here + save_seeds: Save seeds + write_blog_post: Write blog post crops: index: subtitle: "%{crops_size} total" @@ -71,6 +92,7 @@ en: link: You have %{number_crops} crops awaiting approval subtitle: Pending approval title: Requested crops + edit_crop: Edit crop forms: optional: "(Optional)" forums: @@ -82,35 +104,33 @@ en: form: location_helper: If you have a location set in your profile, it will be used when you create a new garden. location: "%{owner}'s %{garden}" - updated: Garden was successfully updated. overview: - gardensphoto: gardens/photo - plantingsthumbnail: plantings/thumbnail - no_plantings: no plantings gardensactions: gardens/actions + gardensphoto: gardens/photo + no_plantings: no plantings + plantingsthumbnail: plantings/thumbnail + updated: Garden was successfully updated. harvests: created: Harvest was successfully created. + harvest_something: Harvest something index: title: crop_harvests: Everyone's %{crop} harvests - planting_harvests: Harvests from %{planting} default: Everyone's harvests owner_harvests: "%{owner} harvests" + planting_harvests: Harvests from %{planting} updated: Harvest was successfully updated. home: blurb: already_html: Or %{sign_in} if you already have an account - intro: > - %{site_name} is a community of food gardeners. We're building an open source - platform to help you learn about growing food, track what you plant and harvest, - and swap seeds and produce with other gardeners near you. + intro: "%{site_name} is a community of food gardeners. We're building an open source platform to help you learn about growing food, track what you plant and harvest, and swap seeds and produce with other gardeners near you.\n" perks: Join now for your free garden journal, seed sharing, forums, and more. sign_in_linktext: sign in sign_up: Sign up crops: our_crops: Some of our crops recently_added: Recently added crops - recently_planted: Recently planted + recently_planted: Recently Planted view_all: View all crops discuss: discussion: Discussion @@ -122,6 +142,7 @@ en: harvest: Harvest plant: Plant post: Post + recently_added: Recently Added welcome: Welcome to %{site_name}, %{member_name} members: title: Some of our members @@ -151,6 +172,8 @@ en: talk_linktext: Growstuff Talk why_linktext: why Growstuff is open source wiki_linktext: Growstuff Wiki + plantings: + recently_planted: Recently Planted seeds: crop: Crop description: Description @@ -195,7 +218,10 @@ en: support_growstuff: Support Growstuff toggle_navigation: Toggle Navigation your_stuff: Your Stuff (%{unread_count}) + links: + my_gardens: My gardens members: + edit_profile: Edit profile index: title: "%{site_name} members" signup: @@ -215,6 +241,14 @@ en: index: title: "%{site_name} Community Map" plantings: + badges: + days_until_finished: days until finished + days_until_harvest: days until harvest + harvesting_now: harvesting now + late_finishing: late finishing + sharedbuttonsfinish_planting: shared/buttons/finish_planting + super_late: super late + plant_something: Plant something form: finish_helper: > A planting is finished when you've harvested all of the crop, or it dies, or it's otherwise @@ -230,13 +264,13 @@ en: badges: late_finishing: late finishing super_late: super late - sharedbuttonsfinish_planting: shared/buttons/finish_planting days_until_finished: days until finished harvesting_now: harvesting now days_until_harvest: days until harvest progress: progress_0_not_planted_yet: 'Progress: 0% - not planted yet' posts: + write_blog_post: Write blog post index: title: author_posts: "%{author} posts" @@ -252,6 +286,7 @@ en: crop_seeds: Everyone's %{crop} seeds default: Everyone's seeds owner_seeds: "%{owner} seeds" + save_seeds: Save seeds string: "%{crop} seeds belonging to %{owner}" unauthorized: create: diff --git a/config/newrelic.yml b/config/newrelic.yml index 63500e405..b7c9cdfdb 100644 --- a/config/newrelic.yml +++ b/config/newrelic.yml @@ -65,7 +65,7 @@ common: &default_settings # encryption involved in SSL communication, but this work is done # asynchronously to the threads that process your application code, # so it should not impact response times. - ssl: false + ssl: true # EXPERIMENTAL: enable verification of the SSL certificate sent by # the server. This setting has no effect unless SSL is enabled diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb index cbc73cf9c..523770bcb 100644 --- a/spec/features/crops/crop_detail_page_spec.rb +++ b/spec/features/crops/crop_detail_page_spec.rb @@ -105,13 +105,13 @@ feature "crop detail page", js: true do background { subject } scenario "has a link to plant the crop" do - expect(page).to have_link "Plant this", href: new_planting_path(crop_id: crop.id) + expect(page).to have_link "Plant #{crop.name}", href: new_planting_path(crop_id: crop.id) end scenario "has a link to harvest the crop" do - expect(page).to have_link "Harvest this", href: new_harvest_path(crop_id: crop.id) + expect(page).to have_link "Harvest #{crop.name}", href: new_harvest_path(crop_id: crop.id) end scenario "has a link to add seeds" do - expect(page).to have_link "Add seeds to stash", href: new_seed_path(crop_id: crop.id) + expect(page).to have_link "Add #{crop.name} seeds to stash", href: new_seed_path(crop_id: crop.id) end end diff --git a/spec/features/crops/crop_wranglers_spec.rb b/spec/features/crops/crop_wranglers_spec.rb index eafc7039f..86dc8a1c0 100644 --- a/spec/features/crops/crop_wranglers_spec.rb +++ b/spec/features/crops/crop_wranglers_spec.rb @@ -32,11 +32,11 @@ feature "crop wranglers", js: true do end end - scenario "visiting a crop can see wrangler links" do - visit crop_path(crops.first) - expect(page).to have_content 'You are a CROP WRANGLER' - expect(page).to have_link 'Edit crop' - expect(page).to have_link 'Delete crop' + describe "visiting a crop can see wrangler links" do + before { visit crop_path(crops.first) } + it { expect(page).to have_content 'You are a CROP WRANGLER' } + it { expect(page).to have_link 'Edit' } + it { expect(page).to have_link 'Delete' } end scenario "can create a new crop" do diff --git a/spec/features/gardens/actions_spec.rb b/spec/features/gardens/actions_spec.rb index a22ab6886..8468cec18 100644 --- a/spec/features/gardens/actions_spec.rb +++ b/spec/features/gardens/actions_spec.rb @@ -9,6 +9,7 @@ feature "Gardens" do background { login_as member } let(:garden) { member.gardens.first } + let(:other_member_garden) { FactoryBot.create :garden } describe '#index' do shared_examples "has buttons bar at top" do @@ -26,13 +27,11 @@ feature "Gardens" do include_examples "has buttons bar at top" it "has actions on garden" do - within '.garden-actions' do - is_expected.to have_link 'Plant something' - is_expected.to have_link 'Mark as inactive' - is_expected.to have_link 'Edit' - is_expected.to have_link 'Add photo' - is_expected.to have_link 'Delete' - end + is_expected.to have_link 'Plant something here' + is_expected.to have_link 'Mark as inactive' + is_expected.to have_link 'Edit' + is_expected.to have_link 'Add photo' + is_expected.to have_link 'Delete' end end @@ -46,14 +45,28 @@ feature "Gardens" do before { visit gardens_path(owner: FactoryBot.create(:member)) } include_examples "has buttons bar at top" - it 'does not show actions on other member garden' do - is_expected.not_to have_link 'Plant something' - is_expected.not_to have_link 'Mark as inactive' + describe 'does not show actions on other member garden' do + it { is_expected.not_to have_link 'Edit' } + it { is_expected.not_to have_link 'Delete' } end end end describe '#show' do + describe 'my garden' do + before { visit garden_path(garden) } + it { is_expected.to have_link 'Edit' } + it { is_expected.to have_link 'Delete' } + it { is_expected.to have_content "Plant something here" } + it { is_expected.to have_content "Add photo" } + end + describe "someone else's garden" do + before { visit garden_path(other_member_garden) } + it { is_expected.not_to have_link 'Edit' } + it { is_expected.not_to have_link 'Delete' } + it { is_expected.not_to have_content "Plant something here" } + it { is_expected.not_to have_content "Add photo" } + end end end diff --git a/spec/features/gardens_spec.rb b/spec/features/gardens_spec.rb index 368389719..0c58f8fdf 100644 --- a/spec/features/gardens_spec.rb +++ b/spec/features/gardens_spec.rb @@ -82,7 +82,7 @@ feature "Planting a crop", js: true do fill_in "Name", with: "New garden" click_button "Save" visit garden_path(Garden.last) - click_link 'delete_garden_link' + click_link 'Delete' expect(page).to have_content "Garden was successfully deleted" expect(page).to have_content "#{garden.owner}'s gardens" end diff --git a/spec/features/harvests/harvesting_a_crop_spec.rb b/spec/features/harvests/harvesting_a_crop_spec.rb index 5f6d85fa2..afb182120 100644 --- a/spec/features/harvests/harvesting_a_crop_spec.rb +++ b/spec/features/harvests/harvesting_a_crop_spec.rb @@ -64,7 +64,9 @@ feature "Harvesting a crop", :js, :elasticsearch do scenario "Harvesting from crop page" do visit crop_path(maize) - click_link "Harvest this" + within '.crop-actions' do + click_link "Harvest #{maize.name}" + end within "form#new_harvest" do select plant_part.name, from: 'harvest[plant_part_id]' expect(page).to have_selector "input[value='maize']" diff --git a/spec/features/home/home_spec.rb b/spec/features/home/home_spec.rb index 3847d532b..d02bb619f 100644 --- a/spec/features/home/home_spec.rb +++ b/spec/features/home/home_spec.rb @@ -84,5 +84,10 @@ feature "home page" do include_examples 'show plantings' include_examples 'show harvests' include_examples 'shows seeds' + + describe 'should say welcome' do + before { visit root_path } + it { expect(page).to have_content "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{member.login_name}" } + end end end diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb index 0bf696f06..3c486fa5b 100644 --- a/spec/features/photos/new_photo_spec.rb +++ b/spec/features/photos/new_photo_spec.rb @@ -13,7 +13,9 @@ feature "new photo page" do scenario "add photo" do visit planting_path(planting) - click_link('Add photo', match: :first) + within '.planting-actions' do + click_link('Add photo') + end expect(page).to have_text planting.crop.name end end @@ -23,7 +25,9 @@ feature "new photo page" do scenario "add photo" do visit harvest_path(harvest) - click_link "Add photo" + within '.harvest-actions' do + click_link "Add photo" + end expect(page).to have_text harvest.crop.name end end diff --git a/spec/features/plantings/planting_a_crop_spec.rb b/spec/features/plantings/planting_a_crop_spec.rb index 1d8b7f745..376c42569 100644 --- a/spec/features/plantings/planting_a_crop_spec.rb +++ b/spec/features/plantings/planting_a_crop_spec.rb @@ -21,15 +21,15 @@ feature "Planting a crop", :js, :elasticsearch do expect(page).to have_content "* denotes a required field" end - it "displays required and optional fields properly" do - expect(page).to have_selector ".form-group.required", text: "What did you plant?" - expect(page).to have_selector ".form-group.required", text: "Where did you plant it?" - expect(page).to have_optional 'input#planting_planted_at' - expect(page).to have_optional 'input#planting_quantity' - expect(page).to have_optional 'select#planting_planted_from' - expect(page).to have_optional 'select#planting_sunniness' - expect(page).to have_optional 'textarea#planting_description' - expect(page).to have_optional 'input#planting_finished_at' + describe "displays required and optional fields properly" do + it { expect(page).to have_selector ".form-group.required", text: "What did you plant?" } + it { expect(page).to have_selector ".form-group.required", text: "Where did you plant it?" } + it { expect(page).to have_optional 'input#planting_planted_at' } + it { expect(page).to have_optional 'input#planting_quantity' } + it { expect(page).to have_optional 'select#planting_planted_from' } + it { expect(page).to have_optional 'select#planting_sunniness' } + it { expect(page).to have_optional 'textarea#planting_description' } + it { expect(page).to have_optional 'input#planting_finished_at' } end scenario "Creating a new planting" do @@ -152,7 +152,9 @@ feature "Planting a crop", :js, :elasticsearch do scenario "Planting from crop page" do visit crop_path(maize) - click_link "Plant this" + within '.crop-actions' do + click_link "Plant maize" + end within "form#new_planting" do expect(page).to have_selector "input[value='maize']" click_button "Save" diff --git a/spec/features/seeds/adding_seeds_spec.rb b/spec/features/seeds/adding_seeds_spec.rb index 67a8b7717..021a24336 100644 --- a/spec/features/seeds/adding_seeds_spec.rb +++ b/spec/features/seeds/adding_seeds_spec.rb @@ -59,7 +59,7 @@ feature "Seeds", :js, :elasticsearch do describe "Adding a seed from crop page" do before do visit crop_path(maize) - click_link "Add seeds to stash" + click_link "Add maize seeds to stash" within "form#new_seed" do expect(page).to have_selector "input[value='maize']" click_button "Save" diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb index e095ed390..941d25f00 100644 --- a/spec/features/seeds/misc_seeds_spec.rb +++ b/spec/features/seeds/misc_seeds_spec.rb @@ -21,10 +21,10 @@ feature "seeds", js: true do describe "button on front page to add seeds" do before do visit root_path - click_link "Add seeds" + click_link "Save seeds" end it { expect(current_path).to eq new_seed_path } - it { expect(page).to have_content 'Add seeds' } + it { expect(page).to have_content 'Save seeds' } end describe "Clicking link to owner's profile" do diff --git a/spec/helpers/buttons_helper_spec.rb b/spec/helpers/buttons_helper_spec.rb new file mode 100644 index 000000000..d3def8e00 --- /dev/null +++ b/spec/helpers/buttons_helper_spec.rb @@ -0,0 +1,33 @@ +require 'rails_helper' + +# Specs in this file have access to a helper object that includes +# the ButtonsHelper. For example: +# +# describe ButtonsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# expect(helper.concat_strings("this","that")).to eq("this that") +# end +# end +# end +RSpec.describe ButtonsHelper, type: :helper do + before { allow(self).to receive(:can?) { true } } + let(:garden) { FactoryBot.create :garden } + let(:planting) { FactoryBot.create :planting } + let(:harvest) { FactoryBot.create :harvest } + let(:seed) { FactoryBot.create :seed } + + describe 'add_photo_button' do + it { expect(add_photo_button(garden)).to include "/photos/new?id=#{garden.id}&type=garden" } + it { expect(add_photo_button(planting)).to include "/photos/new?id=#{planting.id}&type=planting" } + it { expect(add_photo_button(harvest)).to include "/photos/new?id=#{harvest.id}&type=harvest" } + it { expect(add_photo_button(seed)).to include "/photos/new?id=#{seed.id}&type=seed" } + end + + describe 'edit_button' do + it { expect(garden_edit_button(garden)).to include "/gardens/#{garden.slug}/edit" } + it { expect(planting_edit_button(planting)).to include "/plantings/#{planting.slug}/edit" } + it { expect(harvest_edit_button(harvest)).to include "/harvests/#{harvest.slug}/edit" } + it { expect(seed_edit_button(seed)).to include "/seeds/#{seed.slug}/edit" } + end +end diff --git a/spec/views/gardens/show.html.haml_spec.rb b/spec/views/gardens/show.html.haml_spec.rb index 5594c6755..7451f26c8 100644 --- a/spec/views/gardens/show.html.haml_spec.rb +++ b/spec/views/gardens/show.html.haml_spec.rb @@ -12,50 +12,23 @@ describe "gardens/show" do render end - it 'should show the location' do - rendered.should have_content @garden.location + it 'shows the location' do + expect(rendered).to have_content @garden.location end - it 'should show the area' do - rendered.should have_content pluralize(@garden.area, @garden.area_unit) + it 'shows the area' do + expect(rendered).to have_content pluralize(@garden.area, @garden.area_unit) end - it 'should show the description' do - rendered.should have_content "totally cool garden" + it 'shows the description' do + expect(rendered).to have_content "totally cool garden" end it 'renders markdown in the description' do assert_select "strong", "totally" end - it 'should show plantings on the garden page' do - rendered.should have_content @planting.crop.name - end - - it "doesn't show the note about random plantings" do - rendered.should_not have_content "Note: these are a random selection" - end - - context 'signed in' do - before :each do - sign_in @owner - render - end - - it 'should have an edit button' do - rendered.should have_link 'Edit' - end - - it "shows a 'plant something' button" do - rendered.should have_content "Plant something" - end - - it "shows an 'add photo' button" do - rendered.should have_content "Add photo" - end - - it "links to the right crop in the planting link" do - assert_select("a[href='#{new_planting_path}?garden_id=#{@garden.id}']") - end + it 'shows plantings on the garden page' do + expect(rendered).to have_content @planting.crop.name end end diff --git a/spec/views/home/index_spec.rb b/spec/views/home/index_spec.rb index 5e11882fd..4bc1e9c10 100644 --- a/spec/views/home/index_spec.rb +++ b/spec/views/home/index_spec.rb @@ -36,9 +36,5 @@ describe 'home/index.html.haml', type: "view" do controller.stub(:current_user) { @member } render end - - it 'should say welcome' do - rendered.should have_content "Welcome to #{ENV['GROWSTUFF_SITE_NAME']}, #{@member.login_name}" - end end end