"
-
- alt_index = $('#alternate_names .template').length + 1
-
- $('#add-alt_name-row').click ->
- compiled_input = $(alt_template.split("INDEX").join(alt_index))
- $('#alternate_names').append(compiled_input)
- alt_index = alt_index + 1
-
- $('#remove-alt_name-row').click ->
- if (alt_index > 2)
- alt_index = alt_index - 1
- tmp = 'alt_template[' + alt_index + ']'
- element = document.getElementById(tmp)
- console.log("%s",tmp)
- element.remove()
diff --git a/app/assets/stylesheets/bootstrap-accessibility.css b/app/assets/stylesheets/bootstrap-accessibility.css
index b7de73ef0..abf715176 100644
--- a/app/assets/stylesheets/bootstrap-accessibility.css
+++ b/app/assets/stylesheets/bootstrap-accessibility.css
@@ -1 +1 @@
-.btn:focus{outline:dotted 2px #000}div.active:focus{outline:dotted 1px #000}a:focus{outline:dotted 1px #000}.close:hover,.close:focus{outline:dotted 1px #000}.nav>li>a:hover,.nav>li>a:focus{outline:dotted 1px #000}.carousel-inner>.item{position:absolute;top:-999999em;display:block;-moz-transition:ease-in-out 0.6s left;-o-transition:ease-in-out 0.6s left;-webkit-transition:ease-in-out 0.6s left;transition:ease-in-out 0.6s left}.carousel-inner>.active{top:0}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{position:relative}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.alert-success{color:#2d4821}.alert-info{color:#214c62}.alert-warning{color:#6c4a00;background-color:#f9f1c6}.alert-danger{color:#d2322d}.alert-danger:hover{color:#a82824}
+.btn:focus{outline:dotted 2px #000}div.active:focus{outline:dotted 1px #000}a:focus{outline:dotted 1px #000}.close:hover,.close:focus{outline:dotted 1px #000}.nav>li>a:hover,.nav>li>a:focus{outline:dotted 1px #000}.carousel-indicators li,.carousel-indicators li.active{height:18px;width:18px;border-width:2px;position:relative;box-shadow:0px 0px 0px 1px #808080}.carousel-indicators.active li{background-color:rgba(100,149,253,0.6)}.carousel-indicators.active li.active{background-color:white}.carousel-tablist-highlight{display:block;position:absolute;outline:2px solid transparent;background-color:transparent;box-shadow:0px 0px 0px 1px transparent}.carousel-tablist-highlight.focus{outline:2px solid #6495ED;background-color:rgba(0,0,0,0.4)}a.carousel-control:focus{outline:2px solid #6495ED;background-image:linear-gradient(to right, transparent 0px, rgba(0,0,0,0.5) 100%);box-shadow:0px 0px 0px 1px #000000}.carousel-pause-button{position:absolute;top:-30em;left:-300em;display:block}.carousel-pause-button.focus{top:0.5em;left:0.5em}.carousel:hover .carousel-caption,.carousel.contrast .carousel-caption{background-color:rgba(0,0,0,0.5);z-index:10}.alert-success{color:#2d4821}.alert-info{color:#214c62}.alert-warning{color:#6c4a00;background-color:#f9f1c6}.alert-danger{color:#d2322d}.alert-danger:hover{color:#a82824}
diff --git a/app/assets/stylesheets/overrides.sass b/app/assets/stylesheets/overrides.sass
index bdeb64d0d..338a2dbc5 100644
--- a/app/assets/stylesheets/overrides.sass
+++ b/app/assets/stylesheets/overrides.sass
@@ -94,21 +94,6 @@ p.stats
dd
margin-left: auto
-@media (min-width: $screen-md-min)
- .planting-thumbnail
- dl.planting-attributes
- width: 100%
-
- dt
- text-align: left
- width: 120px
- dd
- padding-left: 120px
- margin-left: auto
-
- .navbar .navbar-form
- width: 250px
-
#placesmap, #cropmap
height: 500px
@@ -254,24 +239,6 @@ html, body
a
font-weight: 800
-// Overrides applying only to mobile view. This must be at the end of the overrides file.
-
-@media only screen and (max-width: 767px)
- .sidebar
- margin-left: 0
- border-left: none
- padding-left: 0
-
- #map
- height: 300px
-
- .navbar .nav > li
- display: block
-
- .navbar .navbar-form
- width: 185px
- padding-left: 0
- padding-right: 0
/* override "info" alert boxes to be green, not blue, on Growstuff */
$state-info-text: darken($green, 10%)
@@ -326,3 +293,44 @@ ul.thumbnail-buttons
.hover-wrapper:hover .text
visibility: visible
+
+.homepage-listing
+ padding-bottom: 6px
+
+@media (min-width: $screen-md-min)
+ .planting-thumbnail
+ dl.planting-attributes
+ width: 100%
+
+ dt
+ text-align: left
+ width: 120px
+ dd
+ padding-left: 120px
+ margin-left: auto
+
+ .navbar .navbar-form
+ width: 250px
+
+// Overrides applying only to mobile view. This must be at the end of the overrides file.
+@media only screen and (max-width: 767px)
+ .sidebar
+ margin-left: 0
+ border-left: none
+ padding-left: 0
+
+ #map
+ height: 300px
+
+ .navbar .nav > li
+ display: block
+
+ .navbar .navbar-form
+ width: 185px
+ padding-left: 0
+ padding-right: 0
+ .homepage
+ .thumbnail
+ height: 180px
+ .seed-thumbnail
+ height: 220px
diff --git a/app/controllers/account_types_controller.rb b/app/controllers/account_types_controller.rb
deleted file mode 100644
index f86892346..000000000
--- a/app/controllers/account_types_controller.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-class AccountTypesController < ApplicationController
- before_action :authenticate_member!
- load_and_authorize_resource
- respond_to :html
-
- # GET /account_types
- def index
- @account_types = AccountType.all.order(:name)
- respond_with(@account_types)
- end
-
- # GET /account_types/1
- def show
- respond_with(@account_types)
- end
-
- # GET /account_types/new
- def new
- @account_type = AccountType.new
- respond_with(@account_type)
- end
-
- # GET /account_types/1/edit
- def edit
- respond_with(@account_type)
- end
-
- # POST /account_types
- def create
- @account_type = AccountType.new(account_type_params)
- flash[:notice] = I18n.t('account_types.created') if @account_type.save
- respond_with(@account_type)
- end
-
- # PUT /account_types/1
- def update
- flash[:notice] = I18n.t('account_types.updated') if @account_type.update(account_type_params)
- respond_with(@account_type)
- end
-
- # DELETE /account_types/1
- def destroy
- @account_type.destroy
- flash[:notice] = I18n.t('account_types.deleted')
- respond_with(@account_type)
- end
-
- private
-
- def account_type_params
- params.require(:account_type).permit(:is_paid, :is_permanent_paid, :name)
- end
-end
diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb
deleted file mode 100644
index 040092aba..000000000
--- a/app/controllers/accounts_controller.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-class AccountsController < ApplicationController
- before_action :authenticate_member!
- load_and_authorize_resource
- respond_to :html
-
- # GET /accounts
- def index
- @accounts = Account.all.order(created_at: :desc)
- respond_with(@accounts)
- end
-
- # GET /accounts/1
- def show
- respond_with(@account)
- end
-
- # GET /accounts/1/edit
- def edit; end
-
- # PUT /accounts/1
- def update
- flash[:notice] = I18n.t('account.update') if @account.update(params[:account])
- respond_with(@account)
- end
-
- private
-
- def account_params
- params.require(:account).permit(:account_type_id, :member_id, :paid_until)
- end
-end
diff --git a/app/controllers/admin/orders_controller.rb b/app/controllers/admin/orders_controller.rb
deleted file mode 100644
index d4f727ec0..000000000
--- a/app/controllers/admin/orders_controller.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-module Admin
- class OrdersController < ApplicationController
- def index
- authorize! :manage, :all
- respond_to do |format|
- format.html # index.html.haml
- end
- end
-
- def search
- authorize! :manage, :all
- @orders = Order.search(by: params[:search_by], for: params[:search_text])
-
- if @orders.empty?
- flash[:alert] = "Couldn't find order with #{params[:search_by]} = #{params[:search_text]}"
- end
-
- respond_to do |format|
- format.html # index.html.haml
- end
- end
- end
-end
diff --git a/app/controllers/charts/crops_controller.rb b/app/controllers/charts/crops_controller.rb
new file mode 100644
index 000000000..b5fe3d4a7
--- /dev/null
+++ b/app/controllers/charts/crops_controller.rb
@@ -0,0 +1,30 @@
+module Charts
+ class CropsController < ApplicationController
+ respond_to :json
+
+ def sunniness
+ pie_chart_query 'sunniness'
+ end
+
+ def planted_from
+ pie_chart_query 'planted_from'
+ end
+
+ def harvested_for
+ @crop = Crop.find(params[:crop_id])
+ render json: Harvest.joins(:plant_part)
+ .where(crop: @crop)
+ .group("plant_parts.name").count(:id)
+ end
+
+ private
+
+ def pie_chart_query(field)
+ @crop = Crop.find(params[:crop_id])
+ render json: Planting.where(crop: @crop)
+ .where.not(field.to_sym => nil)
+ .where.not(field.to_sym => '')
+ .group(field.to_sym).count(:id)
+ end
+ end
+end
diff --git a/app/controllers/charts/gardens_controller.rb b/app/controllers/charts/gardens_controller.rb
new file mode 100644
index 000000000..8b67bc106
--- /dev/null
+++ b/app/controllers/charts/gardens_controller.rb
@@ -0,0 +1,16 @@
+module Charts
+ class GardensController < ApplicationController
+ respond_to :json
+ def timeline
+ @data = []
+ @garden = Garden.find(params[:garden_id])
+ @garden.plantings.where.not(planted_at: nil)
+ .order(finished_at: :desc).each do |p|
+ # use finished_at if we have it, otherwise use predictions
+ finish = p.finished_at.presence || p.finish_predicted_at
+ @data << [p.crop.name, p.planted_at, finish] if finish.present?
+ end
+ render json: @data
+ end
+ end
+end
diff --git a/app/controllers/crops_controller.rb b/app/controllers/crops_controller.rb
index d3bd5dcf9..67832c9b1 100644
--- a/app/controllers/crops_controller.rb
+++ b/app/controllers/crops_controller.rb
@@ -51,7 +51,11 @@ class CropsController < ApplicationController
def show
@crop = Crop.includes(:scientific_names, plantings: :photos).find(params[:id])
@posts = @crop.posts.order(created_at: :desc).paginate(page: params[:page])
- respond_with(@crop)
+ # respond_with(@crop)
+ respond_to do |format|
+ format.html
+ format.json { render json: @crop.to_json(crop_json_fields) }
+ end
end
def new
diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb
deleted file mode 100644
index 326cff21f..000000000
--- a/app/controllers/order_items_controller.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-class OrderItemsController < ApplicationController
- before_action :authenticate_member!
- load_and_authorize_resource
- respond_to :html
- responders :flash
-
- # POST /order_items
- def create
- if params[:order_item][:price]
- params[:order_item][:price] = params[:order_item][:price].to_f * 100 # convert to cents
- end
-
- @order_item = OrderItem.new(order_item_params)
- @order_item.order = current_member.current_order || Order.create(member_id: current_member.id)
-
- if @order_item.save
- redirect_to @order_item.order, notice: 'Added item to your order.'
- else
- redirect_to shop_path, alert: errors
- end
- end
-
- private
-
- def errors
- if @order_item.errors.empty?
- "There was a problem with your order."
- else
- @order_item.errors.full_messages.to_sentence
- end
- end
-
- def order_item_params
- params.require(:order_item).permit(:order_id, :price, :product_id, :quantity)
- end
-end
diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb
deleted file mode 100644
index 31c709148..000000000
--- a/app/controllers/orders_controller.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-class OrdersController < ApplicationController
- before_action :authenticate_member!
- load_and_authorize_resource
-
- # GET /orders
- def index
- @orders = Order.by_member(current_member)
-
- respond_to do |format|
- format.html # index.html.erb
- end
- end
-
- # GET /orders/1
- def show
- respond_to do |format|
- format.html # show.html.erb
- end
- end
-
- # GET /orders/new
- def new
- @order = Order.new
-
- respond_to do |format|
- format.html # new.html.erb
- end
- end
-
- # checkout with PayPal
- def checkout
- respond_to do |format|
- if @order.update_attributes(referral_code: params[:referral_code])
- response = EXPRESS_GATEWAY.setup_purchase(
- @order.total,
- items: @order.activemerchant_items,
- currency: Rails.application.config.currency,
- no_shipping: true,
- ip: request.remote_ip,
- return_url: complete_order_url,
- cancel_return_url: shop_url
- )
- format.html { redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token) }
- else
- format.html { render action: "show" }
- end
- end
- end
-
- def complete
- if params[:token] && params['PayerID']
- purchase = EXPRESS_GATEWAY.purchase(
- @order.total,
- currency: Rails.application.config.currency,
- ip: request.remote_ip,
- payer_id: params['PayerID'],
- token: params[:token]
- )
- if purchase.success?
- @order.completed_at = Time.zone.now
- @order.record_paypal_details(params[:token])
- else
- flash[:alert] = "Could not complete your order. Please notify support."
- end
- else
- flash[:alert] = "PayPal didn't return a token or payer_id for your order. Please notify support."
- end
-
- @order.update_account # apply paid account benefits, etc.
-
- respond_to do |format|
- format.html # new.html.erb
- end
- end
-
- def cancel
- respond_to do |format|
- format.html { redirect_to shop_url, notice: 'Order was cancelled.' }
- end
- end
-
- # DELETE /orders/1
- def destroy
- @order.destroy
-
- respond_to do |format|
- format.html { redirect_to shop_url, notice: 'Order was deleted.' }
- end
- end
-end
diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb
index 2866c1549..57b10e5d8 100644
--- a/app/controllers/photos_controller.rb
+++ b/app/controllers/photos_controller.rb
@@ -88,7 +88,7 @@ class PhotosController < ApplicationController
photo = Photo.find_by(flickr_photo_id: flickr_photo_id_param)
photo ||= Photo.new(photo_params)
photo.owner_id = current_member.id
- photo.set_flickr_metadata
+ photo.set_flickr_metadata!
photo
end
diff --git a/app/controllers/plantings_controller.rb b/app/controllers/plantings_controller.rb
index b0e339710..0fa013649 100644
--- a/app/controllers/plantings_controller.rb
+++ b/app/controllers/plantings_controller.rb
@@ -31,12 +31,13 @@ class PlantingsController < ApplicationController
@planting = Planting.includes(:owner, :crop, :garden, :photos)
.friendly
.find(params[:id])
- @photos = @planting.photos.order(created_at: :desc).includes(:owner).paginate(page: params[:page])
+ @photos = @planting.photos.order(date_taken: :desc).includes(:owner).paginate(page: params[:page])
respond_with @planting
end
def new
@planting = Planting.new(planted_at: Time.zone.today)
+ @seed = Seed.find_by(slug: params[:seed_id]) if params[:seed_id]
# using find_by_id here because it returns nil, unlike find
@crop = Crop.approved.find_by(id: params[:crop_id]) || Crop.new
@@ -54,7 +55,8 @@ class PlantingsController < ApplicationController
def create
@planting = Planting.new(planting_params)
@planting.owner = current_member
- @planting.save
+ @planting.crop = @planting.parent_seed.crop if @planting.parent_seed.present?
+ @planting.save!
respond_with @planting
end
@@ -82,6 +84,7 @@ class PlantingsController < ApplicationController
params[:planted_at] = parse_date(params[:planted_at]) if params[:planted_at]
params.require(:planting).permit(
:crop_id, :description, :garden_id, :planted_at,
+ :parent_seed_id,
:quantity, :sunniness, :planted_from, :finished,
:finished_at
)
diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb
deleted file mode 100644
index 8e0a1fb08..000000000
--- a/app/controllers/products_controller.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-class ProductsController < ApplicationController
- before_action :authenticate_member!
- load_and_authorize_resource
- respond_to :html
- responders :flash
-
- def index
- @products = Product.all.order(:name)
- respond_with @products
- end
-
- def show
- respond_with @product
- end
-
- def new
- @product = Product.new
- respond_with @product
- end
-
- def edit
- respond_with @product
- end
-
- def create
- @product = Product.create(product_params)
- respond_with @product
- end
-
- def update
- @product.update(product_params)
- respond_with @product
- end
-
- def destroy
- @product.destroy
- respond_with @product
- end
-
- private
-
- def product_params
- params.require(:product).permit(:description, :min_price, :recommended_price, :name,
- :account_type_id, :paid_months)
- end
-end
diff --git a/app/controllers/seeds_controller.rb b/app/controllers/seeds_controller.rb
index 12445877e..b18e6090a 100644
--- a/app/controllers/seeds_controller.rb
+++ b/app/controllers/seeds_controller.rb
@@ -16,44 +16,37 @@ class SeedsController < ApplicationController
respond_with(@seeds)
end
- # GET /seeds/1
- # GET /seeds/1.json
def show
@photos = @seed.photos.includes(:owner).order(created_at: :desc).paginate(page: params[:page])
respond_with(@seed)
end
- # GET /seeds/new
- # GET /seeds/new.json
def new
@seed = Seed.new
- # using find_by_id here because it returns nil, unlike find
- @crop = Crop.find_or_initialize_by(id: params[:crop_id])
+ if params[:planting_id]
+ @planting = Planting.find_by(slug: params[:planting_id])
+ else
+ @crop = Crop.find_or_initialize_by(id: params[:crop_id])
+ end
respond_with(@seed)
end
- # GET /seeds/1/edit
def edit; end
- # POST /seeds
- # POST /seeds.json
def create
@seed = Seed.new(seed_params)
@seed.owner = current_member
+ @seed.crop = @seed.parent_planting.crop if @seed.parent_planting
flash[:notice] = "Successfully added #{@seed.crop} seed to your stash." if @seed.save
respond_with(@seed)
end
- # PUT /seeds/1
- # PUT /seeds/1.json
def update
flash[:notice] = 'Seed was successfully updated.' if @seed.update(seed_params)
respond_with(@seed)
end
- # DELETE /seeds/1
- # DELETE /seeds/1.json
def destroy
@seed.destroy
respond_with(@seed)
@@ -64,8 +57,11 @@ class SeedsController < ApplicationController
def seed_params
params.require(:seed).permit(
:crop_id, :description, :quantity, :plant_before,
- :days_until_maturity_min, :days_until_maturity_max, :organic, :gmo,
- :heirloom, :tradable_to, :slug
+ :parent_planting_id,
+ :days_until_maturity_min, :days_until_maturity_max,
+ :organic, :gmo,
+ :heirloom, :tradable_to, :slug,
+ :finished, :finished_at
)
end
diff --git a/app/controllers/shop_controller.rb b/app/controllers/shop_controller.rb
deleted file mode 100644
index 964511e50..000000000
--- a/app/controllers/shop_controller.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-class ShopController < ApplicationController
- respond_to :html
- def index
- @products = Product.all
- @order_item = OrderItem.new
-
- # this is (hopefully) part of a short-term hack to prevent people from
- # ordering multiple subscriptions, which would be very confusing to deal
- # with. We check whether they have an order already in progress, and if
- # so, point that out to them and encourage them to checkout, rather than
- # letting them add more stuff to their order.
-
- @order = nil
- @most_recent_item = nil
- return unless current_member
- @order = current_member.current_order
- @most_recent_item = @order.order_items.first if @order
- end
-end
diff --git a/app/helpers/harvests_helper.rb b/app/helpers/harvests_helper.rb
index 14277817b..10ed30888 100644
--- a/app/helpers/harvests_helper.rb
+++ b/app/helpers/harvests_helper.rb
@@ -28,7 +28,12 @@ module HarvestsHelper
end
def display_harvest_description(harvest)
- return "No description provided." if harvest.description.nil?
- harvest.description
+ if harvest.description.nil?
+ "no description provided."
+ else
+ truncate(harvest.description, length: 50, separator: ' ', omission: '... ') do
+ link_to "Read more", harvest_path(harvest)
+ end
+ end
end
end
diff --git a/app/helpers/photos_helper.rb b/app/helpers/photos_helper.rb
new file mode 100644
index 000000000..b77f35bd9
--- /dev/null
+++ b/app/helpers/photos_helper.rb
@@ -0,0 +1,51 @@
+module PhotosHelper
+ def crop_image_path(crop)
+ if crop.default_photo.present?
+ crop.default_photo.thumbnail_url
+ else
+ placeholder_image
+ end
+ end
+
+ def garden_image_path(garden)
+ if garden.default_photo.present?
+ garden.default_photo.thumbnail_url
+ else
+ placeholder_image
+ end
+ end
+
+ def planting_image_path(planting)
+ if planting.photos.present?
+ planting.photos.first.thumbnail_url
+ else
+ placeholder_image
+ end
+ end
+
+ def harvest_image_path(harvest)
+ if harvest.photos.present?
+ harvest.photos.first.thumbnail_url
+ elsif harvest.planting.present? && harvest.planting.photos.present?
+ harvest.planting.photos.first.thumbnail_url
+ else
+ placeholder_image
+ end
+ end
+
+ def seed_image_path(seed)
+ if seed.default_photo.present?
+ seed.default_photo.thumbnail_url
+ elsif seed.crop.default_photo.present?
+ seed.crop.default_photo.thumbnail_url
+ else
+ placeholder_image
+ end
+ end
+
+ private
+
+ def placeholder_image
+ 'placeholder_150.png'
+ end
+end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 283bf45cc..4fd14340e 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -24,14 +24,9 @@ class Ability
# except these, which don't make sense if you're not logged in
cannot :read, Notification
cannot :read, Authentication
- cannot :read, Order
- cannot :read, OrderItem
# and nobody should be able to view this except admins
cannot :read, Role
- cannot :read, Product
- cannot :read, Account
- cannot :read, AccountType
# nobody should be able to view unapproved crops unless they
# are wranglers or admins
@@ -116,23 +111,12 @@ class Ability
can :update, Photo, owner_id: member.id
can :destroy, Photo, owner_id: member.id
- can :create, Seed
- can :update, Seed, owner_id: member.id
+ can :create, Seed
+ can :update, Seed, owner_id: member.id
can :destroy, Seed, owner_id: member.id
-
- # orders/shop/etc
- can :create, Order
- can :read, Order, member_id: member.id
- can :complete, Order, member_id: member.id, completed_at: nil
- can :checkout, Order, member_id: member.id, completed_at: nil
- can :cancel, Order, member_id: member.id, completed_at: nil
- can :destroy, Order, member_id: member.id, completed_at: nil
-
- can :create, OrderItem
- # for now, let's not let people mess with individual order items
- cannot :read, OrderItem, order: { member_id: member.id }
- cannot :update, OrderItem, order: { member_id: member.id, completed_at: nil }
- cannot :destroy, OrderItem, order: { member_id: member.id, completed_at: nil }
+ can :create, Seed, owner_id: member.id, parent_planting: { owner_id: member.id }
+ can :update, Seed, owner_id: member.id, parent_planting: { owner_id: member.id }
+ can :destroy, Seed, owner_id: member.id, parent_planting: { owner_id: member.id }
# following/unfollowing permissions
can :create, Follow
@@ -148,12 +132,6 @@ class Ability
can :read, :all
can :manage, :all
- # can't change order history, because it's *history*
- cannot :create, Order
- cannot :complete, Order
- cannot :destroy, Order
- cannot :manage, OrderItem
-
# can't delete plant parts if they have harvests associated with them
cannot :destroy, PlantPart
can :destroy, PlantPart do |pp|
diff --git a/app/models/account.rb b/app/models/account.rb
deleted file mode 100644
index be5b1e9cf..000000000
--- a/app/models/account.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-class Account < ApplicationRecord
- belongs_to :member
- belongs_to :account_type
-
- validates :member_id, uniqueness: {
- message: 'already has account details associated with it'
- }
-
- before_validation do
- # If not account type, set to the free account
- unless account_type
- self.account_type = AccountType.find_or_create_by(name:
- Rails.application.config.default_account_type)
- end
- end
-
- def paid_until_string
- if account_type.is_permanent_paid
- "forever"
- elsif account_type.is_paid
- paid_until.to_s
- end
- end
-end
diff --git a/app/models/account_type.rb b/app/models/account_type.rb
deleted file mode 100644
index c2294ca53..000000000
--- a/app/models/account_type.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-class AccountType < ApplicationRecord
- #
- # Relationships
- has_many :products
-
- #
- # Validations
- validates :name, presence: true, uniqueness: true
-
- def to_s
- name
- end
-end
diff --git a/app/models/concerns/finishable.rb b/app/models/concerns/finishable.rb
new file mode 100644
index 000000000..42fa4e734
--- /dev/null
+++ b/app/models/concerns/finishable.rb
@@ -0,0 +1,12 @@
+module Finishable
+ extend ActiveSupport::Concern
+
+ included do
+ scope :finished, -> { where(finished: true) }
+ scope :current, -> { where.not(finished: true) }
+
+ def active?
+ !finished
+ end
+ end
+end
diff --git a/app/models/crop.rb b/app/models/crop.rb
index a5105fb94..9f1ec6e59 100644
--- a/app/models/crop.rb
+++ b/app/models/crop.rb
@@ -120,12 +120,7 @@ class Crop < ApplicationRecord
# later we can choose a default photo based on different criteria,
# eg. popularity
def default_photo
- # most recent photo
- return photos.order(created_at: :desc).first if photos.any?
-
- # Crop has no photos? Look for the most recent harvest with a photo.
- harvest_with_photo = Harvest.where(crop_id: id).joins(:photos).order('harvests.id DESC').limit(1).first
- harvest_with_photo.photos.first if harvest_with_photo
+ first_photo(:plantings) || first_photo(:harvests) || first_photo(:seeds)
end
# returns hash indicating whether this crop is grown in
@@ -242,4 +237,8 @@ class Crop < ApplicationRecord
return unless reason_for_rejection == "other" && rejection_notes.blank?
errors.add(:rejection_notes, "must be added if the reason for rejection is \"other\"")
end
+
+ def first_photo(type)
+ Photo.joins(type).where("#{type}": { crop_id: id }).order("photos.created_at DESC").first
+ end
end
diff --git a/app/models/harvest.rb b/app/models/harvest.rb
index a58eaa991..60a43ce44 100644
--- a/app/models/harvest.rb
+++ b/app/models/harvest.rb
@@ -40,6 +40,13 @@ class Harvest < ApplicationRecord
##
## Scopes
default_scope { joins(:owner) } # Ensures owner exists
+ scope :interesting, -> { has_photos.one_per_owner }
+ scope :recent, -> { order(created_at: :desc) }
+ scope :one_per_owner, lambda {
+ joins("JOIN members m ON (m.id=harvests.owner_id)
+ LEFT OUTER JOIN harvests h2
+ ON (m.id=h2.owner_id AND harvests.id < h2.id)").where("h2 IS NULL")
+ }
##
## Validations
diff --git a/app/models/member.rb b/app/models/member.rb
index 7165faf4f..f2427d45d 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -7,7 +7,7 @@ class Member < ApplicationRecord
friendly_id :login_name, use: %i(slugged finders)
#
- # Relationshops
+ # Relationships
has_many :posts, foreign_key: 'author_id'
has_many :comments, foreign_key: 'author_id'
has_many :forums, foreign_key: 'owner_id'
@@ -19,9 +19,6 @@ class Member < ApplicationRecord
has_many :notifications, foreign_key: 'recipient_id'
has_many :sent_notifications, foreign_key: 'sender_id'
has_many :authentications
- has_many :orders
- has_one :account
- has_one :account_type, through: :account
has_many :photos
has_many :requested_crops, class_name: Crop, foreign_key: 'requester_id'
has_many :likes, dependent: :destroy
@@ -77,7 +74,11 @@ class Member < ApplicationRecord
after_validation :geocode
after_validation :empty_unwanted_geocodes
after_save :update_newsletter_subscription
- after_create :create_account_and_garden
+
+ # Give each new member a default garden
+ # we use find_or_create to avoid accidentally creating a second one,
+ # which can happen sometimes especially with FactoryBot associations
+ after_create { |member| Garden.create(name: "Garden", owner_id: member.id) }
# allow login via either login_name or email address
def self.find_first_by_auth_conditions(warden_conditions)
@@ -95,34 +96,6 @@ class Member < ApplicationRecord
roles.any? { |r| r.name.gsub(/\s+/, "_").underscore.to_sym == role_sym }
end
- def current_order
- orders.find_by(completed_at: nil)
- end
-
- # when purchasing a product that gives you a paid account, this method
- # does all the messing around to actually make sure the account is
- # updated correctly -- account type, paid until, etc. Usually this is
- # called by order.update_account, which loops through all order items
- # and does this for each one.
- def update_account_after_purchase(product)
- account.account_type = product.account_type if product.account_type
- if product.paid_months
- start_date = account.paid_until || Time.zone.now
- account.paid_until = start_date + product.paid_months.months
- end
- account.save
- end
-
- def paid?
- if account.account_type.is_permanent_paid
- true
- elsif account.account_type.is_paid && account.paid_until >= Time.zone.now
- true
- else
- false
- end
- end
-
def auth(provider)
authentications.find_by(provider: provider)
end
@@ -232,13 +205,4 @@ class Member < ApplicationRecord
def get_follow(member)
follows.find_by(followed_id: member.id) if already_following?(member)
end
-
- # Give each new member a default garden
- # and an account record (for paid accounts etc)
- # we use find_or_create to avoid accidentally creating a second one,
- # which can happen sometimes especially with FactoryBot associations
- def create_account_and_garden
- Garden.create!(name: "Garden", owner_id: id)
- Account.find_or_create_by!(member_id: id)
- end
end
diff --git a/app/models/order.rb b/app/models/order.rb
deleted file mode 100644
index fe5f65888..000000000
--- a/app/models/order.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-class Order < ApplicationRecord
- #
- # Relationships
- belongs_to :member, -> { with_deleted }
- has_many :order_items, dependent: :destroy
-
- #
- # Validations
- validates :referral_code, format: {
- with: /\A[a-zA-Z0-9 ]*\z/,
- message: "may only include letters and numbers"
- }
-
- #
- # Teiggers
- before_save :standardize_referral_code
-
- #
- # Scopes
- scope :by_member, ->(member) { where(member: member) }
-
- # total price of an order
- def total
- sum = 0
- order_items.each do |i|
- subtotal = i.price * i.quantity
- sum += subtotal
- end
- sum
- end
-
- # return items in the format ActiveMerchant/PayPal want them
- def activemerchant_items
- items = []
- order_items.each do |i|
- items.push(name: i.product.name,
- quantity: i.quantity,
- amount: i.price)
- end
- items
- end
-
- # record the paypal details for reference
- def record_paypal_details(token)
- self.paypal_express_token = token
- details = EXPRESS_GATEWAY.details_for(token)
- self.paypal_express_payer_id = details.payer_id
- save
- end
-
- # when an order is completed, we update the member's account to mark
- # them as paid, or whatever, based on what products they ordered
- def update_account
- order_items.each do |i|
- member.update_account_after_purchase(i.product)
- end
- end
-
- # removes whitespace and forces to uppercase (we're somewhat liberal
- # in what we accept, but we clean it up anyway.)
- def standardize_referral_code
- self.referral_code = referral_code.upcase.gsub(/\s/, '') if referral_code
- end
-
- # search orders (used by admin/orders)
- # usage: Order.search({ :by => 'member', :for => 'Skud' })
- # can search by: member, order_id, paypal_token, paypal_payer_id,
- def self.search(args = {})
- if args[:for]
- case args[:by]
- when "member"
- member = Member.with_deleted.find_by(login_name: args[:for])
- return member.orders if member
- when "order_id"
- order = Order.find_by(id: args[:for])
- return [order] if order
- when "paypal_token"
- order = Order.find_by(paypal_express_token: args[:for])
- return [order] if order
- when "paypal_payer_id"
- order = Order.find_by(paypal_express_payer_id: args[:for])
- return [order] if order
- when "referral_code"
- # coerce to uppercase
- return Order.where(referral_code: args[:for].upcase)
- end
- end
- []
- end
-end
diff --git a/app/models/order_item.rb b/app/models/order_item.rb
deleted file mode 100644
index 771919b55..000000000
--- a/app/models/order_item.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class OrderItem < ApplicationRecord
- belongs_to :order
- belongs_to :product
-
- validate :price_must_be_greater_than_minimum
- validates :order_id, uniqueness: { message: "may only have one item." }
-
- def price_must_be_greater_than_minimum
- @product = Product.find(product_id)
- errors.add(:price, "must be greater than the product's minimum value") if price < @product.min_price
- end
-end
diff --git a/app/models/photo.rb b/app/models/photo.rb
index 0daae7825..c9c8c6a94 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -27,7 +27,8 @@ class Photo < ApplicationRecord
license_url: license.url,
thumbnail_url: FlickRaw.url_q(info),
fullsize_url: FlickRaw.url_z(info),
- link_url: FlickRaw.url_photopage(info)
+ link_url: FlickRaw.url_photopage(info),
+ date_taken: info.dates.taken
}
end
@@ -49,7 +50,11 @@ class Photo < ApplicationRecord
end
end
- def set_flickr_metadata
+ def set_flickr_metadata!
update_attributes(flickr_metadata)
end
+
+ def to_s
+ "#{title} by #{owner.login_name}"
+ end
end
diff --git a/app/models/planting.rb b/app/models/planting.rb
index 32f9d3786..f985565a7 100644
--- a/app/models/planting.rb
+++ b/app/models/planting.rb
@@ -1,6 +1,7 @@
class Planting < ApplicationRecord
extend FriendlyId
include PhotoCapable
+ include Finishable
friendly_id :planting_slug, use: %i(slugged finders)
# Constants
@@ -20,11 +21,15 @@ class Planting < ApplicationRecord
belongs_to :crop, counter_cache: true
has_many :harvests, dependent: :destroy
+ #
+ # Ancestry of food
+ belongs_to :parent_seed, class_name: 'Seed', foreign_key: 'parent_seed_id' # parent
+ has_many :child_seeds, class_name: 'Seed',
+ foreign_key: 'parent_planting_id', dependent: :nullify # children
+
##
## Scopes
default_scope { joins(:owner) } # Ensures the owner still exists
- scope :finished, -> { where(finished: true) }
- scope :current, -> { where(finished: false) }
scope :interesting, -> { has_photos.one_per_owner }
scope :recent, -> { order(created_at: :desc) }
scope :one_per_owner, lambda {
diff --git a/app/models/product.rb b/app/models/product.rb
deleted file mode 100644
index 3946645d3..000000000
--- a/app/models/product.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class Product < ApplicationRecord
- #
- # Relationships
- belongs_to :account_type
- has_and_belongs_to_many :orders # rubocop:disable Rails/HasAndBelongsToMany
-
- #
- # Validations
- validates :paid_months, allow_nil: true, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
- validates :min_price, presence: true
-
- def to_s
- name
- end
-end
diff --git a/app/models/seed.rb b/app/models/seed.rb
index ca99c4fc3..dff707a5c 100644
--- a/app/models/seed.rb
+++ b/app/models/seed.rb
@@ -1,6 +1,7 @@
class Seed < ApplicationRecord
extend FriendlyId
include PhotoCapable
+ include Finishable
friendly_id :seed_slug, use: %i(slugged finders)
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally).freeze
@@ -13,11 +14,13 @@ class Seed < ApplicationRecord
belongs_to :crop
belongs_to :owner, class_name: 'Member', foreign_key: 'owner_id', counter_cache: true
+ belongs_to :parent_planting, class_name: 'Planting', foreign_key: 'parent_planting_id' # parent
+ has_many :child_plantings, class_name: 'Planting',
+ foreign_key: 'parent_seed_id', dependent: :nullify # children
+
#
# Validations
validates :crop, approved: true
- delegate :name, to: :crop
- delegate :default_photo, to: :crop
validates :crop, presence: { message: "must be present and exist in our database" }
validates :quantity, allow_nil: true,
numericality: { only_integer: true, greater_than_or_equal_to: 0 }
@@ -38,6 +41,10 @@ class Seed < ApplicationRecord
inclusion: { in: HEIRLOOM_VALUES, message: "You must say whether the seeds"\
"are heirloom, hybrid, or unknown" }
+ #
+ # Delegations
+ delegate :name, to: :crop
+
#
# Scopes
default_scope { joins(:owner) } # Ensure owner exists
@@ -45,6 +52,10 @@ class Seed < ApplicationRecord
scope :interesting, -> { tradable.has_location }
scope :has_location, -> { joins(:owner).where.not("members.location": nil) }
+ def default_photo
+ photos.order(created_at: :desc).first
+ end
+
def tradable?
tradable_to != 'nowhere'
end
diff --git a/app/views/account_types/_form.html.haml b/app/views/account_types/_form.html.haml
deleted file mode 100644
index 5bfbb539a..000000000
--- a/app/views/account_types/_form.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-= form_for @account_type do |f|
- - if @account_type.errors.any?
- #error_explanation
- %h2
- = pluralize(@account_type.errors.size, "error")
- prohibited this account_type from being saved:
- %ul
- - @account_type.errors.full_messages.each do |msg|
- %li= msg
-
- .field
- = f.label :name
- = f.text_field :name
- .field
- = f.label :is_paid
- = f.check_box :is_paid
- .field
- = f.label :is_permanent_paid
- = f.check_box :is_permanent_paid
- .actions
- = f.submit 'Save'
diff --git a/app/views/account_types/edit.html.haml b/app/views/account_types/edit.html.haml
deleted file mode 100644
index c994c4ff1..000000000
--- a/app/views/account_types/edit.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-- content_for :title, "Editing account type"
-
-= render 'form'
-
-= link_to 'Show', @account_type
-\|
-= link_to 'Back', account_types_path
diff --git a/app/views/account_types/index.html.haml b/app/views/account_types/index.html.haml
deleted file mode 100644
index 6af6d129d..000000000
--- a/app/views/account_types/index.html.haml
+++ /dev/null
@@ -1,23 +0,0 @@
-- content_for :title, "Listing account types"
-
-%table
- %tr
- %th Name
- %th Is paid
- %th Is permanent paid
- %th
- %th
- %th
-
- - @account_types.each do |account_type|
- %tr
- %td= account_type.name
- %td= account_type.is_paid
- %td= account_type.is_permanent_paid
- %td= link_to 'Show', account_type
- %td= link_to 'Edit', edit_account_type_path(account_type)
- %td= link_to 'Destroy', account_type, method: :delete, data: { confirm: 'Are you sure?' }
-
-%br
-
-= link_to 'New Account type', new_account_type_path
diff --git a/app/views/account_types/new.html.haml b/app/views/account_types/new.html.haml
deleted file mode 100644
index 92d309715..000000000
--- a/app/views/account_types/new.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- content_for :title, "New account type"
-
-= render 'form'
-
-= link_to 'Back', account_types_path
diff --git a/app/views/account_types/show.html.haml b/app/views/account_types/show.html.haml
deleted file mode 100644
index a3f7f690b..000000000
--- a/app/views/account_types/show.html.haml
+++ /dev/null
@@ -1,17 +0,0 @@
-%p#notice= notice
-
-%p
- %b Name:
- = @account_type.name
-%p
- %b Is paid:
- = @account_type.is_paid
-%p
- %b Is permanent paid:
- = @account_type.is_permanent_paid
-
-= link_to 'Edit', edit_account_type_path(@account_type)
-\|
-= link_to 'Delete', @account_type, method: :delete, data: { confirm: 'Are you sure?' }
-\|
-= link_to 'Back', account_types_path
diff --git a/app/views/accounts/_form.html.haml b/app/views/accounts/_form.html.haml
deleted file mode 100644
index 410b717fa..000000000
--- a/app/views/accounts/_form.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-= form_for @account do |f|
- - if @account.errors.any?
- #error_explanation
- %h2
- = pluralize(@account.errors.size, "error")
- prohibited this account from being saved:
- %ul
- - @account.errors.full_messages.each do |msg|
- %li= msg
-
- .field
- = f.label :member_id
- = f.number_field :member_id
- .field
- = f.label :account_type
- = f.text_field :account_type
- .field
- = f.label :paid_until
- = f.datetime_select :paid_until
- .actions
- = f.submit 'Save'
diff --git a/app/views/accounts/edit.html.haml b/app/views/accounts/edit.html.haml
deleted file mode 100644
index ef8d08801..000000000
--- a/app/views/accounts/edit.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-- content_for :title, "Editing account"
-
-= render 'form'
-
-= link_to 'Show', @account
-\|
-= link_to 'Back', accounts_path
diff --git a/app/views/accounts/index.html.haml b/app/views/accounts/index.html.haml
deleted file mode 100644
index 8d929dd0f..000000000
--- a/app/views/accounts/index.html.haml
+++ /dev/null
@@ -1,23 +0,0 @@
-- content_for :title, "Listing accounts"
-
-%table
- %tr
- %th Member
- %th Account type
- %th Paid until
- %th
- %th
- %th
-
- - @accounts.each do |account|
- %tr
- %td= account.member_id
- %td= account.account_type
- %td= account.paid_until
- %td= link_to 'Show', account
- %td= link_to 'Edit', edit_account_path(account)
- %td= link_to 'Destroy', account, method: :delete, data: { confirm: 'Are you sure?' }
-
-%br
-
-= link_to 'New Account detail', new_account_path
diff --git a/app/views/accounts/new.html.haml b/app/views/accounts/new.html.haml
deleted file mode 100644
index 9430cc2ed..000000000
--- a/app/views/accounts/new.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- content_for :title, "New account"
-
-= render 'form'
-
-= link_to 'Back', accounts_path
diff --git a/app/views/accounts/show.html.haml b/app/views/accounts/show.html.haml
deleted file mode 100644
index 5c5288674..000000000
--- a/app/views/accounts/show.html.haml
+++ /dev/null
@@ -1,15 +0,0 @@
-%p#notice= notice
-
-%p
- %b Member:
- = @account.member_id
-%p
- %b Account type:
- = @account.account_type.name
-%p
- %b Paid until:
- = @account.paid_until
-
-= link_to 'Edit', edit_account_path(@account)
-\|
-= link_to 'Back', accounts_path
diff --git a/app/views/admin/index.html.haml b/app/views/admin/index.html.haml
index 389cc2dee..f82c5c336 100644
--- a/app/views/admin/index.html.haml
+++ b/app/views/admin/index.html.haml
@@ -6,8 +6,6 @@
.col-md-4
%h2 Site admin
%ul#site_admin
- %li= link_to "Account types", account_types_path
- %li= link_to "Products", products_path
%li= link_to "Roles", roles_path
%li= link_to "Forums", forums_path
-# %li= link_to "CMS", comfy_admin_cms_path
@@ -22,8 +20,3 @@
%ul
%li= link_to "Newsletter subscribers", admin_newsletter_path
%li= link_to "Members", admin_members_path
-
-.row
- .col-md-12
- %h2 Orders
- = render "admin/orders/searchform"
diff --git a/app/views/admin/members/index.html.haml b/app/views/admin/members/index.html.haml
index 2408a55db..d91b1f8a1 100644
--- a/app/views/admin/members/index.html.haml
+++ b/app/views/admin/members/index.html.haml
@@ -11,5 +11,5 @@
%th
- @members.each do |member|
%tr
- %td= ember.login_name
+ %td= member.login_name
%td= member.email
diff --git a/app/views/admin/orders/_searchform.html.haml b/app/views/admin/orders/_searchform.html.haml
deleted file mode 100644
index e0a4dc22c..000000000
--- a/app/views/admin/orders/_searchform.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-= form_tag(url_for(controller: 'admin/orders', action: 'search'), method: :get, class: 'form-inline') do
- = label_tag :distance, "Search orders:", class: 'control-label'
- = text_field_tag :search_text
- = select_tag :search_by,
- options_for_select('Member': 'member', 'Referral code': 'referral_code',
- 'Order ID': 'order_id', 'Paypal Token': 'paypal_token',
- 'Paypal Payer ID': 'paypal_payer_id')
- = submit_tag "Search", class: 'btn btn-primary'
diff --git a/app/views/admin/orders/index.html.haml b/app/views/admin/orders/index.html.haml
deleted file mode 100644
index e5f67f6c3..000000000
--- a/app/views/admin/orders/index.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-- content_for :title, 'Admin Orders'
-
-= render "admin/orders/searchform"
diff --git a/app/views/admin/orders/search.html.haml b/app/views/admin/orders/search.html.haml
deleted file mode 100644
index 23c93d01a..000000000
--- a/app/views/admin/orders/search.html.haml
+++ /dev/null
@@ -1,41 +0,0 @@
-- content_for :title, 'Search Orders'
-
-= render "admin/orders/searchform"
-
-- unless @orders.empty?
- %h2
- Found
- = pluralize(@orders.size, "result")
-
- %table.table.table-striped
- %tr
- %th Member
- %th Order number
- %th Date completed
- %th Referral code
- %th Items
- %th
-
- - @orders.each do |order|
- %tr
- %td
- = link_to order.member.login_name, order.member
- = "(deleted)" if order.member.deleted_at
- %td= order.id
- %td
- - if order.completed_at
- = order.completed_at.to_s
- - else
- In progress
- %td
- = order.referral_code
- %td
- - unless order.order_items.empty?
- - order.order_items.each do |o|
- = o.quantity
- x
- = o.product.name
- @
- = price_with_currency(o.price)
- %br/
- %td= link_to 'Details', order, class: 'btn btn-default btn-xs'
diff --git a/app/views/crops/_actions.html.haml b/app/views/crops/_actions.html.haml
new file mode 100644
index 000000000..26f083d7b
--- /dev/null
+++ b/app/views/crops/_actions.html.haml
@@ -0,0 +1,8 @@
+- if can? :create, Planting
+ = link_to "Plant this", new_planting_path(crop_id: crop.id), class: 'btn btn-default'
+
+- 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'
diff --git a/app/views/crops/_image_with_popover.html.haml b/app/views/crops/_image_with_popover.html.haml
index 6744ccfe1..a8ce256bd 100644
--- a/app/views/crops/_image_with_popover.html.haml
+++ b/app/views/crops/_image_with_popover.html.haml
@@ -1,5 +1,5 @@
- cache crop do
- = link_to image_tag(crop.default_photo.present? ? crop.default_photo.thumbnail_url : 'placeholder_150.png',
+ = link_to image_tag(crop_image_path(crop),
alt: crop.name, class: 'image-responsive crop-image'),
crop.name,
rel: "popover",
diff --git a/app/views/crops/_index_card.html.haml b/app/views/crops/_index_card.html.haml
index 39b9e8da4..99b4a1a7e 100644
--- a/app/views/crops/_index_card.html.haml
+++ b/app/views/crops/_index_card.html.haml
@@ -1,7 +1,7 @@
.well
.row
.col-md-4
- = link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'),
+ = link_to image_tag(crop_image_path(crop),
alt: '',
class: 'img crop-image'),
crop
diff --git a/app/views/crops/_photos.html.haml b/app/views/crops/_photos.html.haml
index 927bf97c8..b799876a9 100644
--- a/app/views/crops/_photos.html.haml
+++ b/app/views/crops/_photos.html.haml
@@ -8,7 +8,7 @@
- unless crop.photos.empty?
%h3 Photos of #{crop.name} plants
.row
- - crop.photos.first(6).each do |p|
+ - crop.photos.order(date_taken: :desc).first(6).each do |p|
.col-xs-6.col-md-2
= render "photos/thumbnail", photo: p
.row
diff --git a/app/views/crops/_thumbnail.html.haml b/app/views/crops/_thumbnail.html.haml
index 1926b31d8..77793ef22 100644
--- a/app/views/crops/_thumbnail.html.haml
+++ b/app/views/crops/_thumbnail.html.haml
@@ -1,8 +1,8 @@
-.thumbnail
- .crop-thumbnail
- - if crop
- - cache cache_key_for(Crop, crop.id) do
- = link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'),
+- cache cache_key_for(Crop, crop.id) do
+ .thumbnail
+ .crop-thumbnail
+ - if crop
+ = link_to image_tag(crop_image_path(crop),
alt: crop.name, class: 'img'),
crop
.cropinfo
diff --git a/app/views/crops/show.html.haml b/app/views/crops/show.html.haml
index 270c0db2b..7700501fa 100644
--- a/app/views/crops/show.html.haml
+++ b/app/views/crops/show.html.haml
@@ -8,18 +8,14 @@
= tag("meta", property: "og:url", content: request.original_url)
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
+- content_for :scripts do
+ = javascript_include_tag "charts"
+
= render partial: 'approval_status_message', locals: { crop: @crop }
- if @crop.approved?
- content_for :buttonbar do
- - if can? :create, Planting
- = link_to "Plant this", new_planting_path(crop_id: @crop.id), class: 'btn btn-default'
-
- - 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'
+ = render 'crops/actions', crop: @crop
.row
.col-md-9
diff --git a/app/views/gardens/_actions.html.haml b/app/views/gardens/_actions.html.haml
index ecf434911..a5187991e 100644
--- a/app/views/gardens/_actions.html.haml
+++ b/app/views/gardens/_actions.html.haml
@@ -1,28 +1,29 @@
-- if can?(:edit, garden) || can?(:delete, garden)
- - if can? :edit, garden
- - if garden.active
- = link_to new_planting_path(garden_id: garden.id), class: 'btn btn-primary' 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',
- data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' }
- - else
- = link_to "Mark as active", garden_path(garden, garden: { active: 1 }),
- method: :put,
- class: 'btn btn-default'
- = link_to edit_garden_path(garden), class: 'btn btn-default', id: 'edit_garden_link' do
- %span.glyphicon.glyphicon-pencil{ title: "Edit garden" }
- Edit
+.garden-actions
+ - if can?(:edit, garden)
+ .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?' }
+ - else
+ = link_to "Mark as active", garden_path(garden, garden: { active: 1 }),
+ method: :put
+ = render 'shared/buttons/edit', path: edit_garden_path(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
+
- if can?(:destroy, garden)
- = link_to garden,
- method: :delete,
- data: { confirm: 'All plantings associated with this garden will also be deleted. Are you sure?' },
- class: 'btn btn-default', id: 'delete_garden_link' do
- %span.glyphicon.glyphicon-trash{ title: "Delete" }
- Delete
- - if can?(:edit, garden) && can?(:create, Photo)
- = link_to new_photo_path(type: "garden", id: garden.id),
- class: 'btn btn-primary' do
- %span.glyphicon.glyphicon-camera{ title: "Add Photo" }
- Add Photo
+ .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
diff --git a/app/views/gardens/_nav.haml b/app/views/gardens/_nav.haml
index 82ae83086..36c828b87 100644
--- a/app/views/gardens/_nav.haml
+++ b/app/views/gardens/_nav.haml
@@ -4,12 +4,7 @@
= link_to "Everyone's gardens", gardens_path, class: 'btn btn-default'
-
- = link_to gardens_active_tickbox_path(@owner, show_all) do
- = check_box_tag 'active', 'all', show_all
- include in-active
-
-- if can?(:create, Garden)
- = link_to 'Add a garden', new_garden_path, class: 'btn btn-primary'
-- unless current_member
- = render partial: 'shared/signin_signup', locals: { to: 'add a new garden' }
+ - 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'
diff --git a/app/views/gardens/_overview.html.haml b/app/views/gardens/_overview.html.haml
index 644115d16..b8f9ce54a 100644
--- a/app/views/gardens/_overview.html.haml
+++ b/app/views/gardens/_overview.html.haml
@@ -1,9 +1,7 @@
-
.panel.panel-success
.panel-heading
%h3.panel-title
= link_to garden.name, garden_path(garden)
-
.panel-body
.row
.col-md-2.col-xs-12.garden-info
@@ -11,15 +9,17 @@
.col-md-12.col-xs-6
= render 'gardens/photo', garden: garden
.col-md-12.col-xs-6
- = render 'gardens/actions', garden: garden
+ = display_garden_description(garden)
.col-md-10
.row
- if garden.plantings.current.size.positive?
- garden.plantings.current.includes(:crop).each do |planting|
.col-md-2.col-sm-6.col-xs-6
.hover-wrapper
- .text= render 'plantings/actions', planting: planting
+ .text
+ = render 'plantings/actions', planting: planting
= render partial: "plantings/thumbnail", locals: { planting: planting }
- else
- no plantings
- -# .panel-footer
+ .col-md-2.col-sm-6.col-xs-6 no plantings
+ - if can?(:edit, garden)
+ .panel-footer= render 'gardens/actions', garden: garden
diff --git a/app/views/gardens/_photo.html.haml b/app/views/gardens/_photo.html.haml
index caf5c04d1..b6d301d2e 100644
--- a/app/views/gardens/_photo.html.haml
+++ b/app/views/gardens/_photo.html.haml
@@ -1,3 +1,3 @@
-= link_to image_tag((garden.default_photo ? garden.default_photo.thumbnail_url : 'placeholder_150.png'),
+= link_to image_tag(garden_image_path(garden),
alt: garden.name, class: 'img-responsive'),
garden_path(garden)
diff --git a/app/views/gardens/_thumbnail.html.haml b/app/views/gardens/_thumbnail.html.haml
index 56c8c9614..a2e4ea7eb 100644
--- a/app/views/gardens/_thumbnail.html.haml
+++ b/app/views/gardens/_thumbnail.html.haml
@@ -8,7 +8,7 @@
.panel-body{ id: "gardens_panel_body" }
.row
.col-md-4
- = link_to image_tag((garden.default_photo ? garden.default_photo.thumbnail_url : 'placeholder_150.png'),
+ = link_to image_tag(garden_image_path(garden),
alt: garden.name, class: 'img'),
garden_path(garden)
.col-md-8
diff --git a/app/views/gardens/index.html.haml b/app/views/gardens/index.html.haml
index 4cf4f0705..a09de73ff 100644
--- a/app/views/gardens/index.html.haml
+++ b/app/views/gardens/index.html.haml
@@ -1,6 +1,10 @@
- content_for :title, @owner ? "#{@owner}'s gardens" : "Everyone's gardens"
-= render 'nav', owner: @owner, show_all: @show_all
+= render 'nav'
+
+= link_to gardens_active_tickbox_path(@owner, @show_all) do
+ = check_box_tag 'active', 'all', @show_all
+ include in-active
.pagination
= page_entries_info @gardens
diff --git a/app/views/gardens/show.html.haml b/app/views/gardens/show.html.haml
index 3928cfa58..8b45b0b16 100644
--- a/app/views/gardens/show.html.haml
+++ b/app/views/gardens/show.html.haml
@@ -11,11 +11,13 @@
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
- content_for :scripts do
+ = javascript_include_tag "charts"
= javascript_include_tag "https://www.gstatic.com/charts/loader.js"
.row
.col-md-9
- %p.btn-group= render 'gardens/actions', garden: @garden
+ = render 'gardens/actions', garden: @garden
+
- unless @garden.active
.alert.alert-warning
@@ -25,20 +27,21 @@
to plant something in this garden.
%div
- :growstuff_markdown
- #{strip_tags @garden.description}
- - unless @garden.description
- .row-fluid
- %p No description available yet.
+ %p
+ :growstuff_markdown
+ #{strip_tags @garden.description}
+ - unless @garden.description
+ .row-fluid
+ %p No description available yet.
- - if can? :edit, @garden
- %p
- Why not
- = link_to 'tell us more.', edit_garden_path(@garden)
+ - if can? :edit, @garden
+ %p
+ Why not
+ = link_to 'tell us more.', edit_garden_path(@garden)
%h3 Garden timeline
.row
- = timeline garden_timeline_path(@garden), adapter: "google"
+ .col-md-12= timeline garden_timeline_path(@garden), adapter: "google"
%h3 Current plantings in garden
.row
diff --git a/app/views/harvests/_actions.html.haml b/app/views/harvests/_actions.html.haml
new file mode 100644
index 000000000..5a2f1febc
--- /dev/null
+++ b/app/views/harvests/_actions.html.haml
@@ -0,0 +1,6 @@
+- if can?(:edit, harvest) || can?(:destroy, harvest)
+ .btn-group.harvest-actions
+ - 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)
diff --git a/app/views/harvests/_card.html.haml b/app/views/harvests/_card.html.haml
index e82d53725..52cfb3627 100644
--- a/app/views/harvests/_card.html.haml
+++ b/app/views/harvests/_card.html.haml
@@ -8,7 +8,7 @@
.panel-body
.row
.col-md-4
- = link_to image_tag((harvest.default_photo ? harvest.default_photo.thumbnail_url : 'placeholder_150.png'),
+ = link_to image_tag(harvest_image_path(harvest),
alt: harvest.crop.name, class: 'img'),
harvest
.col-md-8
@@ -21,9 +21,11 @@
%dd= display_quantity(harvest)
%dt Harvest date :
%dd= harvest.harvested_at
- .panel-footer
- %dt Description
- %dd.truncate
- = display_harvest_description(harvest)
- = if harvest.description.present?
- - link_to "Read more", harvest_path(harvest)
+ %dd Notes:
+ %dt=display_harvest_description(harvest)
+ - if harvest.planting.present?
+ %dt Harvested from
+ %dd= link_to(harvest.planting, planting_path(harvest.planting))
+ .row
+ .col-md-12
+ = render 'harvests/actions', harvest: harvest
diff --git a/app/views/harvests/_image_with_popover.haml b/app/views/harvests/_image_with_popover.haml
new file mode 100644
index 000000000..ebfb187f6
--- /dev/null
+++ b/app/views/harvests/_image_with_popover.haml
@@ -0,0 +1,9 @@
+= link_to image_tag(harvest_image_path(harvest),
+ alt: harvest.to_s,
+ class: 'image-responsive crop-image'),
+ harvest,
+ rel: "popover",
+ 'data-trigger': 'hover',
+ 'data-title': harvest.to_s,
+ 'data-content': render('harvests/popover', harvest: harvest),
+ 'data-html': true
diff --git a/app/views/harvests/_list.html.haml b/app/views/harvests/_list.html.haml
new file mode 100644
index 000000000..bb0178238
--- /dev/null
+++ b/app/views/harvests/_list.html.haml
@@ -0,0 +1,11 @@
+- harvests.each do |h|
+ - cache h do
+ .row
+ .col-md-3.col-xs-4{ style: 'padding-bottom: 6px' }
+ = render 'harvests/image_with_popover', harvest: h
+ .col-md-9.col-xs-4
+ = link_to h.crop, crop_path(h.crop)
+ %br/
+ %small
+ %i
+ = h.owner.location
diff --git a/app/views/harvests/_popover.html.haml b/app/views/harvests/_popover.html.haml
new file mode 100644
index 000000000..508413918
--- /dev/null
+++ b/app/views/harvests/_popover.html.haml
@@ -0,0 +1,3 @@
+%p
+ %small
+ = harvest.harvested_at
diff --git a/app/views/harvests/_thumbnail.html.haml b/app/views/harvests/_thumbnail.html.haml
index 9a9beac0c..4344aed7d 100644
--- a/app/views/harvests/_thumbnail.html.haml
+++ b/app/views/harvests/_thumbnail.html.haml
@@ -1,9 +1,10 @@
.thumbnail
.harvest-thumbnail
- if harvest
- = link_to image_tag((harvest.default_photo ? harvest.default_photo.thumbnail_url : 'placeholder_150.png'),
+ = link_to image_tag(harvest_image_path(harvest),
alt: harvest.crop.name, class: 'img'),
harvest
.harvestinfo
.harvest-name
= link_to harvest, harvest
+ = I18n.l(harvest.harvested_at.to_date)
diff --git a/app/views/harvests/show.html.haml b/app/views/harvests/show.html.haml
index 2f9114084..a584389fe 100644
--- a/app/views/harvests/show.html.haml
+++ b/app/views/harvests/show.html.haml
@@ -32,13 +32,7 @@
%b Quantity:
= display_quantity(@harvest)
- - if can?(:edit, @harvest) || can?(:destroy, @harvest)
- %p
- - if can? :edit, @harvest
- = link_to 'Edit', edit_harvest_path(@harvest), class: 'btn btn-default btn-xs'
- - if can? :destroy, @harvest
- = link_to 'Delete', @harvest, method: :delete, data: { confirm: 'Are you sure?' },
- class: 'btn btn-default btn-xs'
+ = render 'harvests/actions', harvest: @harvest
.col-md-6
= render partial: "crops/index_card", locals: { crop: @harvest.crop }
diff --git a/app/views/home/_crops.html.haml b/app/views/home/_crops.html.haml
index 6f881dc32..bfcbc9a71 100644
--- a/app/views/home/_crops.html.haml
+++ b/app/views/home/_crops.html.haml
@@ -1,28 +1,5 @@
-.row
- .col-md-8
- - cache cache_key_for(Crop, 'interesting'), expires_in: 1.day do
- %h2= t('.our_crops')
- .hidden-xs
- - Crop.interesting.includes(:scientific_names, :photos).first(8).each do |c|
- .col-md-3
- = render partial: 'crops/thumbnail', locals: { crop: c }
- .visible-xs
- - Crop.interesting.includes(:scientific_names, :photos).first(3).each do |c|
- .col-md-3
- = render partial: 'crops/thumbnail', locals: { crop: c }
-
- .col-md-4.hidden-xs
- - cache cache_key_for(Planting) do
- %h2= t('.recently_planted')
- = render 'plantings/list', plantings: Planting.includes(:owner, :photos).interesting.recent.first(6)
-
-.row
- .col-md-12
- - cache cache_key_for(Crop, 'recent') do
- %p{ style: 'margin-top: 11.25px' }
- %strong
- #{t('.recently_added')}:
- != Crop.recent.limit(12).map { |c| link_to(c, c) }.join(", ")
-
- %p.text-right
- = link_to "#{t('.view_all')} »", crops_path
+- cache cache_key_for(Crop, 'interesting'), expires_in: 1.day do
+ .row
+ %h2= t('.our_crops')
+ - Crop.interesting.includes(:scientific_names, :photos).limit(8).each do |c|
+ .col-md-4.col-sm-3.col-xs-6= render 'crops/thumbnail', crop: c
diff --git a/app/views/home/_discuss.html.haml b/app/views/home/_discuss.html.haml
index 36cc1d0f9..0ec3077e1 100644
--- a/app/views/home/_discuss.html.haml
+++ b/app/views/home/_discuss.html.haml
@@ -1,6 +1,6 @@
%h2= t('.discussion')
-- posts = Post.limit(6)
+- posts = Post.order(created_at: :desc).limit(6)
- if posts
= render "posts/summary", posts: posts, howmany: 6
diff --git a/app/views/home/_harvests.html.haml b/app/views/home/_harvests.html.haml
new file mode 100644
index 000000000..d4c2a1117
--- /dev/null
+++ b/app/views/home/_harvests.html.haml
@@ -0,0 +1,3 @@
+- cache cache_key_for(Harvest) do
+ %h2 Recently Harvested
+ = render 'harvests/list', harvests: Harvest.includes(:crop, :owner, :photos).has_photos.recent.first(5)
diff --git a/app/views/home/_members.html.haml b/app/views/home/_members.html.haml
index 0c786ca7b..c3a4392ba 100644
--- a/app/views/home/_members.html.haml
+++ b/app/views/home/_members.html.haml
@@ -1,13 +1,13 @@
- cache cache_key_for(Member) do
.hidden-xs
- - members = Member.interesting.first(6)
+ - members = Member.includes(plantings: :crop).interesting.first(6)
- if members.present?
%section
%h2= t('.title')
.member-cards
- members.each do |m|
- = render partial: "members/thumbnail", locals: { member: m }
+ = render "members/thumbnail", member: m
%p.text-right
= link_to "#{t('.view_all')} »", members_path
diff --git a/app/views/home/_plantings.html.haml b/app/views/home/_plantings.html.haml
new file mode 100644
index 000000000..595ad4586
--- /dev/null
+++ b/app/views/home/_plantings.html.haml
@@ -0,0 +1,3 @@
+- cache cache_key_for(Planting, 'home'), expires_in: 1.day do
+ %h2= t('.recently_planted')
+ = render 'plantings/list', plantings: Planting.includes(:crop, garden: :owner).has_photos.recent.limit(5)
diff --git a/app/views/home/_seeds.html.haml b/app/views/home/_seeds.html.haml
index 7469b90b0..d53759738 100644
--- a/app/views/home/_seeds.html.haml
+++ b/app/views/home/_seeds.html.haml
@@ -1,21 +1,22 @@
- cache cache_key_for(Seed, 'interesting'), expires_in: 1.day do
%h2= t('.title')
.row
- .col-md-8
- - Seed.includes(:owner, crop: :photos).order(created_at: :desc).interesting.first(6).each do |seed|
- .col-md-3
- .thumbnail
- - cache cache_key_for(Crop, seed.id) do
- = link_to image_tag((seed.default_photo ? seed.default_photo.thumbnail_url : 'placeholder_150.png'),
- alt: seed.crop.name, class: 'img'),
- seed
- .seedinfo
- = link_to seed.crop.name, seed
- .trade-to
- %p= seed.owner.location
- %p
+ - Seed.current.tradable.order(created_at: :desc).limit(6).each do |seed|
+ .col-md-2.col-sm-2.col-xs-6
+ .thumbnail.seed-thumbnail
+ - cache cache_key_for(Crop, seed.id) do
+ = link_to image_tag(seed_image_path(seed),
+ alt: seed.crop.name, class: 'img'),
+ seed
+ .seedinfo
+ = link_to seed.crop.name, seed
+ .trade-to
+ %p= seed.owner.location
+ %p
+ %small
Will trade to:
%br/
- #{seed.tradable_to}
+ %em= seed.tradable_to
+
%p.text-right
= link_to "#{t('.view_all')} »", seeds_path
diff --git a/app/views/home/index.html.haml b/app/views/home/index.html.haml
index 655fbd3fc..c28a8985b 100644
--- a/app/views/home/index.html.haml
+++ b/app/views/home/index.html.haml
@@ -1,9 +1,9 @@
-.row
+.homepage.row
.col-md-12
- if member_signed_in?
%h1= t('.welcome', site_name: ENV['GROWSTUFF_SITE_NAME'], member_name: current_member)
- = render partial: 'stats'
+ = render 'stats'
%p
.btn-group
= link_to t('.plant'), new_planting_path, class: 'btn btn-default'
@@ -14,12 +14,30 @@
- else
.hidden-xs
.jumbotron
- = render partial: 'blurb'
+ = render 'blurb'
.visible-xs
- = render partial: 'blurb'
+ = render 'blurb'
- = render partial: 'crops'
- = render partial: 'seeds'
- = render partial: 'members'
- = render partial: 'discuss'
+ .row
+ .col-md-6.col-sm-12
+ = render 'crops'
+ .col-md-3.col-sm-6
+ = render 'plantings'
+ .col-md-3.col-sm-6
+ = render 'harvests'
+ .col-md-12
+ - cache cache_key_for(Crop, 'recent') do
+ %p{ style: 'margin-top: 11.25px' }
+ %strong
+ #{t('.recently_added')}:
+ != Crop.recent.limit(30).map { |c| link_to(c, c) }.join(", ")
+ %p.text-right
+ = link_to "#{t('home.crops.view_all')} »", crops_path
+ .row
+ .col-md-12
+ = render 'seeds'
+ = render 'members'
+ .row
+ .col-md-12
+ = render 'discuss'
diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml
index 3eb0d8ca0..d2b8fd01c 100644
--- a/app/views/layouts/_header.html.haml
+++ b/app/views/layouts/_header.html.haml
@@ -47,7 +47,6 @@
%li= link_to t('.browse_members'), members_path
%li= link_to t('.posts'), posts_path
%li= link_to t('.forums'), forums_path
- %li= link_to t('.support_growstuff'), shop_path
- if member_signed_in?
%li.dropdown<
@@ -64,7 +63,6 @@
%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('.account'), orders_path
%li
- if current_member.notifications.unread_count.positive?
= link_to(t('.inbox_unread', unread_count: current_member.notifications.unread_count),
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index f96e3f22c..6eea27068 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -17,9 +17,7 @@
%small= yield(:subtitle)
- if content_for?(:buttonbar)
- %p
- .btn-group
- = yield(:buttonbar)
+ .btn-group.layout-actions= yield(:buttonbar)
= render partial: "shared/flash_messages", flash: flash
= yield
@@ -29,4 +27,5 @@
Javascripts
\==================================================
/ Placed at the end of the document so the pages load faster
+ = javascript_include_tag "application"
!= Growstuff::Application.config.analytics_code
diff --git a/app/views/members/_account.html.haml b/app/views/members/_account.html.haml
deleted file mode 100644
index cda792ace..000000000
--- a/app/views/members/_account.html.haml
+++ /dev/null
@@ -1,24 +0,0 @@
-%h3 Account details
-
-%p
- %strong Member since:
- = member.created_at.to_s(:date)
-
-%p
- %strong Account type:
- = member.account_type
- account
-
-%p
- %strong Last Login:
- = member.last_sign_in_at
-
-%p
- %strong Member Roles:
- %br
- - if member.role? :admin
- Administrator
- - if member.role? :crop_wrangler
- Crop Wrangler
- - else
- Member
diff --git a/app/views/members/_roles.html.haml b/app/views/members/_roles.html.haml
new file mode 100644
index 000000000..cbfd0b576
--- /dev/null
+++ b/app/views/members/_roles.html.haml
@@ -0,0 +1,9 @@
+%p
+ %strong Member Roles:
+ %br
+ - if member.role? :admin
+ Administrator
+ - if member.role? :crop_wrangler
+ Crop Wrangler
+ - unless (member.role?(:admin) || member.role?(:crop_wrangler))
+ Member
diff --git a/app/views/members/_stats.html.haml b/app/views/members/_stats.html.haml
index 346d71296..a2ebab47d 100644
--- a/app/views/members/_stats.html.haml
+++ b/app/views/members/_stats.html.haml
@@ -1,3 +1,10 @@
+%p
+ %strong Member since:
+ = member.created_at.to_s(:date)
+%p
+ %strong Last Login:
+ = member.last_sign_in_at
+
%h3 Activity
%ul.list-inline
@@ -33,4 +40,3 @@
= link_to pluralize(member.followers.size, "follower"), member_followers_path(member)
- else
0 followers
-
diff --git a/app/views/members/show.html.haml b/app/views/members/show.html.haml
index f0214a52f..478574b3b 100644
--- a/app/views/members/show.html.haml
+++ b/app/views/members/show.html.haml
@@ -10,8 +10,6 @@
- content_for :buttonbar do
- if can? :update, @member
= link_to 'Edit profile', edit_member_registration_path, class: 'btn btn-default'
- - if @member == current_member && !@member.paid?
- = link_to "Upgrade account", shop_path, class: 'btn btn-default'
- if can?(:create, Notification) && current_member != @member
= link_to 'Send message', new_notification_path(recipient_id: @member.id), class: 'btn btn-default'
@@ -33,7 +31,7 @@
= render partial: "gardens", locals: { member: @member, gardens: @gardens }
.col-md-3
= render partial: "avatar", locals: { member: @member }
- = render partial: "account", locals: { member: @member }
+ = render partial: "roles", locals: { member: @member }
= render partial: "stats", locals: { member: @member }
= render partial: "contact", locals: { member: @member,
twitter_auth: @twitter_auth,
diff --git a/app/views/orders/complete.html.haml b/app/views/orders/complete.html.haml
deleted file mode 100644
index e2f4b97ad..000000000
--- a/app/views/orders/complete.html.haml
+++ /dev/null
@@ -1,45 +0,0 @@
-- content_for :title, "Completed order"
-
-%p Thank you for your order.
-
-%p
- %strong Completed at:
- = @order.completed_at
-
-%p
- %strong Order number:
- = @order.id
-
-= render "shared/account_status"
-
-%h2 Order items
-
-%table.table.table-striped
- %tr
- %th Product
- %th Price
- %th Quantity
- %th Subtotal
- - total = 0
- - @order.order_items.each do |i|
- %tr
- %td= i.product.name
- %td
- = price_with_currency(i.price)
- %td= i.quantity
- %td
- - subtotal = i.price * i.quantity
- - total += subtotal
- = price_with_currency(subtotal)
-
- %tr
- %td
- %td
- %td
- %strong Total:
- %td
- %strong
- = price_with_currency(total)
-
-%p
- = link_to "View other orders/order history", orders_path
diff --git a/app/views/orders/index.html.haml b/app/views/orders/index.html.haml
deleted file mode 100644
index b4741c44e..000000000
--- a/app/views/orders/index.html.haml
+++ /dev/null
@@ -1,44 +0,0 @@
-- content_for :title, "Your Account"
-
-= render "shared/account_status"
-
-
-%h2 Orders
-
-
-- if current_member.orders.present?
-
- %p
- Your order history shows what you have bought via our
- = succeed "." do
- = link_to "shop", shop_path
-
- %table.table.table-striped
- %tr
- %th Order number
- %th Date completed
- %th Items
- %th
- - @orders.each do |order|
- %tr
- %td= order.id
- %td
- - if order.completed_at
- = order.completed_at.to_s
- - else
- In progress
- %td
- - unless order.order_items.empty?
- - order.order_items.each do |o|
- = o.quantity
- x
- = o.product.name
- @
- = price_with_currency(o.price)
- %br/
- %td= link_to 'Details', order, class: 'btn btn-default btn-xs'
-- else
- %p
- You have not made any orders. You can place an order via our
- = succeed "." do
- = link_to "shop", shop_path
diff --git a/app/views/orders/show.html.haml b/app/views/orders/show.html.haml
deleted file mode 100644
index 0998407f9..000000000
--- a/app/views/orders/show.html.haml
+++ /dev/null
@@ -1,84 +0,0 @@
-- content_for :title, @order.completed_at ? "Order details (##{@order.id})" : "Current order"
-
-%p
- %strong Order number:
- = @order.id
-
-%p
- %strong Ordered by:
- = link_to @order.member, @order.member
-
-%p
- %strong Date begun:
- = @order.created_at.to_s
-
-- if @order.completed_at
- %p
- %strong Date completed:
- = @order.completed_at.to_s
-
-- if @order.referral_code
- %p
- %strong Referral code:
- = @order.referral_code
-
-- if current_member.role? :admin
- %p
- %strong Paypal Express token:
- = @order.paypal_express_token
- %p
- %strong Paypal Express payer ID:
- = @order.paypal_express_payer_id
-
-%h2 Order items
-
-%table.table.table-striped
- %tr
- %th Product
- %th Price
- %th Quantity
- %th Subtotal
- - @order.order_items.each do |i|
- %tr
- %td= i.product.name
- %td
- = price_with_currency(i.price)
- %td= i.quantity
- %td
- - subtotal = i.price * i.quantity
- = price_with_currency(subtotal)
-
- %tr
- %td
- %td
- %td
- %strong Total:
- %td
- %strong
- = price_with_currency(@order.total)
- = forex_link(@order.total)
-
-- if @order.errors.any?
- .alert
- #error_explanation
- %h3
- = pluralize(@order.errors.size, "error")
- stopped you from checking out:
- %ul
- - @order.errors.full_messages.each do |msg|
- %li= msg
-
-- if can?(:complete, @order) || can?(:destroy, @order)
- = form_tag(checkout_order_path(@order), method: :get, class: 'form-inline') do
- %p
- - if can? :complete, @order
- = label_tag :referral_code, "Do you have a referral code?"
- = text_field_tag :referral_code, @order.referral_code, class: 'input-medium'
- = submit_tag "Checkout with PayPal", class: 'btn btn-primary'
- - if can? :destroy, @order
- = link_to 'Delete this order', @order, method: :delete,
- data: { confirm: 'Are you sure?' },
- class: 'btn btn-default'
- = link_to "View other orders/order history", orders_path, class: 'btn btn-default'
-
-%p
diff --git a/app/views/photos/_actions.html.haml b/app/views/photos/_actions.html.haml
new file mode 100644
index 000000000..878d985ef
--- /dev/null
+++ b/app/views/photos/_actions.html.haml
@@ -0,0 +1,6 @@
+- if can?(:edit, @photo) && can?(:destroy, @photo)
+ %p.photo-actions
+ - if can?(:edit, @photo)
+ = render 'shared/buttons/edit', path: edit_photo_path(@photo)
+ - if can?(:destroy, @photo)
+ = render 'shared/buttons/delete', path: photo_path(@photo)
diff --git a/app/views/photos/_item_photos.haml b/app/views/photos/_item_photos.haml
index 679871680..f0642c336 100644
--- a/app/views/photos/_item_photos.haml
+++ b/app/views/photos/_item_photos.haml
@@ -1,16 +1,14 @@
+%h2 Photos
+
- if photos.size.positive? || (can?(:edit, item) && can?(:create, Photo))
- %h2 Photos
- if photos.size.positive?
+ = page_entries_info photos
+ = will_paginate photos
.row
- .pagination
- = page_entries_info photos
- = will_paginate photos
- .row
- - photos.each do |photo|
- .col-md-2.six-across= render 'photos/thumbnail', photo: photo
- - if can?(:create, Photo) && can?(:edit, item)
- .col-md-2
- .thumbnail
- = link_to new_photo_path(type: type, id: item.id), class: 'btn btn-primary' do
- %span.glyphicon.glyphicon-camera{ title: "Add photo" }
- Add photo
+ - photos.each do |photo|
+ .col-xs-6.col-md-3.six-across= render 'photos/thumbnail', photo: photo
+
+- if can?(:create, Photo) && can?(:edit, item)
+ = link_to new_photo_path(type: type, id: item.id), class: 'btn btn-primary' do
+ %span.glyphicon.glyphicon-camera{ title: "Add photo" }
+ Add photo
diff --git a/app/views/photos/_thumbnail.html.haml b/app/views/photos/_thumbnail.html.haml
index 03a1f0c4c..3be4a26d6 100644
--- a/app/views/photos/_thumbnail.html.haml
+++ b/app/views/photos/_thumbnail.html.haml
@@ -1,10 +1,12 @@
-.thumbnail.photo-thumbnail
- = link_to image_tag(photo.thumbnail_url, alt: photo.title, class: 'img img-responsive'), photo
- .text
- %p
- = link_to photo.title, photo
- %br/
- %small
- %i
- by
- = link_to photo.owner, photo.owner
+.thumbnail
+ .photo-thumbnail
+ = link_to image_tag(photo.thumbnail_url, alt: photo.title, class: 'img img-responsive'), photo
+ .text
+ %p
+ = link_to photo.title, photo
+ %br/
+ %small
+ %i
+ by
+ = link_to photo.owner, photo.owner
+ = I18n.l(photo.created_at.to_date)
diff --git a/app/views/photos/show.html.haml b/app/views/photos/show.html.haml
index 7e52a11e9..3758883b6 100644
--- a/app/views/photos/show.html.haml
+++ b/app/views/photos/show.html.haml
@@ -12,15 +12,7 @@
%p= image_tag(@photo.fullsize_url, alt: @photo.title, class: 'img img-responsive')
.col-md-4
- %p
- - if can? :destroy, @photo
- = link_to @photo, method: :delete,
- data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-trash{ title: "Delete" }
-
- - if can? :edit, @photo
- = link_to edit_photo_path(@photo), class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-pencil{ title: "Edit" }
+ = render 'photos/actions', photo: @photo
%p
%strong Posted by:
= link_to @photo.owner, @photo.owner
diff --git a/app/views/plantings/_actions.html.haml b/app/views/plantings/_actions.html.haml
index b2c2d5f98..87eddc8cf 100644
--- a/app/views/plantings/_actions.html.haml
+++ b/app/views/plantings/_actions.html.haml
@@ -1,27 +1,12 @@
-- if can?(:edit, planting) || can?(:destroy, planting)
- - if can? :edit, planting
- = link_to edit_planting_path(planting), class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-pencil{ title: "Edit" }
- Edit
+- 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')
+
+ - 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 can? :destroy, planting
- = link_to planting, method: :delete,
- data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-trash{ title: "Delete" }
- Delete
-
- - unless 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
-
- - if can? :edit, planting
- = link_to new_planting_harvest_path(planting), class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-leaf{ title: "Harvest" }
- Harvest
-
- - if can?(:edit, planting) && can?(:create, Photo)
- = link_to new_photo_path(id: planting.id, type: 'planting'), class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-camera{ title: "Add photo" }
- Add photo
+ = render 'shared/buttons/delete', path: planting
diff --git a/app/views/plantings/_card.html.haml b/app/views/plantings/_card.html.haml
index a5469461a..0f9518e6c 100644
--- a/app/views/plantings/_card.html.haml
+++ b/app/views/plantings/_card.html.haml
@@ -8,7 +8,7 @@
.panel-body
.row
.col-xs-12.col-md-5
- = link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'),
+ = link_to image_tag(planting_image_path(planting),
alt: planting.crop_id, class: 'img img-responsive'),
planting
.col-xs-12.col-md-7
@@ -35,24 +35,6 @@
%dt Finish expected:
%dd= planting.finish_predicted_at if planting.finish_predicted_at.present?
-
%p= render 'plantings/progress', planting: planting, show_explanation: true
-
- = link_to 'Details', planting_path(planting),
- class: 'btn btn-default btn-xs'
-
- - if can?(:edit, planting) && can?(:create, Harvest)
- = link_to 'Harvest', new_planting_harvest_path(planting),
- class: 'btn btn-default btn-xs'
-
- - if can?(:edit, planting) && !planting.finished
- = link_to "Mark as finished",
- planting_path(planting, planting: { finished: 1 }),
- method: :put,
- class: 'btn btn-default btn-xs append-date'
-
- - if can? :destroy, planting
- = link_to planting, method: :delete,
- data: { confirm: 'Are you sure?' },
- class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-trash{ title: "Delete" }
+ .row
+ .col-md-12= render 'plantings/actions', planting: planting
diff --git a/app/views/plantings/_descendants.html.haml b/app/views/plantings/_descendants.html.haml
new file mode 100644
index 000000000..27e81c6b8
--- /dev/null
+++ b/app/views/plantings/_descendants.html.haml
@@ -0,0 +1,14 @@
+%h2 Seeds saved from this planting
+
+- if planting.child_seeds.size.positive?
+ .row
+ - planting.child_seeds.each do |seed|
+ .col-xs-6.col-sm-4.col-md-3
+ = render 'seeds/thumbnail', seed: seed
+- else
+ %p No seeds saved
+
+- if planting.active? && can?(:create, Seed) && can?(:edit, planting)
+ = link_to new_planting_seed_path(planting), class: 'btn btn-primary' do
+ %span.glyphicon.glyphicon-heart{ title: "Add photo" }
+ Save seeds
diff --git a/app/views/plantings/_form.html.haml b/app/views/plantings/_form.html.haml
index de2e55c30..874b5329b 100644
--- a/app/views/plantings/_form.html.haml
+++ b/app/views/plantings/_form.html.haml
@@ -13,15 +13,19 @@
.form-group.required
= f.label :crop, 'What did you plant?', class: 'control-label col-md-2'
.col-md-8
- = auto_suggest @planting, :crop, class: 'form-control', default: @crop
- %span.help-inline
- Can't find what you're looking for?
- = link_to "Request new crops.", new_crop_path
+ - if @seed.present?
+ = link_to @seed, seed_path(@seed)
+ = f.hidden_field :parent_seed_id, value: @seed.id
+ - else
+ = auto_suggest @planting, :crop, class: 'form-control', default: @crop
+ %span.help-inline
+ Can't find what you're looking for?
+ = link_to "Request new crops.", new_crop_path
.form-group.required
= f.label :garden_id, 'Where did you plant it?', class: 'control-label col-md-2'
.col-md-8
= collection_select(:planting, :garden_id,
- Garden.active.where(owner_id: current_member),
+ current_member.gardens.active.order("lower(gardens.name)"),
:id, :name,
selected: @planting.garden_id || @garden.id,
class: 'form-control')
diff --git a/app/views/plantings/_harvests.html.haml b/app/views/plantings/_harvests.html.haml
index 5edf14a3d..a845e980e 100644
--- a/app/views/plantings/_harvests.html.haml
+++ b/app/views/plantings/_harvests.html.haml
@@ -1,12 +1,13 @@
+%h2 Harvests
- if planting.harvests.empty?
- %p no harvests yet
+ %p No harvests
- else
.row
- planting.harvests.order(created_at: :desc).includes(:crop).each do |harvest|
- .col-xs-6.col-md-2
+ .col-xs-6.col-sm-4.col-md-3
= render 'harvests/thumbnail', harvest: harvest
- - if can? :edit, planting
- .col-xs-6.col-md-2
- = link_to new_planting_harvest_path(planting), class: 'btn btn-primary' do
- %span.glyphicon.glyphicon-leaf{ title: "Harvest" }
- Harvest
+
+- if planting.active? && can?(:edit, planting)
+ = link_to new_planting_harvest_path(planting), class: 'btn btn-primary' do
+ %span.glyphicon.glyphicon-leaf{ title: "Harvest" }
+ Harvest
diff --git a/app/views/plantings/_image_with_popover.html.haml b/app/views/plantings/_image_with_popover.html.haml
index d958a9d41..70bfc1836 100644
--- a/app/views/plantings/_image_with_popover.html.haml
+++ b/app/views/plantings/_image_with_popover.html.haml
@@ -1,10 +1,10 @@
- cache planting do
- = link_to image_tag(planting.photos.present? ? planting.photos.first.thumbnail_url : 'placeholder_150.png',
+ = link_to image_tag(planting_image_path(planting),
alt: planting.to_s,
class: 'image-responsive crop-image'),
planting,
rel: "popover",
'data-trigger': 'hover',
'data-title': planting.to_s,
- 'data-content': render(partial: 'plantings/popover', locals: { planting: planting }),
+ 'data-content': render('plantings/popover', planting: planting),
'data-html': true
diff --git a/app/views/plantings/_list.html.haml b/app/views/plantings/_list.html.haml
index cf678c8a6..aa7dcf9fa 100644
--- a/app/views/plantings/_list.html.haml
+++ b/app/views/plantings/_list.html.haml
@@ -1,9 +1,9 @@
- plantings.each do |p|
- cache p do
.row
- .col-md-3{ style: 'padding-bottom: 6px' }
- = render partial: 'plantings/image_with_popover', locals: { planting: p }
- .col-md-9
+ .col-md-3.col-xs-4.homepage-listing
+ = render 'plantings/image_with_popover', planting: p
+ .col-md-9.col-xs-4
= link_to p.crop, p.crop
in
= succeed "'s" do
@@ -12,4 +12,4 @@
%br/
%small
%i
- = p.owner.location
+ = p.location
diff --git a/app/views/plantings/_thumbnail.html.haml b/app/views/plantings/_thumbnail.html.haml
index 15ff2553e..e34c653da 100644
--- a/app/views/plantings/_thumbnail.html.haml
+++ b/app/views/plantings/_thumbnail.html.haml
@@ -1,7 +1,7 @@
.thumbnail
.planting-thumbnail
- if planting
- = link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'),
+ = link_to image_tag(planting_image_path(planting),
alt: planting.crop.name, class: 'img'),
planting
.plantinginfo
diff --git a/app/views/plantings/show.html.haml b/app/views/plantings/show.html.haml
index 88789ed5a..49be10fa5 100644
--- a/app/views/plantings/show.html.haml
+++ b/app/views/plantings/show.html.haml
@@ -9,9 +9,11 @@
= tag("meta", property: "og:url", content: request.original_url)
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
-%p= render 'plantings/actions', planting: @planting
+- content_for :buttonbar do
+ = render 'plantings/actions', planting: @planting
+
.row.planting
- .col-md-6
+ .col-xs-12.col-sm-6
%dl.dl-horizontal.planting-attributes
%dt Owner:
%dd
@@ -26,14 +28,17 @@
%dd
= link_to "#{@planting.owner}'s", @planting.owner
= link_to @planting.garden, @planting.garden
- - unless @planting.owner.location.blank?
+ - if @planting.owner.location.present?
(#{@planting.owner.location})
%dt Quantity:
%dd= display_planting_quantity(@planting)
- - unless @planting.planted_from.blank?
- %dt Planted from:
- %dd= display_planted_from(@planting)
+ %dt Planted from:
+ %dd
+ - if @planting.parent_seed
+ = link_to @planting.parent_seed, seed_path(@planting.parent_seed)
+ - else
+ = display_planted_from(@planting)
%dt Sun or shade?
%dd
@@ -64,23 +69,23 @@
%dt Last Harvest:
%dd #{@planting.days_to_last_harvest} days after planting
+ %dt Progress
+ %dd= render 'plantings/progress', planting: @planting, show_explanation: true
- %h2 Progress
- %p= render 'plantings/progress', planting: @planting, show_explanation: true
- %h2 Harvests
- %p= render 'plantings/harvests', planting: @planting
-
- .col-md-6
+ .col-xs-12.col-sm-6
= render partial: "crops/index_card", locals: { crop: @planting.crop }
- if @planting.owner.location
%p
%small
View other plantings, members and more near
= link_to @planting.owner.location, place_path(@planting.owner.location, anchor: "plantings")
-- if @planting.description
- %h2 Notes
-
- :growstuff_markdown
- #{ @planting.description != "" ? strip_tags(@planting.description) : "No description given." }
-
-= render 'photos/item_photos', item: @planting, type: 'planting', photos: @photos
+.row
+ .col-md-6
+ - if @planting.description
+ %h2 Notes
+ :growstuff_markdown
+ #{ @planting.description != "" ? strip_tags(@planting.description) : "No description given." }
+ = render 'plantings/harvests', planting: @planting
+ = render 'plantings/descendants', planting: @planting
+ .col-md-6
+ = render 'photos/item_photos', item: @planting, type: 'planting', photos: @photos
diff --git a/app/views/products/_form.html.haml b/app/views/products/_form.html.haml
deleted file mode 100644
index a3aa8a2f0..000000000
--- a/app/views/products/_form.html.haml
+++ /dev/null
@@ -1,32 +0,0 @@
-= form_for @product do |f|
- - if @product.errors.any?
- #error_explanation
- %h2
- = pluralize(@product.errors.size, "error")
- prohibited this product from being saved:
- %ul
- - @product.errors.full_messages.each do |msg|
- %li= msg
-
- .field
- = f.label :name
- = f.text_field :name, class: 'form-control'
- .field
- = f.label :description
- = f.text_area :description, class: 'form-control'
- .field
- = f.label :min_price, "Minimum price (in cents)"
- = f.text_field :min_price
- .field
- = f.label :recommended_price, "Recommended price (in cents)"
- = f.text_field :recommended_price
- .field
- = f.label :account_type
- = collection_select(:product, :account_type_id, AccountType.all, :id,
- :name, selected: @product.account_type_id)
- .field
- = f.label :paid_months
- = f.text_field :paid_months
- .form-group
- .actions
- = f.submit 'Save'
diff --git a/app/views/products/edit.html.haml b/app/views/products/edit.html.haml
deleted file mode 100644
index 84ebcb870..000000000
--- a/app/views/products/edit.html.haml
+++ /dev/null
@@ -1,7 +0,0 @@
-- content_for :title, "Editing product"
-
-= render 'form'
-
-= link_to 'Show', @product
-\|
-= link_to 'Back', products_path
diff --git a/app/views/products/index.html.haml b/app/views/products/index.html.haml
deleted file mode 100644
index 4945d130e..000000000
--- a/app/views/products/index.html.haml
+++ /dev/null
@@ -1,29 +0,0 @@
-- content_for :title, "Listing products"
-
-%table
- %tr
- %th Name
- %th Description
- %th Min price
- %th Recommended price
- %th Account type
- %th Paid months
- %th
- %th
- %th
-
- - @products.each do |product|
- %tr
- %td= product.name
- %td= product.description
- %td= product.min_price
- %td= product.recommended_price
- %td= product.account_type ? product.account_type.name : ""
- %td= product.paid_months
- %td= link_to 'Show', product
- %td= link_to 'Edit', edit_product_path(product)
- %td= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' }
-
-%br
-
-= link_to 'New Product', new_product_path
diff --git a/app/views/products/new.html.haml b/app/views/products/new.html.haml
deleted file mode 100644
index 57b944d9a..000000000
--- a/app/views/products/new.html.haml
+++ /dev/null
@@ -1,5 +0,0 @@
-- content_for :title, "New product"
-
-= render 'form'
-
-= link_to 'Back', products_path
diff --git a/app/views/products/show.html.haml b/app/views/products/show.html.haml
deleted file mode 100644
index 61b35519f..000000000
--- a/app/views/products/show.html.haml
+++ /dev/null
@@ -1,25 +0,0 @@
-%p#notice= notice
-
-%p
- %b Name:
- = @product.name
-%p
- %b Description:
- :growstuff_markdown
- #{strip_tags(@product.description)}
-%p
- %b Min price:
- = @product.min_price
-%p
- %b Recommended price:
- = @product.recommended_price
-%p
- %b Account type:
- = @product.account_type.name
-%p
- %b Paid months:
- = @product.paid_months
-
-= link_to 'Edit', edit_product_path(@product)
-\|
-= link_to 'Back', products_path
diff --git a/app/views/seeds/_actions.html.haml b/app/views/seeds/_actions.html.haml
index 9584182f0..803b63b2d 100644
--- a/app/views/seeds/_actions.html.haml
+++ b/app/views/seeds/_actions.html.haml
@@ -1,11 +1,15 @@
-- if can? :edit, @seed
- = link_to edit_seed_path(@seed), class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-pencil{ title: "Edit" }
- Edit
- = link_to new_photo_path(id: seed.id, type: 'seed'), class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-camera{ title: "Add photo" }
- Add photo
-- if can? :destroy, @seed
- = link_to @seed, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs' do
- %span.glyphicon.glyphicon-trash{ title: "Delete" }
- Delete
+
+- 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')
+
+ - if can?(:create, Planting) && seed.active?
+ = link_to new_planting_path(seed_id: seed), class: 'btn btn-default btn-xs' do
+ %span.glyphicon.glyphicon-grain{ title: "Plant seeds" }
+ Plant seeds
+
+ = render 'shared/buttons/finish_seeds', seed: seed
+
+- if can? :destroy, seed
+ = render 'shared/buttons/delete', path: seed
diff --git a/app/views/seeds/_card.html.haml b/app/views/seeds/_card.html.haml
new file mode 100644
index 000000000..8cb70f64f
--- /dev/null
+++ b/app/views/seeds/_card.html.haml
@@ -0,0 +1,32 @@
+.panel.panel-success
+ .panel-heading
+ %h3.panel-title
+ = link_to seed, seed
+ - if can? :edit, seed
+ %a.pull-right{ href: edit_seed_path(seed), role: "button", id: "edit_seed_glyphicon" }
+ %span.glyphicon.glyphicon-pencil{ title: "Edit" }
+ .panel-body
+ .row
+ .col-md-4
+ = link_to image_tag(seed_image_path(seed),
+ alt: seed.crop.name, class: 'img'),
+ seed.crop
+ .col-md-8
+ %dl.dl-horizontal
+ %dt Crop :
+ %dd= link_to seed.crop.name, seed.crop
+ - if seed.parent_planting.present?
+ %dt Saved from
+ %dd= link_to seed.parent_planting, planting_path(seed.parent_planting)
+ %dt Plant before :
+ %dd= seed.plant_before
+ %dt Quantity :
+ %dd= seed.quantity
+ %dt Will trade to :
+ %dd= seed.tradable_to
+ %dt From location :
+ %dd= seed.owner.location
+ %dt Owner :
+ %dd= link_to seed.owner.login_name, seed.owner
+ .col-md-12
+ %p= render 'seeds/actions', seed: seed
diff --git a/app/views/seeds/_descendants.html.haml b/app/views/seeds/_descendants.html.haml
new file mode 100644
index 000000000..1736d0bca
--- /dev/null
+++ b/app/views/seeds/_descendants.html.haml
@@ -0,0 +1,13 @@
+%h2 Plants grown from these seeds
+- if @seed.child_plantings
+ .row
+ - seed.child_plantings.each do |planting|
+ .col-md-3
+ = render 'plantings/thumbnail', planting: planting
+- else
+ %p No plants grown yet.
+
+- if can?(:create, Planting) && can?(:edit, seed)
+ = link_to new_seed_planting_path(seed), class: 'btn btn-primary' do
+ %span.glyphicon.glyphicon-grain{ title: "Plant seeds" }
+ Plant seeds
diff --git a/app/views/seeds/_form.html.haml b/app/views/seeds/_form.html.haml
index b7cb3ea36..9bd2dd280 100644
--- a/app/views/seeds/_form.html.haml
+++ b/app/views/seeds/_form.html.haml
@@ -9,14 +9,17 @@
%ul
- @seed.errors.full_messages.each do |msg|
%li= msg
-
.form-group.required
= f.label :crop, 'Crop:', class: 'control-label col-md-2'
.col-md-8
- = auto_suggest @seed, :crop, class: 'form-control', default: @crop
- %span.help-inline
- Can't find what you're looking for?
- = link_to "Request new crops.", new_crop_path
+ - if @planting
+ = link_to @planting, planting_path(@planting)
+ = f.hidden_field :parent_planting_id, value: @planting.id
+ - else
+ = auto_suggest @seed, :crop, class: 'form-control', default: @crop
+ %span.help-inline
+ Can't find what you're looking for?
+ = link_to "Request new crops.", new_crop_path
.form-group
= f.label :quantity, 'Quantity:', class: 'control-label col-md-2'
.col-md-2
@@ -28,6 +31,19 @@
= f.text_field :plant_before, class: 'add-datepicker form-control',
value: @seed.plant_before ? @seed.plant_before.to_s(:ymd) : ''
= render partial: 'shared/form_optional'
+ .form-group
+ = f.label :finished, 'Mark as finished', class: 'control-label col-md-2'
+ .col-md-8
+ = f.check_box :finished
+ = render partial: 'shared/form_optional'
+ %span.help-block
+ = t('.finish_helper')
+ .form-group
+ = f.label :finished_at, 'Finished at:', class: 'control-label col-md-2'
+ .col-md-2
+ = f.text_field :finished_at, class: 'add-datepicker form-control',
+ value: @seed.finished_at ? @seed.finished_at.to_s(:ymd) : ''
+ = render partial: 'shared/form_optional'
.form-group
= f.label :days_until_maturity_min, 'Days until maturity:', class: 'control-label col-md-2'
%fieldset
diff --git a/app/views/seeds/_thumbnail.html.haml b/app/views/seeds/_thumbnail.html.haml
index edd464e57..38aa66d65 100644
--- a/app/views/seeds/_thumbnail.html.haml
+++ b/app/views/seeds/_thumbnail.html.haml
@@ -1,31 +1,14 @@
-.panel.panel-success
- .panel-heading
- %h3.panel-title
- = link_to "#{seed.owner.login_name}'s seed", seed
- - if can? :edit, seed
- %a.pull-right{ href: edit_seed_path(seed), role: "button", id: "edit_seed_glyphicon" }
- %span.glyphicon.glyphicon-pencil{ title: "Edit" }
- .panel-body
- .row
- .col-md-4
- = link_to image_tag((seed.crop.default_photo ? seed.crop.default_photo.thumbnail_url : 'placeholder_150.png'),
- alt: seed.crop.name, class: 'img'),
- seed.crop
- .col-md-8
- %dl.dl-horizontal
- %dt Crop :
- %dd= link_to seed.crop.name, seed.crop
- %dt Plant before :
- %dd= seed.plant_before
- %dt Quantity :
- %dd= seed.quantity
- %dt Will trade to :
- %dd= seed.tradable_to
- %dt From location :
- %dd= seed.owner.location
- %dt Owner :
- %dd= link_to seed.owner.login_name, seed.owner
- .panel-footer
- %dt Description
- %dd
- = display_seed_description(seed)
+.thumbnail
+ .seed-thumbnail
+ = link_to image_tag(seed_image_path(seed),
+ alt: seed.crop.name, class: 'img'),
+ seed_path(seed)
+ .seedinfo
+ .seed-name
+ = link_to seed, seed_path(seed)
+ .trade-to
+ %p= seed.owner.location
+ %p
+ Will trade to:
+ %br/
+ = seed.tradable_to
diff --git a/app/views/seeds/index.html.haml b/app/views/seeds/index.html.haml
index 3108bfc56..e7e1ec3e3 100644
--- a/app/views/seeds/index.html.haml
+++ b/app/views/seeds/index.html.haml
@@ -28,7 +28,7 @@
- unless @seeds.empty?
- @seeds.each do |seed|
.col-md-6
- = render partial: 'seeds/thumbnail', locals: { seed: seed }
+ = render 'seeds/card', seed: seed
.pagination
= page_entries_info @seeds
diff --git a/app/views/seeds/show.html.haml b/app/views/seeds/show.html.haml
index e15ffb46d..681a21324 100644
--- a/app/views/seeds/show.html.haml
+++ b/app/views/seeds/show.html.haml
@@ -9,47 +9,56 @@
= 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 'seeds/actions', seed: @seed
+
.row
.col-md-6
- %p
- %b Owner:
- = link_to @seed.owner, @seed.owner
- —
- = link_to "view all #{@seed.owner}'s seeds", seeds_by_owner_path(owner: @seed.owner.slug)
- %p
- %b Quantity:
- = @seed.quantity.blank? ? "not specified" : @seed.quantity
- %p
- %b Plant before:
- = @seed.plant_before.to_s
- %p
- %b Days until maturity:
- = render partial: 'days_until_maturity', locals: { seed: @seed }
- %p
- %b Organic?
- = @seed.organic
- %p
- %b GMO?
- = @seed.gmo
- %p
- %b Heirloom?
- = @seed.heirloom
- %p
- %b Will trade:
- = @seed.tradable_to
- - if @seed.owner.location.blank?
- (from unspecified location)
- - if current_member == @seed.owner
- = link_to "Set Location", edit_registration_path(current_member), class: 'btn btn-default btn-xs'
- - else
- (from
- = succeed ")" do
- = link_to @seed.owner.location, place_path(@seed.owner.location, anchor: "seeds")
+ %dl.dl-horizontal
+ %dt Owner
+ %dd
+ = link_to @seed.owner, @seed.owner
+ —
+ = link_to "view all #{@seed.owner}'s seeds",
+ seeds_by_owner_path(owner: @seed.owner.slug)
+ %dt Quantity:
+ %dd= @seed.quantity.blank? ? "not specified" : @seed.quantity
+ %dt Plant before:
+ %dd= @seed.plant_before.to_s
+ -if @seed.finished_at
+ %dt Finished at:
+ %dd= @seed.finished_at.to_s
+ %dt Days until maturity:
+ %dd= render partial: 'days_until_maturity', locals: { seed: @seed }
+ %dt Organic?
+ %dd= @seed.organic
+ %dt GMO?
+ %dd= @seed.gmo
+ %dt Heirloom?
+ %dd= @seed.heirloom
+ %dt Will trade:
+ %dd
+ = @seed.tradable_to
+ - if @seed.owner.location.blank?
+ (from unspecified location)
+ - if current_member == @seed.owner
+ = link_to "Set Location", edit_registration_path(current_member), class: 'btn btn-default btn-xs'
+ - else
+ (from
+ = succeed ")" do
+ = link_to @seed.owner.location, place_path(@seed.owner.location, anchor: "seeds")
- %p
- %b Description:
- :growstuff_markdown
- #{ @seed.description != "" ? strip_tags(@seed.description) : "No description given." }
+ %dt When?
+ %dd
+ = @seed.created_at
+ - if @seed.parent_planting
+ %dt Saved from planting:
+ %dd
+ = link_to @seed.parent_planting, planting_path(@seed.parent_planting)
+ %dt Description:
+ %dd
+ :growstuff_markdown
+ #{ @seed.description != "" ? strip_tags(@seed.description) : "No description given." }
- if current_member
- if @seed.tradable? && current_member != @seed.owner
@@ -60,9 +69,9 @@
- else
= render 'shared/signin_signup', to: 'request seeds'
- - if can?(:edit, @seed) || can?(:destroy, @seed)
- %p
- = render 'actions', seed: @seed
+ = render 'seeds/descendants', seed: @seed
+ = render 'photos/item_photos', item: @seed, type: 'seed', photos: @photos
+
.col-md-6
= render partial: "crops/index_card", locals: { crop: @seed.crop }
- if @seed.owner.location
@@ -75,5 +84,3 @@
Or
= link_to "purchase seeds via Ebay",
crop_ebay_seeds_url(@seed.crop), target: "_blank", rel: "noopener noreferrer"
-
-= render 'photos/item_photos', item: @seed, type: 'seed', photos: @photos
diff --git a/app/views/shared/_account_status.html.haml b/app/views/shared/_account_status.html.haml
deleted file mode 100644
index a39870956..000000000
--- a/app/views/shared/_account_status.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-%h2 Your current account status
-
-%p
- %strong Account type:
- = current_member.account_type.name
-
-- if current_member.account.paid_until_string
- %p
- %strong Paid until:
- = current_member.account.paid_until_string
-
-- unless current_member.paid?
- = link_to "Upgrade and support #{ENV['GROWSTUFF_SITE_NAME']}", shop_path, class: 'btn btn-primary'
diff --git a/app/views/shared/buttons/_add_photo.haml b/app/views/shared/buttons/_add_photo.haml
new file mode 100644
index 000000000..71e97c0e9
--- /dev/null
+++ b/app/views/shared/buttons/_add_photo.haml
@@ -0,0 +1,4 @@
+- if can?(:create, Photo)
+ = link_to path, class: 'btn btn-default btn-xs' do
+ %span.glyphicon.glyphicon-camera{ title: "Add photo" }
+ Add photo
diff --git a/app/views/shared/buttons/_delete.haml b/app/views/shared/buttons/_delete.haml
new file mode 100644
index 000000000..b7490837b
--- /dev/null
+++ b/app/views/shared/buttons/_delete.haml
@@ -0,0 +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
diff --git a/app/views/shared/buttons/_edit.haml b/app/views/shared/buttons/_edit.haml
new file mode 100644
index 000000000..87d464023
--- /dev/null
+++ b/app/views/shared/buttons/_edit.haml
@@ -0,0 +1,3 @@
+= link_to path, class: 'btn btn-default btn-xs' do
+ %span.glyphicon.glyphicon-pencil{ title: "Edit" }
+ Edit
diff --git a/app/views/shared/buttons/_finish_planting.html.haml b/app/views/shared/buttons/_finish_planting.html.haml
new file mode 100644
index 000000000..9a3b6ce75
--- /dev/null
+++ b/app/views/shared/buttons/_finish_planting.html.haml
@@ -0,0 +1,5 @@
+- unless planting.finished
+ = link_to planting_path(planting, planting: { finished: 1 }),
+ method: :put, class: 'btn btn-default btn-xs append-date' do
+ %span.glyphicon.glyphicon-ok{ title: "Finished" }
+ Mark as finished
diff --git a/app/views/shared/buttons/_finish_seeds.haml b/app/views/shared/buttons/_finish_seeds.haml
new file mode 100644
index 000000000..211e3ec8b
--- /dev/null
+++ b/app/views/shared/buttons/_finish_seeds.haml
@@ -0,0 +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
diff --git a/app/views/shared/buttons/_harvest_planting.haml b/app/views/shared/buttons/_harvest_planting.haml
new file mode 100644
index 000000000..c90e163ad
--- /dev/null
+++ b/app/views/shared/buttons/_harvest_planting.haml
@@ -0,0 +1,4 @@
+- planting.active? && if can?(:create, Harvest) && can?(:edit, planting)
+ = link_to new_planting_harvest_path(planting), class: 'btn btn-default btn-xs' do
+ %span.glyphicon.glyphicon-leaf{ title: "Harvest" }
+ Harvest
diff --git a/app/views/shared/buttons/_save_seeds.haml b/app/views/shared/buttons/_save_seeds.haml
new file mode 100644
index 000000000..00d5febb0
--- /dev/null
+++ b/app/views/shared/buttons/_save_seeds.haml
@@ -0,0 +1,4 @@
+- if planting.active?
+ = link_to new_planting_seed_path(planting), class: 'btn btn-default btn-xs' do
+ %span.glyphicon.glyphicon-heart{ title: "Save seeds" }
+ Save seeds
diff --git a/app/views/shop/index.html.haml b/app/views/shop/index.html.haml
deleted file mode 100644
index 6266050f0..000000000
--- a/app/views/shop/index.html.haml
+++ /dev/null
@@ -1,83 +0,0 @@
-- content_for :title, t('.title')
-
-%p
- Growstuff relies on your support to build and run this open source
- platform for food growers. We do not have outside investment, and do
- not accept ads. Instead, we offer paid memberships, which give you
- access to premium features, and ensure that we focus our efforts on
- keeping you, our members, happy.
-
-%p
- We are currently developing a number of advanced features for paid
- members. We will announce our progress on these in our
- = link_to "Feedback and Support forum", "http://www.growstuff.org/forums/growstuff-feedback-support"
- as well as via other channels.
-
-%p
- All our accounts are priced on a sliding scale. You can choose how
- much you want to pay. Remember, your subscription supports an open
- source, open data platform supporting home food growers and promoting
- sustainable food systems!
-
-- if current_member && current_member.paid?
- %h2 Thank you for supporting Growstuff
-
- %p You currently have a paid membership, and can't buy another one at this time.
-
- = render "shared/account_status"
-
-- elsif @order && !@order.order_items.empty?
- %h2 Your current order
-
- %p
- You currently have the following item in your cart:
- %strong
- = @most_recent_item.product
- @
- = price_with_currency(@most_recent_item.price)
-
- %p
- = link_to "View order and checkout", order_path(@order)
- or
- = succeed "." do
- = link_to 'delete this order', @order, method: :delete,
- data: { confirm: 'Are you sure?' }
-
-- else
- - @products.each do |p|
- %h2= p.name
-
- %div
- :growstuff_markdown
- #{ strip_tags p.description }
-
- %p
- Pay what you want, starting at
- = succeed "." do
- = price_with_currency(p.min_price)
- = forex_link(p.min_price)
- - if p.recommended_price
- Recommended price:
- = succeed "." do
- = price_with_currency(p.recommended_price)
- = forex_link(p.recommended_price)
-
- %div
- - if can? :create, Order
-
- = form_for @order_item do |f|
- .field
- = f.text_field :price, value: price_in_dollars(p.recommended_price || p.min_price)
- .field
- = f.hidden_field :product_id, value: p.id
- .field
- = f.hidden_field :quantity, value: 1
- .actions
- = f.submit 'Buy', class: 'btn btn-primary'
-
- - else
- Please
- = link_to "sign in", new_member_session_path
- or
- = link_to "sign up", new_member_registration_path
- to purchase.
diff --git a/config/application.rb b/config/application.rb
index 3a07ca429..0a00a917a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -44,9 +44,6 @@ module Growstuff
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
- # Configure a default account type
- config.default_account_type = "Free"
-
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
diff --git a/config/application.yml.example b/config/application.yml.example
index 4aa23e439..ba343b6d0 100644
--- a/config/application.yml.example
+++ b/config/application.yml.example
@@ -57,11 +57,6 @@ GROWSTUFF_TWITTER_SECRET: ""
GROWSTUFF_FLICKR_KEY: ""
GROWSTUFF_FLICKR_SECRET: ""
-# Paypal is used for payments, obviously.
-GROWSTUFF_PAYPAL_USERNAME: "dummy"
-GROWSTUFF_PAYPAL_PASSWORD: "dummy"
-GROWSTUFF_PAYPAL_SIGNATURE: "dummy"
-
# https://developers.facebook.com/
GROWSTUFF_FACEBOOK_KEY: ""
GROWSTUFF_FACEBOOK_SECRET: ""
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 39abd19f1..363c0e32a 100644
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -72,17 +72,6 @@ Rails.application.configure do
config.mapbox_map_id = 'growstuff.i3n2il6a'
config.mapbox_access_token = 'pk.eyJ1IjoiZ3Jvd3N0dWZmIiwiYSI6IkdxMkx4alUifQ.n0igaBsw97s14zMa0lwKCA'
- config.after_initialize do
- ActiveMerchant::Billing::Base.mode = :test
- paypal_options = {
- login: ENV['GROWSTUFF_PAYPAL_USERNAME'] || 'dummy',
- password: ENV['GROWSTUFF_PAYPAL_PASSWORD'] || 'dummy',
- signature: ENV['GROWSTUFF_PAYPAL_SIGNATURE'] || 'dummy'
- }
- ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
- ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
- end
-
config.action_controller.action_on_unpermitted_parameters = :raise
config.active_job.queue_adapter = :sidekiq
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 99e25d577..9d377db43 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -104,17 +104,6 @@ Rails.application.configure do
config.mapbox_map_id = 'growstuff.i3n2c4ie'
config.mapbox_access_token = 'pk.eyJ1IjoiZ3Jvd3N0dWZmIiwiYSI6IkdxMkx4alUifQ.n0igaBsw97s14zMa0lwKCA'
- config.after_initialize do
- ActiveMerchant::Billing::Base.mode = :production
- paypal_options = {
- login: ENV['GROWSTUFF_PAYPAL_USERNAME'],
- password: ENV['GROWSTUFF_PAYPAL_PASSWORD'],
- signature: ENV['GROWSTUFF_PAYPAL_SIGNATURE']
- }
- ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
- ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
- end
-
config.active_job.queue_adapter = :sidekiq
# Do not dump schema after migrations.
diff --git a/config/environments/staging.rb b/config/environments/staging.rb
index ce1eeaf7c..aa2afd565 100644
--- a/config/environments/staging.rb
+++ b/config/environments/staging.rb
@@ -89,16 +89,5 @@ Rails.application.configure do
config.mapbox_map_id = 'growstuff.i3n2hao7'
config.mapbox_access_token = 'pk.eyJ1IjoiZ3Jvd3N0dWZmIiwiYSI6IkdxMkx4alUifQ.n0igaBsw97s14zMa0lwKCA'
- config.after_initialize do
- ActiveMerchant::Billing::Base.mode = :test
- paypal_options = {
- login: ENV['GROWSTUFF_PAYPAL_USERNAME'],
- password: ENV['GROWSTUFF_PAYPAL_PASSWORD'],
- signature: ENV['GROWSTUFF_PAYPAL_SIGNATURE']
- }
- ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalGateway.new(paypal_options)
- ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
- end
-
config.active_job.queue_adapter = :sidekiq
end
diff --git a/config/environments/test.rb b/config/environments/test.rb
index 43a86a23a..617338127 100644
--- a/config/environments/test.rb
+++ b/config/environments/test.rb
@@ -48,13 +48,6 @@ Rails.application.configure do
config.analytics_code = ''
config.currency = 'AUD'
end
-
- config.after_initialize do
- require "active_merchant/ext/paypal_bogus_gateway"
- ActiveMerchant::Billing::Base.mode = :test
- ::STANDARD_GATEWAY = ActiveMerchant::Billing::PaypalBogusGateway.new
- ::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalBogusGateway.new
- end
end
Geocoder.configure(lookup: :test)
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index 4b828e80c..60484d4a4 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -12,3 +12,4 @@ Rails.application.config.assets.paths << Rails.root.join('node_modules')
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
+Rails.application.config.assets.precompile += %w(charts.js)
diff --git a/config/locales/en.yml b/config/locales/en.yml
index d2848cecd..d5d3364a6 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1,11 +1,5 @@
---
en:
- account:
- update: Account detail was successfully updated.
- account_types:
- created: Account type was successfully created.
- deleted: Account type was successfully deleted.
- updated: Account type was successfully updated.
activerecord:
models:
comment:
@@ -99,7 +93,6 @@ en:
open:
ad_free_linktext: ad-free
api_docs_linktext: API documentation
- buy_account_linktext: buying a paid account
creative_commons_linktext: Creative Commons license
get_involved_body_html: >
We believe in collaboration, and work closely with our members and the wider food-growing community.
@@ -213,9 +206,6 @@ en:
default: Everyone's seeds
owner_seeds: "%{owner} seeds"
string: "%{crop} seeds belonging to %{owner}"
- shop:
- index:
- title: Shop
unauthorized:
create:
all: Please sign in or sign up to create a %{subject}.
diff --git a/config/routes.rb b/config/routes.rb
index af84f5a07..7ef095562 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -23,16 +23,19 @@ Rails.application.routes.draw do
resources :plantings do
resources :harvests
+ resources :seeds
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' => 'gardens#timeline'
+ get 'timeline' => 'charts/gardens#timeline'
end
get '/gardens/owner/:owner' => 'gardens#index', as: 'gardens_by_owner'
- resources :seeds
+ resources :seeds do
+ resources :plantings
+ end
get '/seeds/owner/:owner' => 'seeds#index', as: 'seeds_by_owner'
get '/seeds/crop/:crop' => 'seeds#index', as: 'seeds_by_crop'
@@ -52,9 +55,9 @@ Rails.application.routes.draw do
get 'crops/search' => 'crops#search', as: 'crops_search'
resources :crops do
get 'photos' => 'photos#index'
- get 'sunniness' => 'crops#sunniness'
- get 'planted_from' => 'crops#planted_from'
- get 'harvested_for' => 'crops#harvested_for'
+ get 'sunniness' => 'charts/crops#sunniness'
+ get 'planted_from' => 'charts/crops#planted_from'
+ get 'harvested_for' => 'charts/crops#harvested_for'
end
resources :comments
@@ -72,17 +75,6 @@ Rails.application.routes.draw do
get '/places/search' => 'places#search', as: 'search_places'
get '/places/:place' => 'places#show', as: 'place'
- # everything for paid accounts etc
- resources :account_types
- resources :accounts
- resources :orders
- get 'orders/:id/checkout' => 'orders#checkout', as: 'checkout_order'
- get 'orders/:id/complete' => 'orders#complete', as: 'complete_order'
- get 'orders/:id/cancel' => 'orders#cancel', as: 'cancel_order'
-
- resources :order_items
- resources :products
-
resources :likes, only: %i(create destroy)
get "home/index"
@@ -91,15 +83,11 @@ Rails.application.routes.draw do
get 'auth/:provider/callback' => 'authentications#create'
get 'members/auth/:provider/callback' => 'authentications#create'
- get '/shop' => 'shop#index'
- get '/shop/:action' => 'shop#:action'
-
- # comfy_route :cms_admin, path: '/admin/cms'
+ comfy_route :cms_admin, path: '/admin/cms'
namespace :admin do
resources :members
end
- get '/admin/orders' => 'admin/orders#index'
- get '/admin/orders/:action' => 'admin/orders#:action'
+
get '/admin' => 'admin#index'
get '/admin/newsletter' => 'admin#newsletter', as: :admin_newsletter
get '/admin/:action' => 'admin#:action'
diff --git a/db/migrate/20180118112809_add_datetaken_to_photos.rb b/db/migrate/20180118112809_add_datetaken_to_photos.rb
new file mode 100644
index 000000000..42afaf23b
--- /dev/null
+++ b/db/migrate/20180118112809_add_datetaken_to_photos.rb
@@ -0,0 +1,5 @@
+class AddDatetakenToPhotos < ActiveRecord::Migration
+ def change
+ add_column :photos, :date_taken, :datetime
+ end
+end
diff --git a/db/migrate/20180205000612_remove_shop.rb b/db/migrate/20180205000612_remove_shop.rb
new file mode 100644
index 000000000..fa0fc8793
--- /dev/null
+++ b/db/migrate/20180205000612_remove_shop.rb
@@ -0,0 +1,9 @@
+class RemoveShop < ActiveRecord::Migration
+ def up
+ drop_table :order_items
+ drop_table :orders
+ drop_table :products
+ drop_table :account_types
+ drop_table :accounts
+ end
+end
diff --git a/db/migrate/20180213005731_seed_usage.rb b/db/migrate/20180213005731_seed_usage.rb
new file mode 100644
index 000000000..f768451d2
--- /dev/null
+++ b/db/migrate/20180213005731_seed_usage.rb
@@ -0,0 +1,22 @@
+class SeedUsage < ActiveRecord::Migration
+ def change
+ # # seed can be all sown, meaning there is none left
+ add_column(:seeds, :finished, :boolean, default: false)
+ add_column(:seeds, :finished_at, :date, default: nil)
+
+ # plantings can be grown from a seed
+ add_column(:plantings, :parent_seed_id, :integer)
+ add_foreign_key(:plantings, :seeds,
+ column: :parent_seed_id,
+ primary_key: :id,
+ name: :parent_seed,
+ on_delete: :nullify)
+ # seeds can be harvest from planting
+ add_column(:seeds, :parent_planting_id, :integer)
+ add_foreign_key(:seeds, :plantings,
+ column: :parent_planting_id,
+ primary_key: :id,
+ name: :parent_planting,
+ on_delete: :nullify)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index dec08cc13..0651dbc56 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,27 +10,11 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20171129041341) do
+ActiveRecord::Schema.define(version: 20180213005731) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
- create_table "account_types", id: :serial, force: :cascade do |t|
- t.string "name", null: false
- t.boolean "is_paid"
- t.boolean "is_permanent_paid"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- create_table "accounts", id: :serial, force: :cascade do |t|
- t.integer "member_id", null: false
- t.integer "account_type_id"
- t.datetime "paid_until"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
create_table "alternate_names", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.integer "crop_id", null: false
@@ -339,25 +323,6 @@ ActiveRecord::Schema.define(version: 20171129041341) do
t.datetime "updated_at"
end
- create_table "order_items", id: :serial, force: :cascade do |t|
- t.integer "order_id"
- t.integer "product_id"
- t.integer "price"
- t.integer "quantity"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- create_table "orders", id: :serial, force: :cascade do |t|
- t.datetime "created_at"
- t.datetime "updated_at"
- t.datetime "completed_at"
- t.integer "member_id"
- t.string "paypal_express_token"
- t.string "paypal_express_payer_id"
- t.string "referral_code"
- end
-
create_table "orders_products", id: false, force: :cascade do |t|
t.integer "order_id"
t.integer "product_id"
@@ -384,6 +349,7 @@ ActiveRecord::Schema.define(version: 20171129041341) do
t.string "license_url"
t.string "link_url", null: false
t.string "flickr_photo_id"
+ t.datetime "date_taken"
end
create_table "photos_plantings", id: false, force: :cascade do |t|
@@ -421,6 +387,7 @@ ActiveRecord::Schema.define(version: 20171129041341) do
t.integer "lifespan"
t.integer "days_to_first_harvest"
t.integer "days_to_last_harvest"
+ t.integer "parent_seed_id"
t.index ["slug"], name: "index_plantings_on_slug", unique: true
end
@@ -436,17 +403,6 @@ ActiveRecord::Schema.define(version: 20171129041341) do
t.index ["slug"], name: "index_posts_on_slug", unique: true
end
- create_table "products", id: :serial, force: :cascade do |t|
- t.string "name", null: false
- t.text "description", null: false
- t.integer "min_price", null: false
- t.datetime "created_at"
- t.datetime "updated_at"
- t.integer "account_type_id"
- t.integer "paid_months"
- t.integer "recommended_price"
- end
-
create_table "roles", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.text "description"
@@ -479,9 +435,14 @@ ActiveRecord::Schema.define(version: 20171129041341) do
t.text "organic", default: "unknown"
t.text "gmo", default: "unknown"
t.text "heirloom", default: "unknown"
+ t.boolean "finished", default: false
+ t.date "finished_at"
+ t.integer "parent_planting_id"
t.index ["slug"], name: "index_seeds_on_slug", unique: true
end
add_foreign_key "harvests", "plantings"
add_foreign_key "photographings", "photos"
+ add_foreign_key "plantings", "seeds", column: "parent_seed_id", name: "parent_seed", on_delete: :nullify
+ add_foreign_key "seeds", "plantings", column: "parent_planting_id", name: "parent_planting", on_delete: :nullify
end
diff --git a/db/seeds.rb b/db/seeds.rb
index a91c19048..4781bc80f 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -7,12 +7,9 @@ def load_data
Crop.transaction do
# for all Growstuff sites, including production ones
load_roles
- load_basic_account_types
create_cropbot
load_crops
load_plant_parts
- load_paid_account_types
- load_products
# We don't load these in an environment except development to
# prevent creating users in the wild - especially admins - with
@@ -44,20 +41,6 @@ def load_roles
@wrangler = Role.create(name: 'Crop Wrangler')
end
-def load_basic_account_types
- puts "Adding 'free' and 'staff' account types..."
- AccountType.create!(
- name: "Free",
- is_paid: false,
- is_permanent_paid: false
- )
- AccountType.create!(
- name: "Staff",
- is_paid: true,
- is_permanent_paid: true
- )
-end
-
def load_test_users # rubocop:disable Metrics/AbcSize
puts "Loading test users..."
@@ -141,39 +124,6 @@ def create_cropbot
@cropbot_user.skip_confirmation!
@cropbot_user.roles << @wrangler
@cropbot_user.save!
- @cropbot_user.account.account_type = AccountType.find_by(name: "Staff")
- @cropbot_user.account.save
-end
-
-def load_paid_account_types
- puts "Adding 'paid' and 'seed' account types..."
- @paid_account = AccountType.create!(
- name: "Paid",
- is_paid: true,
- is_permanent_paid: false
- )
- @seed_account = AccountType.create!(
- name: "Seed",
- is_paid: true,
- is_permanent_paid: true
- )
-end
-
-def load_products
- puts "Adding products..."
- Product.create!(
- name: "Annual subscription",
- description: "Paid account, 1 year",
- min_price: 3000,
- account_type_id: @paid_account.id,
- paid_months: 12
- )
- Product.create!(
- name: "Seed account",
- description: "Paid account, in perpetuity",
- min_price: 15_000,
- account_type_id: @seed_account.id
- )
end
def load_plant_parts
diff --git a/lib/tasks/growstuff.rake b/lib/tasks/growstuff.rake
index 03b2e3d0e..e6ec0650d 100644
--- a/lib/tasks/growstuff.rake
+++ b/lib/tasks/growstuff.rake
@@ -51,7 +51,7 @@ namespace :growstuff do
send_on_day = 3 # wednesday
every_n_weeks = 2 # send fortnightly
- if Time.zone.today.cwday == send_on_day and Time.zone.today.cweek % every_n_weeks == 0
+ if (Time.zone.today.cwday == send_on_day) && (Time.zone.today.cweek % every_n_weeks == 0)
Member.confirmed.find_each do |m|
Notifier.planting_reminder(m).deliver_now!
end
@@ -62,7 +62,7 @@ namespace :growstuff do
# this fixes up anyone who has erroneously wound up with a 0,0 lat/long
task depopulate_null_island: :environment do
Member.find_each do |m|
- if m.location and (m.latitude.nil? and m.longitude.nil?)
+ if m.location && (m.latitude.nil? && m.longitude.nil?)
m.geocode
m.save
end
@@ -88,84 +88,13 @@ namespace :growstuff do
# site is small and there aren't many of them, so it shouldn't matter
# for this one-off script.
Garden.all.each do |g|
- if g.name.nil? or g.name =~ /^\s*$/
+ if g.name.nil? || g.name =~ /^\s*$/
g.name = "Garden"
g.save
end
end
end
- desc "June 2013: create account types and products."
- task setup_shop: :environment do
- puts "Adding account types..."
- AccountType.find_or_create_by(
- name: "Free",
- is_paid: false,
- is_permanent_paid: false
- )
- @paid_account = AccountType.find_or_create_by(
- name: "Paid",
- is_paid: true,
- is_permanent_paid: false
- )
- @seed_account = AccountType.find_or_create_by(
- name: "Seed",
- is_paid: true,
- is_permanent_paid: true
- )
- @staff_account = AccountType.find_or_create_by(
- name: "Staff",
- is_paid: true,
- is_permanent_paid: true
- )
-
- puts "Adding products..."
- Product.find_or_create_by(
- name: "Annual subscription",
- description: "An annual subscription gives you access "\
- "to paid account features for one year. Does not auto-renew.",
- min_price: 3000,
- account_type_id: @paid_account.id,
- paid_months: 12
- )
- Product.find_or_create_by(
- name: "Seed account",
- description: "A seed account helps Growstuff grow in its "\
- "early days. It gives you all the features of "\
- "a paid account, in perpetuity. This account "\
- "type never expires.",
- min_price: 15_000,
- account_type_id: @seed_account.id
- )
-
- puts "Giving each member an account record..."
- Member.all.each do |m|
- Account.create(member_id: m.id) unless m.account
- end
-
- puts "Making Skud a staff account..."
- @skud = Member.find_by(login_name: 'Skud')
- if @skud
- @skud.account.account_type = @staff_account
- @skud.account.save
- end
-
- puts "Done setting up shop."
- end
-
- desc "June 2013: replace nil account_types with free accounts"
- task nil_account_type: :environment do
- free = AccountType.find_by(name: "Free")
- raise "Free account type not found: run rake growstuff:oneoff:setup_shop"\
- unless free
- Account.all.each do |a|
- unless a.account_type
- a.account_type = free
- a.save
- end
- end
- end
-
desc "July 2013: replace nil seed.tradable_to with nowhere"
task tradable_to_nowhere: :environment do
Seed.all.each do |s|
@@ -187,8 +116,6 @@ namespace :growstuff do
task set_default_crop_creator: :environment do
cropbot = Member.find_by(login_name: "cropbot")
raise "cropbot not found: create cropbot member on site or run rake db:seed" unless cropbot
- cropbot.account.account_type = AccountType.find_by(name: "Staff") # set this just because it's nice
- cropbot.account.save
Crop.find_each do |crop|
unless crop.creator
crop.creator = cropbot
diff --git a/package-lock.json b/package-lock.json
index e7029eb14..baf5adb61 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -177,17 +177,6 @@
"dev": true,
"requires": {
"color-convert": "1.9.1"
- },
- "dependencies": {
- "color-convert": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
- "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
- "dev": true,
- "requires": {
- "color-name": "1.1.3"
- }
- }
}
},
"supports-color": {
@@ -270,6 +259,15 @@
"integrity": "sha1-dg8Cck9fCRG+fO+jSo4OEMXYUSo=",
"dev": true
},
+ "color-convert": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+ "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
@@ -1199,7 +1197,7 @@
"semver": {
"version": "5.4.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
- "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
+ "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=",
"dev": true
},
"shebang-command": {
diff --git a/spec/controllers/account_types_controller_spec.rb b/spec/controllers/account_types_controller_spec.rb
deleted file mode 100644
index 010c8bf1f..000000000
--- a/spec/controllers/account_types_controller_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'rails_helper'
-
-describe AccountTypesController do
- subject { response }
-
- context 'anon' do
- describe '#index' do
- before { get :index }
- it { is_expected.not_to be_success }
- end
- end
- context 'member' do
- login_member(:member)
- describe '#index' do
- before { get :index }
- it { is_expected.not_to be_success }
- end
- end
- context 'admin' do
- login_member(:admin_member)
- describe '#index' do
- let!(:aaa) { FactoryBot.create :account_type, name: 'aaa' }
- let!(:zzz) { FactoryBot.create :account_type, name: 'zzz' }
-
- before { get :index }
- it { is_expected.to be_success }
- it { expect(assigns[:account_types].first).to eql(aaa) }
- it { expect(assigns[:account_types].last).to eql(zzz) }
- end
- end
-end
diff --git a/spec/controllers/accounts_controller_spec.rb b/spec/controllers/accounts_controller_spec.rb
deleted file mode 100644
index 2b4222f1d..000000000
--- a/spec/controllers/accounts_controller_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'rails_helper'
-
-describe AccountsController do
- login_member(:admin_member)
-
- def valid_attributes
- { "paid_until" => Time.now }
- end
-
- def create_account
- # account details are automatically created when you create a new
- # member; creating them manually will just cause errors as only one is
- # allowed. This method has been left here in case it's useful in
- # future.
- member = FactoryBot.create(:member)
- member.account
- end
-end
diff --git a/spec/controllers/admin/orders_controller_spec.rb b/spec/controllers/admin/orders_controller_spec.rb
deleted file mode 100644
index 207112f39..000000000
--- a/spec/controllers/admin/orders_controller_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'rails_helper'
-
-describe Admin::OrdersController do
- login_member(:admin_member)
-
- describe "GET search" do
- it "assigns @orders" do
- order = FactoryBot.create(:order)
- get :search, params: { search_by: 'order_id', search_text: order.id }
- assigns(:orders).should eq([order])
- end
-
- it "sets an error message if nothing found" do
- get :search, params: { search_by: 'order_id', search_text: 'foo' }
- flash[:alert].should have_text "Couldn't find order with"
- end
- end
-end
diff --git a/spec/controllers/charts/crops_controller_spec b/spec/controllers/charts/crops_controller_spec
new file mode 100644
index 000000000..5a4aa6548
--- /dev/null
+++ b/spec/controllers/charts/crops_controller_spec
@@ -0,0 +1,19 @@
+require 'rails_helper'
+
+describe Charts::CropsController do
+ describe 'GET charts' do
+ let(:crop) { FactoryBot.create :crop }
+ describe 'sunniness' do
+ before { get :sunniness, crop_id: crop.to_param }
+ it { expect(response).to be_success }
+ end
+ describe 'planted_from' do
+ before { get :planted_from, crop_id: crop.to_param }
+ it { expect(response).to be_success }
+ end
+ describe 'harvested_for' do
+ before { get :harvested_for, crop_id: crop.to_param }
+ it { expect(response).to be_success }
+ end
+ end
+end
diff --git a/spec/controllers/charts/gardens_controller_spec.rb b/spec/controllers/charts/gardens_controller_spec.rb
new file mode 100644
index 000000000..daa50a811
--- /dev/null
+++ b/spec/controllers/charts/gardens_controller_spec.rb
@@ -0,0 +1,23 @@
+require 'rails_helper'
+
+describe Charts::GardensController do
+ include Devise::Test::ControllerHelpers
+ let(:valid_params) { { name: 'My second Garden' } }
+
+ let(:garden) { FactoryBot.create :garden }
+ context "when not signed in" do
+ describe 'GET timeline' do
+ before { get :timeline, garden_id: garden.to_param }
+ it { expect(response).to be_success }
+ end
+ end
+ context "when signed in" do
+ before(:each) { sign_in member }
+
+ let!(:member) { FactoryBot.create(:member) }
+ describe 'GET timeline' do
+ before { get :timeline, garden_id: garden.to_param }
+ it { expect(response).to be_success }
+ end
+ end
+end
diff --git a/spec/controllers/order_items_controller_spec.rb b/spec/controllers/order_items_controller_spec.rb
deleted file mode 100644
index 9064a0f2a..000000000
--- a/spec/controllers/order_items_controller_spec.rb
+++ /dev/null
@@ -1,57 +0,0 @@
-require 'rails_helper'
-
-describe OrderItemsController do
- login_member(:admin_member)
-
- let(:member) { FactoryBot.create(:member) }
- let(:product) { FactoryBot.create(:product) }
- let(:order) { FactoryBot.create(:order, member: member) }
- let(:order_item) do
- FactoryBot.create(:order_item,
- order: order,
- product: product,
- price: product.min_price)
- end
-
- context 'signed in' do
- before { sign_in member }
-
- describe "POST create" do
- describe "redirects to order" do
- before do
- post :create, params: {
- order_item: { order_id: order.id, product_id: product.id, price: product.min_price }
- }
- end
- it { expect(response).to redirect_to(OrderItem.last.order) }
- it { expect(OrderItem.last.order).to be_an_instance_of Order }
- end
-
- describe 'creates an order for you' do
- it do
- expect do
- post :create, params: {
- order_item: {
- product_id: product.id,
- price: product.min_price
- }
- }
- end.to change(Order, :count).by(1)
- end
- end
-
- describe "with non-int price" do
- it "converts 3.33 to 333 cents" do
- order = FactoryBot.create(:order, member: member)
- product = FactoryBot.create(:product, min_price: 1)
- expect do
- post :create, params: {
- order_item: { order_id: order.id, product_id: product.id, price: 3.33 }
- }
- end.to change(OrderItem, :count).by(1)
- OrderItem.last.price.should eq 333
- end
- end
- end
- end
-end
diff --git a/spec/controllers/orders_controller_spec.rb b/spec/controllers/orders_controller_spec.rb
deleted file mode 100644
index a36365aad..000000000
--- a/spec/controllers/orders_controller_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-require 'rails_helper'
-
-describe OrdersController do
- login_member(:admin_member)
-
- def valid_attributes
- { "member_id" => 1 }
- end
-
- def valid_session
- {}
- end
-
- describe "GET checkout" do
- it 'sets the referral_code' do
- member = FactoryBot.create(:member)
- sign_in member
- order = Order.create!(member_id: member.id)
- get :checkout, params: { id: order.to_param, referral_code: 'FOOBAR' }
- order.reload
- order.referral_code.should eq 'FOOBAR'
- end
-
- it "redirects to Paypal" do
- member = FactoryBot.create(:member)
- sign_in member
- order = Order.create!(member_id: member.id)
- get :checkout, params: { id: order.to_param }
- response.status.should eq 302
- response.redirect_url.should match(/paypal\.com/)
- end
- end
-
- describe "GET complete" do
- it "assigns the requested order as @order" do
- member = FactoryBot.create(:member)
- sign_in member
- order = Order.create!(member_id: member.id)
- get :complete, params: { id: order.to_param }
- assigns(:order).should eq(order)
- end
- end
-
- describe "DELETE destroy" do
- it "redirects to the shop" do
- member = FactoryBot.create(:member)
- sign_in member
- order = Order.create!(member_id: member.id)
- delete :destroy, params: { id: order.id }
- response.should redirect_to(shop_url)
- end
- end
-end
diff --git a/spec/controllers/plantings_controller_spec.rb b/spec/controllers/plantings_controller_spec.rb
index c1e4cd72b..8567a3386 100644
--- a/spec/controllers/plantings_controller_spec.rb
+++ b/spec/controllers/plantings_controller_spec.rb
@@ -85,6 +85,14 @@ describe PlantingsController do
it { expect(assigns(:planting).planted_at).to eq Time.zone.today }
end
+ context 'with parent seed' do
+ let(:seed) { FactoryBot.create :seed, owner: member }
+ before { get :new, seed_id: seed.to_param }
+ it { expect(assigns(:seed)).to eq(seed) }
+ end
+ end
+
+ describe 'POST :create' do
describe "sets the owner automatically" do
before { post :create, params: { planting: valid_attributes } }
it { expect(assigns(:planting).owner).to eq subject.current_member }
diff --git a/spec/controllers/products_controller_spec.rb b/spec/controllers/products_controller_spec.rb
deleted file mode 100644
index 173ef9ba4..000000000
--- a/spec/controllers/products_controller_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'rails_helper'
-
-describe ProductsController do
- login_member(:admin_member)
-
- def valid_attributes
- {
- name: "product name",
- description: 'some description',
- min_price: 9.99
- }
- end
-
- def valid_session
- {}
- end
-end
diff --git a/spec/controllers/seeds_controller_spec.rb b/spec/controllers/seeds_controller_spec.rb
index 123516e43..3ff8051f1 100644
--- a/spec/controllers/seeds_controller_spec.rb
+++ b/spec/controllers/seeds_controller_spec.rb
@@ -1,6 +1,8 @@
require 'rails_helper'
describe SeedsController do
+ let(:owner) { FactoryBot.create(:member) }
+
describe "GET index" do
let(:owner) { FactoryBot.create(:member) }
describe "picks up owner from params" do
@@ -8,4 +10,20 @@ describe SeedsController do
it { expect(assigns(:owner)).to eq(owner) }
end
end
+
+ describe 'GET new' do
+ before { sign_in owner }
+
+ it { expect(response).to be_success }
+
+ context 'no parent planting' do
+ before { get :new }
+ end
+
+ context 'with parent planting' do
+ let(:planting) { FactoryBot.create :planting, owner: owner }
+ before { get :new, planting_id: planting.to_param }
+ it { expect(assigns(:planting)).to eq(planting) }
+ end
+ end
end
diff --git a/spec/controllers/shop_controller_spec.rb b/spec/controllers/shop_controller_spec.rb
deleted file mode 100644
index f7e23b25f..000000000
--- a/spec/controllers/shop_controller_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-require 'rails_helper'
-
-describe ShopController do
- let!(:product1) { FactoryBot.create(:product, name: 'aaa') }
- let!(:product2) { FactoryBot.create(:product, name: 'zzz') }
-
- describe "GET index" do
- describe 'not logged in' do
- before { get :index, params: {} }
-
- describe "assigns all products as @products ordered by name" do
- it { expect(assigns(:products)).to eq([product1, product2]) }
- end
-
- describe "assigns a new @order_item to build forms" do
- it { expect(assigns(:order_item)).to be_an_instance_of OrderItem }
- end
-
- describe "assigns @order as nil if the user doesn't have one" do
- it { expect(assigns(:order)).to be_nil }
- end
- end
- describe 'logged in' do
- describe "assigns @order as current_order if there is one" do
- let(:member) { FactoryBot.create(:member) }
- let!(:order) { FactoryBot.create(:order, member: member) }
-
- before do
- sign_in member
- get :index, params: {}
- end
- it { expect(assigns(:order)).to eq order }
- end
- end
- end
-end
diff --git a/spec/factories/account_types.rb b/spec/factories/account_types.rb
deleted file mode 100644
index 66717492f..000000000
--- a/spec/factories/account_types.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# Read about factories at https://github.com/thoughtbot/factory_bot
-
-FactoryBot.define do
- factory :account_type do
- name { Faker::Name.unique.name }
- is_paid false
- is_permanent_paid false
-
- factory :free_account_type do
- name "Free"
- is_paid false
- is_permanent_paid false
- end
-
- factory :paid_account_type do
- name "Paid"
- is_paid true
- is_permanent_paid false
- end
-
- factory :permanent_paid_account_type do
- name "Permanent paid"
- is_paid true
- is_permanent_paid true
- end
-
- factory :staff_account_type do
- name "Staff"
- is_paid true
- is_permanent_paid true
- end
- end
-end
diff --git a/spec/factories/accounts.rb b/spec/factories/accounts.rb
deleted file mode 100644
index fb4805964..000000000
--- a/spec/factories/accounts.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-# Read about factories at https://github.com/thoughtbot/factory_bot
-
-FactoryBot.define do
- # never do this directly.
- # create a member then look at member.account_detail instead.
- # (because it's auto-created, and there can only be one.)
-end
diff --git a/spec/factories/order_items.rb b/spec/factories/order_items.rb
deleted file mode 100644
index 5dfba00ab..000000000
--- a/spec/factories/order_items.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# Read about factories at https://github.com/thoughtbot/factory_bot
-
-FactoryBot.define do
- factory :order_item do
- order
- product
- price "999"
- quantity 42
- end
-end
diff --git a/spec/factories/orders.rb b/spec/factories/orders.rb
deleted file mode 100644
index 514eb4a22..000000000
--- a/spec/factories/orders.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# Read about factories at https://github.com/thoughtbot/factory_bot
-
-FactoryBot.define do
- factory :order do
- member
- factory :completed_order do
- completed_at '2013-05-08 01:01:01'
- end
-
- factory :referred_order do
- referral_code 'CAMPAIGN1'
- end
- end
-end
diff --git a/spec/factories/products.rb b/spec/factories/products.rb
deleted file mode 100644
index 444c8597d..000000000
--- a/spec/factories/products.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# Read about factories at https://github.com/thoughtbot/factory_bot
-
-FactoryBot.define do
- factory :product do
- name "annual subscription"
- description "paid membership, renewing yearly, *hurrah*"
- min_price "999"
- account_type
- paid_months 12
-
- factory :product_with_recommended_price do
- recommended_price "1200"
- end
- end
-end
diff --git a/spec/factories/seeds.rb b/spec/factories/seeds.rb
index 41b3d404f..b58193671 100644
--- a/spec/factories/seeds.rb
+++ b/spec/factories/seeds.rb
@@ -13,9 +13,17 @@ FactoryBot.define do
heirloom 'unknown'
days_until_maturity_min nil
days_until_maturity_max nil
+ finished_at nil
+
+ factory :finished_seed do
+ finished true
+ finished_at { Date.new }
+ end
factory :tradable_seed do
tradable_to "locally"
+ finished false
+ finished_at nil
end
factory :untradable_seed do
diff --git a/spec/features/admin/account_types_spec.rb b/spec/features/admin/account_types_spec.rb
deleted file mode 100644
index dac241586..000000000
--- a/spec/features/admin/account_types_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require 'rails_helper'
-
-feature "account types", js: true do
- context "admin user" do
- let(:member) { create :admin_member }
- let(:account_type) { create :account_type }
-
- background do
- login_as member
- end
-
- scenario "navigating to account type admin with JavaScript on" do
- visit root_path
- # Extra click for the expandable login menu
- click_link member.login_name
- click_link "Admin"
- expect(current_path).to eq admin_path
- click_link "Account types"
- expect(current_path).to eq account_types_path
- end
-
- scenario "navigating to account type admin without JavaScript - Accessility version", js: false do
- visit root_path
- # Extra link not needed as menu is already expanded
- click_link "Admin"
- expect(current_path).to eq admin_path
- click_link "Account types"
- expect(current_path).to eq account_types_path
- end
-
- scenario "adding an account type" do
- visit account_types_path
- click_link "New Account type"
- expect(current_path).to eq new_account_type_path
- fill_in 'Name', with: 'Guest'
- click_button 'Save'
- expect(current_path).to eq account_type_path(AccountType.last)
- expect(page).to have_content 'Account type was successfully created'
- end
-
- scenario 'editing account type' do
- visit account_type_path account_type
- click_link 'Edit'
- fill_in 'Name', with: 'Something else'
- click_button 'Save'
- expect(current_path).to eq account_type_path(account_type)
- expect(page).to have_content 'Account type was successfully updated'
- expect(page).to have_content 'Something else'
- end
-
- scenario 'deleting account type' do
- visit account_type_path account_type
- click_link 'Delete'
- expect(current_path).to eq account_types_path
- expect(page).to have_content 'Account type was successfully deleted'
- end
- end
-end
diff --git a/spec/features/admin/products_spec.rb b/spec/features/admin/products_spec.rb
deleted file mode 100644
index ca24daf83..000000000
--- a/spec/features/admin/products_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require 'rails_helper'
-
-feature "products" do
- context "admin user" do
- let(:member) { create :admin_member }
- let(:product) { create :product }
-
- background do
- login_as member
- end
-
- scenario "navigating to product admin" do
- visit admin_path
- click_link "Products"
- expect(current_path).to eq products_path
- end
-
- scenario "adding a product" do
- visit products_path
- click_link "New Product"
- expect(current_path).to eq new_product_path
- fill_in 'Name', with: 'Special offer'
- # note that failing to fill in a mandatory field has a messy error.
- # This is not a priority defect but should be raised at some point.
- fill_in 'Minimum price', with: '150'
- click_button 'Save'
- expect(current_path).to eq product_path(Product.last)
- expect(page).to have_content 'Product was successfully created'
- end
-
- scenario 'editing product' do
- visit product_path product
- click_link 'Edit'
- fill_in 'Name', with: 'Something else'
- click_button 'Save'
- expect(current_path).to eq product_path(product)
- expect(page).to have_content 'Product was successfully updated'
- expect(page).to have_content 'Something else'
- end
-
- scenario 'deleting product'
- # this isn't possible. Should it be?
- end
-end
diff --git a/spec/features/crops/crop_detail_page_spec.rb b/spec/features/crops/crop_detail_page_spec.rb
index bbf37e996..b7dca2e8d 100644
--- a/spec/features/crops/crop_detail_page_spec.rb
+++ b/spec/features/crops/crop_detail_page_spec.rb
@@ -1,6 +1,15 @@
require 'rails_helper'
feature "crop detail page", js: true do
+ subject do
+ # Update the medians after all the
+ # data has been loaded
+ crop.reload
+ crop.update_medians
+
+ visit crop_path(crop)
+ page
+ end
let(:crop) { create :crop }
context "varieties" do
@@ -187,16 +196,6 @@ feature "crop detail page", js: true do
end
end
- subject do
- # Update the medians after all the
- # data has been loaded
- crop.reload
- crop.update_medians
-
- visit crop_path(crop)
- page
- end
-
context 'predictions' do
let!(:planting) do
FactoryBot.create(:planting, crop: crop,
diff --git a/spec/features/crops/crop_photos_spec.rb b/spec/features/crops/crop_photos_spec.rb
index 9d92449ea..81e506feb 100644
--- a/spec/features/crops/crop_photos_spec.rb
+++ b/spec/features/crops/crop_photos_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
feature "crop detail page", js: true do
+ subject { page }
let(:member) { create :member }
let(:crop) { create :crop, plantings: [planting], harvests: [harvest] }
@@ -39,7 +40,6 @@ feature "crop detail page", js: true do
harvest.photos << photo4
visit crop_path(crop)
end
- subject { page }
shared_examples "shows photos" do
describe "show planting photos" do
diff --git a/spec/features/gardens/actions_spec.rb b/spec/features/gardens/actions_spec.rb
new file mode 100644
index 000000000..7342fe55e
--- /dev/null
+++ b/spec/features/gardens/actions_spec.rb
@@ -0,0 +1,84 @@
+require 'rails_helper'
+require 'custom_matchers'
+
+feature "Gardens" do
+ context 'logged in' do
+ let(:member) { FactoryBot.create :member }
+ background { login_as member }
+ subject { page }
+ let(:garden) { member.gardens.first }
+
+ 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 "Everyone's gardens"
+ end
+ end
+ end
+
+ context 'my gardens' do
+ before { visit gardens_path(owner: member) }
+ 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
+ end
+ end
+ context 'all gardens' do
+ before { visit gardens_path }
+ include_examples "has buttons bar at top"
+ end
+ context "other member's garden" do
+ before { visit gardens_path(owner: FactoryBot.create(:member)) }
+ include_examples "has buttons bar at top"
+ it 'does not show actions on other member garden' do
+ is_expected.not_to have_link 'Plant something'
+ is_expected.not_to have_link 'Mark as inactive'
+ end
+ end
+ end
+
+ describe '#show' do
+ end
+ end
+
+ # background do
+ # login_as member
+ # visit new_garden_path
+ # end
+
+ # it "has the required fields help text" 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: "Name"
+ # expect(page).to have_optional 'textarea#garden_description'
+ # expect(page).to have_optional 'input#garden_location'
+ # expect(page).to have_optional 'input#garden_area'
+ # end
+
+ # scenario "Create new garden" do
+ # fill_in "Name", with: "New garden"
+ # click_button "Save"
+ # expect(page).to have_content "Garden was successfully created"
+ # expect(page).to have_content "New garden"
+ # end
+
+ # scenario "Refuse to create new garden with negative area" do
+ # visit new_garden_path
+ # fill_in "Name", with: "Negative Garden"
+ # fill_in "Area", with: -5
+ # click_button "Save"
+ # expect(page).not_to have_content "Garden was successfully created"
+ # expect(page).to have_content "Area must be greater than or equal to 0"
+ # end
+end
diff --git a/spec/features/gardens_spec.rb b/spec/features/gardens_spec.rb
index 0954d35eb..368389719 100644
--- a/spec/features/gardens_spec.rb
+++ b/spec/features/gardens_spec.rb
@@ -59,7 +59,7 @@ feature "Planting a crop", js: true do
end
scenario "button on index to edit garden" do
- first(".garden-info").click_link("edit_garden_link")
+ click_link href: edit_garden_path(garden)
expect(page).to have_content 'Edit garden'
end
end
@@ -68,7 +68,9 @@ feature "Planting a crop", js: true do
visit new_garden_path
fill_in "Name", with: "New garden"
click_button "Save"
- click_link 'edit_garden_link'
+ within '.garden-actions' do
+ click_link 'Edit'
+ end
fill_in "Name", with: "Different name"
click_button "Save"
expect(page).to have_content "Garden was successfully updated"
diff --git a/spec/features/harvests/browse_harvests_spec.rb b/spec/features/harvests/browse_harvests_spec.rb
index 2a8400c2e..c51be9f41 100644
--- a/spec/features/harvests/browse_harvests_spec.rb
+++ b/spec/features/harvests/browse_harvests_spec.rb
@@ -4,19 +4,14 @@ feature "browse harvests" do
let!(:member) { create :member }
let!(:harvest) { create :harvest, owner: member }
- background do
- login_as member
- end
-
+ background { login_as member }
+ subject { page }
feature 'blank optional fields' do
let!(:harvest) { create :harvest, :no_description }
-
- before(:each) do
- visit harvests_path
- end
+ before { visit harvests_path }
scenario 'read more' do
- expect(page).not_to have_link "Read more"
+ is_expected.not_to have_link "Read more"
end
end
@@ -28,11 +23,11 @@ feature "browse harvests" do
end
scenario 'read more' do
- expect(page).to have_link "Read more"
+ is_expected.to have_link "Read more"
end
it 'links to #show' do
- expect(page).to have_link harvest.crop.name, href: harvest_path(harvest)
+ is_expected.to have_link harvest.crop.name, href: harvest_path(harvest)
end
end
end
diff --git a/spec/features/harvests/harvesting_a_crop_spec.rb b/spec/features/harvests/harvesting_a_crop_spec.rb
index 84c4b5a7f..e99c5e814 100644
--- a/spec/features/harvests/harvesting_a_crop_spec.rb
+++ b/spec/features/harvests/harvesting_a_crop_spec.rb
@@ -78,7 +78,9 @@ feature "Harvesting a crop", :js, :elasticsearch do
scenario "Harvesting from planting page" do
planting = create :planting, crop: maize, owner: member, garden: member.gardens.first
visit planting_path(planting)
- click_link "Harvest"
+ within ".planting-actions" do
+ click_link "Harvest"
+ end
select plant_part.name, from: 'harvest[plant_part_id]'
click_button "Save"
diff --git a/spec/features/home/home_spec.rb b/spec/features/home/home_spec.rb
new file mode 100644
index 000000000..4137b5e5a
--- /dev/null
+++ b/spec/features/home/home_spec.rb
@@ -0,0 +1,84 @@
+require 'rails_helper'
+
+feature "home page" do
+ let(:member) { FactoryBot.create :member }
+ # let(:seed_photo) { FactoryBot.create :photo }
+ let(:photo) { FactoryBot.create :photo }
+ let(:crop) { FactoryBot.create :crop, created_at: 1.day.ago }
+
+ let(:planting) { FactoryBot.create :planting, owner: member, crop: crop }
+ let(:seed) { FactoryBot.create :tradable_seed, owner: member, crop: crop }
+ let(:harvest) { FactoryBot.create :harvest, owner: member, crop: crop }
+
+ let!(:tradable_seed) { FactoryBot.create :tradable_seed, finished: false }
+ let!(:finished_seed) { FactoryBot.create :tradable_seed, finished: true }
+ let!(:untradable_seed) { FactoryBot.create :untradable_seed }
+ background do
+ # Add photos, so they can appear on home page
+ planting.photos << photo
+ seed.photos << photo
+ harvest.photos << photo
+ end
+
+ subject { page }
+ before { visit root_path }
+
+ shared_examples 'shows seeds' do
+ it "show tradeable seed" do
+ is_expected.to have_link href: seed_path(tradable_seed)
+ end
+ it "does not show finished seeds" do
+ is_expected.not_to have_link href: seed_path(finished_seed)
+ end
+ it "does not show untradable seeds" do
+ is_expected.not_to have_link href: seed_path(untradable_seed)
+ end
+
+ it { is_expected.to have_text 'View all seeds' }
+ end
+
+ shared_examples 'show plantings' do
+ it 'shows plantings section' do
+ is_expected.to have_text 'Recently Planted'
+ is_expected.to have_link href: planting_path(planting)
+ end
+ end
+ shared_examples 'show harvests' do
+ it 'shows harvests section' do
+ is_expected.to have_text 'Recently Harvested'
+ is_expected.to have_link href: harvest_path(harvest)
+ end
+ end
+
+ shared_examples "show crops" do
+ describe 'shows crops section' do
+ it { is_expected.to have_text 'Some of our crops' }
+ it { is_expected.to have_link href: crop_path(crop) }
+ end
+ describe 'shows recently added crops' do
+ it { is_expected.to have_text 'Recently Added' }
+ it 'link to newest crops' do
+ is_expected.to have_link crop.name, href: crop_path(crop)
+ end
+ end
+ it 'includes a link to all crops' do
+ is_expected.to have_link 'View all crops'
+ end
+ end
+
+ context 'when anonymous' do
+ include_examples 'show crops'
+ include_examples 'show plantings'
+ include_examples 'show harvests'
+ include_examples 'shows seeds'
+ it { is_expected.to have_text 'community of food gardeners' }
+ end
+
+ context "when signed in" do
+ background { login_as member }
+ include_examples 'show crops'
+ include_examples 'show plantings'
+ include_examples 'show harvests'
+ include_examples 'shows seeds'
+ end
+end
diff --git a/spec/features/member_profile_spec.rb b/spec/features/member_profile_spec.rb
index 32b11bda1..9f1005894 100644
--- a/spec/features/member_profile_spec.rb
+++ b/spec/features/member_profile_spec.rb
@@ -9,7 +9,6 @@ feature "member profile", js: true do
expect(page).to have_css("h1", text: member.login_name)
expect(page).to have_content member.bio
expect(page).to have_content "Member since: #{member.created_at.to_s(:date)}"
- expect(page).to have_content "Account type: Free account"
expect(page).to have_content "#{member.login_name}'s gardens"
expect(page).to have_link "More about this garden...", href: garden_path(member.gardens.first)
end
@@ -141,10 +140,6 @@ feature "member profile", js: true do
scenario "has a button to edit profile" do
expect(page).to have_link "Edit profile", href: edit_member_registration_path
end
-
- scenario "has a button to upgrade account" do
- expect(page).to have_link "Upgrade account", href: shop_path
- end
end
context "someone else's profile page" do
diff --git a/spec/features/members/deletion_spec.rb b/spec/features/members/deletion_spec.rb
index 793a6ada5..22b91a33b 100644
--- a/spec/features/members/deletion_spec.rb
+++ b/spec/features/members/deletion_spec.rb
@@ -10,7 +10,6 @@ feature "member deletion" do
let!(:harvest) { FactoryBot.create(:harvest, owner: member) }
let!(:seed) { FactoryBot.create(:seed, owner: member) }
let!(:secondgarden) { FactoryBot.create(:garden, owner: member) }
- let!(:order) { FactoryBot.create(:order, member: member, completed_at: Time.zone.now) }
let(:admin) { FactoryBot.create(:admin_member) }
background do
@@ -115,16 +114,6 @@ feature "member deletion" do
expect(page).to have_content "Member Deleted"
end
- scenario "leaves a record of orders and payments intact" do
- login_as(admin)
- visit admin_path
- fill_in "search_text", with: member.login_name.to_s
- find("#maincontainer").click_button("Search", exact: true)
- expect(page).to have_content member.login_name.to_s
- expect(page).to have_content "Found 1 result"
- logout
- end
-
scenario "can't be interesting" do
expect(Member.interesting).not_to include(member)
expect(Planting.interesting).not_to include(planting)
diff --git a/spec/features/photos/new_photo_spec.rb b/spec/features/photos/new_photo_spec.rb
index 1c13b2793..ee2a50691 100644
--- a/spec/features/photos/new_photo_spec.rb
+++ b/spec/features/photos/new_photo_spec.rb
@@ -33,7 +33,9 @@ feature "new photo page" do
scenario "add photo" do
visit garden_path(garden)
- click_link "Add photo"
+ within '.garden-actions' do
+ click_link "Add photo"
+ end
expect(page).to have_text garden.name
end
end
diff --git a/spec/features/seeds/misc_seeds_spec.rb b/spec/features/seeds/misc_seeds_spec.rb
index 1db053a80..ec1946d2c 100644
--- a/spec/features/seeds/misc_seeds_spec.rb
+++ b/spec/features/seeds/misc_seeds_spec.rb
@@ -5,9 +5,7 @@ feature "seeds", js: true do
let(:member) { create :member }
let(:crop) { create :crop }
- background do
- login_as member
- end
+ background { login_as member }
scenario "button on index to edit seed" do
seed = create :seed, owner: member
diff --git a/spec/features/seeds/seed_photos.rb b/spec/features/seeds/seed_photos.rb
index 3d57f2cfe..7e26ece28 100644
--- a/spec/features/seeds/seed_photos.rb
+++ b/spec/features/seeds/seed_photos.rb
@@ -2,14 +2,13 @@ require 'rails_helper'
require 'custom_matchers'
feature "Seeds", :js do
- let(:member) { FactoryBot.create :member }
- let!(:seed) { FactoryBot.create :seed, owner: member }
-
subject do
login_as member
visit seed_path(seed)
page
end
+ let(:member) { FactoryBot.create :member }
+ let!(:seed) { FactoryBot.create :seed, owner: member }
it { is_expected.to have_content 'Add photo' }
diff --git a/spec/helpers/photos_helper_spec.rb b/spec/helpers/photos_helper_spec.rb
new file mode 100644
index 000000000..589cf8104
--- /dev/null
+++ b/spec/helpers/photos_helper_spec.rb
@@ -0,0 +1,79 @@
+require 'rails_helper'
+
+describe PhotosHelper do
+ let(:crop) { FactoryBot.create :crop }
+
+ let(:garden) { FactoryBot.create :garden }
+ let(:garden_photo) { FactoryBot.create(:photo, thumbnail_url: 'garden.jpg') }
+ let(:planting) { FactoryBot.create :planting, crop: crop }
+ let(:planting_photo) { FactoryBot.create(:photo, thumbnail_url: 'planting.jpg') }
+ let(:harvest) { FactoryBot.create :harvest, crop: crop }
+ let(:harvest_photo) { FactoryBot.create(:photo, thumbnail_url: 'harvest.jpg') }
+ let(:seed) { FactoryBot.create :seed, crop: crop }
+ let(:seed_photo) { FactoryBot.create(:photo, thumbnail_url: 'seed.jpg') }
+
+ describe "crops" do
+ subject { crop_image_path(crop) }
+
+ it { is_expected.to eq 'placeholder_150.png' }
+
+ describe "with a planting" do
+ before { planting.photos << planting_photo }
+ it "uses planting photos" do
+ is_expected.to eq planting_photo.thumbnail_url
+ end
+ end
+
+ describe "with a harvest photos" do
+ before { harvest.photos << harvest_photo }
+ it "uses harvest photos" do
+ is_expected.to eq harvest_photo.thumbnail_url
+ end
+ end
+
+ describe "uses seed photo" do
+ before { seed.photos << seed_photo }
+ it "uses seed photos" do
+ is_expected.to eq seed_photo.thumbnail_url
+ end
+ end
+ end
+
+ describe "gardens" do
+ subject { garden_image_path(garden) }
+ it { is_expected.to eq 'placeholder_150.png' }
+
+ describe "uses garden's own photo" do
+ before { garden.photos << garden_photo }
+ it { is_expected.to eq garden_photo.thumbnail_url }
+ end
+ end
+
+ describe 'plantings' do
+ subject { planting_image_path(planting) }
+ it { is_expected.to eq 'placeholder_150.png' }
+ describe "uses planting's own photo" do
+ before { planting.photos << planting_photo }
+ it { is_expected.to eq planting_photo.thumbnail_url }
+ end
+ end
+
+ describe 'harvests' do
+ subject { harvest_image_path(harvest) }
+ it { is_expected.to eq 'placeholder_150.png' }
+ describe "uses harvest's own photo" do
+ before { harvest.photos << harvest_photo }
+ it { is_expected.to eq harvest_photo.thumbnail_url }
+ end
+ end
+
+ describe 'seeds' do
+ subject { seed_image_path(seed) }
+ it { is_expected.to eq 'placeholder_150.png' }
+
+ describe "uses seed's own photo" do
+ before { seed.photos << seed_photo }
+ it { is_expected.to eq seed_photo.thumbnail_url }
+ end
+ end
+end
diff --git a/spec/javascripts/support/jasmine.css b/spec/javascripts/support/jasmine.css
deleted file mode 100644
index 4736015b6..000000000
--- a/spec/javascripts/support/jasmine.css
+++ /dev/null
@@ -1,13 +0,0 @@
-body {
- padding-top: 0;
-}
-
-#jasmine_content {
- width: 1000px;
- height: 1000px;
- position: absolute;
- -webkit-transform: rotateY(-90deg);
- -moz-transform: rotateY(-90deg);
- -ms-transform: rotateY(-90deg);
- transform: rotateY(-90deg);
-}
\ No newline at end of file
diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml
deleted file mode 100644
index 41a71db95..000000000
--- a/spec/javascripts/support/jasmine.yml
+++ /dev/null
@@ -1,123 +0,0 @@
-# src_files
-#
-# Return an array of filepaths relative to src_dir to include before jasmine specs.
-# Default: []
-#
-# EXAMPLE:
-#
-# src_files:
-# - lib/source1.js
-# - lib/source2.js
-# - dist/**/*.js
-#
-src_files:
- - assets/application.js
-
-# stylesheets
-#
-# Return an array of stylesheet filepaths relative to src_dir to include before jasmine specs.
-# Default: []
-#
-# EXAMPLE:
-#
-# stylesheets:
-# - css/style.css
-# - stylesheets/*.css
-#
-stylesheets:
- - assets/application.css
- - spec/javascripts/support/jasmine.css
-# helpers
-#
-# Return an array of filepaths relative to spec_dir to include before jasmine specs.
-# Default: ["helpers/**/*.js"]
-#
-# EXAMPLE:
-#
-# helpers:
-# - helpers/**/*.js
-#
-helpers:
- - 'support/**/*.js'
-
-# spec_files
-#
-# Return an array of filepaths relative to spec_dir to include.
-# Default: ["**/*[sS]pec.js"]
-#
-# EXAMPLE:
-#
-# spec_files:
-# - **/*[sS]pec.js
-#
-spec_files:
- - '**/*[sS]pec.js'
-
-# src_dir
-#
-# Source directory path. Your src_files must be returned relative to this path. Will use root if left blank.
-# Default: project root
-#
-# EXAMPLE:
-#
-# src_dir: public
-#
-src_dir:
-
-# spec_dir
-#
-# Spec directory path. Your spec_files must be returned relative to this path.
-# Default: spec/javascripts
-#
-# EXAMPLE:
-#
-# spec_dir: spec/javascripts
-#
-spec_dir:
-
-# spec_helper
-#
-# Ruby file that Jasmine server will require before starting.
-# Returned relative to your root path
-# Default spec/javascripts/support/jasmine_helper.rb
-#
-# EXAMPLE:
-#
-# spec_helper: spec/javascripts/support/jasmine_helper.rb
-#
-spec_helper: spec/javascripts/support/jasmine_helper.rb
-
-# boot_dir
-#
-# Boot directory path. Your boot_files must be returned relative to this path.
-# Default: Built in boot file
-#
-# EXAMPLE:
-#
-# boot_dir: spec/javascripts/support/boot
-#
-boot_dir:
-
-# boot_files
-#
-# Return an array of filepaths relative to boot_dir to include in order to boot Jasmine
-# Default: Built in boot file
-#
-# EXAMPLE
-#
-# boot_files:
-# - '**/*.js'
-#
-boot_files:
-
-# rack_options
-#
-# Extra options to be passed to the rack server
-# by default, Port and AccessLog are passed.
-#
-# This is an advanced options, and left empty by default
-#
-# EXAMPLE
-#
-# rack_options:
-# server: 'thin'
diff --git a/spec/javascripts/support/jasmine_helper.rb b/spec/javascripts/support/jasmine_helper.rb
deleted file mode 100644
index 35ec28327..000000000
--- a/spec/javascripts/support/jasmine_helper.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# Use this file to set/override Jasmine configuration options
-# You can remove it if you don't need it.
-# This file is loaded *after* jasmine.yml is interpreted.
-#
-# Example: using a different boot file.
-# Jasmine.configure do |config|
-# config.boot_dir = '/absolute/path/to/boot_dir'
-# config.boot_files = lambda { ['/absolute/path/to/boot_dir/file.js'] }
-# end
-#
-# Example: prevent PhantomJS auto install, uses PhantomJS already on your path.
-# Jasmine.configure do |config|
-# config.prevent_phantom_js_auto_install = true
-# end
-
-Jasmine.configure do |config|
- # Enable console.log for debugging
- config.show_console_log = true
-end
diff --git a/spec/javascripts/support/vendor/jasmine-jquery.js b/spec/javascripts/support/vendor/jasmine-jquery.js
deleted file mode 100644
index 89071b063..000000000
--- a/spec/javascripts/support/vendor/jasmine-jquery.js
+++ /dev/null
@@ -1,813 +0,0 @@
-/*!
-Jasmine-jQuery: a set of jQuery helpers for Jasmine tests.
-
-Version 2.0.5
-
-https://github.com/velesin/jasmine-jquery
-
-Copyright (c) 2010-2014 Wojciech Zawistowski, Travis Jeffery
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-+function (window, jasmine, $) { "use strict";
-
- jasmine.spiedEventsKey = function (selector, eventName) {
- return [$(selector).selector, eventName].toString()
- }
-
- jasmine.getFixtures = function () {
- return jasmine.currentFixtures_ = jasmine.currentFixtures_ || new jasmine.Fixtures()
- }
-
- jasmine.getStyleFixtures = function () {
- return jasmine.currentStyleFixtures_ = jasmine.currentStyleFixtures_ || new jasmine.StyleFixtures()
- }
-
- jasmine.Fixtures = function () {
- this.containerId = 'jasmine-fixtures'
- this.fixturesCache_ = {}
- this.fixturesPath = 'spec/javascripts/fixtures'
- }
-
- jasmine.Fixtures.prototype.set = function (html) {
- this.cleanUp()
- return this.createContainer_(html)
- }
-
- jasmine.Fixtures.prototype.appendSet= function (html) {
- this.addToContainer_(html)
- }
-
- jasmine.Fixtures.prototype.preload = function () {
- this.read.apply(this, arguments)
- }
-
- jasmine.Fixtures.prototype.load = function () {
- this.cleanUp()
- this.createContainer_(this.read.apply(this, arguments))
- }
-
- jasmine.Fixtures.prototype.appendLoad = function () {
- this.addToContainer_(this.read.apply(this, arguments))
- }
-
- jasmine.Fixtures.prototype.read = function () {
- var htmlChunks = []
- , fixtureUrls = arguments
-
- for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
- htmlChunks.push(this.getFixtureHtml_(fixtureUrls[urlIndex]))
- }
-
- return htmlChunks.join('')
- }
-
- jasmine.Fixtures.prototype.clearCache = function () {
- this.fixturesCache_ = {}
- }
-
- jasmine.Fixtures.prototype.cleanUp = function () {
- $('#' + this.containerId).remove()
- }
-
- jasmine.Fixtures.prototype.sandbox = function (attributes) {
- var attributesToSet = attributes || {}
- return $('').attr(attributesToSet)
- }
-
- jasmine.Fixtures.prototype.createContainer_ = function (html) {
- var container = $('
')
- .attr('id', this.containerId)
- .html(html)
-
- $(document.body).append(container)
- return container
- }
-
- jasmine.Fixtures.prototype.addToContainer_ = function (html){
- var container = $(document.body).find('#'+this.containerId).append(html)
-
- if (!container.length) {
- this.createContainer_(html)
- }
- }
-
- jasmine.Fixtures.prototype.getFixtureHtml_ = function (url) {
- if (typeof this.fixturesCache_[url] === 'undefined') {
- this.loadFixtureIntoCache_(url)
- }
- return this.fixturesCache_[url]
- }
-
- jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
- var self = this
- , url = this.makeFixtureUrl_(relativeUrl)
- , htmlText = ''
- , request = $.ajax({
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
- cache: false,
- url: url,
- success: function (data, status, $xhr) {
- htmlText = $xhr.responseText
- }
- }).fail(function ($xhr, status, err) {
- throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
- })
-
- var scripts = $($.parseHTML(htmlText, true)).find('script[src]') || [];
-
- scripts.each(function(){
- $.ajax({
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
- cache: false,
- dataType: 'script',
- url: $(this).attr('src'),
- success: function (data, status, $xhr) {
- htmlText += ''
- },
- error: function ($xhr, status, err) {
- throw new Error('Script could not be loaded: ' + scriptSrc + ' (status: ' + status + ', message: ' + err.message + ')')
- }
- });
- })
-
- self.fixturesCache_[relativeUrl] = htmlText;
- }
-
- jasmine.Fixtures.prototype.makeFixtureUrl_ = function (relativeUrl){
- return this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
- }
-
- jasmine.Fixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
- return this[methodName].apply(this, passedArguments)
- }
-
-
- jasmine.StyleFixtures = function () {
- this.fixturesCache_ = {}
- this.fixturesNodes_ = []
- this.fixturesPath = 'spec/javascripts/fixtures'
- }
-
- jasmine.StyleFixtures.prototype.set = function (css) {
- this.cleanUp()
- this.createStyle_(css)
- }
-
- jasmine.StyleFixtures.prototype.appendSet = function (css) {
- this.createStyle_(css)
- }
-
- jasmine.StyleFixtures.prototype.preload = function () {
- this.read_.apply(this, arguments)
- }
-
- jasmine.StyleFixtures.prototype.load = function () {
- this.cleanUp()
- this.createStyle_(this.read_.apply(this, arguments))
- }
-
- jasmine.StyleFixtures.prototype.appendLoad = function () {
- this.createStyle_(this.read_.apply(this, arguments))
- }
-
- jasmine.StyleFixtures.prototype.cleanUp = function () {
- while(this.fixturesNodes_.length) {
- this.fixturesNodes_.pop().remove()
- }
- }
-
- jasmine.StyleFixtures.prototype.createStyle_ = function (html) {
- var styleText = $('').html(html).text()
- , style = $('')
-
- this.fixturesNodes_.push(style)
- $('head').append(style)
- }
-
- jasmine.StyleFixtures.prototype.clearCache = jasmine.Fixtures.prototype.clearCache
- jasmine.StyleFixtures.prototype.read_ = jasmine.Fixtures.prototype.read
- jasmine.StyleFixtures.prototype.getFixtureHtml_ = jasmine.Fixtures.prototype.getFixtureHtml_
- jasmine.StyleFixtures.prototype.loadFixtureIntoCache_ = jasmine.Fixtures.prototype.loadFixtureIntoCache_
- jasmine.StyleFixtures.prototype.makeFixtureUrl_ = jasmine.Fixtures.prototype.makeFixtureUrl_
- jasmine.StyleFixtures.prototype.proxyCallTo_ = jasmine.Fixtures.prototype.proxyCallTo_
-
- jasmine.getJSONFixtures = function () {
- return jasmine.currentJSONFixtures_ = jasmine.currentJSONFixtures_ || new jasmine.JSONFixtures()
- }
-
- jasmine.JSONFixtures = function () {
- this.fixturesCache_ = {}
- this.fixturesPath = 'spec/javascripts/fixtures/json'
- }
-
- jasmine.JSONFixtures.prototype.load = function () {
- this.read.apply(this, arguments)
- return this.fixturesCache_
- }
-
- jasmine.JSONFixtures.prototype.read = function () {
- var fixtureUrls = arguments
-
- for(var urlCount = fixtureUrls.length, urlIndex = 0; urlIndex < urlCount; urlIndex++) {
- this.getFixtureData_(fixtureUrls[urlIndex])
- }
-
- return this.fixturesCache_
- }
-
- jasmine.JSONFixtures.prototype.clearCache = function () {
- this.fixturesCache_ = {}
- }
-
- jasmine.JSONFixtures.prototype.getFixtureData_ = function (url) {
- if (!this.fixturesCache_[url]) this.loadFixtureIntoCache_(url)
- return this.fixturesCache_[url]
- }
-
- jasmine.JSONFixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
- var self = this
- , url = this.fixturesPath.match('/$') ? this.fixturesPath + relativeUrl : this.fixturesPath + '/' + relativeUrl
-
- $.ajax({
- async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
- cache: false,
- dataType: 'json',
- url: url,
- success: function (data) {
- self.fixturesCache_[relativeUrl] = data
- },
- error: function ($xhr, status, err) {
- throw new Error('JSONFixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
- }
- })
- }
-
- jasmine.JSONFixtures.prototype.proxyCallTo_ = function (methodName, passedArguments) {
- return this[methodName].apply(this, passedArguments)
- }
-
- jasmine.jQuery = function () {}
-
- jasmine.jQuery.browserTagCaseIndependentHtml = function (html) {
- return $('').append(html).html()
- }
-
- jasmine.jQuery.elementToString = function (element) {
- return $(element).map(function () { return this.outerHTML; }).toArray().join(', ')
- }
-
- var data = {
- spiedEvents: {}
- , handlers: []
- }
-
- jasmine.jQuery.events = {
- spyOn: function (selector, eventName) {
- var handler = function (e) {
- data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)] = jasmine.util.argsToArray(arguments)
- }
-
- $(selector).on(eventName, handler)
- data.handlers.push(handler)
-
- return {
- selector: selector,
- eventName: eventName,
- handler: handler,
- reset: function (){
- delete data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
- }
- }
- },
-
- args: function (selector, eventName) {
- var actualArgs = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
-
- if (!actualArgs) {
- throw "There is no spy for " + eventName + " on " + selector.toString() + ". Make sure to create a spy using spyOnEvent."
- }
-
- return actualArgs
- },
-
- wasTriggered: function (selector, eventName) {
- return !!(data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)])
- },
-
- wasTriggeredWith: function (selector, eventName, expectedArgs, util, customEqualityTesters) {
- var actualArgs = jasmine.jQuery.events.args(selector, eventName).slice(1)
-
- if (Object.prototype.toString.call(expectedArgs) !== '[object Array]')
- actualArgs = actualArgs[0]
-
- return util.equals(expectedArgs, actualArgs, customEqualityTesters)
- },
-
- wasPrevented: function (selector, eventName) {
- var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
- , e = args ? args[0] : undefined
-
- return e && e.isDefaultPrevented()
- },
-
- wasStopped: function (selector, eventName) {
- var args = data.spiedEvents[jasmine.spiedEventsKey(selector, eventName)]
- , e = args ? args[0] : undefined
- return e && e.isPropagationStopped()
- },
-
- cleanUp: function () {
- data.spiedEvents = {}
- data.handlers = []
- }
- }
-
- var hasProperty = function (actualValue, expectedValue) {
- if (expectedValue === undefined)
- return actualValue !== undefined
-
- return actualValue === expectedValue
- }
-
- beforeEach(function () {
- jasmine.addMatchers({
- toHaveClass: function () {
- return {
- compare: function (actual, className) {
- return { pass: $(actual).hasClass(className) }
- }
- }
- },
-
- toHaveCss: function () {
- return {
- compare: function (actual, css) {
- for (var prop in css){
- var value = css[prop]
- // see issue #147 on gh
- ;if (value === 'auto' && $(actual).get(0).style[prop] === 'auto') continue
- if ($(actual).css(prop) !== value) return { pass: false }
- }
- return { pass: true }
- }
- }
- },
-
- toBeVisible: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':visible') }
- }
- }
- },
-
- toBeHidden: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':hidden') }
- }
- }
- },
-
- toBeSelected: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':selected') }
- }
- }
- },
-
- toBeChecked: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':checked') }
- }
- }
- },
-
- toBeEmpty: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).is(':empty') }
- }
- }
- },
-
- toBeInDOM: function () {
- return {
- compare: function (actual) {
- return { pass: $.contains(document.documentElement, $(actual)[0]) }
- }
- }
- },
-
- toExist: function () {
- return {
- compare: function (actual) {
- return { pass: $(actual).length }
- }
- }
- },
-
- toHaveLength: function () {
- return {
- compare: function (actual, length) {
- return { pass: $(actual).length === length }
- }
- }
- },
-
- toHaveAttr: function () {
- return {
- compare: function (actual, attributeName, expectedAttributeValue) {
- return { pass: hasProperty($(actual).attr(attributeName), expectedAttributeValue) }
- }
- }
- },
-
- toHaveProp: function () {
- return {
- compare: function (actual, propertyName, expectedPropertyValue) {
- return { pass: hasProperty($(actual).prop(propertyName), expectedPropertyValue) }
- }
- }
- },
-
- toHaveId: function () {
- return {
- compare: function (actual, id) {
- return { pass: $(actual).attr('id') == id }
- }
- }
- },
-
- toHaveHtml: function () {
- return {
- compare: function (actual, html) {
- return { pass: $(actual).html() == jasmine.jQuery.browserTagCaseIndependentHtml(html) }
- }
- }
- },
-
- toContainHtml: function () {
- return {
- compare: function (actual, html) {
- var actualHtml = $(actual).html()
- , expectedHtml = jasmine.jQuery.browserTagCaseIndependentHtml(html)
-
- return { pass: (actualHtml.indexOf(expectedHtml) >= 0) }
- }
- }
- },
-
- toHaveText: function () {
- return {
- compare: function (actual, text) {
- var actualText = $(actual).text()
- var trimmedText = $.trim(actualText)
-
- if (text && $.isFunction(text.test)) {
- return { pass: text.test(actualText) || text.test(trimmedText) }
- } else {
- return { pass: (actualText == text || trimmedText == text) }
- }
- }
- }
- },
-
- toContainText: function () {
- return {
- compare: function (actual, text) {
- var trimmedText = $.trim($(actual).text())
-
- if (text && $.isFunction(text.test)) {
- return { pass: text.test(trimmedText) }
- } else {
- return { pass: trimmedText.indexOf(text) != -1 }
- }
- }
- }
- },
-
- toHaveValue: function () {
- return {
- compare: function (actual, value) {
- return { pass: $(actual).val() === value }
- }
- }
- },
-
- toHaveData: function () {
- return {
- compare: function (actual, key, expectedValue) {
- return { pass: hasProperty($(actual).data(key), expectedValue) }
- }
- }
- },
-
- toContainElement: function () {
- return {
- compare: function (actual, selector) {
- if (window.debug) debugger
- return { pass: $(actual).find(selector).length }
- }
- }
- },
-
- toBeMatchedBy: function () {
- return {
- compare: function (actual, selector) {
- return { pass: $(actual).filter(selector).length }
- }
- }
- },
-
- toBeDisabled: function () {
- return {
- compare: function (actual, selector) {
- return { pass: $(actual).is(':disabled') }
- }
- }
- },
-
- toBeFocused: function (selector) {
- return {
- compare: function (actual, selector) {
- return { pass: $(actual)[0] === $(actual)[0].ownerDocument.activeElement }
- }
- }
- },
-
- toHandle: function () {
- return {
- compare: function (actual, event) {
- var events = $._data($(actual).get(0), "events")
-
- if (!events || !event || typeof event !== "string") {
- return { pass: false }
- }
-
- var namespaces = event.split(".")
- , eventType = namespaces.shift()
- , sortedNamespaces = namespaces.slice(0).sort()
- , namespaceRegExp = new RegExp("(^|\\.)" + sortedNamespaces.join("\\.(?:.*\\.)?") + "(\\.|$)")
-
- if (events[eventType] && namespaces.length) {
- for (var i = 0; i < events[eventType].length; i++) {
- var namespace = events[eventType][i].namespace
-
- if (namespaceRegExp.test(namespace))
- return { pass: true }
- }
- } else {
- return { pass: (events[eventType] && events[eventType].length > 0) }
- }
-
- return { pass: false }
- }
- }
- },
-
- toHandleWith: function () {
- return {
- compare: function (actual, eventName, eventHandler) {
- var normalizedEventName = eventName.split('.')[0]
- , stack = $._data($(actual).get(0), "events")[normalizedEventName]
-
- for (var i = 0; i < stack.length; i++) {
- if (stack[i].handler == eventHandler) return { pass: true }
- }
-
- return { pass: false }
- }
- }
- },
-
- toHaveBeenTriggeredOn: function () {
- return {
- compare: function (actual, selector) {
- var result = { pass: jasmine.jQuery.events.wasTriggered(selector, actual) }
-
- result.message = result.pass ?
- "Expected event " + $(actual) + " not to have been triggered on " + selector :
- "Expected event " + $(actual) + " to have been triggered on " + selector
-
- return result;
- }
- }
- },
-
- toHaveBeenTriggered: function (){
- return {
- compare: function (actual) {
- var eventName = actual.eventName
- , selector = actual.selector
- , result = { pass: jasmine.jQuery.events.wasTriggered(selector, eventName) }
-
- result.message = result.pass ?
- "Expected event " + eventName + " not to have been triggered on " + selector :
- "Expected event " + eventName + " to have been triggered on " + selector
-
- return result
- }
- }
- },
-
- toHaveBeenTriggeredOnAndWith: function (j$, customEqualityTesters) {
- return {
- compare: function (actual, selector, expectedArgs) {
- var wasTriggered = jasmine.jQuery.events.wasTriggered(selector, actual)
- , result = { pass: wasTriggered && jasmine.jQuery.events.wasTriggeredWith(selector, actual, expectedArgs, j$, customEqualityTesters) }
-
- if (wasTriggered) {
- var actualArgs = jasmine.jQuery.events.args(selector, actual, expectedArgs)[1]
- result.message = result.pass ?
- "Expected event " + actual + " not to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs) :
- "Expected event " + actual + " to have been triggered with " + jasmine.pp(expectedArgs) + " but it was triggered with " + jasmine.pp(actualArgs)
-
- } else {
- // todo check on this
- result.message = result.pass ?
- "Expected event " + actual + " not to have been triggered on " + selector :
- "Expected event " + actual + " to have been triggered on " + selector
- }
-
- return result
- }
- }
- },
-
- toHaveBeenPreventedOn: function () {
- return {
- compare: function (actual, selector) {
- var result = { pass: jasmine.jQuery.events.wasPrevented(selector, actual) }
-
- result.message = result.pass ?
- "Expected event " + actual + " not to have been prevented on " + selector :
- "Expected event " + actual + " to have been prevented on " + selector
-
- return result
- }
- }
- },
-
- toHaveBeenPrevented: function () {
- return {
- compare: function (actual) {
- var eventName = actual.eventName
- , selector = actual.selector
- , result = { pass: jasmine.jQuery.events.wasPrevented(selector, eventName) }
-
- result.message = result.pass ?
- "Expected event " + eventName + " not to have been prevented on " + selector :
- "Expected event " + eventName + " to have been prevented on " + selector
-
- return result
- }
- }
- },
-
- toHaveBeenStoppedOn: function () {
- return {
- compare: function (actual, selector) {
- var result = { pass: jasmine.jQuery.events.wasStopped(selector, actual) }
-
- result.message = result.pass ?
- "Expected event " + actual + " not to have been stopped on " + selector :
- "Expected event " + actual + " to have been stopped on " + selector
-
- return result;
- }
- }
- },
-
- toHaveBeenStopped: function () {
- return {
- compare: function (actual) {
- var eventName = actual.eventName
- , selector = actual.selector
- , result = { pass: jasmine.jQuery.events.wasStopped(selector, eventName) }
-
- result.message = result.pass ?
- "Expected event " + eventName + " not to have been stopped on " + selector :
- "Expected event " + eventName + " to have been stopped on " + selector
-
- return result
- }
- }
- }
- })
-
- jasmine.getEnv().addCustomEqualityTester(function(a, b) {
- if (a && b) {
- if (a instanceof $ || jasmine.isDomNode(a)) {
- var $a = $(a)
-
- if (b instanceof $)
- return $a.length == b.length && a.is(b)
-
- return $a.is(b);
- }
-
- if (b instanceof $ || jasmine.isDomNode(b)) {
- var $b = $(b)
-
- if (a instanceof $)
- return a.length == $b.length && $b.is(a)
-
- return $(b).is(a);
- }
- }
- })
-
- jasmine.getEnv().addCustomEqualityTester(function (a, b) {
- if (a instanceof $ && b instanceof $ && a.size() == b.size())
- return a.is(b)
- })
- })
-
- afterEach(function () {
- jasmine.getFixtures().cleanUp()
- jasmine.getStyleFixtures().cleanUp()
- jasmine.jQuery.events.cleanUp()
- })
-
- window.readFixtures = function () {
- return jasmine.getFixtures().proxyCallTo_('read', arguments)
- }
-
- window.preloadFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('preload', arguments)
- }
-
- window.loadFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('load', arguments)
- }
-
- window.appendLoadFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('appendLoad', arguments)
- }
-
- window.setFixtures = function (html) {
- return jasmine.getFixtures().proxyCallTo_('set', arguments)
- }
-
- window.appendSetFixtures = function () {
- jasmine.getFixtures().proxyCallTo_('appendSet', arguments)
- }
-
- window.sandbox = function (attributes) {
- return jasmine.getFixtures().sandbox(attributes)
- }
-
- window.spyOnEvent = function (selector, eventName) {
- return jasmine.jQuery.events.spyOn(selector, eventName)
- }
-
- window.preloadStyleFixtures = function () {
- jasmine.getStyleFixtures().proxyCallTo_('preload', arguments)
- }
-
- window.loadStyleFixtures = function () {
- jasmine.getStyleFixtures().proxyCallTo_('load', arguments)
- }
-
- window.appendLoadStyleFixtures = function () {
- jasmine.getStyleFixtures().proxyCallTo_('appendLoad', arguments)
- }
-
- window.setStyleFixtures = function (html) {
- jasmine.getStyleFixtures().proxyCallTo_('set', arguments)
- }
-
- window.appendSetStyleFixtures = function (html) {
- jasmine.getStyleFixtures().proxyCallTo_('appendSet', arguments)
- }
-
- window.loadJSONFixtures = function () {
- return jasmine.getJSONFixtures().proxyCallTo_('load', arguments)
- }
-
- window.getJSONFixture = function (url) {
- return jasmine.getJSONFixtures().proxyCallTo_('read', arguments)[url]
- }
-}(window, window.jasmine, window.jQuery);
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index ef746c8bc..e95dfbdc6 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -71,201 +71,6 @@ describe Ability do
end
end
- context "products" do
- let(:product) { FactoryBot.create(:product) }
-
- context "standard member" do
- it "can't read or manage products" do
- ability.should_not be_able_to(:read, product)
- ability.should_not be_able_to(:create, Product)
- ability.should_not be_able_to(:update, product)
- ability.should_not be_able_to(:destroy, product)
- end
- end
-
- context "admin" do
- let(:role) { FactoryBot.create(:admin) }
-
- before do
- member.roles << role
- end
-
- it "has admin role" do
- member.role?(:admin).should be true
- end
-
- it "can read products" do
- ability.should be_able_to(:read, product)
- end
- it "can create products" do
- ability.should be_able_to(:create, Product)
- end
- it "can update products" do
- ability.should be_able_to(:update, product)
- end
- it "can destroy products" do
- ability.should be_able_to(:destroy, product)
- end
- end
- end
-
- context "orders" do
- let(:order) { FactoryBot.create(:order, member: member) }
- let(:strangers_order) do
- FactoryBot.create(:order,
- member: FactoryBot.create(:member))
- end
- let(:completed_order) do
- FactoryBot.create(:completed_order,
- member: member)
- end
- let(:order_item) { FactoryBot.create(:order_item, order: order) }
- let(:strangers_order_item) do
- FactoryBot.create(:order_item,
- order: strangers_order)
- end
- let(:completed_order_item) do
- FactoryBot.create(:order_item,
- order: completed_order)
- end
-
- context "standard member" do
- it "can read their own orders" do
- ability.should be_able_to(:read, order)
- ability.should be_able_to(:read, completed_order)
- end
-
- it "can't read other people's orders" do
- ability.should_not be_able_to(:read, strangers_order)
- end
-
- it "can create a new order" do
- ability.should be_able_to(:create, Order)
- end
-
- it "can complete their own current order" do
- ability.should be_able_to(:complete, order)
- end
-
- it "can't complete someone else's order" do
- ability.should_not be_able_to(:complete, strangers_order)
- end
-
- it "can't complete a completed order" do
- ability.should_not be_able_to(:complete, completed_order)
- end
-
- it "can delete a current order" do
- ability.should be_able_to(:destroy, order)
- end
-
- it "can't delete someone else's order" do
- ability.should_not be_able_to(:destroy, strangers_order)
- end
-
- it "can't delete a completed order" do
- ability.should_not be_able_to(:destroy, completed_order)
- end
-
- it "can't read their own order items" do
- ability.should_not be_able_to(:read, order_item)
- ability.should_not be_able_to(:read, completed_order_item)
- end
-
- it "can't read other people's order items" do
- ability.should_not be_able_to(:read, strangers_order_item)
- end
-
- it "can create a new order item" do
- ability.should be_able_to(:create, OrderItem)
- end
-
- it "can't update their own order items" do
- ability.should_not be_able_to(:update, order_item)
- end
-
- it "can't update other people's order items" do
- ability.should_not be_able_to(:update, strangers_order_item)
- end
-
- it "can't updated items in completed orders" do
- ability.should_not be_able_to(:update, completed_order_item)
- end
-
- it "can't delete their own order item" do
- ability.should_not be_able_to(:destroy, order_item)
- end
-
- it "can't delete someone else's order item" do
- ability.should_not be_able_to(:destroy, strangers_order_item)
- end
-
- it "can't delete items from completed orders" do
- ability.should_not be_able_to(:destroy, completed_order_item)
- end
- end
-
- context "admin" do
- let(:role) { FactoryBot.create(:admin) }
-
- before do
- member.roles << role
- end
-
- it "has admin role" do
- member.role?(:admin).should be true
- end
-
- it "can read orders" do
- ability.should be_able_to(:read, order)
- end
-
- it "cannot create orders" do
- ability.should_not be_able_to(:create, order)
- end
-
- it "cannot complete orders" do
- ability.should_not be_able_to(:complete, order)
- end
-
- it "cannot delete orders" do
- ability.should_not be_able_to(:destroy, order)
- end
- end
- end
-
- context 'account details' do
- let(:account) { member.account }
-
- context 'ordinary member' do
- it "can't read account details" do
- ability.should_not be_able_to(:read, account)
- end
- it "can't manage account details" do
- ability.should_not be_able_to(:create, Account)
- ability.should_not be_able_to(:update, account)
- ability.should_not be_able_to(:destroy, account)
- end
- end
-
- context 'admin' do
- let(:role) { FactoryBot.create(:admin) }
-
- before do
- member.roles << role
- end
-
- it "can read account details" do
- ability.should be_able_to(:read, account)
- end
- it "can manage account details" do
- ability.should be_able_to(:create, Account)
- ability.should be_able_to(:update, account)
- ability.should be_able_to(:destroy, account)
- end
- end
- end
-
context 'plant parts' do
let(:plant_part) { FactoryBot.create(:plant_part) }
diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb
deleted file mode 100644
index 15eb68084..000000000
--- a/spec/models/account_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require 'rails_helper'
-
-describe Account do
- let(:member) { FactoryBot.create(:member) }
-
- it "auto-creates an account detail record when a member is created" do
- member.account.should be_an_instance_of Account
- end
-
- it "won't let you create two account details for the same member" do
- @details = Account.new(member_id: member.id)
- @details.should_not be_valid
- end
-
- it "formats the 'paid until' date nicely" do
- member.account.account_type = FactoryBot.create(:account_type)
- member.account.paid_until_string.should eq nil
-
- member.account.account_type = FactoryBot.create(:permanent_paid_account_type)
- member.account.paid_until_string.should eq "forever"
-
- member.account.account_type = FactoryBot.create(:paid_account_type)
- @time = Time.zone.now
- member.account.paid_until = @time
- member.account.paid_until_string.should eq @time.to_s
- end
-end
diff --git a/spec/models/account_type_spec.rb b/spec/models/account_type_spec.rb
deleted file mode 100644
index c65c113ba..000000000
--- a/spec/models/account_type_spec.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-require 'rails_helper'
-
-describe AccountType do
-end
diff --git a/spec/models/crop_spec.rb b/spec/models/crop_spec.rb
index 9e6173221..3f49a249d 100644
--- a/spec/models/crop_spec.rb
+++ b/spec/models/crop_spec.rb
@@ -276,6 +276,7 @@ describe Crop do
end
context 'interesting' do
+ subject { Crop.interesting }
let(:photo) { FactoryBot.create :photo }
# first, a couple of candidate crops
let(:crop1) { FactoryBot.create(:crop) }
@@ -284,8 +285,6 @@ describe Crop do
let(:crop1_planting) { crop1.plantings.first }
let(:crop2_planting) { crop2.plantings.first }
- subject { Crop.interesting }
-
describe 'lists interesting crops' do
before do
# they need 3+ plantings each to be interesting
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index c0b082d13..e02935d8e 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -23,15 +23,6 @@ describe 'member' do
expect(member.gardens.count).to eq 1
end
- it 'should have a accounts entry' do
- expect(member.account).to be_an_instance_of Account
- end
-
- it "should have a default-type account by default" do
- member.account.account_type.name.should eq Rails.application.config.default_account_type
- expect(member.paid?).to eq false
- end
-
it "doesn't show email by default" do
expect(member.show_email).to eq false
end
@@ -292,89 +283,6 @@ describe 'member' do
end
end
- context 'orders' do
- it 'finds the current order' do
- member = FactoryBot.create(:member)
- FactoryBot.create(:completed_order, member: member)
- order2 = FactoryBot.create(:order, member: member)
- member.current_order.should eq order2
- end
-
- it "copes if there's no current order" do
- member = FactoryBot.create(:member)
- FactoryBot.create(:completed_order, member: member)
- FactoryBot.create(:completed_order, member: member)
- member.current_order.should be_nil
- end
- end
-
- context "paid accounts" do
- let(:member) { FactoryBot.create(:member) }
-
- it "recognises a permanent paid account" do
- account_type = FactoryBot.create(:account_type,
- is_paid: true, is_permanent_paid: true)
- member.account.account_type = account_type
- member.paid?.should be(true)
- end
-
- it "recognises a current paid account" do
- account_type = FactoryBot.create(:account_type,
- is_paid: true, is_permanent_paid: false)
- member.account.account_type = account_type
- member.account.paid_until = Time.zone.now + 1.month
- member.paid?.should be(true)
- end
-
- it "recognises an expired paid account" do
- account_type = FactoryBot.create(:account_type,
- is_paid: true, is_permanent_paid: false)
- member.account.account_type = account_type
- member.account.paid_until = Time.zone.now - 1.minute
- member.paid?.should be(false)
- end
-
- it "recognises a free account" do
- account_type = FactoryBot.create(:account_type,
- is_paid: false, is_permanent_paid: false)
- member.account.account_type = account_type
- member.paid?.should be(false)
- end
-
- it "recognises a free account even with paid_until set" do
- account_type = FactoryBot.create(:account_type,
- is_paid: false, is_permanent_paid: false)
- member.account.account_type = account_type
- member.account.paid_until = Time.zone.now + 1.month
- member.paid?.should be(false)
- end
- end
-
- context "update account" do
- let(:product) do
- FactoryBot.create(:product,
- paid_months: 3)
- end
- let(:member) { FactoryBot.create(:member) }
-
- it "sets account_type" do
- member.update_account_after_purchase(product)
- member.account.account_type.should eq product.account_type
- end
-
- it "sets paid_until" do
- member.account.paid_until = nil # blank for now, as if never paid before
- member.update_account_after_purchase(product)
-
- # stringify to avoid millisecond problems...
- member.account.paid_until.to_s.should eq((Time.zone.now + 3.months).to_s)
-
- # and again to make sure it works for currently paid accounts
- member.update_account_after_purchase(product)
- member.account.paid_until.to_s.should eq((Time.zone.now + 3.months + 3.months).to_s)
- end
- end
-
context 'harvests' do
it 'has harvests' do
member = FactoryBot.create(:member)
diff --git a/spec/models/order_item_spec.rb b/spec/models/order_item_spec.rb
deleted file mode 100644
index 7c2de24c6..000000000
--- a/spec/models/order_item_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'rails_helper'
-
-describe OrderItem do
- let(:order_item) { FactoryBot.create(:order_item) }
-
- it "has an order and a product" do
- order_item.order.should be_an_instance_of Order
- order_item.product.should be_an_instance_of Product
- end
-
- it "validates price > product.min_price" do
- @product = FactoryBot.create(:product)
- order_item = FactoryBot.build(:order_item, price: @product.min_price - 1)
- order_item.should_not be_valid
- end
-
- it "doesn't let you add two items to an order" do
- @product = FactoryBot.create(:product)
- @order = FactoryBot.create(:order)
- order_item = FactoryBot.build(:order_item, order: @order)
- order_item.should be_valid
- order_item.save
- @order_item2 = FactoryBot.build(:order_item, order: @order)
- @order_item2.should_not be_valid
- end
-end
diff --git a/spec/models/order_spec.rb b/spec/models/order_spec.rb
deleted file mode 100644
index 9abb381ba..000000000
--- a/spec/models/order_spec.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-require 'rails_helper'
-
-describe Order do
- before(:each) do
- @order = FactoryBot.create(:order)
- @product = FactoryBot.create(:product)
- @order_item = FactoryBot.create(:order_item,
- order_id: @order.id, product_id: @product.id)
- end
-
- describe '#by_member_id' do
- before do
- @member1 = FactoryBot.create(:member)
- @member2 = FactoryBot.create(:member)
- @order1 = Order.create!(member_id: @member1.id)
- @order2 = Order.create!(member_id: @member2.id)
- end
-
- it "only returns orders belonging to member" do
- Order.by_member(@member1).should eq [@order1]
- end
- end
-
- it 'has order_items' do
- @order.order_items.first.should eq @order_item
- end
-
- it 'updates the account details' do
- @member = FactoryBot.create(:member)
- @order = FactoryBot.create(:order, member: @member)
- @account_type = FactoryBot.create(:account_type, name: 'paid')
- @product = FactoryBot.create(:product,
- account_type: @account_type,
- paid_months: 3)
- @order_item = FactoryBot.create(:order_item,
- order_id: @order.id, product_id: @product.id)
-
- @member.account.paid_until.should be_nil
-
- @order.update_account
-
- @member.account.account_type.should eq @account_type
- @member.account.paid_until.should_not be_nil
- end
-
- it "totals the amount due" do
- @member = FactoryBot.create(:member)
- @order = FactoryBot.create(:order, member: @member)
- @product = FactoryBot.create(:product,
- min_price: 1000)
- # we force an order to only have one item at present. Add more if wanted
- # later.
- @order_item1 = FactoryBot.create(:order_item,
- order_id: @order.id, product_id: @product.id, price: 1111, quantity: 1)
-
- @order.total.should eq 1111
- end
-
- it "gives the correct total for quantities more than 1" do
- @member = FactoryBot.create(:member)
- @order = FactoryBot.create(:order, member: @member)
- @product = FactoryBot.create(:product,
- min_price: 1000)
- # we force an order to only have one item at present. Add more if wanted
- # later.
- @order_item1 = FactoryBot.create(:order_item,
- order_id: @order.id, product_id: @product.id, price: 1111, quantity: 2)
-
- @order.total.should eq 2222
- end
-
- it "formats order items for activemerchant" do
- @member = FactoryBot.create(:member)
- @order = FactoryBot.create(:order, member: @member)
- @product = FactoryBot.create(:product,
- name: 'foo',
- min_price: 1000)
- # we force an order to only have one item at present. Add more if wanted
- # later.
- @order_item1 = FactoryBot.create(:order_item,
- order_id: @order.id, product_id: @product.id, price: 1111, quantity: 1)
-
- @order.activemerchant_items.should eq [{
- name: 'foo',
- quantity: 1,
- amount: 1111
- }]
- end
-
- context "referral codes" do
- it "has a referral code" do
- referred_order = FactoryBot.create(:referred_order)
- referred_order.referral_code.should_not be nil
- end
-
- it "validates referral codes" do
- referred_order = FactoryBot.build(:order, referral_code: 'CAMP_AIGN1?')
- referred_order.should_not be_valid
- end
-
- it "cleans up messy referral codes" do
- referred_order = FactoryBot.create(:order, referral_code: 'CaMpAiGn 1 ')
- referred_order.referral_code.should eq 'CAMPAIGN1'
- end
- end
-
- context 'search' do
- it 'finds orders by member' do
- order = FactoryBot.create(:order)
- Order.search(by: 'member', for: order.member.login_name).should eq [order]
- end
-
- it 'finds orders by order_id' do
- order = FactoryBot.create(:order)
- Order.search(by: 'order_id', for: order.id).should eq [order]
- end
-
- it 'finds orders by paypal_token' do
- order = FactoryBot.create(:order, paypal_express_token: 'foo')
- Order.search(by: 'paypal_token', for: 'foo').should eq [order]
- end
-
- it 'finds orders by paypal_payer_id' do
- order = FactoryBot.create(:order, paypal_express_payer_id: 'bar')
- Order.search(by: 'paypal_payer_id', for: 'bar').should eq [order]
- end
-
- it 'finds orders by referral_code' do
- order = FactoryBot.create(:order, referral_code: 'baz')
- Order.search(by: 'referral_code', for: 'baz').should eq [order]
- end
- end
-end
diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb
index c971ce2fd..5f07a3e29 100644
--- a/spec/models/photo_spec.rb
+++ b/spec/models/photo_spec.rb
@@ -50,7 +50,7 @@ describe Photo do
it "automatically if unused" do
photo.destroy_if_unused
- expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound
+ expect(-> { photo.reload }).to raise_error ActiveRecord::RecordNotFound
end
it 'they are used by plantings but not harvests' do
@@ -58,7 +58,7 @@ describe Photo do
planting.photos << photo
harvest.destroy # photo is now used by harvest but not planting
photo.destroy_if_unused
- expect(lambda { photo.reload }).not_to raise_error
+ expect(-> { photo.reload }).not_to raise_error
end
it 'they are used by harvests but not plantings' do
@@ -66,7 +66,7 @@ describe Photo do
planting.photos << photo
planting.destroy # photo is now used by harvest but not planting
photo.destroy_if_unused
- expect(lambda { photo.reload }).not_to raise_error
+ expect(-> { photo.reload }).not_to raise_error
end
it 'they are used by gardens but not plantings' do
@@ -74,7 +74,7 @@ describe Photo do
planting.photos << photo
planting.destroy # photo is now used by garden but not planting
photo.destroy_if_unused
- expect(lambda { photo.reload }).not_to raise_error
+ expect(-> { photo.reload }).not_to raise_error
end
it 'they are no longer used by anything' do
@@ -99,7 +99,7 @@ describe Photo do
expect(photo.harvests.size).to eq 0
expect(photo.gardens.size).to eq 0
photo.destroy_if_unused
- expect(lambda { photo.reload }).to raise_error ActiveRecord::RecordNotFound
+ expect(-> { photo.reload }).to raise_error ActiveRecord::RecordNotFound
end
it 'does not occur when a photo is still in use' do
diff --git a/spec/models/planting_spec.rb b/spec/models/planting_spec.rb
index 95e120c32..42bf04a4b 100644
--- a/spec/models/planting_spec.rb
+++ b/spec/models/planting_spec.rb
@@ -426,6 +426,22 @@ describe Planting do
expect(Planting.joins(:owner).all).not_to include(planting)
end
+ context 'ancestry' do
+ let(:parent_seed) { FactoryBot.create :seed }
+ let(:planting) { FactoryBot.create :planting, parent_seed: parent_seed }
+ it "planting has a parent seed" do
+ expect(planting.parent_seed).to eq(parent_seed)
+ end
+ it "seed has a child planting" do
+ expect(parent_seed.child_plantings).to eq [planting]
+ end
+ describe 'grandchildren' do
+ let(:grandchild_seed) { FactoryBot.create :seed, parent_planting: planting }
+ it { expect(grandchild_seed.parent_planting).to eq planting }
+ it { expect(grandchild_seed.parent_planting.parent_seed).to eq parent_seed }
+ end
+ end
+
# it 'predicts harvest times' do
# crop = FactoryBot.create :crop
# 10.times do
diff --git a/spec/models/product_spec.rb b/spec/models/product_spec.rb
deleted file mode 100644
index 2cc684667..000000000
--- a/spec/models/product_spec.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require 'rails_helper'
-
-describe Product do
- it "stringifies using the name" do
- @product = FactoryBot.create(:product)
- @product.to_s.should eq @product.name
- end
-end
diff --git a/spec/models/role_spec.rb b/spec/models/role_spec.rb
index a7cfbecd3..76e309aa0 100644
--- a/spec/models/role_spec.rb
+++ b/spec/models/role_spec.rb
@@ -1,13 +1,12 @@
require 'rails_helper'
describe Role do
- let(:member) { FactoryBot.create(:member) }
-
subject do
role = FactoryBot.create(:role, name: 'Crop Wrangler')
role.members << member
role
end
+ let(:member) { FactoryBot.create(:member) }
it 'has members' do
subject.members.first.should eq member
diff --git a/spec/models/seed_spec.rb b/spec/models/seed_spec.rb
index d8cb1e35d..690e8c75f 100644
--- a/spec/models/seed_spec.rb
+++ b/spec/models/seed_spec.rb
@@ -158,4 +158,38 @@ describe Seed do
Seed.has_photos.should include(seed)
end
end
+
+ context 'ancestry' do
+ let(:parent_planting) { FactoryBot.create :planting }
+ let(:seed) { FactoryBot.create :seed, parent_planting: parent_planting }
+ it "seed has a parent planting" do
+ expect(seed.parent_planting).to eq(parent_planting)
+ end
+ it "planting has a child seed" do
+ expect(parent_planting.child_seeds).to eq [seed]
+ end
+ end
+
+ context "finished" do
+ describe 'has finished fields' do
+ let(:seed) { FactoryBot.create(:finished_seed) }
+ it { expect(seed.finished).to eq true }
+ it { expect(seed.finished_at).to be_an_instance_of Date }
+ end
+
+ describe 'scopes' do
+ let!(:seed) { FactoryBot.create(:seed) }
+ let!(:finished_seed) { FactoryBot.create(:finished_seed) }
+
+ describe 'has finished scope' do
+ it { expect(Seed.finished).to include finished_seed }
+ it { expect(Seed.finished).not_to include seed }
+ end
+
+ describe 'has current scope' do
+ it { expect(Seed.current).to include seed }
+ it { expect(Seed.current).not_to include finished_seed }
+ end
+ end
+ end
end
diff --git a/spec/requests/api/v1/crop_request_spec.rb b/spec/requests/api/v1/crop_request_spec.rb
index 598a6993e..815ae8853 100644
--- a/spec/requests/api/v1/crop_request_spec.rb
+++ b/spec/requests/api/v1/crop_request_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
RSpec.describe 'Plantings', type: :request do
+ subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:crop) { FactoryBot.create :crop }
let(:crop_encoded_as_json_api) do
@@ -54,7 +55,6 @@ RSpec.describe 'Plantings', type: :request do
}
end
- subject { JSON.parse response.body }
describe '#index' do
before { get '/api/v1/crops', params: {}, headers: headers }
it { expect(subject['data']).to include(crop_encoded_as_json_api) }
diff --git a/spec/requests/api/v1/gardens_request_spec.rb b/spec/requests/api/v1/gardens_request_spec.rb
index ac1bb6786..e89deec3d 100644
--- a/spec/requests/api/v1/gardens_request_spec.rb
+++ b/spec/requests/api/v1/gardens_request_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
RSpec.describe 'Gardens', type: :request do
+ subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:garden) { FactoryBot.create :garden }
let(:garden_encoded_as_json_api) do
@@ -36,7 +37,6 @@ RSpec.describe 'Gardens', type: :request do
"related" => "#{resource_url}/photos" } }
end
- subject { JSON.parse response.body }
scenario '#index' do
get '/api/v1/gardens', params: {}, headers: headers
expect(subject['data']).to include(garden_encoded_as_json_api)
diff --git a/spec/requests/api/v1/harvest_request_spec.rb b/spec/requests/api/v1/harvest_request_spec.rb
index ebb0b59ba..833fe1928 100644
--- a/spec/requests/api/v1/harvest_request_spec.rb
+++ b/spec/requests/api/v1/harvest_request_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
RSpec.describe 'Harvests', type: :request do
+ subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:harvest) { FactoryBot.create :harvest }
let(:harvest_encoded_as_json_api) do
@@ -55,7 +56,6 @@ RSpec.describe 'Harvests', type: :request do
}
end
- subject { JSON.parse response.body }
describe '#index' do
before { get '/api/v1/harvests', params: {}, headers: headers }
it { expect(subject['data']).to include(harvest_encoded_as_json_api) }
diff --git a/spec/requests/api/v1/member_request_spec.rb b/spec/requests/api/v1/member_request_spec.rb
index 9536ec7c1..bbe01eeaf 100644
--- a/spec/requests/api/v1/member_request_spec.rb
+++ b/spec/requests/api/v1/member_request_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
RSpec.describe 'Members', type: :request do
+ subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:member) { FactoryBot.create :member }
let(:member_encoded_as_json_api) do
@@ -55,7 +56,6 @@ RSpec.describe 'Members', type: :request do
}
end
- subject { JSON.parse response.body }
describe '#index' do
before { get '/api/v1/members', params: {}, headers: headers }
it { expect(subject['data']).to include(member_encoded_as_json_api) }
diff --git a/spec/requests/api/v1/photos_request_spec.rb b/spec/requests/api/v1/photos_request_spec.rb
index 3af370a54..070b29be2 100644
--- a/spec/requests/api/v1/photos_request_spec.rb
+++ b/spec/requests/api/v1/photos_request_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
RSpec.describe 'Photos', type: :request do
+ subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:photo) { FactoryBot.create :photo }
let(:photo_encoded_as_json_api) do
@@ -53,7 +54,6 @@ RSpec.describe 'Photos', type: :request do
}
end
- subject { JSON.parse response.body }
describe '#index' do
before { get '/api/v1/photos', params: {}, headers: headers }
it { expect(subject['data']).to include(photo_encoded_as_json_api) }
diff --git a/spec/requests/api/v1/plantings_request_spec.rb b/spec/requests/api/v1/plantings_request_spec.rb
index ae561a66d..f84fa8092 100644
--- a/spec/requests/api/v1/plantings_request_spec.rb
+++ b/spec/requests/api/v1/plantings_request_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
RSpec.describe 'Plantings', type: :request do
+ subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:planting) { FactoryBot.create :planting }
let(:planting_encoded_as_json_api) do
@@ -66,7 +67,6 @@ RSpec.describe 'Plantings', type: :request do
}
end
- subject { JSON.parse response.body }
scenario '#index' do
get '/api/v1/plantings', params: {}, headers: headers
expect(subject['data']).to include(planting_encoded_as_json_api)
diff --git a/spec/requests/api/v1/seeds_request_spec.rb b/spec/requests/api/v1/seeds_request_spec.rb
index 243e645f5..f4ebcc2fd 100644
--- a/spec/requests/api/v1/seeds_request_spec.rb
+++ b/spec/requests/api/v1/seeds_request_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
RSpec.describe 'Photos', type: :request do
+ subject { JSON.parse response.body }
let(:headers) { { 'Accept' => 'application/vnd.api+json' } }
let!(:seed) { FactoryBot.create :seed }
let(:seed_encoded_as_json_api) do
@@ -42,7 +43,6 @@ RSpec.describe 'Photos', type: :request do
}
end
- subject { JSON.parse response.body }
describe '#index' do
before { get '/api/v1/seeds', params: {}, headers: headers }
it { expect(subject['data']).to include(seed_encoded_as_json_api) }
diff --git a/spec/routing/account_types_routing_spec.rb b/spec/routing/account_types_routing_spec.rb
deleted file mode 100644
index 8402dd727..000000000
--- a/spec/routing/account_types_routing_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require "rails_helper"
-
-describe AccountTypesController do
- describe "routing" do
- it "routes to #index" do
- get("/account_types").should route_to("account_types#index")
- end
-
- it "routes to #new" do
- get("/account_types/new").should route_to("account_types#new")
- end
-
- it "routes to #show" do
- get("/account_types/1").should route_to("account_types#show", id: "1")
- end
-
- it "routes to #edit" do
- get("/account_types/1/edit").should route_to("account_types#edit", id: "1")
- end
-
- it "routes to #create" do
- post("/account_types").should route_to("account_types#create")
- end
-
- it "routes to #update" do
- put("/account_types/1").should route_to("account_types#update", id: "1")
- end
-
- it "routes to #destroy" do
- delete("/account_types/1").should route_to("account_types#destroy", id: "1")
- end
- end
-end
diff --git a/spec/routing/order_items_routing_spec.rb b/spec/routing/order_items_routing_spec.rb
deleted file mode 100644
index 7487cb9f5..000000000
--- a/spec/routing/order_items_routing_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require "rails_helper"
-
-describe OrderItemsController do
- describe "routing" do
- it "routes to #index" do
- get("/order_items").should route_to("order_items#index")
- end
-
- it "routes to #new" do
- get("/order_items/new").should route_to("order_items#new")
- end
-
- it "routes to #show" do
- get("/order_items/1").should route_to("order_items#show", id: "1")
- end
-
- it "routes to #edit" do
- get("/order_items/1/edit").should route_to("order_items#edit", id: "1")
- end
-
- it "routes to #create" do
- post("/order_items").should route_to("order_items#create")
- end
-
- it "routes to #update" do
- put("/order_items/1").should route_to("order_items#update", id: "1")
- end
-
- it "routes to #destroy" do
- delete("/order_items/1").should route_to("order_items#destroy", id: "1")
- end
- end
-end
diff --git a/spec/routing/orders_routing_spec.rb b/spec/routing/orders_routing_spec.rb
deleted file mode 100644
index 38184ef33..000000000
--- a/spec/routing/orders_routing_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require "rails_helper"
-
-describe OrdersController do
- describe "routing" do
- it "routes to #index" do
- get("/orders").should route_to("orders#index")
- end
-
- it "routes to #new" do
- get("/orders/new").should route_to("orders#new")
- end
-
- it "routes to #show" do
- get("/orders/1").should route_to("orders#show", id: "1")
- end
-
- it "routes to #edit" do
- get("/orders/1/edit").should route_to("orders#edit", id: "1")
- end
-
- it "routes to #create" do
- post("/orders").should route_to("orders#create")
- end
-
- it "routes to #update" do
- put("/orders/1").should route_to("orders#update", id: "1")
- end
-
- it "routes to #destroy" do
- delete("/orders/1").should route_to("orders#destroy", id: "1")
- end
- end
-end
diff --git a/spec/routing/products_routing_spec.rb b/spec/routing/products_routing_spec.rb
deleted file mode 100644
index 15166a805..000000000
--- a/spec/routing/products_routing_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require "rails_helper"
-
-describe ProductsController do
- describe "routing" do
- it "routes to #index" do
- get("/products").should route_to("products#index")
- end
-
- it "routes to #new" do
- get("/products/new").should route_to("products#new")
- end
-
- it "routes to #show" do
- get("/products/1").should route_to("products#show", id: "1")
- end
-
- it "routes to #edit" do
- get("/products/1/edit").should route_to("products#edit", id: "1")
- end
-
- it "routes to #create" do
- post("/products").should route_to("products#create")
- end
-
- it "routes to #update" do
- put("/products/1").should route_to("products#update", id: "1")
- end
-
- it "routes to #destroy" do
- delete("/products/1").should route_to("products#destroy", id: "1")
- end
- end
-end
diff --git a/spec/views/account_types/edit.html.haml_spec.rb b/spec/views/account_types/edit.html.haml_spec.rb
deleted file mode 100644
index 1bd22be03..000000000
--- a/spec/views/account_types/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'rails_helper'
-
-describe "account_types/edit" do
- before(:each) do
- @account_type = assign(:account_type, stub_model(AccountType,
- name: "MyString",
- is_paid: false,
- is_permanent_paid: false))
- end
-
- it "renders the edit account_type form" do
- render
-
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "form", action: account_types_path(@account_type), method: "post" do
- assert_select "input#account_type_name", name: "account_type[name]"
- assert_select "input#account_type_is_paid", name: "account_type[is_paid]"
- assert_select "input#account_type_is_permanent_paid", name: "account_type[is_permanent_paid]"
- end
- end
-end
diff --git a/spec/views/account_types/index.html.haml_spec.rb b/spec/views/account_types/index.html.haml_spec.rb
deleted file mode 100644
index 56020fc35..000000000
--- a/spec/views/account_types/index.html.haml_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require 'rails_helper'
-
-describe "account_types/index" do
- before(:each) do
- @type = FactoryBot.create(:account_type)
- assign(:account_types, [@type, @type])
- end
-
- it "renders a list of account_types" do
- render
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "tr>td", text: @type.name.to_s, count: 2
- end
-end
diff --git a/spec/views/account_types/new.html.haml_spec.rb b/spec/views/account_types/new.html.haml_spec.rb
deleted file mode 100644
index 027a1b7c1..000000000
--- a/spec/views/account_types/new.html.haml_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require 'rails_helper'
-
-describe "account_types/new" do
- before(:each) do
- assign(:account_type, stub_model(AccountType,
- name: "MyString",
- is_paid: false,
- is_permanent_paid: false).as_new_record)
- end
-
- it "renders new account_type form" do
- render
-
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "form", action: account_types_path, method: "post" do
- assert_select "input#account_type_name", name: "account_type[name]"
- assert_select "input#account_type_is_paid", name: "account_type[is_paid]"
- assert_select "input#account_type_is_permanent_paid", name: "account_type[is_permanent_paid]"
- end
- end
-end
diff --git a/spec/views/account_types/show.html.haml_spec.rb b/spec/views/account_types/show.html.haml_spec.rb
deleted file mode 100644
index a31d4bc33..000000000
--- a/spec/views/account_types/show.html.haml_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'rails_helper'
-
-describe "account_types/show" do
- before(:each) do
- @account_type = assign(:account_type, stub_model(AccountType,
- name: "Name",
- is_paid: false,
- is_permanent_paid: false))
- end
-
- it "renders attributes in
" do
- render
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- rendered.should match(/Name/)
- rendered.should match(/false/)
- rendered.should match(/false/)
- end
-end
diff --git a/spec/views/accounts/edit.html.haml_spec.rb b/spec/views/accounts/edit.html.haml_spec.rb
deleted file mode 100644
index bc5c3b5a3..000000000
--- a/spec/views/accounts/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'rails_helper'
-
-describe "accounts/edit" do
- before(:each) do
- @member = FactoryBot.create(:member)
- @account = assign(:account, @member.account)
- end
-
- it "renders the edit account form" do
- render
-
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "form", action: accounts_path(@account), method: "post" do
- assert_select "input#account_member_id", name: "account[member_id]"
- assert_select "input#account_account_type", name: "account[account_type]"
- end
- end
-end
diff --git a/spec/views/accounts/index.html.haml_spec.rb b/spec/views/accounts/index.html.haml_spec.rb
deleted file mode 100644
index 4ec76151e..000000000
--- a/spec/views/accounts/index.html.haml_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-describe "accounts/index" do
- before(:each) do
- @member = FactoryBot.create(:member)
- @account = @member.account
- assign(:accounts, [@account, @account])
- end
-
- it "renders a list of accounts" do
- render
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "tr>td", text: @account.member_id.to_s, count: 2
- end
-end
diff --git a/spec/views/accounts/new.html.haml_spec.rb b/spec/views/accounts/new.html.haml_spec.rb
deleted file mode 100644
index 77f6ff20f..000000000
--- a/spec/views/accounts/new.html.haml_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'rails_helper'
-
-describe "accounts/new" do
- before(:each) do
- @member = FactoryBot.create(:member)
- assign(:account, @member.account)
- end
-
- it "renders new account form" do
- render
-
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "form", action: accounts_path, method: "post" do
- assert_select "input#account_member_id", name: "account[member_id]"
- assert_select "input#account_account_type", name: "account[account_type]"
- end
- end
-end
diff --git a/spec/views/accounts/show.html.haml_spec.rb b/spec/views/accounts/show.html.haml_spec.rb
deleted file mode 100644
index d96fbbd96..000000000
--- a/spec/views/accounts/show.html.haml_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'rails_helper'
-
-describe "accounts/show" do
- before(:each) do
- @member = FactoryBot.create(:member)
- @account = assign(:account, @member.account)
- end
-
- it "renders attributes in
" do
- render
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- rendered.should have_content @account.member_id.to_s
- rendered.should have_content 'Free'
- rendered.should have_content @account.paid_until.to_s
- end
-end
diff --git a/spec/views/admin/index_spec.rb b/spec/views/admin/index_spec.rb
index beb0eacbd..cc8b145d3 100644
--- a/spec/views/admin/index_spec.rb
+++ b/spec/views/admin/index_spec.rb
@@ -9,8 +9,6 @@ describe 'admin/index.html.haml', type: "view" do
end
it "includes links to manage various things" do
- assert_select "a", href: account_types_path
- assert_select "a", href: products_path
assert_select "a", href: roles_path
assert_select "a", href: forums_path
end
diff --git a/spec/views/admin/orders/index_spec.rb b/spec/views/admin/orders/index_spec.rb
deleted file mode 100644
index 8d80dc3ef..000000000
--- a/spec/views/admin/orders/index_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-require 'rails_helper'
-
-describe 'admin/orders/index.html.haml', type: "view" do
- before(:each) do
- @member = FactoryBot.create(:admin_member)
- sign_in @member
- controller.stub(:current_user) { @member }
- render
- end
-
- it "includes a search form for orders" do
- assert_select "form"
- assert_select "input#search_text"
- assert_select "select#search_by"
- end
-
- it "lets you search by referral code" do
- assert_select "option[value=referral_code]", text: "Referral code"
- end
-end
diff --git a/spec/views/crops/_planting_advice.html.haml_spec.rb b/spec/views/crops/_planting_advice.html.haml_spec.rb
index 38499e2d9..12064a1b8 100644
--- a/spec/views/crops/_planting_advice.html.haml_spec.rb
+++ b/spec/views/crops/_planting_advice.html.haml_spec.rb
@@ -1,9 +1,8 @@
require 'rails_helper'
describe "crops/_planting_advice" do
- let(:planting) { FactoryBot.create(:planting) }
-
subject { rendered }
+ let(:planting) { FactoryBot.create(:planting) }
shared_examples "render planting_advice" do
before { render 'crops/planting_advice', crop: planting.crop }
diff --git a/spec/views/gardens/show.html.haml_spec.rb b/spec/views/gardens/show.html.haml_spec.rb
index 7130e2e4f..5594c6755 100644
--- a/spec/views/gardens/show.html.haml_spec.rb
+++ b/spec/views/gardens/show.html.haml_spec.rb
@@ -43,7 +43,7 @@ describe "gardens/show" do
end
it 'should have an edit button' do
- rendered.should have_link 'edit_garden_link'
+ rendered.should have_link 'Edit'
end
it "shows a 'plant something' button" do
diff --git a/spec/views/harvests/show.html.haml_spec.rb b/spec/views/harvests/show.html.haml_spec.rb
index 624cf88c4..4aec453ff 100644
--- a/spec/views/harvests/show.html.haml_spec.rb
+++ b/spec/views/harvests/show.html.haml_spec.rb
@@ -1,6 +1,7 @@
require 'rails_helper'
describe "harvests/show" do
+ subject { render }
let!(:harvest) { FactoryBot.create(:harvest) }
before do
@@ -10,8 +11,6 @@ describe "harvests/show" do
render
end
- subject { render }
-
describe "renders attributes" do
it { is_expected.to have_content harvest.crop.name }
it { is_expected.to have_content harvest.harvested_at.to_s }
diff --git a/spec/views/home/_crops.html.haml_spec.rb b/spec/views/home/_crops.html.haml_spec.rb
deleted file mode 100644
index bfc8dc856..000000000
--- a/spec/views/home/_crops.html.haml_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'rails_helper'
-
-describe 'home/_crops.html.haml', type: "view" do
- let(:crop) { FactoryBot.create(:crop, name: 'pūhā') }
- let(:photo) { FactoryBot.create(:photo) }
- before(:each) do
- plantings = FactoryBot.create_list(:planting, 3, crop: crop)
- plantings.each do |p|
- p.photos << photo
- end
- render
- end
- let(:planting) { crop.plantings.first }
- it 'shows crops section' do
- assert_select 'h2', text: 'Some of our crops'
- assert_select "a[href='#{crop_path(crop)}']"
- end
-
- it 'shows plantings section' do
- assert_select 'h2', text: 'Recently planted'
- rendered.should have_content planting.location
- end
-
- it 'shows recently added crops' do
- assert_select 'h2', text: 'Recently planted'
- end
-
- it 'includes a link to all crops' do
- assert_select "a[href='#{crops_path}']", text: /View all crops/
- end
-end
diff --git a/spec/views/orders/index.html.haml_spec.rb b/spec/views/orders/index.html.haml_spec.rb
deleted file mode 100644
index c95f204e2..000000000
--- a/spec/views/orders/index.html.haml_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require 'rails_helper'
-
-describe "orders/index" do
- before(:each) do
- @member = FactoryBot.create(:member)
- sign_in @member
- @order1 = FactoryBot.create(:order, member: @member)
- @order2 = FactoryBot.create(:completed_order, member: @member)
- assign(:orders, [@order1, @order2])
- end
-
- it "shows your current account status" do
- render
- rendered.should have_content "Your current account status"
- end
-
- it "renders a list of orders" do
- render
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "tr>td a/@href", text: "/orders/#{@order1.id}"
- assert_select "tr>td a/@href", text: "/orders/#{@order2.id}"
- end
-end
diff --git a/spec/views/orders/show.html.haml_spec.rb b/spec/views/orders/show.html.haml_spec.rb
deleted file mode 100644
index 4f9c7d7f6..000000000
--- a/spec/views/orders/show.html.haml_spec.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-require 'rails_helper'
-
-describe "orders/show" do
- before(:each) do
- @member = FactoryBot.create(:member)
- sign_in @member
- controller.stub(:current_user) { @member }
- end
-
- context "current order" do
- before(:each) do
- @order = assign(:order, FactoryBot.create(:order, member: @member))
- @order_item = FactoryBot.create(:order_item,
- order: @order,
- quantity: 2,
- price: 9900)
- render
- end
-
- it "displays order number" do
- rendered.should have_content "Order number"
- end
-
- it "shows order items in a table" do
- assert_select "table>tr>th", text: "Product"
- end
-
- it "shows the total" do
- rendered.should have_content "Total:"
- assert_select "strong", /198.00/
- end
-
- it "shows a foreign exchange link for the total" do
- currency = Rails.application.config.currency
- assert_select("a[href='http://www.wolframalpha.com/input/?i=198.00+#{currency}']")
- end
-
- it "asks for a referral code" do
- assert_select "input[id='referral_code']"
- end
-
- it "shows a checkout button" do
- assert_select "input[value='Checkout with PayPal']"
- end
-
- it "shows a delete order button" do
- assert_select "a", text: "Delete this order"
- end
- end
-
- context "completed order" do
- before(:each) do
- @order = assign(:order, FactoryBot.create(:completed_order, member: @member))
- @order_item = FactoryBot.create(:order_item,
- order: @order,
- quantity: 2,
- price: 9900)
- render
- end
-
- it "doesn't show a checkout button" do
- assert_select "a", text: "Checkout", count: 0
- end
-
- it "doesn't show delete order button" do
- assert_select "a", text: "Delete this order", count: 0
- end
- end
-end
diff --git a/spec/views/plantings/_form.html.haml_spec.rb b/spec/views/plantings/_form.html.haml_spec.rb
index 692b53173..6371311ae 100644
--- a/spec/views/plantings/_form.html.haml_spec.rb
+++ b/spec/views/plantings/_form.html.haml_spec.rb
@@ -2,7 +2,6 @@ require 'rails_helper'
describe "plantings/_form" do
before(:each) do
- controller.stub(:current_user) { nil }
@member = FactoryBot.create(:member)
@garden = FactoryBot.create(:garden, owner: @member)
@uppercase = FactoryBot.create(:uppercasecrop)
@@ -14,6 +13,8 @@ describe "plantings/_form" do
crop: @crop,
owner: @member,
planted_at: Date.new(2013, 3, 1))
+
+ sign_in @member
render
end
diff --git a/spec/views/plantings/show.html.haml_spec.rb b/spec/views/plantings/show.html.haml_spec.rb
index 899724ac7..47a742c58 100644
--- a/spec/views/plantings/show.html.haml_spec.rb
+++ b/spec/views/plantings/show.html.haml_spec.rb
@@ -35,11 +35,10 @@ describe "plantings/show" do
rendered.should have_content 'cutting'
end
- it "doesn't show planted_from if blank" do
+ it "shows planted_from if blank" do
planting.update(planted_from: '')
render
- rendered.should_not have_content 'Planted from:'
- rendered.should_not have_content 'cutting'
+ rendered.should have_content 'Planted from: not specified'
end
end
diff --git a/spec/views/posts/show.html.haml_spec.rb b/spec/views/posts/show.html.haml_spec.rb
index 79f352486..aaad30fab 100644
--- a/spec/views/posts/show.html.haml_spec.rb
+++ b/spec/views/posts/show.html.haml_spec.rb
@@ -1,13 +1,13 @@
require 'rails_helper'
describe "posts/show" do
+ subject { rendered }
let(:author) { FactoryBot.create(:member, login_name: 'mary') }
before(:each) do
controller.stub(:current_user) { nil }
assign(:post, post)
end
- subject { rendered }
describe 'render post' do
before { render }
diff --git a/spec/views/products/edit.html.haml_spec.rb b/spec/views/products/edit.html.haml_spec.rb
deleted file mode 100644
index 3d60c9e95..000000000
--- a/spec/views/products/edit.html.haml_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'rails_helper'
-
-describe "products/edit" do
- before(:each) do
- @product = assign(:product, stub_model(Product,
- name: "MyString",
- description: "MyString",
- min_price: "9.99"))
- end
-
- it "renders the edit product form" do
- render
-
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "form", action: products_path(@product), method: "post" do
- assert_select "input#product_name", name: "product[name]"
- assert_select "textarea#product_description", name: "product[description]"
- assert_select "input#product_min_price", name: "product[min_price]"
- assert_select "input#product_recommended_price", name: "product[recommended_price]"
- end
- end
-end
diff --git a/spec/views/products/index.html.haml_spec.rb b/spec/views/products/index.html.haml_spec.rb
deleted file mode 100644
index 90e08e2a3..000000000
--- a/spec/views/products/index.html.haml_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'rails_helper'
-
-describe "products/index" do
- before(:each) do
- @product = FactoryBot.create(:product)
- assign(:products, [@product, @product])
- end
-
- it "renders a list of products" do
- render
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "tr>td", text: @product.name, count: 2
- assert_select "tr>td", text: @product.description, count: 2
- assert_select "tr>td", text: @product.min_price.to_s, count: 2
- end
-end
diff --git a/spec/views/products/new.html.haml_spec.rb b/spec/views/products/new.html.haml_spec.rb
deleted file mode 100644
index 336c6bac1..000000000
--- a/spec/views/products/new.html.haml_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-require 'rails_helper'
-
-describe "products/new" do
- before(:each) do
- assign(:product, stub_model(Product,
- name: "MyString",
- description: "MyString",
- min_price: "9.99").as_new_record)
- end
-
- it "renders new product form" do
- render
-
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- assert_select "form", action: products_path, method: "post" do
- assert_select "input#product_name", name: "product[name]"
- assert_select "textarea#product_description", name: "product[description]"
- assert_select "input#product_min_price", name: "product[min_price]"
- assert_select "input#product_recommended_price", name: "product[recommended_price]"
- assert_select "select#product_account_type_id", name: "product[account_type_id]"
- assert_select "input#product_paid_months", name: "product[paid_months]"
- end
- end
-end
diff --git a/spec/views/products/show.html.haml_spec.rb b/spec/views/products/show.html.haml_spec.rb
deleted file mode 100644
index 315d9caae..000000000
--- a/spec/views/products/show.html.haml_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'rails_helper'
-
-describe "products/show" do
- before(:each) do
- @product = assign(:product, FactoryBot.create(:product))
- end
-
- it "renders attributes in
" do
- render
- # Run the generator again with the --webrat flag if you want to use webrat matchers
- rendered.should have_content @product.name
- rendered.should have_content @product.min_price.to_s
- rendered.should have_content @product.recommended_price.to_s
- end
-end
diff --git a/spec/views/shop/index_spec.rb b/spec/views/shop/index_spec.rb
deleted file mode 100644
index 29b740c92..000000000
--- a/spec/views/shop/index_spec.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-require 'rails_helper'
-
-describe 'shop/index.html.haml', type: "view" do
- before(:each) do
- @product1 = FactoryBot.create(:product)
- @product2 = FactoryBot.create(:product_with_recommended_price)
- assign(:products, [@product1, @product2])
- assign(:order_item, OrderItem.new)
- end
-
- context "signed in" do
- before(:each) do
- @member = FactoryBot.create(:member)
- controller.stub(:current_user) { @member }
- render
- end
-
- it 'shows products' do
- assert_select("h2", text: @product1.name)
- end
-
- it 'shows prices in configured currency' do
- rendered.should have_content format('9.99 %s', Rails.application.config.currency)
- end
-
- it 'should contain an exchange rate link' do
- currency = Rails.application.config.currency
- assert_select("a[href='http://www.wolframalpha.com/input/?i=9.99+#{currency}']")
- end
-
- it 'shows recommended price for products that have it' do
- rendered.should have_content format('12.00 %s', Rails.application.config.currency)
- end
-
- it 'should contain an exchange rate link for recommended price' do
- currency = Rails.application.config.currency
- assert_select("a[href='http://www.wolframalpha.com/input/?i=12.00+#{currency}']")
- end
-
- it 'displays the order form' do
- assert_select "form", count: 2
- end
-
- it 'renders markdown in product descriptions' do
- assert_select "em", text: 'hurrah', count: 2
- end
- end
-
- context "is paid" do
- before(:each) do
- @member = FactoryBot.create(:member)
- @member.account.account_type = FactoryBot.create(:paid_account_type)
- @member.account.paid_until = Time.zone.now + 1.year
- controller.stub(:current_member) { @member }
- end
-
- it "recognises the paid member" do
- @member.paid?.should be(true)
- end
-
- it "tells you you have a paid membership" do
- render
- rendered.should have_content "You currently have a paid"
- end
-
- it "doesn't show shop" do
- render
- assert_select "form", false
- end
- end
-
- context "signed out" do
- before(:each) do
- controller.stub(:current_user) { nil }
- render
- end
-
- it "tells you to sign up/sign in" do
- rendered.should have_content "sign in or sign up"
- end
- end
-end