mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-05-18 13:38:24 -04:00
Merge branch 'dev' into photos/seeds
This commit is contained in:
@@ -51,7 +51,7 @@ GEM
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.5.2)
|
||||
addressable (2.6.0)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
arel (9.0.0)
|
||||
ast (2.4.0)
|
||||
@@ -80,7 +80,7 @@ GEM
|
||||
uniform_notifier (~> 1.11)
|
||||
byebug (10.0.2)
|
||||
cancancan (2.3.0)
|
||||
capybara (3.12.0)
|
||||
capybara (3.13.0)
|
||||
addressable
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (~> 1.8)
|
||||
@@ -294,7 +294,7 @@ GEM
|
||||
multi_json (1.11.3)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
newrelic_rpm (5.6.0.349)
|
||||
newrelic_rpm (6.0.0.351)
|
||||
nio4r (2.3.1)
|
||||
nokogiri (1.10.1)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
|
||||
1
app.json
1
app.json
@@ -38,7 +38,6 @@
|
||||
},
|
||||
"addons": [
|
||||
"heroku-postgresql",
|
||||
"bonsai-elasticsearch",
|
||||
"memcachier",
|
||||
"newrelic",
|
||||
"sendgrid"
|
||||
|
||||
@@ -54,4 +54,4 @@ $(document).ready(function() {
|
||||
$('.btn.toggle.crop-hierarchy').click(function () {
|
||||
$('.toggle.crop-hierarchy').toggleClass('hide');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -11,7 +11,7 @@ module Charts
|
||||
end
|
||||
|
||||
def harvested_for
|
||||
@crop = Crop.find(params[:crop_id])
|
||||
@crop = Crop.find_by!(slug: params[:crop_slug])
|
||||
render json: Harvest.joins(:plant_part)
|
||||
.where(crop: @crop)
|
||||
.group("plant_parts.name").count(:id)
|
||||
@@ -20,7 +20,7 @@ module Charts
|
||||
private
|
||||
|
||||
def pie_chart_query(field)
|
||||
@crop = Crop.find(params[:crop_id])
|
||||
@crop = Crop.find_by!(slug: params[:crop_slug])
|
||||
render json: Planting.where(crop: @crop)
|
||||
.where.not(field.to_sym => nil)
|
||||
.where.not(field.to_sym => '')
|
||||
|
||||
@@ -49,7 +49,7 @@ class CropsController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
@crop = Crop.includes(:scientific_names, plantings: :photos).find(params[:id])
|
||||
@crop = Crop.includes(:scientific_names, plantings: :photos).find_by!(slug: params[:slug])
|
||||
@posts = @crop.posts.order(created_at: :desc).paginate(page: params[:page])
|
||||
# respond_with(@crop)
|
||||
respond_to do |format|
|
||||
@@ -67,6 +67,7 @@ class CropsController < ApplicationController
|
||||
end
|
||||
|
||||
def edit
|
||||
@crop = Crop.find_by!(slug: params[:slug])
|
||||
@crop.alternate_names.build if @crop.alternate_names.blank?
|
||||
@crop.scientific_names.build if @crop.scientific_names.blank?
|
||||
end
|
||||
@@ -87,6 +88,7 @@ class CropsController < ApplicationController
|
||||
end
|
||||
|
||||
def update
|
||||
@crop = Crop.find_by!(slug: params[:slug])
|
||||
previous_status = @crop.approval_status
|
||||
|
||||
@crop.creator = current_member if previous_status == "pending"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
class FollowsController < ApplicationController
|
||||
before_action :authenticate_member!
|
||||
before_action :set_member, only: %i(index followers)
|
||||
load_and_authorize_resource
|
||||
skip_load_resource only: :create
|
||||
|
||||
# POST /follows
|
||||
def create
|
||||
@follow = current_member.follows.build(followed_id: follow_params[:followed_id])
|
||||
@follow = current_member.follows.build(followed: Member.find(params[:followed]))
|
||||
|
||||
if @follow.save
|
||||
flash[:notice] = "Followed #{@follow.followed.login_name}"
|
||||
@@ -15,19 +15,30 @@ class FollowsController < ApplicationController
|
||||
redirect_back fallback_location: root_path
|
||||
end
|
||||
|
||||
# DELETE /follows/1
|
||||
def destroy
|
||||
@follow = current_member.follows.find(follow_params[:id])
|
||||
unfollowed_name = @follow.followed.login_name
|
||||
@follow = current_member.follows.find(params[:id])
|
||||
@unfollowed = @follow.followed
|
||||
@follow.destroy
|
||||
|
||||
flash[:notice] = "Unfollowed #{unfollowed_name}"
|
||||
redirect_to root_path
|
||||
flash[:notice] = "Unfollowed #{@unfollowed.login_name}"
|
||||
redirect_to @unfollowed
|
||||
end
|
||||
|
||||
def index
|
||||
@follows = @member.followed.paginate(page: params[:page])
|
||||
end
|
||||
|
||||
def followers
|
||||
@followers = @member.followers.paginate(page: params[:page])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_member
|
||||
@member = Member.confirmed.find(params[:member_slug])
|
||||
end
|
||||
|
||||
def follow_params
|
||||
params.permit(:id, :followed_id, :follower_id, :authenticity_token, :_method)
|
||||
params.permit(:id, :followed, :follower)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,9 +7,12 @@ class GardensController < ApplicationController
|
||||
# GET /gardens
|
||||
# GET /gardens.json
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:owner])
|
||||
@owner = Member.find_by(slug: params[:member_slug])
|
||||
@show_all = params[:all] == '1'
|
||||
@gardens = gardens
|
||||
|
||||
@gardens = @gardens.active unless @show_all
|
||||
@gardens = @gardens.where(owner: @owner) if @owner.present?
|
||||
@gardens = @gardens.joins(:owner).order(:name).paginate(page: params[:page])
|
||||
respond_with(@gardens)
|
||||
end
|
||||
|
||||
@@ -57,7 +60,7 @@ class GardensController < ApplicationController
|
||||
def destroy
|
||||
@garden.destroy
|
||||
flash[:notice] = I18n.t('gardens.deleted')
|
||||
redirect_to(gardens_by_owner_path(owner: @garden.owner))
|
||||
redirect_to(member_gardens_path(@garden.owner))
|
||||
end
|
||||
|
||||
private
|
||||
@@ -66,10 +69,4 @@ class GardensController < ApplicationController
|
||||
params.require(:garden).permit(:name, :slug, :description, :active,
|
||||
:location, :latitude, :longitude, :area, :area_unit)
|
||||
end
|
||||
|
||||
def gardens
|
||||
g = @owner ? @owner.gardens : Garden.all
|
||||
g = g.active unless @show_all
|
||||
g.joins(:owner).order(:name).paginate(page: params[:page])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,12 +7,17 @@ class HarvestsController < ApplicationController
|
||||
responders :flash
|
||||
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:owner]) if params[:owner]
|
||||
@crop = Crop.find_by(slug: params[:crop]) if params[:crop]
|
||||
@planting = Planting.find_by(slug: params[:planting_id]) if params[:planting_id]
|
||||
@owner = Member.find_by(slug: params[:member_slug])
|
||||
@crop = Crop.find_by(slug: params[:crop_slug])
|
||||
@planting = Planting.find_by(slug: params[:planting_id])
|
||||
|
||||
@harvests = @harvests.where(owner: @owner) if @owner.present?
|
||||
@harvests = @harvests.where(crop: @crop) if @crop.present?
|
||||
@harvests = @harvests.where(planting: @planting) if @planting.present?
|
||||
@harvests = @harvests.order(harvested_at: :desc).joins(:owner, :crop).paginate(page: params[:page])
|
||||
|
||||
@harvests = harvests
|
||||
@filename = csv_filename
|
||||
|
||||
respond_with(@harvests)
|
||||
end
|
||||
|
||||
@@ -67,23 +72,11 @@ class HarvestsController < ApplicationController
|
||||
.where('(finished_at IS NULL OR finished_at >= ?)', @harvest.harvested_at)
|
||||
end
|
||||
|
||||
def harvests
|
||||
if @owner
|
||||
@owner.harvests
|
||||
elsif @crop
|
||||
@crop.harvests
|
||||
elsif @planting
|
||||
@planting.harvests
|
||||
else
|
||||
Harvest.all
|
||||
end.order(harvested_at: :desc).joins(:owner, :crop).paginate(page: params[:page])
|
||||
end
|
||||
|
||||
def csv_filename
|
||||
specifics = if @owner
|
||||
"#{@owner.login_name}-"
|
||||
"#{@owner.to_param}-"
|
||||
elsif @crop
|
||||
"#{@crop.name}-"
|
||||
"#{@crop.to_param}-"
|
||||
end
|
||||
"Growstuff-#{specifics}Harvests-#{Time.zone.now.to_s(:number)}.csv"
|
||||
end
|
||||
|
||||
@@ -13,7 +13,7 @@ class MembersController < ApplicationController
|
||||
end
|
||||
|
||||
def show
|
||||
@member = Member.confirmed.find(params[:id])
|
||||
@member = Member.confirmed.find_by!(slug: params[:slug])
|
||||
@twitter_auth = @member.auth('twitter')
|
||||
@flickr_auth = @member.auth('flickr')
|
||||
@facebook_auth = @member.auth('facebook')
|
||||
@@ -38,16 +38,6 @@ class MembersController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def view_follows
|
||||
@member = Member.confirmed.find(params[:login_name])
|
||||
@follows = @member.followed.paginate(page: params[:page])
|
||||
end
|
||||
|
||||
def view_followers
|
||||
@member = Member.confirmed.find(params[:login_name])
|
||||
@followers = @member.followers.paginate(page: params[:page])
|
||||
end
|
||||
|
||||
EMAIL_TYPE_STRING = {
|
||||
send_notification_email: "direct message notifications",
|
||||
send_planting_reminder: "planting reminders"
|
||||
|
||||
@@ -27,7 +27,7 @@ class NotificationsController < ApplicationController
|
||||
# GET /notifications/1/reply
|
||||
def reply
|
||||
@notification = Notification.new
|
||||
@sender_notification = Notification.find_by(id: params[:id], recipient: current_member)
|
||||
@sender_notification = Notification.find_by!(id: params[:notification_id], recipient: current_member)
|
||||
@sender_notification.read = true
|
||||
@sender_notification.save
|
||||
@recipient = @sender_notification.sender
|
||||
|
||||
@@ -10,17 +10,20 @@ class PlantingsController < ApplicationController
|
||||
responders :flash
|
||||
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:owner]) if params[:owner]
|
||||
@crop = Crop.find_by(slug: params[:crop]) if params[:crop]
|
||||
@owner = Member.find_by(slug: params[:member_slug]) if params[:member_slug]
|
||||
@crop = Crop.find_by(slug: params[:crop_slug]) if params[:crop_slug]
|
||||
|
||||
@show_all = params[:all] == '1'
|
||||
|
||||
@plantings = plantings
|
||||
@plantings = @plantings.where(owner: @owner) if @owner.present?
|
||||
@plantings = @plantings.where(crop: @crop) if @crop.present?
|
||||
|
||||
specifics = if @owner
|
||||
"#{@owner.login_name}-"
|
||||
elsif @crop
|
||||
"#{@crop.name}-"
|
||||
end
|
||||
@plantings = @plantings.active unless params[:all] == '1'
|
||||
|
||||
@plantings = @plantings.joins(:owner, :crop, :garden)
|
||||
.order(created_at: :desc)
|
||||
.includes(:crop, :owner, :garden)
|
||||
.paginate(page: params[:page])
|
||||
|
||||
@filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_s(:number)}.csv"
|
||||
|
||||
@@ -104,4 +107,12 @@ class PlantingsController < ApplicationController
|
||||
.includes(:crop, :owner, :garden)
|
||||
.paginate(page: params[:page])
|
||||
end
|
||||
|
||||
def specifics
|
||||
if @owner.present?
|
||||
"#{@owner.to_param}-"
|
||||
elsif @crop.present?
|
||||
"#{@crop.to_param}-"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,9 +8,13 @@ class SeedsController < ApplicationController
|
||||
# GET /seeds
|
||||
# GET /seeds.json
|
||||
def index
|
||||
@owner = Member.find_by(slug: params[:owner])
|
||||
@crop = Crop.find_by(slug: params[:crop])
|
||||
@seeds = seeds(owner: @owner, crop: @crop)
|
||||
@owner = Member.find_by(slug: params[:member_slug]) if params[:member_slug].present?
|
||||
@crop = Crop.find_by(slug: params[:crop_slug]) if params[:crop_slug].present?
|
||||
|
||||
@seeds = @seeds.where(owner: @owner) if @owner.present?
|
||||
@seeds = @seeds.where(crop: @crop) if @crop.present?
|
||||
@seeds = @seeds.order(created_at: :desc).includes(:owner, :crop).paginate(page: params[:page])
|
||||
|
||||
@filename = csv_filename
|
||||
|
||||
respond_with(@seeds)
|
||||
@@ -65,19 +69,9 @@ class SeedsController < ApplicationController
|
||||
)
|
||||
end
|
||||
|
||||
def seeds(owner: nil, crop: nil)
|
||||
if owner
|
||||
owner.seeds
|
||||
elsif crop
|
||||
crop.seeds
|
||||
else
|
||||
Seed
|
||||
end.order(created_at: :desc).includes(:owner, :crop).paginate(page: params[:page])
|
||||
end
|
||||
|
||||
def csv_filename
|
||||
if @owner
|
||||
"Growstuff-#{@owner}-Seeds-#{Time.zone.now.to_s(:number)}.csv"
|
||||
"Growstuff-#{@owner.to_param}-Seeds-#{Time.zone.now.to_s(:number)}.csv"
|
||||
else
|
||||
"Growstuff-Seeds-#{Time.zone.now.to_s(:number)}.csv"
|
||||
end
|
||||
|
||||
@@ -70,8 +70,8 @@ module ApplicationHelper
|
||||
def show_inactive_tickbox_path(type, owner, show_all)
|
||||
all = show_all ? '' : 1
|
||||
if owner
|
||||
return plantings_by_owner_path(owner: owner.slug, all: all) if type == 'plantings'
|
||||
return gardens_by_owner_path(owner: owner.slug, all: all) if type == 'gardens'
|
||||
return member_plantings_path(owner, all: all) if type == 'plantings'
|
||||
return member_gardens_path(owner, all: all) if type == 'gardens'
|
||||
end
|
||||
|
||||
return plantings_path(all: all) if type == 'plantings'
|
||||
|
||||
@@ -10,7 +10,7 @@ module AutoSuggestHelper
|
||||
end
|
||||
|
||||
resource = resource.class.name.downcase
|
||||
source_path = Rails.application.routes.url_helpers.send("#{source}s_search_path")
|
||||
source_path = Rails.application.routes.url_helpers.send("search_#{source}s_path")
|
||||
|
||||
%(
|
||||
<input id="#{source}" class="auto-suggest #{options[:class]}"
|
||||
|
||||
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
|
||||
@@ -5,7 +5,7 @@ module NotificationsHelper
|
||||
new_comment_url(post_id: notification.post.id)
|
||||
else
|
||||
# by default, reply link sends a PM in return
|
||||
reply_notification_url(notification)
|
||||
notification_reply_url(notification)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -113,6 +113,10 @@ class Crop < ApplicationRecord
|
||||
name
|
||||
end
|
||||
|
||||
def to_param
|
||||
slug
|
||||
end
|
||||
|
||||
def default_scientific_name
|
||||
scientific_names.first.name unless scientific_names.empty?
|
||||
end
|
||||
@@ -155,12 +159,7 @@ class Crop < ApplicationRecord
|
||||
end
|
||||
|
||||
def interesting?
|
||||
min_plantings = 3 # needs this many plantings to be interesting
|
||||
min_photos = 3 # needs this many photos to be interesting
|
||||
return false unless photos.size >= min_photos
|
||||
return false unless plantings_count >= min_plantings
|
||||
|
||||
true
|
||||
photos.size >= 3 || plantings_count >= 3
|
||||
end
|
||||
|
||||
def pending?
|
||||
|
||||
@@ -18,8 +18,9 @@ class Garden < ApplicationRecord
|
||||
scope :active, -> { where(active: true) }
|
||||
scope :inactive, -> { where(active: false) }
|
||||
|
||||
validates :location,
|
||||
length: { maximum: 255 }
|
||||
validates :location, length: { maximum: 255 }
|
||||
validates :slug, uniqueness: true
|
||||
validates :name, uniqueness: { scope: :owner_id }
|
||||
|
||||
validates :name,
|
||||
format: {
|
||||
|
||||
@@ -106,6 +106,10 @@ class Member < ApplicationRecord
|
||||
login_name
|
||||
end
|
||||
|
||||
def to_param
|
||||
slug
|
||||
end
|
||||
|
||||
def role?(role_sym)
|
||||
roles.any? { |r| r.name.gsub(/\s+/, "_").underscore.to_sym == role_sym }
|
||||
end
|
||||
|
||||
@@ -33,6 +33,7 @@ class Planting < ApplicationRecord
|
||||
##
|
||||
## Scopes
|
||||
default_scope { joins(:owner) } # Ensures the owner still exists
|
||||
scope :active, -> { where(finished_at: nil) }
|
||||
scope :interesting, -> { has_photos.one_per_owner.order(planted_at: :desc) }
|
||||
scope :recent, -> { order(created_at: :desc) }
|
||||
scope :one_per_owner, lambda {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
= link_to "#{seed.owner} will trade #{seed.tradable_to}.", seed_path(seed)
|
||||
= render partial: 'members/location', locals: { member: seed.owner }
|
||||
%p
|
||||
= link_to "View all #{crop.name} seeds", seeds_by_crop_path(crop)
|
||||
= link_to "View all #{crop.name} seeds", crop_seeds_path(crop)
|
||||
%p
|
||||
= link_to "Purchase seeds via Ebay",
|
||||
crop_ebay_seeds_url(crop),
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
= distance_of_time_in_words(harvest.created_at, Time.zone.now)
|
||||
ago.
|
||||
%p
|
||||
= link_to "View all #{crop.name} harvests", harvests_by_crop_path(crop)
|
||||
= link_to "View all #{crop.name} harvests", crop_harvests_path(crop)
|
||||
- if crop.approved?
|
||||
- if current_member
|
||||
%p= link_to "Harvest #{crop.name}", new_harvest_path(crop_id: crop.id)
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
.col-xs-6.col-md-2
|
||||
= render "photos/thumbnail", photo: p
|
||||
.row
|
||||
= link_to "more photos", crop_photos_path(crop_id: crop.id)
|
||||
= link_to "more photos", crop_photos_path(crop)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
= distance_of_time_in_words(planting.created_at, Time.zone.now)
|
||||
ago.
|
||||
%p
|
||||
= link_to "View all #{crop.name} plantings", plantings_by_crop_path(crop)
|
||||
= link_to "View all #{crop.name} plantings", crop_plantings_path(crop)
|
||||
- if crop.approved?
|
||||
- if current_member
|
||||
%p= link_to "Plant #{crop.name}", new_planting_path(crop_id: crop.id)
|
||||
|
||||
9
app/views/crops/_search_bar.haml
Normal file
9
app/views/crops/_search_bar.haml
Normal file
@@ -0,0 +1,9 @@
|
||||
= form_tag search_crops_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
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
things to consider when suggesting a new crop:
|
||||
%ul
|
||||
%li
|
||||
First, you might want to #{link_to 'search our crops', crops_search_path}
|
||||
First, you might want to #{link_to 'search our crops', search_crops_path}
|
||||
to make sure we don't have it already, perhaps under an alternate name.
|
||||
%li
|
||||
The Growstuff database only contains edible crops. In future we hope to
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
- content_for :title, "Crop search"
|
||||
|
||||
%div
|
||||
= form_tag crops_search_path, method: :get, id: 'crop-search', class: 'form-inline' do
|
||||
= form_tag search_crops_path, method: :get, id: 'crop-search', class: 'form-inline' do
|
||||
.form-group
|
||||
= label_tag :term, "Search crops:", class: 'sr-only'
|
||||
= text_field_tag 'term', nil,
|
||||
|
||||
@@ -21,9 +21,6 @@
|
||||
.col-md-9
|
||||
.row
|
||||
.col-md-12
|
||||
- if member_signed_in?
|
||||
= display_seed_availability(@current_member, @crop)
|
||||
= link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug)
|
||||
|
||||
%h2
|
||||
- if !@crop.plantings.empty?
|
||||
@@ -34,7 +31,6 @@
|
||||
- else
|
||||
Nobody is growing this yet. You could be the first!
|
||||
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
%h2 Predictions
|
||||
@@ -47,14 +43,13 @@
|
||||
.row
|
||||
.col-md-3
|
||||
%h2 Sunniness
|
||||
= pie_chart crop_sunniness_path(@crop), legend: "bottom"
|
||||
|
||||
= pie_chart crop_sunniness_path(@crop, format: :json), legend: "bottom"
|
||||
.col-md-3
|
||||
%h2 Planted from
|
||||
= pie_chart crop_planted_from_path(@crop), legend: "bottom"
|
||||
= pie_chart crop_planted_from_path(@crop, format: :json), legend: "bottom"
|
||||
.col-md-3
|
||||
%h2 Harvested for
|
||||
= pie_chart crop_harvested_for_path(@crop), legend: "bottom"
|
||||
= pie_chart crop_harvested_for_path(@crop, format: :json), legend: "bottom"
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
@@ -92,6 +87,24 @@
|
||||
|
||||
= render partial: 'wrangle', locals: { crop: @crop }
|
||||
|
||||
%p
|
||||
%li
|
||||
= link_to crop_seeds_path(@crop) do
|
||||
View all #{@crop.name} seeds
|
||||
(#{@crop.seeds.size})
|
||||
%li
|
||||
= link_to crop_plantings_path(@crop) do
|
||||
View all #{@crop.name} plantings
|
||||
(#{@crop.plantings.size})
|
||||
%li
|
||||
= link_to crop_harvests_path(@crop) do
|
||||
View all #{@crop.name} harvests
|
||||
(#{@crop.harvests.size})
|
||||
- if member_signed_in?
|
||||
%p
|
||||
= link_to member_seeds_path(current_member, crop_slug: @crop.slug) do
|
||||
= display_seed_availability(@current_member, @crop)
|
||||
|
||||
%h4 How to grow #{@crop.name.pluralize}
|
||||
|
||||
= render 'grown_for', crop: @crop
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
%li= link_to "Requests for new crops", 'http://growstuff.org/posts/skud-20130319-requests-for-new-crops'
|
||||
%li= link_to "Crop wrangler guidelines", "http://wiki.growstuff.org/index.php/Crop_wrangling"
|
||||
%li= link_to "crop-wranglers mailing list", "http://lists.growstuff.org/listinfo/crop-wranglers"
|
||||
%li= link_to "Full crop hierarchy", crops_hierarchy_path
|
||||
%li= link_to "Full crop hierarchy", hierarchy_crops_path
|
||||
%li= link_to "Add Crop", new_crop_path
|
||||
|
||||
.crop_wranglers
|
||||
|
||||
@@ -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?')
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
- content_for :buttonbar do
|
||||
- if current_member
|
||||
= link_to 'My Gardens', gardens_by_owner_path(owner: current_member.slug), class: 'btn btn-default'
|
||||
|
||||
= link_to "Everyone's gardens", gardens_path, class: 'btn btn-default'
|
||||
|
||||
- if can?(:create, Garden)
|
||||
= link_to 'Add a garden', new_garden_path, class: 'btn btn-default'
|
||||
- unless current_member
|
||||
= render 'shared/signin_signup', to: 'add a new garden'
|
||||
@@ -1,6 +1,6 @@
|
||||
- content_for :title, @owner ? "#{@owner}'s gardens" : "Everyone's gardens"
|
||||
|
||||
= render 'nav'
|
||||
= render 'layouts/nav', model: Garden
|
||||
|
||||
= link_to gardens_active_tickbox_path(@owner, @show_all) do
|
||||
= check_box_tag 'active', 'all', @show_all
|
||||
|
||||
@@ -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,15 +0,0 @@
|
||||
%p
|
||||
- if can? :create, Harvest
|
||||
- if @planting && @planting.owner == current_member
|
||||
= link_to 'Add harvest', new_planting_harvest_path(planting: @planting), class: 'btn btn-primary'
|
||||
- elsif @owner
|
||||
%p
|
||||
- if @owner == current_member
|
||||
= link_to 'Add harvest', new_harvest_path, class: 'btn btn-primary'
|
||||
= link_to "View everyone's harvests", harvests_path, class: 'btn btn-default'
|
||||
- else # everyone's harvests
|
||||
= link_to 'Add harvest', new_harvest_path, class: 'btn btn-primary'
|
||||
- if current_member
|
||||
= link_to 'View your harvests', harvests_by_owner_path(owner: current_member.slug), class: 'btn btn-default'
|
||||
- else
|
||||
= render partial: 'shared/signin_signup', locals: { to: 'track your harvests' }
|
||||
@@ -7,7 +7,8 @@
|
||||
#{ENV['GROWSTUFF_SITE_NAME']} helps you track what you're
|
||||
harvesting from your home garden and see how productive it is.
|
||||
|
||||
= render "nav"
|
||||
= render 'layouts/nav', model: Harvest
|
||||
|
||||
.pagination
|
||||
= page_entries_info @harvests
|
||||
= will_paginate @harvests
|
||||
@@ -24,9 +25,9 @@
|
||||
%ul.list-inline
|
||||
%li The data on this page is available in the following formats:
|
||||
- if @owner
|
||||
%li= link_to "RSS", harvests_by_owner_path(@owner, format: 'rss')
|
||||
%li= link_to "CSV", harvests_by_owner_path(@owner, format: 'csv')
|
||||
%li= link_to "JSON", harvests_by_owner_path(@owner, format: 'json')
|
||||
%li= link_to "RSS", member_harvests_path(@owner, format: 'rss')
|
||||
%li= link_to "CSV", member_harvests_path(@owner, format: 'csv')
|
||||
%li= link_to "JSON", member_harvests_path(@owner, format: 'json')
|
||||
- else
|
||||
%li= link_to "RSS", harvests_path(format: 'rss')
|
||||
%li= link_to "CSV", harvests_path(format: 'csv')
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
- content_for :title, "New Harvest"
|
||||
- content_for :title, t('harvests.harvest_something')
|
||||
|
||||
= render 'form'
|
||||
|
||||
@@ -8,13 +8,16 @@
|
||||
= 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
|
||||
%b Owner:
|
||||
= link_to @harvest.owner, @harvest.owner
|
||||
—
|
||||
= link_to "view all #{@harvest.owner}'s harvests", harvests_by_owner_path(owner: @harvest.owner.slug)
|
||||
= link_to "view all #{@harvest.owner}'s harvests", member_harvests_path(@harvest.owner)
|
||||
%p
|
||||
%b Plant part:
|
||||
- if @harvest.plant_part
|
||||
@@ -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
|
||||
@@ -58,11 +50,11 @@
|
||||
%b.caret
|
||||
%ul.dropdown-menu
|
||||
%li= link_to t('.profile'), member_path(current_member)
|
||||
%li= link_to t('.gardens'), gardens_by_owner_path(owner: current_member.slug)
|
||||
%li= link_to t('.plantings'), plantings_by_owner_path(owner: current_member.slug)
|
||||
%li= link_to t('.harvest'), harvests_by_owner_path(owner: current_member.slug)
|
||||
%li= link_to t('.seeds'), seeds_by_owner_path(owner: current_member.slug)
|
||||
%li= link_to t('.posts'), posts_by_author_path(author: current_member.slug)
|
||||
%li= link_to t('.gardens'), member_gardens_path(current_member)
|
||||
%li= link_to t('.plantings'), member_plantings_path(current_member)
|
||||
%li= link_to t('.harvest'), member_harvests_path(current_member)
|
||||
%li= link_to t('.seeds'), member_seeds_path(current_member)
|
||||
%li= link_to t('.posts'), member_posts_path(current_member)
|
||||
%li
|
||||
- if current_member.notifications.unread_count.positive?
|
||||
= link_to(t('.inbox_unread', unread_count: current_member.notifications.unread_count),
|
||||
|
||||
14
app/views/layouts/_nav.haml
Normal file
14
app/views/layouts/_nav.haml
Normal file
@@ -0,0 +1,14 @@
|
||||
- content_for :buttonbar do
|
||||
- if current_member.present?
|
||||
= link_to url_for([current_member, model]), class: 'btn btn-default' do
|
||||
My #{model.model_name.human.pluralize}
|
||||
|
||||
= link_to model, class: 'btn btn-default' do
|
||||
Everyone's #{model.model_name.human.pluralize}
|
||||
|
||||
- if can?(:create, model)
|
||||
= link_to url_for([model, action: :new]), class: 'btn btn-default' do
|
||||
Add a #{model.model_name.human}
|
||||
|
||||
- unless current_member
|
||||
= render 'shared/signin_signup', to: 'add a new seed'
|
||||
@@ -7,20 +7,27 @@
|
||||
|
||||
#maincontainer
|
||||
.row
|
||||
.col-md-12
|
||||
.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)
|
||||
.btn-group.layout-actions
|
||||
= yield(:buttonbar)
|
||||
|
||||
.col-md-6
|
||||
= render 'shared/global_actions'
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
= render partial: "shared/flash_messages", flash: flash
|
||||
= yield
|
||||
|
||||
%footer
|
||||
= render partial: "layouts/footer"
|
||||
= render "layouts/footer"
|
||||
/
|
||||
Javascripts
|
||||
\==================================================
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
- if member.location.blank?
|
||||
unknown location
|
||||
- else
|
||||
= link_to member.location, place_path(place: member.location, anchor: "members")
|
||||
= link_to member.location, place_path(member.location, anchor: "members")
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
%ul.activity-list
|
||||
%li
|
||||
- if !member.plantings.empty?
|
||||
= link_to localize_plural(member.plantings, Planting), plantings_by_owner_path(owner: member)
|
||||
= link_to localize_plural(member.plantings, Planting), member_plantings_path(member)
|
||||
- else
|
||||
0 plantings
|
||||
%li
|
||||
- if !member.harvests.empty?
|
||||
= link_to localize_plural(member.harvests, Harvest), harvests_by_owner_path(owner: member)
|
||||
= link_to localize_plural(member.harvests, Harvest), member_harvests_path(member)
|
||||
- else
|
||||
0 harvests
|
||||
%li
|
||||
- if !member.seeds.empty?
|
||||
= link_to localize_plural(member.seeds, Seed), seeds_by_owner_path(owner: member)
|
||||
= link_to localize_plural(member.seeds, Seed), member_seeds_path(member)
|
||||
- else
|
||||
0 seeds
|
||||
%li
|
||||
- if !member.posts.empty?
|
||||
= link_to localize_plural(member.posts, Post), posts_by_author_path(author: member)
|
||||
= link_to localize_plural(member.posts, Post), member_posts_path(member)
|
||||
- else
|
||||
0 posts
|
||||
|
||||
|
||||
@@ -7,16 +7,22 @@
|
||||
= 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)
|
||||
- if !follow && can?(:create, Follow) # not already following
|
||||
= link_to 'Follow', follows_path(followed_id: @member.id), method: :post, class: 'btn btn-default pull-right'
|
||||
= link_to 'Follow', follows_path(followed: @member), method: :post, class: 'btn btn-default pull-right'
|
||||
- if follow && can?(:destroy, follow) # already following
|
||||
= link_to 'Unfollow', follow_path(follow), method: :delete, class: 'btn btn-default pull-right'
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
- if can?(:edit, @photo) && can?(:destroy, @photo)
|
||||
%p
|
||||
- if can?(:edit, @photo)
|
||||
= render 'shared/buttons/edit', path: edit_photo_path(@photo)
|
||||
= edit_button(@photo)
|
||||
- if can?(:destroy, @photo)
|
||||
= render 'shared/buttons/delete', path: photo_path(@photo)
|
||||
= delete_button(@photo)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
- if can? :edit, photo
|
||||
= link_to photo_associations_path(photo_id: photo.id, type: type, id: thing.id),
|
||||
method: 'delete', class: 'btn btn-default btn-xs' do
|
||||
%span.glyphicon.glyphicon-remove{ title: "Remove link" }
|
||||
= delete_icon
|
||||
|
||||
@@ -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,17 +0,0 @@
|
||||
|
||||
- content_for :buttonbar do
|
||||
- if current_member
|
||||
= link_to 'My Plantings', plantings_by_owner_path(owner: current_member.slug), class: 'btn btn-default'
|
||||
- if owner && owner != current_member
|
||||
= link_to "#{owner.login_name}'s Plantings", plantings_by_owner_path(owner: owner.slug), class: 'btn btn-default'
|
||||
= link_to "Everyone's plantings", plantings_path, class: 'btn btn-default'
|
||||
|
||||
= link_to plantings_active_tickbox_path(@owner, show_all) do
|
||||
= check_box_tag 'active', 'all', show_all
|
||||
include in-active
|
||||
|
||||
- if current_member
|
||||
- if can? :create, Planting
|
||||
= link_to 'Plant something', new_planting_path, class: 'btn btn-primary'
|
||||
- else
|
||||
= render partial: 'shared/signin_signup', locals: { to: "track what you've planted" }
|
||||
@@ -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,6 +1,10 @@
|
||||
- content_for :title, title('plantings', @owner, @crop, @planting)
|
||||
|
||||
= render 'nav', owner: @owner, show_all: @show_all
|
||||
= render 'layouts/nav', model: Planting
|
||||
|
||||
= link_to plantings_active_tickbox_path(@owner, @show_all) do
|
||||
= check_box_tag 'active', 'all', @show_all
|
||||
include in-active
|
||||
|
||||
- if @owner
|
||||
= link_to t('.view_owners_profile', owner: @owner), member_path(@owner)
|
||||
@@ -23,4 +27,4 @@
|
||||
%li= t('.the_data_on_this_page_is_available_in_the_following_formats')
|
||||
- ['csv', 'json', 'rss'].each do |format|
|
||||
%li= link_to format.upcase,
|
||||
(@owner ? plantings_by_owner_path(@owner, format: format) : plantings_path(format: format))
|
||||
(@owner ? member_plantings_path(@owner, format: format) : plantings_path(format: format))
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
= content_for :title, "Plant something"
|
||||
= content_for :title, t('plantings.plant_something')
|
||||
|
||||
= render 'form'
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
%dd
|
||||
= link_to @planting.owner, @planting.owner
|
||||
—
|
||||
= link_to "view all #{@planting.owner}'s plantings", plantings_by_owner_path(owner: @planting.owner.slug)
|
||||
= link_to "view all #{@planting.owner}'s plantings", member_plantings_path(@planting.owner)
|
||||
|
||||
%dt Planted on:
|
||||
%dd= @planting.planted_at ? @planting.planted_at : "not specified"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
- else # everyone's posts
|
||||
= link_to 'Post something', new_post_path, class: 'btn btn-primary'
|
||||
- if current_member
|
||||
= link_to 'View your posts', posts_by_author_path(author: current_member.slug), class: 'btn btn-default'
|
||||
= link_to 'View your posts', member_posts_path(current_member), class: 'btn btn-default'
|
||||
- else
|
||||
= render partial: 'shared/signin_signup', locals: { to: 'write a post' }
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
- if @author
|
||||
Subscribe to
|
||||
= succeed "." do
|
||||
= link_to "#{@author}'s posts RSS feed", posts_by_author_path(format: 'rss', author: @author)
|
||||
= link_to "#{@author}'s posts RSS feed", member_posts_path(@author, format: 'rss')
|
||||
|
||||
- else
|
||||
Subscribe to the #{ENV['GROWSTUFF_SITE_NAME']}
|
||||
|
||||
@@ -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,4 +1,5 @@
|
||||
- content_for :title, title('seeds', @owner, @crop, @planting)
|
||||
|
||||
- if @owner
|
||||
= link_to "View #{@owner}'s profile >>", member_path(@owner)
|
||||
|
||||
@@ -6,19 +7,7 @@
|
||||
#{ENV['GROWSTUFF_SITE_NAME']} helps you track your seed
|
||||
stash or trade seeds with other members.
|
||||
|
||||
%p
|
||||
- if can? :create, Seed
|
||||
- if @owner
|
||||
%p
|
||||
- if @owner == current_member
|
||||
= link_to 'Add seeds', new_seed_path, class: 'btn btn-primary'
|
||||
= link_to "View everyone's seeds", seeds_path, class: 'btn btn-default'
|
||||
- else # everyone's seeds
|
||||
= link_to 'Add seeds', new_seed_path, class: 'btn btn-primary'
|
||||
- if current_member
|
||||
= link_to 'View your seeds', seeds_by_owner_path(owner: current_member.slug), class: 'btn btn-default'
|
||||
- else
|
||||
= render partial: 'shared/signin_signup', locals: { to: 'add seeds to your stash' }
|
||||
= render 'layouts/nav', model: Seed
|
||||
|
||||
.pagination
|
||||
= page_entries_info @seeds
|
||||
@@ -37,9 +26,9 @@
|
||||
%ul.list-inline
|
||||
%li The data on this page is available in the following formats:
|
||||
- if @owner
|
||||
%li= link_to "CSV", seeds_by_owner_path(@owner, format: 'csv')
|
||||
%li= link_to "JSON", seeds_by_owner_path(@owner, format: 'json')
|
||||
%li= link_to "RSS", seeds_by_owner_path(@owner, format: 'rss')
|
||||
%li= link_to "CSV", member_seeds_path(@owner, format: 'csv')
|
||||
%li= link_to "JSON", member_seeds_path(@owner, format: 'json')
|
||||
%li= link_to "RSS", member_seeds_path(@owner, format: 'rss')
|
||||
- else
|
||||
%li= link_to "CSV", seeds_path(format: 'csv')
|
||||
%li= link_to "JSON", seeds_path(format: 'json')
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
- content_for :title, "Add seeds"
|
||||
- content_for :title, t('seeds.save_seeds')
|
||||
|
||||
= render 'form'
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
= link_to @seed.owner, @seed.owner
|
||||
—
|
||||
= link_to "view all #{@seed.owner}'s seeds",
|
||||
seeds_by_owner_path(owner: @seed.owner.slug)
|
||||
member_seeds_path(@seed.owner)
|
||||
%dt Quantity:
|
||||
%dd= @seed.quantity.blank? ? "not specified" : @seed.quantity
|
||||
%dt Plant before:
|
||||
|
||||
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 member_gardens_path(current_member), 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
|
||||
@@ -31,13 +31,6 @@ RAILS_SECRET_TOKEN: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
# name that appears on the site, eg. in page titles
|
||||
GROWSTUFF_SITE_NAME: Growstuff (dev)
|
||||
|
||||
# Mandrill is used to send transactional email (eg. signup
|
||||
# confirmations). If using Heroku connect to Mandrill via Heroku addons
|
||||
# list then go to tools menu (upper right) and choose "SMTP and API
|
||||
# Credentials"
|
||||
GROWSTUFF_MANDRILL_USERNAME: "dummy"
|
||||
GROWSTUFF_MANDRILL_APIKEY: "dummy"
|
||||
|
||||
# Mailchimp is used for subscribing/unsubscribing people from the newsletter
|
||||
# To fetch list IDs using Gibbon (and thus find the ID of your newsletter):
|
||||
# $ rails c
|
||||
|
||||
@@ -63,13 +63,6 @@ Rails.application.configure do
|
||||
config.action_mailer.default_url_options = { host: 'localhost:3000' }
|
||||
|
||||
config.action_mailer.delivery_method = :letter_opener
|
||||
config.action_mailer.smtp_settings = {
|
||||
port: '587',
|
||||
address: 'smtp.mandrillapp.com',
|
||||
user_name: ENV['GROWSTUFF_MANDRILL_USERNAME'],
|
||||
password: ENV['GROWSTUFF_MANDRILL_APIKEY'],
|
||||
authentication: :login
|
||||
}
|
||||
|
||||
config.host = 'localhost:3000'
|
||||
config.analytics_code = ''
|
||||
|
||||
@@ -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:
|
||||
|
||||
121
config/routes.rb
121
config/routes.rb
@@ -1,8 +1,6 @@
|
||||
Rails.application.routes.draw do
|
||||
get '/robots.txt' => 'robots#robots'
|
||||
|
||||
resources :plant_parts
|
||||
|
||||
devise_for :members, controllers: {
|
||||
registrations: "registrations",
|
||||
passwords: "passwords",
|
||||
@@ -14,84 +12,105 @@ Rails.application.routes.draw do
|
||||
end
|
||||
match '/members/:id/finish_signup' => 'members#finish_signup', via: %i(get patch), as: :finish_signup
|
||||
|
||||
resources :members
|
||||
|
||||
resources :photos
|
||||
delete 'photo_associations' => 'photo_associations#destroy'
|
||||
|
||||
resources :authentications, only: %i(create destroy)
|
||||
|
||||
resources :plantings do
|
||||
get "home/index"
|
||||
root to: 'home#index'
|
||||
|
||||
concern :has_photos do
|
||||
resources :photos, only: :index
|
||||
end
|
||||
|
||||
resources :gardens, concerns: :has_photos do
|
||||
get 'timeline' => 'charts/gardens#timeline', constraints: { format: 'json' }
|
||||
end
|
||||
|
||||
resources :plantings, concerns: :has_photos do
|
||||
resources :harvests
|
||||
resources :seeds
|
||||
collection do
|
||||
get 'crop/:crop' => 'plantings#index', as: 'plantings_by_crop'
|
||||
end
|
||||
end
|
||||
get '/plantings/owner/:owner' => 'plantings#index', as: 'plantings_by_owner'
|
||||
get '/plantings/crop/:crop' => 'plantings#index', as: 'plantings_by_crop'
|
||||
|
||||
resources :gardens do
|
||||
get 'timeline' => 'charts/gardens#timeline'
|
||||
end
|
||||
get '/gardens/owner/:owner' => 'gardens#index', as: 'gardens_by_owner'
|
||||
|
||||
resources :seeds do
|
||||
resources :seeds, concerns: :has_photos do
|
||||
resources :plantings
|
||||
get 'crop/:crop' => 'seeds#index', as: 'seeds_by_crop', on: :collection
|
||||
end
|
||||
get '/seeds/owner/:owner' => 'seeds#index', as: 'seeds_by_owner'
|
||||
get '/seeds/crop/:crop' => 'seeds#index', as: 'seeds_by_crop'
|
||||
|
||||
resources :harvests
|
||||
get '/harvests/owner/:owner' => 'harvests#index', as: 'harvests_by_owner'
|
||||
get '/harvests/crop/:crop' => 'harvests#index', as: 'harvests_by_crop'
|
||||
resources :harvests, concerns: :has_photos do
|
||||
get 'crop/:crop' => 'harvests#index', as: 'harvests_by_crop', on: :collection
|
||||
end
|
||||
|
||||
resources :posts
|
||||
get '/posts/author/:author' => 'posts#index', as: 'posts_by_author'
|
||||
resources :posts do
|
||||
get 'author/:author' => 'posts#index', as: 'by_author', on: :collection
|
||||
end
|
||||
|
||||
resources :scientific_names
|
||||
resources :alternate_names
|
||||
resources :plant_parts
|
||||
resources :photos
|
||||
|
||||
get 'crops/requested' => 'crops#requested', as: 'requested_crops'
|
||||
get 'crops/wrangle' => 'crops#wrangle', as: 'wrangle_crops'
|
||||
get 'crops/hierarchy' => 'crops#hierarchy', as: 'crops_hierarchy'
|
||||
get 'crops/search' => 'crops#search', as: 'crops_search'
|
||||
resources :crops do
|
||||
get 'photos' => 'photos#index'
|
||||
get 'sunniness' => 'charts/crops#sunniness'
|
||||
get 'planted_from' => 'charts/crops#planted_from'
|
||||
get 'harvested_for' => 'charts/crops#harvested_for'
|
||||
delete 'photo_associations' => 'photo_associations#destroy'
|
||||
|
||||
resources :crops, param: :slug, concerns: :has_photos do
|
||||
get 'gardens' => 'gardens#index'
|
||||
get 'harvests' => 'harvests#index'
|
||||
get 'plantings' => 'plantings#index'
|
||||
get 'seeds' => 'seeds#index'
|
||||
|
||||
get 'places' => 'places#index'
|
||||
get 'members' => 'members#index'
|
||||
|
||||
# Charts json
|
||||
get 'sunniness' => 'charts/crops#sunniness', constraints: { format: 'json' }
|
||||
get 'planted_from' => 'charts/crops#planted_from', constraints: { format: 'json' }
|
||||
get 'harvested_for' => 'charts/crops#harvested_for', constraints: { format: 'json' }
|
||||
|
||||
collection do
|
||||
get 'requested'
|
||||
get 'wrangle'
|
||||
get 'hierarchy'
|
||||
get 'search'
|
||||
end
|
||||
end
|
||||
|
||||
resources :comments
|
||||
resources :roles
|
||||
resources :forums
|
||||
resources :notifications do
|
||||
get 'reply', on: :member
|
||||
end
|
||||
|
||||
resources :follows, only: %i(create destroy)
|
||||
get '/members/:login_name/follows' => 'members#view_follows', as: 'member_follows'
|
||||
get '/members/:login_name/followers' => 'members#view_followers', as: 'member_followers'
|
||||
|
||||
get '/places' => 'places#index'
|
||||
get '/places/search' => 'places#search', as: 'search_places'
|
||||
get '/places/:place' => 'places#show', as: 'place'
|
||||
|
||||
resources :likes, only: %i(create destroy)
|
||||
|
||||
get "home/index"
|
||||
root to: 'home#index'
|
||||
resources :members, param: :slug do
|
||||
resources :gardens
|
||||
resources :seeds
|
||||
resources :plantings
|
||||
resources :harvests
|
||||
resources :posts
|
||||
|
||||
resources :follows
|
||||
get 'followers' => 'follows#followers'
|
||||
end
|
||||
|
||||
resources :notifications do
|
||||
get 'reply'
|
||||
end
|
||||
|
||||
resources :places, only: %i(index show), param: :place do
|
||||
get 'search', on: :collection
|
||||
end
|
||||
|
||||
get 'auth/:provider/callback' => 'authentications#create'
|
||||
get 'members/auth/:provider/callback' => 'authentications#create'
|
||||
|
||||
comfy_route :cms_admin, path: '/admin/cms'
|
||||
namespace :admin do
|
||||
resources :members
|
||||
scope :admin do
|
||||
resources :members, controller: 'admin/members', as: 'admin_members'
|
||||
get '/' => 'admin#index', as: 'admin'
|
||||
get '/newsletter' => 'admin#newsletter', as: 'admin_newsletter'
|
||||
comfy_route :cms_admin, path: '/cms'
|
||||
end
|
||||
|
||||
get '/admin' => 'admin#index'
|
||||
get '/admin/newsletter' => 'admin#newsletter', as: :admin_newsletter
|
||||
get '/admin/:action' => 'admin#:action'
|
||||
|
||||
namespace :api do
|
||||
namespace :v1 do
|
||||
jsonapi_resources :photos
|
||||
|
||||
@@ -4,15 +4,15 @@ describe Charts::CropsController do
|
||||
describe 'GET charts' do
|
||||
let(:crop) { FactoryBot.create :crop }
|
||||
describe 'sunniness' do
|
||||
before { get :sunniness, params: { crop_id: crop.to_param } }
|
||||
before { get :sunniness, params: { crop_slug: crop.to_param } }
|
||||
it { expect(response).to be_success }
|
||||
end
|
||||
describe 'planted_from' do
|
||||
before { get :planted_from, params: { crop_id: crop.to_param } }
|
||||
before { get :planted_from, params: { crop_slug: crop.to_param } }
|
||||
it { expect(response).to be_success }
|
||||
end
|
||||
describe 'harvested_for' do
|
||||
before { get :harvested_for, params: { crop_id: crop.to_param } }
|
||||
before { get :harvested_for, params: { crop_slug: crop.to_param } }
|
||||
it { expect(response).to be_success }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,26 +13,26 @@ describe HarvestsController do
|
||||
end
|
||||
|
||||
describe "GET index" do
|
||||
let(:member1) { FactoryBot.create(:member) }
|
||||
let!(:member1) { FactoryBot.create(:member) }
|
||||
let(:member2) { FactoryBot.create(:member) }
|
||||
let(:tomato) { FactoryBot.create(:tomato) }
|
||||
let(:maize) { FactoryBot.create(:maize) }
|
||||
let(:harvest1) { FactoryBot.create(:harvest, owner_id: member1.id, crop_id: tomato.id) }
|
||||
let(:harvest2) { FactoryBot.create(:harvest, owner_id: member2.id, crop_id: maize.id) }
|
||||
let!(:harvest1) { FactoryBot.create(:harvest, owner_id: member1.id, crop_id: tomato.id) }
|
||||
let!(:harvest2) { FactoryBot.create(:harvest, owner_id: member2.id, crop_id: maize.id) }
|
||||
|
||||
describe "assigns all harvests as @harvests" do
|
||||
before { get :index, params: {} }
|
||||
it { assigns(:harvests).should =~ [harvest1, harvest2] }
|
||||
it { expect(assigns(:harvests)).to eq [harvest1, harvest2] }
|
||||
end
|
||||
|
||||
describe "picks up owner from params and shows owner's harvests only" do
|
||||
before { get :index, params: { owner: member1.slug } }
|
||||
before { get :index, params: { member_slug: member1.slug } }
|
||||
it { expect(assigns(:owner)).to eq member1 }
|
||||
it { expect(assigns(:harvests)).to eq [harvest1] }
|
||||
end
|
||||
|
||||
describe "picks up crop from params and shows the harvests for the crop only" do
|
||||
before { get :index, params: { crop: maize.name } }
|
||||
before { get :index, params: { crop_slug: maize.name } }
|
||||
it { expect(assigns(:crop)).to eq maize }
|
||||
it { expect(assigns(:harvests)).to eq [harvest2] }
|
||||
end
|
||||
@@ -82,15 +82,15 @@ describe HarvestsController do
|
||||
end.to change(Harvest, :count).by(1)
|
||||
end
|
||||
|
||||
it "assigns a newly created harvest as @harvest" do
|
||||
post :create, params: { harvest: valid_attributes }
|
||||
assigns(:harvest).should be_a(Harvest)
|
||||
assigns(:harvest).should be_persisted
|
||||
describe "assigns a newly created harvest as @harvest" do
|
||||
before { post :create, params: { harvest: valid_attributes } }
|
||||
it { expect(assigns(:harvest)).to be_a(Harvest) }
|
||||
it { expect(assigns(:harvest)).to be_persisted }
|
||||
end
|
||||
|
||||
it "redirects to the created harvest" do
|
||||
post :create, params: { harvest: valid_attributes }
|
||||
response.should redirect_to(Harvest.last)
|
||||
describe "redirects to the created harvest" do
|
||||
before { post :create, params: { harvest: valid_attributes } }
|
||||
it { expect(response).to redirect_to(Harvest.last) }
|
||||
end
|
||||
|
||||
describe "links to planting" do
|
||||
@@ -105,13 +105,13 @@ describe HarvestsController do
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Harvest.any_instance.stub(:save).and_return(false)
|
||||
post :create, params: { harvest: { "crop_id" => "invalid value" } }
|
||||
assigns(:harvest).should be_a_new(Harvest)
|
||||
expect(assigns(:harvest)).to be_a_new(Harvest)
|
||||
end
|
||||
|
||||
it "re-renders the 'new' template" do
|
||||
describe "re-renders the 'new' template" do
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
post :create, params: { harvest: { "crop_id" => "invalid value" } }
|
||||
response.should render_template("new")
|
||||
before { post :create, params: { harvest: { "crop_id" => "invalid value" } } }
|
||||
it { expect(response).to render_template("new") }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -132,8 +132,8 @@ describe HarvestsController do
|
||||
|
||||
describe "PUT update" do
|
||||
describe "with valid params" do
|
||||
let(:harvest) { Harvest.create! valid_attributes }
|
||||
it "updates the requested harvest" do
|
||||
harvest = FactoryBot.create :harvest, valid_attributes
|
||||
new_crop = FactoryBot.create :crop
|
||||
expect do
|
||||
put :update, params: { id: harvest.to_param, harvest: { crop_id: new_crop.id } }
|
||||
@@ -141,16 +141,14 @@ describe HarvestsController do
|
||||
end.to change(harvest, :crop_id).to(new_crop.id)
|
||||
end
|
||||
|
||||
it "assigns the requested harvest as @harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
put :update, params: { id: harvest.to_param, harvest: valid_attributes }
|
||||
assigns(:harvest).should eq(harvest)
|
||||
describe "assigns the requested harvest as @harvest" do
|
||||
before { put :update, params: { id: harvest.to_param, harvest: valid_attributes } }
|
||||
it { expect(assigns(:harvest)).to eq(harvest) }
|
||||
end
|
||||
|
||||
it "redirects to the harvest" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
put :update, params: { id: harvest.to_param, harvest: valid_attributes }
|
||||
response.should redirect_to(harvest)
|
||||
describe "redirects to the harvest" do
|
||||
before { put :update, params: { id: harvest.to_param, harvest: valid_attributes } }
|
||||
it { expect(response).to redirect_to(harvest) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -160,13 +158,13 @@ describe HarvestsController do
|
||||
# Trigger the behavior that occurs when invalid params are submitted
|
||||
Harvest.any_instance.stub(:save).and_return(false)
|
||||
put :update, params: { id: harvest.to_param, harvest: { "crop_id" => "invalid value" } }
|
||||
assigns(:harvest).should eq(harvest)
|
||||
expect(assigns(:harvest)).to eq(harvest)
|
||||
end
|
||||
|
||||
it "re-renders the 'edit' template" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
put :update, params: { id: harvest.to_param, harvest: { "crop_id" => "invalid value" } }
|
||||
response.should render_template("edit")
|
||||
expect(response).to render_template("edit")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -196,7 +194,7 @@ describe HarvestsController do
|
||||
it "redirects to the harvests list" do
|
||||
harvest = Harvest.create! valid_attributes
|
||||
delete :destroy, params: { id: harvest.to_param }
|
||||
response.should redirect_to(harvests_url)
|
||||
expect(response).to redirect_to(harvests_url)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,43 +24,43 @@ describe MembersController do
|
||||
|
||||
describe "GET show" do
|
||||
it "provides JSON for member profile" do
|
||||
get :show, params: { id: @member.id }, format: 'json'
|
||||
get :show, params: { slug: @member.to_param }, format: 'json'
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it "assigns @posts with the member's posts" do
|
||||
get :show, params: { id: @member.id }
|
||||
get :show, params: { slug: @member.to_param }
|
||||
assigns(:posts).should eq(@posts)
|
||||
end
|
||||
|
||||
it "assigns @twitter_auth" do
|
||||
get :show, params: { id: @member.id }
|
||||
get :show, params: { slug: @member.to_param }
|
||||
assigns(:twitter_auth).should eq(@twitter_auth)
|
||||
end
|
||||
|
||||
it "assigns @flickr_auth" do
|
||||
get :show, params: { id: @member.id }
|
||||
get :show, params: { slug: @member.to_param }
|
||||
assigns(:flickr_auth).should eq(@flickr_auth)
|
||||
end
|
||||
|
||||
it "doesn't show completely nonsense members" do
|
||||
get :show, params: { id: 9999 }
|
||||
get :show, params: { slug: 9999 }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
it "doesn't show unconfirmed members" do
|
||||
@member2 = FactoryBot.create(:unconfirmed_member)
|
||||
get :show, params: { id: @member2.id }
|
||||
get :show, params: { slug: @member2.id }
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET member's RSS feed" do
|
||||
it "returns an RSS feed" do
|
||||
get :show, params: { id: @member.to_param }, format: "rss"
|
||||
response.should be_success
|
||||
response.should render_template("members/show")
|
||||
response.content_type.should eq("application/rss+xml")
|
||||
describe "returns an RSS feed" do
|
||||
before { get :show, params: { slug: @member.to_param }, format: "rss" }
|
||||
it { response.should be_success }
|
||||
it { response.should render_template("members/show") }
|
||||
it { response.content_type.should eq("application/rss+xml") }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,23 +11,6 @@ describe NotificationsController do
|
||||
}
|
||||
end
|
||||
|
||||
# this gets a bit confused because for most of the notification tests
|
||||
# (reading, etc) the logged in member needs to be the recipient.
|
||||
# However, for sending private messages (create, etc) the logged in
|
||||
# member needs to be the sender. Hence this separate set of
|
||||
# attributes.
|
||||
def valid_attributes_for_sender
|
||||
{
|
||||
"sender_id" => subject.current_member.id,
|
||||
"recipient_id" => FactoryBot.create(:member).id,
|
||||
"subject" => 'test'
|
||||
}
|
||||
end
|
||||
|
||||
def valid_session
|
||||
{}
|
||||
end
|
||||
|
||||
describe "GET index" do
|
||||
it "assigns all notifications as @notifications" do
|
||||
notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id)
|
||||
@@ -65,7 +48,7 @@ describe NotificationsController do
|
||||
describe "GET reply" do
|
||||
it "marks notifications as read" do
|
||||
notification = FactoryBot.create(:notification, recipient_id: subject.current_member.id)
|
||||
get :reply, params: { id: notification.to_param }
|
||||
get :reply, params: { notification_id: notification.to_param }
|
||||
# we need to fetch it from the db again, can't test against the old one
|
||||
n = Notification.find(notification.id)
|
||||
n.read.should eq true
|
||||
|
||||
@@ -25,13 +25,13 @@ describe PlantingsController do
|
||||
end
|
||||
|
||||
describe "picks up owner from params and shows owner's plantings only" do
|
||||
before { get :index, params: { owner: member1.slug } }
|
||||
before { get :index, params: { member_slug: member1.slug } }
|
||||
it { expect(assigns(:owner)).to eq member1 }
|
||||
it { expect(assigns(:plantings)).to eq [planting1] }
|
||||
end
|
||||
|
||||
describe "picks up crop from params and shows the plantings for the crop only" do
|
||||
before { get :index, params: { crop: maize.name } }
|
||||
before { get :index, params: { crop_slug: maize.slug } }
|
||||
it { expect(assigns(:crop)).to eq maize }
|
||||
it { expect(assigns(:plantings)).to eq [planting2] }
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ describe SeedsController do
|
||||
describe "GET index" do
|
||||
let(:owner) { FactoryBot.create(:member) }
|
||||
describe "picks up owner from params" do
|
||||
before { get :index, params: { owner: owner.slug } }
|
||||
before { get :index, params: { member_slug: owner.slug } }
|
||||
it { expect(assigns(:owner)).to eq(owner) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -157,23 +157,20 @@ feature "crop detail page", js: true do
|
||||
|
||||
scenario "User not signed in" do
|
||||
visit crop_path(seed.crop)
|
||||
expect(page).not_to have_content "You have 20 seeds of this crop"
|
||||
expect(page).not_to have_content "You don't have any seeds of this crop"
|
||||
expect(page).not_to have_link "View your seeds"
|
||||
expect(page).not_to have_content "You have 20 seeds"
|
||||
end
|
||||
|
||||
scenario "User signed in" do
|
||||
login_as(member)
|
||||
visit crop_path(seed.crop)
|
||||
expect(page).to have_content "You have 20 seeds of this crop."
|
||||
expect(page).to have_link "View your seeds"
|
||||
expect(page).to have_link "You have 20 seeds of this crop."
|
||||
end
|
||||
|
||||
scenario "click link to your owned seeds" do
|
||||
login_as(member)
|
||||
visit crop_path(seed.crop)
|
||||
click_link "View your seeds"
|
||||
expect(current_path).to eq seeds_by_owner_path(owner: member.slug)
|
||||
click_link "You have 20 seeds of this crop."
|
||||
expect(current_path).to eq member_seeds_path(member_slug: member.slug)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -11,12 +11,12 @@ feature "crop search" do
|
||||
end
|
||||
|
||||
scenario "search page with no search term shows suitable title" do
|
||||
visit crops_search_path
|
||||
visit search_crops_path
|
||||
expect(page).to have_css "h1", text: "Crop search"
|
||||
end
|
||||
|
||||
scenario "search page has a search form on it" do
|
||||
visit crops_search_path
|
||||
visit search_crops_path
|
||||
expect(page).to have_css "form#crop-search"
|
||||
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
|
||||
|
||||
@@ -26,12 +26,10 @@ feature "follows", :js do
|
||||
end
|
||||
|
||||
context "following another member" do
|
||||
background do
|
||||
visit member_path(other_member)
|
||||
end
|
||||
background { visit member_path(other_member) }
|
||||
|
||||
scenario "has a follow button" do
|
||||
expect(page).to have_link "Follow", href: follows_path(followed_id: other_member.id)
|
||||
expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug)
|
||||
end
|
||||
|
||||
scenario "has correct message and unfollow button" do
|
||||
@@ -43,12 +41,7 @@ feature "follows", :js do
|
||||
scenario "has a followed member listed in the following page" do
|
||||
click_link 'Follow'
|
||||
visit member_follows_path(member)
|
||||
expect(page).to have_content other_member.login_name.to_s
|
||||
end
|
||||
|
||||
scenario "does not die when passed an authenticity_token" do
|
||||
visit member_follows_path member, params: { authenticity_token: "Ultima ratio regum" }
|
||||
expect(page.status_code).to equal 200
|
||||
expect(page).to have_content other_member.login_name
|
||||
end
|
||||
|
||||
scenario "has correct message and follow button after unfollow" do
|
||||
@@ -56,28 +49,28 @@ feature "follows", :js do
|
||||
click_link 'Unfollow'
|
||||
expect(page).to have_content "Unfollowed #{other_member.login_name}"
|
||||
visit member_path(other_member) # unfollowing redirects to root
|
||||
expect(page).to have_link "Follow", href: follows_path(followed_id: other_member.id)
|
||||
expect(page).to have_link "Follow", href: follows_path(followed: other_member.slug)
|
||||
end
|
||||
|
||||
scenario "has member in following list" do
|
||||
click_link 'Follow'
|
||||
visit member_follows_path(member)
|
||||
expect(page).to have_content other_member.login_name.to_s
|
||||
expect(page).to have_content other_member.login_name
|
||||
end
|
||||
|
||||
scenario "appears in in followed member's followers list" do
|
||||
click_link 'Follow'
|
||||
visit member_followers_path(other_member)
|
||||
expect(page).to have_content member.login_name.to_s
|
||||
expect(page).to have_content member.login_name
|
||||
end
|
||||
|
||||
scenario "removes members from following and followers lists after unfollow" do
|
||||
click_link 'Follow'
|
||||
click_link 'Unfollow'
|
||||
visit member_follows_path(member)
|
||||
expect(page).not_to have_content other_member.login_name.to_s
|
||||
expect(page).not_to have_content other_member.login_name
|
||||
visit member_followers_path(other_member)
|
||||
expect(page).to have_content member.login_name.to_s
|
||||
expect(page).to have_content member.login_name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,30 +9,29 @@ 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
|
||||
it "has buttons bar at top" do
|
||||
within '.layout-actions' do
|
||||
is_expected.to have_link 'Add a garden'
|
||||
is_expected.to have_link 'My Gardens'
|
||||
is_expected.to have_link 'My gardens'
|
||||
is_expected.to have_link "Everyone's gardens"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'my gardens' do
|
||||
before { visit gardens_path(owner: member) }
|
||||
before { visit gardens_path(member_slug: member.slug) }
|
||||
|
||||
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
|
||||
|
||||
@@ -43,17 +42,31 @@ feature "Gardens" do
|
||||
end
|
||||
|
||||
context "other member's garden" do
|
||||
before { visit gardens_path(owner: FactoryBot.create(:member)) }
|
||||
before { visit gardens_path(member_slug: FactoryBot.create(:member).slug) }
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ feature "Gardens#index", :js do
|
||||
context "with 10 gardens" do
|
||||
before do
|
||||
FactoryBot.create_list :garden, 10, owner: member
|
||||
visit gardens_path(owner: member.login_name)
|
||||
visit member_gardens_path(member_slug: member.slug)
|
||||
end
|
||||
|
||||
it "displays each of the gardens" do
|
||||
@@ -29,7 +29,7 @@ feature "Gardens#index", :js do
|
||||
let!(:active_garden) { FactoryBot.create :garden, name: "My active garden", owner: member }
|
||||
let!(:inactive_garden) { FactoryBot.create :inactive_garden, name: "retired garden", owner: member }
|
||||
|
||||
before { visit gardens_path(member: member) }
|
||||
before { visit member_gardens_path(member_slug: member.slug) }
|
||||
|
||||
it "show active garden" do
|
||||
expect(page).to have_text active_garden.name
|
||||
@@ -57,7 +57,7 @@ feature "Gardens#index", :js do
|
||||
end
|
||||
|
||||
before do
|
||||
visit gardens_path(member: member)
|
||||
visit member_gardens_path(member_slug: member.slug)
|
||||
end
|
||||
|
||||
it "shows planting in garden" do
|
||||
@@ -90,7 +90,7 @@ feature "Gardens#index", :js do
|
||||
|
||||
garden.update! name: 'super awesome garden'
|
||||
assert planting
|
||||
visit gardens_path(owner: member.login_name)
|
||||
visit member_gardens_path(member_slug: member.slug)
|
||||
end
|
||||
|
||||
describe 'harvest still growing' do
|
||||
|
||||
@@ -14,9 +14,13 @@ feature "Planting a crop", js: true do
|
||||
scenario "View gardens" do
|
||||
visit gardens_path
|
||||
expect(page).to have_content "Everyone's gardens"
|
||||
click_link "My Gardens"
|
||||
within '.layout-actions' do
|
||||
click_link "My gardens"
|
||||
end
|
||||
expect(page).to have_content "#{garden.owner.login_name}'s gardens"
|
||||
click_link "Everyone's gardens"
|
||||
within '.layout-actions' do
|
||||
click_link "Everyone's gardens"
|
||||
end
|
||||
expect(page).to have_content "Everyone's gardens"
|
||||
end
|
||||
|
||||
@@ -82,7 +86,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
|
||||
|
||||
@@ -57,14 +57,16 @@ feature "Harvesting a crop", :js, :elasticsearch do
|
||||
end
|
||||
|
||||
scenario "Clicking link to owner's profile" do
|
||||
visit harvests_by_owner_path(member)
|
||||
visit member_harvests_path(member)
|
||||
click_link "View #{member}'s profile >>"
|
||||
expect(current_path).to eq member_path member
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
@@ -81,10 +81,10 @@ feature "member profile", js: true do
|
||||
create_list :seed, 4, owner: member
|
||||
create_list :post, 5, author: member
|
||||
visit member_path(member)
|
||||
expect(page).to have_link "2 plantings", href: plantings_by_owner_path(owner: member)
|
||||
expect(page).to have_link "3 harvests", href: harvests_by_owner_path(owner: member)
|
||||
expect(page).to have_link "4 seeds", href: seeds_by_owner_path(owner: member)
|
||||
expect(page).to have_link "5 posts", href: posts_by_author_path(author: member)
|
||||
expect(page).to have_link "2 plantings", href: member_plantings_path(member)
|
||||
expect(page).to have_link "3 harvests", href: member_harvests_path(member)
|
||||
expect(page).to have_link "4 seeds", href: member_seeds_path(member)
|
||||
expect(page).to have_link "5 posts", href: member_posts_path(member)
|
||||
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
|
||||
@@ -49,7 +49,7 @@ feature "Planting a crop", :js, :elasticsearch do
|
||||
end
|
||||
|
||||
scenario "Clicking link to owner's profile" do
|
||||
visit plantings_by_owner_path(member)
|
||||
visit member_plantings_path(member)
|
||||
click_link "View #{member}'s profile >>"
|
||||
expect(current_path).to eq member_path(member)
|
||||
end
|
||||
@@ -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,15 +21,15 @@ 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
|
||||
before do
|
||||
visit seeds_by_owner_path(member)
|
||||
visit member_seeds_path(member)
|
||||
click_link "View #{member}'s profile >>"
|
||||
end
|
||||
it { expect(current_path).to eq member_path(member) }
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user