mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-03-29 04:02:17 -04:00
Merge branch 'dev' into app-json-heroku
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
101
app/helpers/buttons_helper.rb
Normal file
101
app/helpers/buttons_helper.rb
Normal file
@@ -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
|
||||
34
app/helpers/icons_helper.rb
Normal file
34
app/helpers/icons_helper.rb
Normal file
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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'
|
||||
|
||||
9
app/views/crops/_search_bar.haml
Normal file
9
app/views/crops/_search_bar.haml
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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?')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
- content_for :title, "New Harvest"
|
||||
- content_for :title, t('harvests.harvest_something')
|
||||
|
||||
= render 'form'
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
\==================================================
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
= content_for :title, "Plant something"
|
||||
= content_for :title, t('plantings.plant_something')
|
||||
|
||||
= render 'form'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
- content_for :title, "Add seeds"
|
||||
- content_for :title, t('seeds.save_seeds')
|
||||
|
||||
= render 'form'
|
||||
|
||||
22
app/views/shared/_global_actions.html.haml
Normal file
22
app/views/shared/_global_actions.html.haml
Normal file
@@ -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'
|
||||
2
app/views/shared/_glyphicon.html.haml
Normal file
2
app/views/shared/_glyphicon.html.haml
Normal file
@@ -0,0 +1,2 @@
|
||||
%span.glyphicon{class: "glyphicon-#{icon}", title: t(title) }
|
||||
=t(title)
|
||||
@@ -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
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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']"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
33
spec/helpers/buttons_helper_spec.rb
Normal file
33
spec/helpers/buttons_helper_spec.rb
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user