Merging dev

This commit is contained in:
Ryan Clark
2013-07-16 17:23:15 -07:00
607 changed files with 56966 additions and 7712 deletions

7
.gitignore vendored
View File

@@ -1,9 +1,14 @@
/log/*
/doc
/db/*.sqlite3
/tmp/*
coverage
.pt
.*.sw*
*~
*.DS_Store
credentials.sh
Pathogen:
Pathogen:
custom_plan.rb
zeus.json
.bundle

View File

@@ -1,10 +1,14 @@
---
language: ruby
bundler_args: --without development assets
env: RAILS_ENV=travis
rvm:
- 1.9.3
- 1.9.3
before_script:
- psql -c 'create database growstuff_test;' -U postgres
script:
- bundle exec rake db:migrate --trace
- bundle exec rspec spec/
- bundle exec rake db:migrate --trace
- bundle exec rspec spec/
# after_success:
# - if [[ "$TRAVIS_BRANCH" == "dev" ]]; then git remote add heroku git@heroku.com:growstuff-dev.git
@@ -20,6 +24,6 @@ script:
# - heroku restart
# - fi
env:
global:
secure: "QFQbCdNGyjeatp/H0j0y0oGiue45fpG2w6eA2QAbq2RmvhabgXbd5WIobN90\ndrae3S7TRxPDpMpus90icykX6EzOTLXCEvaC4rh9pCcRktj3SZqq5b9rVTvs\n1MvlS6HhtsVqsrKjQUb0WmPpnganIzTs0RtGaQspo2joPJO18A4="
# env:
# global:
# secure: "QFQbCdNGyjeatp/H0j0y0oGiue45fpG2w6eA2QAbq2RmvhabgXbd5WIobN90\ndrae3S7TRxPDpMpus90icykX6EzOTLXCEvaC4rh9pCcRktj3SZqq5b9rVTvs\n1MvlS6HhtsVqsrKjQUb0WmPpnganIzTs0RtGaQspo2joPJO18A4="

26
.watchr
View File

@@ -1,26 +0,0 @@
def run_spec(file)
unless File.exist?(file)
puts "#{file} does not exist"
return
end
puts "Running #{file}"
system "bundle exec rspec #{file}"
puts
end
watch("spec/.*/*_spec.rb") do |match|
run_spec match[0]
end
watch("app/(.*/.*).rb") do |match|
run_spec %{spec/#{match[1]}_spec.rb}
end
watch("app/(.*/.*).html.haml") do |match|
run_spec %{spec/#{match[1]}_spec.rb}
end
watch("app/(.*/.*).html.erb") do |match|
run_spec %{spec/#{match[1]}_spec.rb}
end

39
CONTRIBUTORS.md Normal file
View File

@@ -0,0 +1,39 @@
This is a list of contributors to Growstuff's codebase. We maintain
this list because we work in pairs, but Github only knows about the
person who actually does the commits. This gives credit to both members
of the pair.
If you contribute, please add yourself to the bottom of the list and
submit the change with your pull request.
## Committers
- Alex Bayley / [Skud](https://github.com/Skud)
- Cesy / [cesy](https://github.com/cesy)
- Miles Gould / [pozorvlak](https://github.com/pozorvlak)
- Joseph Caudle / [jcaudle](https://github.com/jcaudle)
## Contributors
- Ricky Amianym / [amianym](https://github.com/amianym)
- Juliet Kemp / [julietk](https://github.com/julietk)
- Federico Mena Quintero / [federicomenaquintero](https://github.com/federicomenaquintero)
- Jay Springett / [thejaymo](https://github.com/thejaymo)
- Maia Sauren / [sauramaia](https://github.com/sauramaia)
- Norman Ancajas / [nbancajas](https://github.com/nbancajas)
- Jonathan "Duke" Leto / [leto](https://github.com/leto)
- Mackenzie Morgan / [maco](https://github.com/maco)
- Amy Hendrix / [sabreuse](https://github.com/sabreuse)
- CephLPod / [cephLpod](https://github.com/cephLpod/)
- Gemma Mason / [gemmaellen](https://github.com/gemmaellen)
- Courtney Webster / [phazel](https://github.com/phazel/)
- Cathy Sullivan / [cesullivan](https://github.com/cesullivan)
- Jared McCorkindale / [jmcorkindale](https://github.com/jmcorkindale)
- Florian Vallen / [flov](https://github.com/flov)
- Samuel Cochrane / [sj26](https://github.com/sj26)
- Craig Read / [Catharz](https://github.com/Catharz)
- Ju Transcendancing / [transcendancing](https://github.com/transcendancing)
- Lillian Ryan / [attlebish](https://github.com/attlebish)
- Gary Traffanstedt / [blimey85](https://github.com/blimey85)
- Yaw Boakye / [yawboakye](https://github.com/yawboakye)
- Ryan Clark / [IAMRYO](https://github.com/IAMRYO)

64
Gemfile
View File

@@ -6,36 +6,52 @@ gem 'rails', '3.2.13'
gem 'rack', '~>1.4.5'
gem 'json', '~>1.7.7'
gem 'haml'
gem 'unicorn' # http server
gem 'cancan'
gem 'cancan' # for checking member privileges
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
# vendored activemerchant for testing- needed for bogus paypal
# gateway monkeypatch
gem 'activemerchant', '1.33.0',
:path => 'vendor/gems/activemerchant-1.33.0',
:require => 'active_merchant'
gem 'active_utils', '1.0.5',
:path => 'vendor/gems/active_utils-1.0.5'
group :production, :staging do
gem 'pg'
gem 'newrelic_rpm'
gem 'unicorn'
gem 'dalli'
gem 'memcachier'
end
# Gems used only for assets and not required
# in production environments by default.
group :assets do
# CSS preprocessor, used for app/assets/stylesheets/application.css
gem 'sass-rails', '~> 3.2.3'
# CoffeeScript is a Python-like language that compiles to JavaScript
gem 'coffee-rails', '~> 3.2.1'
# less-rails depends on a JavaScript engine; we use therubyracer.
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# long term, we'll probably want node.js for performance, but this will do for now as it's easier for new people to install
# long term, we'll probably want node.js for performance, but this will do
# for now as it's easier for new people to install
gem 'therubyracer', '~> 0.10.2', :platforms => :ruby
# Another CSS preprocessor, used for Bootstrap overrides
gem "less-rails"
gem "twitter-bootstrap-rails", '~> 2.2.2'
# CSS framework
gem "twitter-bootstrap-rails",
:git => 'https://github.com/seyhunak/twitter-bootstrap-rails.git',
:ref => '2c7c52'
gem 'uglifier', '>= 1.0.3'
gem 'uglifier', '>= 1.0.3' # JavaScript compressor
gem 'compass-rails', '~> 1.0.3'
gem 'compass-rails', '~> 1.0.3' # Yet Another CSS framework
end
gem 'jquery-rails'
gem 'flickraw'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
@@ -46,13 +62,12 @@ gem 'jquery-rails'
# Use unicorn as the app server
# gem 'unicorn'
# Deploy with Capistrano
gem 'capistrano'
gem 'rvm-capistrano'
gem 'capistrano-ext'
# To use debugger
gem 'debugger'
group :development do
# Installation of the debugger gem fails on Travis CI,
# so we don't use it in the test environment
gem 'debugger'
end
# Markdown formatting for updates etc
gem 'bluecloth'
@@ -80,19 +95,16 @@ gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-flickr'
# for phusion passenger (i.e. mod_rails) on the server
gem 'passenger'
gem 'rake', '>= 10.0.0'
gem 'cape', '~> 1.5.0'
gem 'diff-lcs'
group :development, :test do
gem 'thin'
gem 'sqlite3'
gem 'haml-rails'
gem 'rspec-rails', '~> 2.12.1'
gem 'webrat'
gem 'watchr'
gem 'factory_girl_rails', '~> 4.0'
gem 'sqlite3' # database engine
end
group :development, :test, :travis do
gem 'haml-rails' # HTML templating language
gem 'rspec-rails', '~> 2.12.1' # unit testing framework
gem 'webrat' # provides HTML matchers for view tests
gem 'factory_girl_rails', '~> 4.0' # for creating test data
gem 'coveralls', require: false # coverage analysis
end

View File

@@ -1,3 +1,26 @@
GIT
remote: https://github.com/seyhunak/twitter-bootstrap-rails.git
revision: 2c7c527c354d9068ce49346d4fd8389328d32ce6
ref: 2c7c52
specs:
twitter-bootstrap-rails (2.2.7)
actionpack (>= 3.1)
execjs
rails (>= 3.1)
railties (>= 3.1)
PATH
remote: vendor/gems/active_utils-1.0.5
specs:
active_utils (1.0.5)
activesupport (>= 2.3.11)
i18n
PATH
remote: vendor/gems/activemerchant-1.33.0
specs:
activemerchant (1.33.0)
GEM
remote: https://rubygems.org/
specs:
@@ -35,15 +58,6 @@ GEM
railties (>= 3.0)
builder (3.0.4)
cancan (1.6.9)
cape (1.5.0)
capistrano (2.14.2)
highline
net-scp (>= 1.0.0)
net-sftp (>= 2.0.0)
net-ssh (>= 2.0.14)
net-ssh-gateway (>= 1.1.0)
capistrano-ext (1.2.1)
capistrano (>= 1.0.0)
chunky_png (1.2.7)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
@@ -52,6 +66,7 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.6.2)
colorize (0.5.8)
columnize (0.3.6)
commonjs (0.2.6)
compass (0.12.2)
@@ -60,14 +75,19 @@ GEM
sass (~> 3.1)
compass-rails (1.0.3)
compass (>= 0.12.2, < 0.14)
daemon_controller (1.1.2)
daemons (1.1.9)
debugger (1.5.0)
coveralls (0.6.7)
colorize
multi_json (~> 1.3)
rest-client
simplecov (>= 0.7)
thor
dalli (2.6.4)
debugger (1.6.0)
columnize (>= 0.3.1)
debugger-linecache (~> 1.2.0)
debugger-ruby_core_source (~> 1.2.0)
debugger-ruby_core_source (~> 1.2.1)
debugger-linecache (1.2.0)
debugger-ruby_core_source (1.2.0)
debugger-ruby_core_source (1.2.2)
devise (2.2.3)
bcrypt-ruby (~> 3.0)
orm_adapter (~> 0.1)
@@ -75,7 +95,6 @@ GEM
warden (~> 1.2.1)
diff-lcs (1.1.3)
erubis (2.7.0)
eventmachine (1.0.3)
execjs (1.4.0)
multi_json (~> 1.0)
factory_girl (4.2.0)
@@ -83,7 +102,7 @@ GEM
factory_girl_rails (4.2.1)
factory_girl (~> 4.2.0)
railties (>= 3.0.0)
fastthread (1.0.7)
flickraw (0.9.6)
friendly_id (4.0.9)
fssm (0.2.10)
geocoder (1.1.6)
@@ -96,7 +115,6 @@ GEM
haml (>= 3.1, < 4.1)
railties (>= 3.1, < 4.1)
hashie (1.2.0)
highline (1.6.16)
hike (1.2.1)
i18n (0.6.1)
journey (1.0.4)
@@ -115,17 +133,13 @@ GEM
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
memcachier (0.0.2)
mime-types (1.21)
mini_portile (0.5.0)
multi_json (1.7.1)
net-scp (1.1.0)
net-ssh (>= 2.6.5)
net-sftp (2.1.1)
net-ssh (>= 2.6.5)
net-ssh (2.6.6)
net-ssh-gateway (1.2.0)
net-ssh (>= 2.6.5)
newrelic_rpm (3.5.8.72)
nokogiri (1.5.8)
nokogiri (1.6.0)
mini_portile (~> 0.5.0)
oauth (0.4.7)
omniauth (1.1.3)
hashie (~> 1.2)
@@ -139,11 +153,6 @@ GEM
multi_json (~> 1.3)
omniauth-oauth (~> 1.0)
orm_adapter (0.4.0)
passenger (3.0.19)
daemon_controller (>= 1.0.0)
fastthread (>= 1.0.1)
rack
rake (>= 0.8.1)
pg (0.14.1)
polyglot (0.3.3)
rack (1.4.5)
@@ -172,6 +181,8 @@ GEM
rake (10.0.3)
rdoc (3.12.2)
json (~> 1.4)
rest-client (1.6.7)
mime-types (>= 1.16)
rspec-core (2.12.2)
rspec-expectations (2.12.1)
diff-lcs (~> 1.1.3)
@@ -183,13 +194,15 @@ GEM
rspec-core (~> 2.12.0)
rspec-expectations (~> 2.12.0)
rspec-mocks (~> 2.12.0)
rvm-capistrano (1.2.7)
capistrano (>= 2.0.0)
sass (3.2.7)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
simplecov (0.7.1)
multi_json (~> 1.0)
simplecov-html (~> 0.7.1)
simplecov-html (0.7.1)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
@@ -198,19 +211,11 @@ GEM
sqlite3 (1.3.7)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
thin (1.5.1)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
rack (>= 1.0.0)
thor (0.17.0)
tilt (1.3.6)
treetop (1.4.12)
polyglot
polyglot (>= 0.3.1)
twitter-bootstrap-rails (2.2.6)
actionpack (>= 3.1)
execjs
railties (>= 3.1)
tzinfo (0.3.37)
uglifier (1.3.0)
execjs (>= 0.3.0)
@@ -221,7 +226,6 @@ GEM
raindrops (~> 0.7)
warden (1.2.1)
rack (>= 1.0)
watchr (0.7)
webrat (0.7.3)
nokogiri (>= 1.2.0)
rack (>= 1.0)
@@ -232,19 +236,20 @@ PLATFORMS
ruby
DEPENDENCIES
active_utils (= 1.0.5)!
activemerchant (= 1.33.0)!
bluecloth
bootstrap-datepicker-rails
bundler (>= 1.1.5)
cancan
cape (~> 1.5.0)
capistrano
capistrano-ext
coffee-rails (~> 3.2.1)
compass-rails (~> 1.0.3)
coveralls
dalli
debugger
devise
diff-lcs
factory_girl_rails (~> 4.0)
flickraw
friendly_id
geocoder
gravatar-ultimate
@@ -253,24 +258,21 @@ DEPENDENCIES
jquery-rails
json (~> 1.7.7)
less-rails
memcachier
newrelic_rpm
omniauth
omniauth-flickr
omniauth-twitter
passenger
pg
rack (~> 1.4.5)
rails (= 3.2.13)
rake (>= 10.0.0)
rspec-rails (~> 2.12.1)
rvm-capistrano
sass-rails (~> 3.2.3)
sqlite3
therubyracer (~> 0.10.2)
thin
twitter-bootstrap-rails (~> 2.2.2)
twitter-bootstrap-rails!
uglifier (>= 1.0.3)
unicorn
watchr
webrat
will_paginate (~> 3.0)

View File

@@ -1,6 +1,7 @@
# Growstuff
[![Build Status](https://travis-ci.org/Growstuff/growstuff.png)](https://travis-ci.org/Growstuff/growstuff)
[![Coverage Status](https://coveralls.io/repos/Growstuff/growstuff/badge.png)](https://coveralls.io/r/Growstuff/growstuff)
Welcome to the Growstuff project.

View File

@@ -2,6 +2,7 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require 'rake/dsl_definition'
require File.expand_path('../config/application', __FILE__)
Growstuff::Application.load_tasks

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/

View File

@@ -1,21 +1,33 @@
@import "twitter/bootstrap/bootstrap";
body { padding-top: 60px; }
@import "twitter/bootstrap/responsive";
// Set the correct sprite paths
@iconSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings.png");
@iconWhiteSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings-white.png");
@iconSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings");
@iconWhiteSpritePath: asset-path("twitter/bootstrap/glyphicons-halflings-white");
// Set the Font Awesome (Font Awesome is default. You can disable by commenting below lines)
// Note: If you use asset_path() here, your compiled bootstrap_and_overrides.css will not
// have the proper paths. So for now we use the absolute path.
@fontAwesomeEotPath: asset-path("fontawesome-webfont.eot?v=3.0.2");
@fontAwesomeEotPath_iefix: asset-path("fontawesome-webfont.eot?#iefix&v=3.0.2");
@fontAwesomeWoffPath: asset-path("fontawesome-webfont.woff?v=3.0.2");
@fontAwesomeTtfPath: asset-path("fontawesome-webfont.ttf?v=3.0.2");
@fontAwesomeEotPath: asset-url("fontawesome-webfont.eot");
@fontAwesomeEotPath_iefix: asset-url("fontawesome-webfont.eot#iefix");
@fontAwesomeWoffPath: asset-url("fontawesome-webfont.woff");
@fontAwesomeTtfPath: asset-url("fontawesome-webfont.ttf");
@fontAwesomeSvgPath: asset-url("fontawesome-webfont.svg#fontawesomeregular");
// Font Awesome
@import "fontawesome";
@import "fontawesome/font-awesome";
// Glyphicons
//@import "twitter/bootstrap/sprites.less";
// Your custom LESS stylesheets goes here
//
// Since bootstrap was imported above you have access to its mixins which
// you may use and inherit here
//
// If you'd like to override bootstrap's own variables, you can do so here as well
// See http://twitter.github.com/bootstrap/customize.html#variables for their names and documentation
//
// Example:
// @linkColor: #ff0000;
// Base colours
@@ -66,6 +78,7 @@ body { padding-top: 60px; }
@dropdownLinkBackgroundHover: lighten(@green, 50%);
body {
padding-top: @navbarHeight + 10px;
padding-bottom: @navbarHeight + 10px;
}
ul.inline > li.first {

View File

@@ -0,0 +1,84 @@
class AccountTypesController < ApplicationController
load_and_authorize_resource
# GET /account_types
# GET /account_types.json
def index
@account_types = AccountType.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @account_types }
end
end
# GET /account_types/1
# GET /account_types/1.json
def show
@account_type = AccountType.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @account_type }
end
end
# GET /account_types/new
# GET /account_types/new.json
def new
@account_type = AccountType.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @account_type }
end
end
# GET /account_types/1/edit
def edit
@account_type = AccountType.find(params[:id])
end
# POST /account_types
# POST /account_types.json
def create
@account_type = AccountType.new(params[:account_type])
respond_to do |format|
if @account_type.save
format.html { redirect_to @account_type, notice: 'Account type was successfully created.' }
format.json { render json: @account_type, status: :created, location: @account_type }
else
format.html { render action: "new" }
format.json { render json: @account_type.errors, status: :unprocessable_entity }
end
end
end
# PUT /account_types/1
# PUT /account_types/1.json
def update
@account_type = AccountType.find(params[:id])
respond_to do |format|
if @account_type.update_attributes(params[:account_type])
format.html { redirect_to @account_type, notice: 'Account type was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @account_type.errors, status: :unprocessable_entity }
end
end
end
# DELETE /account_types/1
# DELETE /account_types/1.json
def destroy
@account_type = AccountType.find(params[:id])
@account_type.destroy
respond_to do |format|
format.html { redirect_to account_types_url }
format.json { head :no_content }
end
end
end

View File

@@ -0,0 +1,46 @@
class AccountsController < ApplicationController
load_and_authorize_resource
# GET /accounts
# GET /accounts.json
def index
@accounts = Account.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @accounts }
end
end
# GET /accounts/1
# GET /accounts/1.json
def show
@account = Account.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @account }
end
end
# GET /accounts/1/edit
def edit
@account = Account.find(params[:id])
end
# PUT /accounts/1
# PUT /accounts/1.json
def update
@account = Account.find(params[:id])
respond_to do |format|
if @account.update_attributes(params[:account])
format.html { redirect_to @account, notice: 'Account detail was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @account.errors, status: :unprocessable_entity }
end
end
end
end

View File

@@ -0,0 +1,46 @@
class Admin::OrdersController < ApplicationController
def index
authorize! :manage, :all
respond_to do |format|
format.html # index.html.haml
end
end
def search
authorize! :manage, :all
@orders = []
if params[:search_text]
case params[:search_by]
when "member"
member = Member.find_by_login_name(params[:search_text])
if member
@orders = member.orders
end
when "order_id"
order = Order.find_by_id(params[:search_text])
if order
@orders = [order]
end
when "paypal_token"
order = Order.find_by_paypal_express_token(params[:search_text])
if order
@orders = [order]
end
when "paypal_payer_id"
order = Order.find_by_paypal_express_payer_id(params[:search_text])
if order
@orders = [order]
end
end
if @orders.empty?
flash[:alert] = "Couldn't find order with #{params[:search_by]} = #{params[:search_text]}"
end
end
respond_to do |format|
format.html # index.html.haml
end
end
end

View File

@@ -0,0 +1,8 @@
class AdminController < ApplicationController
def index
authorize! :manage, :all
respond_to do |format|
format.html # index.html.haml
end
end
end

View File

@@ -1,6 +1,8 @@
class ApplicationController < ActionController::Base
protect_from_forgery
include ApplicationHelper
# tweak CanCan defaults because we don't have a "current_user" method
# this means that we use current_user in specs but current_member everywhere
# else in the code.

View File

@@ -37,7 +37,7 @@ class AuthenticationsController < ApplicationController
else
flash[:notice] = "Authentication failed."
end
redirect_to edit_member_registration_path
redirect_to request.env['omniauth.origin'] || edit_member_registration_path
end
# DELETE /authentications/1

View File

@@ -2,12 +2,12 @@ class CommentsController < ApplicationController
# GET /comments
# GET /comments.json
def index
@comments = Comment.all
@recent_comments = Comment.limit(100).order('created_at desc').all
@comments = Comment.paginate(:page => params[:page])
respond_to do |format|
format.html # index.html.erb
format.json { render json: @comments }
format.rss { render :layout => false }
end
end

View File

@@ -5,7 +5,6 @@ class CropsController < ApplicationController
# GET /crops.json
def index
@crops = Crop.paginate(:page => params[:page])
@new_crops = Crop.limit(20).order('created_at desc').all
respond_to do |format|
format.html # index.html.haml

View File

@@ -7,17 +7,14 @@ class HomeController < ApplicationController
@planting_count = Planting.count
@garden_count = Garden.count
@interesting_members = Member.interesting.limit(6)
# choose 6 recently-signed-in members sort of at random
@interesting_members = Member.interesting.limit(30).shuffle.first(6)
# customise what we show on the homepage based on whether you're
# logged in or not.
@member = current_member
@plantings = current_member ?
current_member.plantings.limit(10) :
Planting.limit(10)
@posts = current_member ?
current_member.posts.limit(10) :
Post.limit(10)
@plantings = Planting.limit(15)
@posts = Post.limit(10)
respond_to do |format|
format.html # index.html.haml

View File

@@ -12,8 +12,8 @@ class MembersController < ApplicationController
def show
@member = Member.confirmed.find(params[:id])
@twitter_auth = @member.authentications.find_by_provider('twitter')
@flickr_auth = @member.authentications.find_by_provider('flickr')
@twitter_auth = @member.auth('twitter')
@flickr_auth = @member.auth('flickr')
@posts = @member.posts
# The garden form partial is called from the "New Garden" tab;
# it requires a garden to be passed in @garden.

View File

@@ -0,0 +1,25 @@
class OrderItemsController < ApplicationController
load_and_authorize_resource
# POST /order_items
# POST /order_items.json
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(params[:order_item])
@order_item.order = current_member.current_order || Order.create(:member_id => current_member.id)
respond_to do |format|
if @order_item.save
format.html { redirect_to @order_item.order, notice: 'Added item to your order.' }
format.json { render json: @order_item, status: :created, location: @order_item }
else
errors = @order_item.errors.empty? ?
"There was a problem with your order." : @order_item.errors.full_messages.to_sentence
format.html { redirect_to shop_path, alert: errors }
format.json { render json: @order_item.errors, status: :unprocessable_entity }
end
end
end
end

View File

@@ -0,0 +1,95 @@
class OrdersController < ApplicationController
load_and_authorize_resource
# GET /orders
def index
@orders = Order.find_all_by_member_id(current_member.id)
respond_to do |format|
format.html # index.html.erb
end
end
# GET /orders/1
def show
@order = Order.find(params[:id])
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
@order = Order.find(params[:id])
response = EXPRESS_GATEWAY.setup_purchase(
@order.total,
:items => @order.activemerchant_items,
:currency => Growstuff::Application.config.currency,
:no_shipping => true,
:ip => request.remote_ip,
:return_url => complete_order_url,
:cancel_return_url => shop_url
)
redirect_to EXPRESS_GATEWAY.redirect_url_for(response.token)
end
def complete
@order = Order.find(params[:id])
@order.save
if (params[:token] && params['PayerID'])
purchase = EXPRESS_GATEWAY.purchase(
@order.total,
:currency => Growstuff::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
@order = Order.find(params[:id])
respond_to do |format|
format.html { redirect_to shop_url, notice: 'Order was cancelled.' }
end
end
# DELETE /orders/1
def destroy
@order = Order.find(params[:id])
@order.destroy
respond_to do |format|
format.html { redirect_to shop_url, notice: 'Order was deleted.' }
end
end
end

View File

@@ -0,0 +1,113 @@
class PhotosController < ApplicationController
load_and_authorize_resource
# GET /photos
# GET /photos.json
def index
@photos = Photo.paginate(:page => params[:page])
respond_to do |format|
format.html # index.html.erb
format.json { render json: @photos }
end
end
# GET /photos/1
# GET /photos/1.json
def show
@photo = Photo.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @photo }
end
end
# GET /photos/new
# GET /photos/new.json
def new
@photo = Photo.new
@planting_id = params[:planting_id]
page = params[:page] || 1
@flickr_auth = current_member.auth('flickr')
if @flickr_auth
photos = current_member.flickr_photos(page)
total = photos.instance_of?(FlickRaw::ResponseList) ? photos.total : 0
@photos = WillPaginate::Collection.create(page, 30, total) do |pager|
pager.replace photos.to_a
end
end
respond_to do |format|
format.html # new.html.erb
format.json { render json: @photo }
end
end
# GET /photos/1/edit
def edit
@photo = Photo.find(params[:id])
end
# POST /photos
# POST /photos.json
def create
@photo = Photo.find_by_flickr_photo_id(params[:photo][:flickr_photo_id]) ||
Photo.new(params[:photo])
@photo.owner_id = current_member.id
@photo.set_flickr_metadata
if params[:planting_id]
planting = Planting.find_by_id(params[:planting_id])
if planting
if planting.owner.id == current_member.id
@photo.plantings << planting unless @photo.plantings.include?(planting)
else
flash[:alert] = "You must own both the planting and the photo."
end
else
flash[:alert] = "Couldn't find planting to connect to photo."
end
end
respond_to do |format|
if @photo.save
format.html { redirect_to @photo, notice: 'Photo was successfully added.' }
format.json { render json: @photo, status: :created, location: @photo }
else
format.html { render action: "new" }
format.json { render json: @photo.errors, status: :unprocessable_entity }
end
end
end
# PUT /photos/1
# PUT /photos/1.json
def update
@photo = Photo.find(params[:id])
respond_to do |format|
if @photo.update_attributes(params[:photo])
format.html { redirect_to @photo, notice: 'Photo was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @photo.errors, status: :unprocessable_entity }
end
end
end
# DELETE /photos/1
# DELETE /photos/1.json
def destroy
@photo = Photo.find(params[:id])
@photo.destroy
respond_to do |format|
format.html { redirect_to photos_url }
format.json { head :no_content }
end
end
end

View File

@@ -1,10 +1,12 @@
class PlantingsController < ApplicationController
load_and_authorize_resource
cache_sweeper :planting_sweeper
# GET /plantings
# GET /plantings.json
def index
@plantings = Planting.all
@recent_plantings = Planting.limit(100).order('created_at desc').all
@plantings = Planting.paginate(:page => params[:page])
respond_to do |format|
format.html # index.html.erb
@@ -28,8 +30,7 @@ class PlantingsController < ApplicationController
# GET /plantings/new
# GET /plantings/new.json
def new
@planting = Planting.new
@planting.planted_at = Date.today
@planting = Planting.new('planted_at' => Date.today)
# using find_by_id here because it returns nil, unlike find
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
@@ -44,6 +45,7 @@ class PlantingsController < ApplicationController
# GET /plantings/1/edit
def edit
@planting = Planting.find(params[:id])
# the following are needed to display the form but aren't used
@crop = Crop.new
@garden = Garden.new
@@ -52,6 +54,7 @@ class PlantingsController < ApplicationController
# POST /plantings
# POST /plantings.json
def create
params[:planted_at] = parse_date(params[:planted_at])
@planting = Planting.new(params[:planting])
respond_to do |format|
@@ -69,6 +72,7 @@ class PlantingsController < ApplicationController
# PUT /plantings/1.json
def update
@planting = Planting.find(params[:id])
params[:planted_at] = parse_date(params[:planted_at])
respond_to do |format|
if @planting.update_attributes(params[:planting])

View File

@@ -1,11 +1,13 @@
class PostsController < ApplicationController
load_and_authorize_resource
cache_sweeper :post_sweeper
# GET /posts
# GET /posts.json
def index
@posts = Post.paginate(:page => params[:page])
@recent_posts = Post.limit(100).order('created_at desc').all
respond_to do |format|
format.html # index.html.haml
@@ -23,6 +25,10 @@ class PostsController < ApplicationController
respond_to do |format|
format.html # show.html.haml
format.json { render json: @post }
format.rss { render(
:layout => false,
:locals => { :post => @post }
)}
end
end

View File

@@ -0,0 +1,84 @@
class ProductsController < ApplicationController
load_and_authorize_resource
# GET /products
# GET /products.json
def index
@products = Product.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @products }
end
end
# GET /products/1
# GET /products/1.json
def show
@product = Product.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @product }
end
end
# GET /products/new
# GET /products/new.json
def new
@product = Product.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @product }
end
end
# GET /products/1/edit
def edit
@product = Product.find(params[:id])
end
# POST /products
# POST /products.json
def create
@product = Product.new(params[:product])
respond_to do |format|
if @product.save
format.html { redirect_to @product, notice: 'Product was successfully created.' }
format.json { render json: @product, status: :created, location: @product }
else
format.html { render action: "new" }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# PUT /products/1
# PUT /products/1.json
def update
@product = Product.find(params[:id])
respond_to do |format|
if @product.update_attributes(params[:product])
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
@product = Product.find(params[:id])
@product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
end

View File

@@ -2,8 +2,8 @@
class RegistrationsController < Devise::RegistrationsController
def edit
@twitter_auth = current_member.authentications.find_by_provider('twitter')
@flickr_auth = current_member.authentications.find_by_provider('flickr')
@twitter_auth = current_member.auth('twitter')
@flickr_auth = current_member.auth('flickr')
render "edit"
end

View File

@@ -0,0 +1,25 @@
class ShopController < ApplicationController
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
if current_member
@order = current_member.current_order
if @order
@most_recent_item = @order.order_items.first
end
end
respond_to do |format|
format.html # index.html.haml
end
end
end

View File

@@ -0,0 +1,28 @@
module ApplicationHelper
def price_in_dollars(price)
return sprintf('%.2f', price / 100.0)
end
# 999 cents becomes 9.99 AUD -- for products/orders/etc
def price_with_currency(price)
return sprintf('%.2f %s', price / 100.0,
Growstuff::Application.config.currency)
end
def parse_date(str)
str ||= '' # Date.parse barfs on nil
return str == '' ? nil : Date.parse(str)
end
def forex_link(price)
pid = price_in_dollars(price)
currency = Growstuff::Application.config.currency
link = "http://www.wolframalpha.com/input/?i=#{pid}+#{currency}"
return link_to "(convert)",
link,
:target => "_blank"
end
end

View File

@@ -6,24 +6,21 @@ class Ability
# everyone can do these things, even non-logged in
can :read, :all
cannot :read, Notification
cannot :create, Notification
cannot :read, Authentication
# nobody should be able to view this except admins
# 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
if member
if member.has_role? :admin
# admin user roles (for authorization)
can :read, Role
can :manage, Role
# for now, only admins can create/edit forums
can :manage, Forum
end
# managing your own user settings
can :update, Member, :id => member.id
@@ -50,21 +47,53 @@ class Ability
# anyone can create a post, or comment on a post,
# but only the author can edit/destroy it.
can :create, Post
can :update, Post, :author_id => member.id
can :create, Post
can :update, Post, :author_id => member.id
can :destroy, Post, :author_id => member.id
can :create, Comment
can :update, Comment, :author_id => member.id
can :create, Comment
can :update, Comment, :author_id => member.id
can :destroy, Comment, :author_id => member.id
# same deal for gardens and plantings
can :create, Garden
can :update, Garden, :owner_id => member.id
can :create, Garden
can :update, Garden, :owner_id => member.id
can :destroy, Garden, :owner_id => member.id
can :create, Planting
can :update, Planting, :garden => { :owner_id => member.id }
can :create, Planting
can :update, Planting, :garden => { :owner_id => member.id }
can :destroy, Planting, :garden => { :owner_id => member.id }
can :create, Photo
can :update, Photo, :owner_id => member.id
can :destroy, Photo, :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 }
if member.has_role? :admin
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
end
end
end
end

26
app/models/account.rb Normal file
View File

@@ -0,0 +1,26 @@
class Account < ActiveRecord::Base
attr_accessible :account_type_id, :member_id, :paid_until
belongs_to :member
belongs_to :account_type
validates :member_id, :uniqueness => {
:message => 'already has account details associated with it'
}
before_create do |account|
unless account.account_type
account.account_type = AccountType.find_or_create_by_name(
Growstuff::Application.config.default_account_type
)
end
end
def paid_until_string
if account_type.is_permanent_paid
return "forever"
elsif account_type.is_paid
return paid_until.to_s
end
end
end

View File

@@ -0,0 +1,8 @@
class AccountType < ActiveRecord::Base
attr_accessible :is_paid, :is_permanent_paid, :name
has_many :products
def to_s
name
end
end

View File

@@ -3,7 +3,8 @@ class Comment < ActiveRecord::Base
belongs_to :author, :class_name => 'Member'
belongs_to :post
default_scope order("created_at asc")
default_scope order("created_at DESC")
scope :post_order, reorder("created_at ASC") # for display on post page
after_create do
recipient = self.post.author.id

View File

@@ -5,6 +5,7 @@ class Crop < ActiveRecord::Base
has_many :scientific_names
has_many :plantings
has_many :photos, :through => :plantings
belongs_to :parent, :class_name => 'Crop'
has_many :varieties, :class_name => 'Crop', :foreign_key => 'parent_id'
@@ -38,4 +39,8 @@ class Crop < ActiveRecord::Base
return plantings.count
end
def default_photo
return photos.first
end
end

View File

@@ -4,14 +4,24 @@ class Member < ActiveRecord::Base
has_many :posts, :foreign_key => 'author_id'
has_many :comments, :foreign_key => 'author_id'
has_many :forums, :foreign_key => 'owner_id'
has_many :gardens, :foreign_key => 'owner_id'
has_many :plantings, :through => :gardens
has_many :forums, :foreign_key => 'owner_id'
has_and_belongs_to_many :roles
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
default_scope order("lower(login_name) asc")
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :located, where('location IS NOT NULL')
@@ -67,6 +77,11 @@ class Member < ActiveRecord::Base
# Give each new member a default garden
after_create {|member| Garden.create(:name => "Garden", :owner_id => member.id) }
# 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 FactoryGirl associations
after_create {|member| Account.find_or_create_by_member_id(:member_id => member.id) }
# allow login via either login_name or email address
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
@@ -85,6 +100,62 @@ class Member < ActiveRecord::Base
roles.any? { |r| r.name.gsub(/\s+/, "_").underscore.to_sym == role_sym }
end
def current_order
orders.where(:completed_at => nil).first
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)
if product.account_type
account.account_type = product.account_type
end
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 is_paid?
if account.account_type.is_permanent_paid
return true
elsif account.account_type.is_paid and account.paid_until >= Time.zone.now
return true
else
return false
end
end
def auth(provider)
return authentications.find_by_provider(provider)
end
def flickr
if @flickr.nil?
flickr_auth = auth('flickr')
if flickr_auth
FlickRaw.api_key = ENV['FLICKR_KEY']
FlickRaw.shared_secret = ENV['FLICKR_SECRET']
@flickr = FlickRaw::Flickr.new
@flickr.access_token = flickr_auth.token
@flickr.access_secret = flickr_auth.secret
end
end
return @flickr
end
def flickr_photos(page_num=1)
return flickr.people.getPhotos(
:user_id => 'me',
:page => page_num,
:per_page => 30
)
end
protected
def empty_unwanted_geocodes
if self.location.to_s == ''

48
app/models/order.rb Normal file
View File

@@ -0,0 +1,48 @@
class Order < ActiveRecord::Base
attr_accessible :member_id, :completed_at
belongs_to :member
has_many :order_items, :dependent => :destroy
default_scope order('created_at DESC')
# total price of an order
def total
sum = 0
for i in order_items do
subtotal = i.price * i.quantity
sum += subtotal
end
return 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
return 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
self.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
end

17
app/models/order_item.rb Normal file
View File

@@ -0,0 +1,17 @@
class OrderItem < ActiveRecord::Base
attr_accessible :order_id, :price, :product_id, :quantity
belongs_to :order
belongs_to :product
validate :price_must_be_greater_than_minimum
validates_uniqueness_of :order_id, :message => "may only have one item."
def price_must_be_greater_than_minimum
@product = Product.find(product_id)
if price < @product.min_price
errors.add(:price, "must be greater than the product's minimum value")
end
end
end

33
app/models/photo.rb Normal file
View File

@@ -0,0 +1,33 @@
class Photo < ActiveRecord::Base
attr_accessible :flickr_photo_id, :owner_id, :title, :license_name,
:license_url, :thumbnail_url, :fullsize_url, :link_url
belongs_to :owner, :class_name => 'Member'
has_and_belongs_to_many :plantings
before_destroy {|photo| photo.plantings.clear}
default_scope order("created_at desc")
# This is split into a side-effect free method and a side-effecting method
# for easier stubbing and testing.
def flickr_metadata
flickr = owner.flickr
info = flickr.photos.getInfo(:photo_id => flickr_photo_id)
licenses = flickr.photos.licenses.getInfo()
license = licenses.find { |l| l.id == info.license }
return {
:title => info.title || "Untitled",
:license_name => license.name,
:license_url => license.url,
:thumbnail_url => FlickRaw.url_q(info),
:fullsize_url => FlickRaw.url_z(info),
:link_url => FlickRaw.url_photopage(info)
}
end
def set_flickr_metadata
self.update_attributes(flickr_metadata)
end
end

View File

@@ -3,11 +3,14 @@ class Planting < ActiveRecord::Base
friendly_id :planting_slug, use: :slugged
attr_accessible :crop_id, :description, :garden_id, :planted_at,
:quantity, :sunniness, :planted_at_string
:quantity, :sunniness, :planted_from
belongs_to :garden
belongs_to :crop
has_and_belongs_to_many :photos
before_destroy {|planting| planting.photos.clear}
default_scope order("created_at desc")
delegate :system_name,
@@ -16,6 +19,7 @@ class Planting < ActiveRecord::Base
:plantings_count,
:to => :crop,
:prefix => true
delegate :owner, :to => :garden
default_scope order("created_at desc")
@@ -25,6 +29,22 @@ class Planting < ActiveRecord::Base
:allow_nil => true,
:allow_blank => true
PLANTED_FROM_VALUES = [
'seed',
'seedling',
'cutting',
'root division',
'runner',
'bare root plant',
'advanced plant',
'graft',
'layering'
]
validates :planted_from, :inclusion => { :in => PLANTED_FROM_VALUES,
:message => "%{value} is not a valid planting method" },
:allow_nil => true,
:allow_blank => true
def planting_slug
"#{owner.login_name}-#{garden}-#{crop}".downcase.gsub(' ', '-')
end
@@ -33,19 +53,11 @@ class Planting < ActiveRecord::Base
return "#{garden.owner.login_name}'s #{garden}"
end
def owner
return garden.owner
def to_s
self.crop_system_name + " in " + self.location
end
def planted_at_string
if planted_at
planted_at.strftime("%F")
else
"Not yet set"
end
end
def planted_at_string=(str)
self.planted_at = str == '' ? nil : Time.parse(str)
def default_photo
return photos.first
end
end

View File

@@ -0,0 +1,21 @@
class PlantingSweeper < ActionController::Caching::Sweeper
observe Planting
def after_create(planting)
expire_cache_for(planting)
end
def after_update(planting)
expire_cache_for(planting)
end
def after_destroy(planting)
expire_cache_for(planting)
end
private
def expire_cache_for(planting)
expire_fragment('recent_plantings')
end
end

View File

@@ -26,7 +26,7 @@ class Post < ActiveRecord::Base
end
def recent_activity
self.comments.last ? self.comments.last.created_at : self.created_at
self.comments.reorder.last ? self.comments.reorder.last.created_at : self.created_at
end
def Post.recently_active

View File

@@ -0,0 +1,16 @@
class PostSweeper < ActionController::Caching::Sweeper
observe Post
def after_create(post)
expire_fragment('recent_posts')
end
def after_update(post)
expire_fragment('recent_posts')
end
def after_destroy(post)
expire_fragment('recent_posts')
end
end

15
app/models/product.rb Normal file
View File

@@ -0,0 +1,15 @@
class Product < ActiveRecord::Base
attr_accessible :description, :min_price, :recommended_price, :name,
:account_type_id, :paid_months
has_and_belongs_to_many :orders
belongs_to :account_type
validates :paid_months, :numericality => { :only_integer => true,
:allow_nil => true }
def to_s
name
end
end

View File

@@ -0,0 +1,19 @@
= form_for @account_type do |f|
- if @account_type.errors.any?
#error_explanation
%h2= "#{pluralize(@account_type.errors.count, "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'

View File

@@ -0,0 +1,7 @@
%h1 Editing account_type
= render 'form'
= link_to 'Show', @account_type
\|
= link_to 'Back', account_types_path

View File

@@ -0,0 +1,23 @@
%h1 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

View File

@@ -0,0 +1,5 @@
%h1 New account_type
= render 'form'
= link_to 'Back', account_types_path

View File

@@ -0,0 +1,15 @@
%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 'Back', account_types_path

View File

@@ -0,0 +1,19 @@
= form_for @account do |f|
- if @account.errors.any?
#error_explanation
%h2= "#{pluralize(@account.errors.count, "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'

View File

@@ -0,0 +1,7 @@
%h1 Editing account
= render 'form'
= link_to 'Show', @account
\|
= link_to 'Back', accounts_path

View File

@@ -0,0 +1,23 @@
%h1 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

View File

@@ -0,0 +1,5 @@
%h1 New account
= render 'form'
= link_to 'Back', accounts_path

View File

@@ -0,0 +1,15 @@
%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

View File

@@ -0,0 +1,13 @@
-content_for :title, 'Admin'
%h2 Manage
%ul
%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
%h2 Orders
=render "admin/orders/searchform"

View File

@@ -0,0 +1,5 @@
= 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', 'Order ID' => 'order_id', 'Paypal Token' => 'paypal_token', 'Paypal Payer ID' => 'paypal_payer_id' })
= submit_tag "Search", :class => 'btn btn-primary'

View File

@@ -0,0 +1,3 @@
-content_for :title, 'Admin Orders'
=render "admin/orders/searchform"

View File

@@ -0,0 +1,36 @@
-content_for :title, 'Search Orders'
=render "admin/orders/searchform"
- unless @orders.empty?
%h2
Found
= pluralize(@orders.count, "result")
%table.table.table-striped
%tr
%th Member
%th Order number
%th Date completed
%th Items
%th
- @orders.each do |order|
%tr
%td= link_to order.member.login_name, order.member
%td= order.id
%td
- if order.completed_at
= order.completed_at.to_s
- else
In progress
%td
- if order.order_items.count > 0
- 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-mini'

View File

@@ -1,8 +1,3 @@
= render :partial => "posts/single", :locals => { :post => @post || @comment.post, :subject => true }
= render :partial => "posts/comments"
%h2 Your comment
= form_for @comment do |f|
- if @comment.errors.any?
#error_explanation

View File

@@ -1,3 +1,7 @@
= content_for :title, "Editing comment"
%p
Editing comment on
= link_to @comment.post.subject, @comment.post
= render 'form'

View File

@@ -1,7 +1,15 @@
= content_for :title, "Recent comments"
- @recent_comments.each do |comment|
%div.pagination
= page_entries_info @comments, :model => "comments"
= will_paginate @comments
- @comments.each do |comment|
%h2
Comment on
= link_to comment.post.subject, comment.post
= render :partial => "single", :locals => { :comment => comment }
%div.pagination
= page_entries_info @comments, :model => "comments"
= will_paginate @comments

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
%rss{:version => 2.0}
%channel
%title #{Growstuff::Application.config.site_name} - Recent comments on all posts
%link= comments_url
- @comments.each do |comment|
%item
%title Comment by #{comment.author.login_name} on #{comment.post.subject}
%author= comment.author.login_name
%description
:escaped
<p>
Comment on
#{ link_to comment.post.subject, post_url(comment.post) }
</p>
:escaped_markdown
#{ strip_tags comment.body }
%pubDate= comment.created_at.to_s(:rfc822)
%link= post_url(comment.post)
%guid= comment_url(comment)

View File

@@ -1,3 +1,9 @@
= content_for :title, "New comment"
= render :partial => "posts/single", :locals => { :post => @post || @comment.post, :subject => true }
= render :partial => "posts/comments", :locals => {:post => @post || @comment.post}
%p Your comment:
= render 'form'

View File

@@ -1,6 +1,6 @@
.thumbnail(style='height: 220px')
- if crop
= link_to image_tag('http://placehold.it/150x150', :alt => '', :class => 'img-rounded'), crop
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => crop.system_name, :class => 'img-rounded'), crop
%p
= link_to crop.system_name, crop
- if crop.scientific_names.count > 0
@@ -12,6 +12,3 @@
%small
Planted
= pluralize(crop.plantings_count, "time")
- else
= image_tag('http://placehold.it/150x150', :alt => '', :class => 'img-rounded')
Sample crop

View File

@@ -1,16 +0,0 @@
xml.instruct! :xml, :version => "1.0"
xml.rss :version => "2.0" do
xml.channel do
xml.title "#{Growstuff::Application.config.site_name} - Recently added crops"
xml.link crops_url
for crop in @new_crops
xml.item do
xml.title crop.system_name
xml.pubDate crop.created_at.to_s(:rfc822)
xml.link crop_url(crop)
xml.guid crop_url(crop)
end
end
end
end

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
%rss{:version => 2.0}
%channel
%title #{Growstuff::Application.config.site_name} - Recently added crops
%link= crops_url
- @crops.each do |crop|
%item
%title= crop.system_name
%pubDate= crop.created_at.to_s(:rfc822)
%link= post_url(crop)
%guid= post_url(crop)

View File

@@ -27,25 +27,14 @@
= link_to 'Add', new_garden_path, :class => 'btn btn-mini'
.span4
- if current_member.has_role?(:admin)
%p
%b You are an ADMIN USER.
- if current_member.forums.count > 0
%p
%b Forums you administer:
%ul
- current_member.forums.each do |f|
%li= link_to f.name, f
.row
.span6
%h2 Your recent plantings
= render :partial => 'shared/recent_plantings'
.span6
%h2 Your recent posts
= render :partial => 'shared/recent_posts'
%p
Your account:
%strong
= current_member.account_type
account
%br/
- if current_member == current_member && !current_member.is_paid?
= link_to "Upgrade and Support #{Growstuff::Application.config.site_name}", shop_path, :class => 'btn btn-primary'
- else
.visible-desktop.visible-tablet
@@ -54,17 +43,17 @@
.visible-phone
= render :partial => 'blurb'
- if @interesting_members
- if @interesting_members.present?
%h2 Some of our members
%ul.thumbnails
- @interesting_members.each do |m|
%li.span2
= render :partial => "members/thumbnail", :locals => { :member => m }
.row
.span6
%h2 Recent plantings
= render :partial => 'shared/recent_plantings'
.span6
%h2 Recent posts
= render :partial => 'shared/recent_posts'
.row
.span6
%h2 Recent plantings
= render :partial => 'shared/recent_plantings'
.span6
%h2 Recent posts
= render :partial => 'shared/recent_posts'

View File

@@ -12,6 +12,9 @@
%li= link_to "Members", members_path
%li= link_to "Posts", posts_path
%li= link_to "Forums", forums_path
%li= link_to "Shop", shop_path
-if member_signed_in? and current_member.has_role?(:admin)
%li= link_to "Admin", admin_path
%li.divider-vertical
- if member_signed_in?
%li.dropdown<
@@ -21,6 +24,7 @@
%ul.dropdown-menu
%li= link_to "Profile", member_path(current_member)
%li= link_to "Settings", edit_member_registration_path
%li= link_to "Account", orders_path
%li= link_to "Sign out", destroy_member_session_path, :method => :delete
%li
- if current_member.notifications.unread_count > 0

View File

@@ -15,6 +15,14 @@
%strong Member since:
= @member.created_at.to_s(:date)
%p
%strong Account type:
= @member.account_type
account
- if @member == current_member && !@member.is_paid?
= link_to "Upgrade", shop_path, :class => 'btn btn-primary btn-mini'
- if @twitter_auth || @flickr_auth || @member.show_email
%h4 Contact
@@ -42,12 +50,12 @@
= @member.location
%br/
= link_to 'Find members near here', nearby_members_path(:location => @member.location)
%p
- if current_member == @member
%p
= link_to 'Edit Settings', "edit", :class => 'btn btn-mini'
.span9
%p
- if can? :update, @member
%p
= link_to 'Edit your profile', "edit", :class => 'btn btn-primary'
.tabbable
%ul.nav.nav-tabs
- first_garden = true
@@ -66,7 +74,7 @@
%div
:markdown
#{g.description}
#{ strip_tags g.description }
%h3 What's planted here?
- g.featured_plantings.each do |p|

View File

@@ -1,18 +0,0 @@
xml.instruct! :xml, :version => "1.0"
xml.rss :version => "2.0" do
xml.channel do
xml.title "#{Growstuff::Application.config.site_name} - #{@member.login_name}'s recent posts"
xml.link member_url(@member)
for post in @posts
xml.item do
xml.author @member.login_name
xml.title post.subject
xml.description post.body
xml.pubDate post.created_at.to_s(:rfc822)
xml.link post_url(post)
xml.guid post_url(post)
end
end
end
end

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
%rss{:version => 2.0}
%channel
%title #{Growstuff::Application.config.site_name} - #{@member.login_name}'s recent posts
%link= member_url(@member)
- @posts.each do |post|
%item
%pubDate= post.created_at.to_s(:rfc822)
%link= post_url(post)
%guid= post_url(post)
%author= @member.login_name
%title= post.subject
%description
:escaped_markdown
#{ strip_tags post.body }

View File

@@ -0,0 +1,45 @@
-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

View File

@@ -0,0 +1,44 @@
- 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
- if order.order_items.count > 0
- 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-mini'
- else
%p
You have not made any orders. You can place an order via our
=succeed "." do
=link_to "shop", shop_path

View File

@@ -0,0 +1,64 @@
-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
%p
- if @order.completed_at
%strong Date completed:
= @order.completed_at.to_s
- if current_member.has_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)
%p
- if can? :destroy, @order
= link_to 'Delete this order', @order, method: :delete, |
data: { confirm: 'Are you sure?' }, :class => 'btn'
- if can? :complete, @order
= link_to 'Checkout with PayPal', checkout_order_path(@order), :class => 'btn btn-primary'
%p
= link_to "View other orders/order history", orders_path

View File

@@ -0,0 +1,2 @@
- content_for :title, "Edit Photo"

View File

@@ -0,0 +1,28 @@
- content_for :title, "Photos"
%p Most recent photos added to #{Growstuff::Application.config.site_name}.
%div.pagination
= page_entries_info @photos, :model => "photos"
= will_paginate @photos
- c = 0
%ul.thumbnails
.row
- @photos.each do |p|
- c += 1
%li.span2
.thumbnail(style='height: 220px')
= link_to image_tag(p.thumbnail_url, :alt => p.title, :class => 'img-rounded'), p
%p
= link_to p.title, p
by
= link_to p.owner, p.owner
- if (c % 6) == 0
.row
%div.pagination
= page_entries_info @photos, :model => "photos"
= will_paginate @photos

View File

@@ -0,0 +1,34 @@
- content_for :title, "New Photo"
- if @flickr_auth
%p
Connected to Flickr as
= succeed "." do
= link_to @flickr_auth.name, "http://flickr.com/photos/#{@flickr_auth.uid}"
Please select a photo from your recent uploads.
%div.pagination
= page_entries_info @photos, :model => "photos"
= will_paginate @photos
- c = 0
%ul.thumbnails
.row
- @photos.each do |p|
- c += 1
%li.span2
.thumbnail(style='height: 220px')
= link_to image_tag(FlickRaw.url_q(p), :alt => '', :class => 'img-rounded'), photos_path(:photo => { :flickr_photo_id => p.id }, :planting_id => @planting_id), :method => :post
%p
=p.title
- if (c % 6) == 0
.row
- else
.alert
You must
=link_to "connect your account to Flickr", '/auth/flickr'
to add photos.

View File

@@ -0,0 +1,29 @@
-content_for :title, @photo.title
.row
.span6
%p
%strong Posted by:
= link_to @photo.owner, @photo.owner
%p
%strong License:
- if @photo.license_url
= link_to @photo.license_name, @photo.license_url
- else
= succeed "." do
= @photo.license_name
%p
= link_to "View on Flickr", @photo.link_url
- if can? :destroy, @photo
%p= link_to 'Delete Photo', @photo, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'
.span6
- if @photo.plantings.count > 0
%p This photo depicts:
%ul
- @photo.plantings.each do |p|
%li= link_to p, p
%p= image_tag(@photo.fullsize_url, :alt => @photo.title, :class => 'img-rounded')

View File

@@ -15,11 +15,15 @@
Garden.where(:owner_id => current_member), :id, :name, :selected => @planting.garden_id || @garden.id)
.control-group
= f.label 'When?', :class => 'control-label'
.controls= f.text_field :planted_at_string, :class => 'add-datepicker'
.controls= f.text_field :planted_at, :value => @planting.planted_at ? @planting.planted_at.to_s(:ymd) : '', :class => 'add-datepicker'
.control-group
= f.label 'How many?', :class => 'control-label'
.controls
= f.number_field :quantity, :class => 'input-small'
.control-group
= f.label 'Planted from:', :class => 'control-label'
.controls
= f.select(:planted_from, Planting::PLANTED_FROM_VALUES, {:include_blank => true})
.control-group
= f.label 'Sun or shade?', :class => 'control-label'
.controls

View File

@@ -1,32 +1,37 @@
.well
%h4
- if defined?(title) && title == 'owner'
= link_to planting.owner, planting.owner
- else
= link_to planting.crop.system_name, planting
.row-fluid
.span3
= link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded'), planting
.span9
%h4
- if defined?(title) && title == 'owner'
= link_to planting.owner, planting.owner
- else
= link_to planting.crop.system_name, planting
%p
Planted
- if planting.planted_at
= planting.planted_at
in
= link_to planting.location, planting.garden
%p
Planted
- if planting.planted_at
= planting.planted_at
in
= link_to planting.location, planting.garden
%p
- if planting.quantity
Quantity:
= planting.quantity
- else
&nbsp;
%p
- if planting.quantity
Quantity:
= planting.quantity
- else
&nbsp;
- if planting.description && ! defined?(hide_description)
%div
:markdown
#{ planting.description }
- if planting.description && ! defined?(hide_description)
%div
:markdown
#{ planting.description }
- if can? :edit, planting or can? :destroy, planting
%p
- if can? :edit, planting
=link_to 'Edit', edit_planting_path(planting), :class => 'btn btn-mini'
- if can? :destroy, planting
=link_to 'Delete', planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'
- if can? :edit, planting or can? :destroy, planting
%p
- if can? :edit, planting
=link_to 'Edit', edit_planting_path(planting), :class => 'btn btn-mini'
- if can? :destroy, planting
=link_to 'Delete', planting, method: :delete, data: { confirm: 'Are you sure?' }, :class => 'btn btn-mini'

View File

@@ -2,7 +2,13 @@
%p Here are the latest things planted by #{Growstuff::Application.config.site_name} members.
- @recent_plantings.each do |p|
%div.pagination
= page_entries_info @plantings, :model => "plantings"
= will_paginate @plantings
- @plantings.each do |p|
= render :partial => "plantings/thumbnail", :locals => { :planting => p }
%div.pagination
= page_entries_info @plantings, :model => "plantings"
= will_paginate @plantings

View File

@@ -1,18 +0,0 @@
xml.instruct! :xml, :version => "1.0"
xml.rss :version => "2.0" do
xml.channel do
xml.title "#{Growstuff::Application.config.site_name} - Recent plantings from all members"
xml.link plantings_url
for planting in @recent_plantings
xml.item do
xml.author planting.owner.login_name
xml.title planting.crop.system_name
xml.pubDate planting.created_at.to_s(:rfc822)
xml.description planting.description
xml.link planting_url(planting)
xml.guid planting_url(planting)
end
end
end
end

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
%rss{:version => 2.0}
%channel
%title #{Growstuff::Application.config.site_name} - Recent plantings from all members
%link= plantings_url
- @plantings.each do |planting|
%item
%author= planting.owner.login_name
%title= planting.crop.system_name
%pubDate= planting.created_at.to_s(:rfc822)
%description
:escaped_markdown
#{ strip_tags planting.description }
%link= planting_url(planting)
%guid= planting_url(planting)

View File

@@ -13,7 +13,12 @@
= "(#{@planting.owner.location})"
%p
%b Quantity:
= @planting.quantity != 0 ? @planting.quantity : "not specified"
= @planting.quantity.blank? ? "not specified" : @planting.quantity
- if ! @planting.planted_from.blank?
%p
%b Planted from:
= @planting.planted_from
- if ! @planting.sunniness.blank?
%p
@@ -30,33 +35,54 @@
.span6
.well
%h3
= link_to @planting.crop, @planting.crop
- if can? :edit, @planting
= link_to 'Plant another', new_planting_path, :class => 'btn btn-primary'
- elsif can? :create, Planting
= link_to 'Plant this', new_planting_path, :class => 'btn btn-primary'
.row-fluid
.span4
= link_to image_tag((@planting.crop.default_photo ? @planting.crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded'), @planting.crop
.span8
%h3
= link_to @planting.crop, @planting.crop
- if can? :edit, @planting
= link_to 'Plant another', new_planting_path, :class => 'btn btn-primary'
- elsif can? :create, Planting
= link_to 'Plant this', new_planting_path, :class => 'btn btn-primary'
%p
%b Scientific name:
= @planting.crop_default_scientific_name
%p
%b
Planted
= pluralize(@planting.crop_plantings_count, "time")
by #{Growstuff::Application.config.site_name} members
%p
%b Scientific name:
= @planting.crop_default_scientific_name
%p
%b
Planted
= pluralize(@planting.crop_plantings_count, "time")
by #{Growstuff::Application.config.site_name} members
%h2 Pictures
.row
- (1..6).each do
.span2
= image_tag('http://placehold.it/150x150', :alt => '', :class => 'img-rounded')
%h2
Notes
%h2 Notes
:markdown
#{ @planting.description != "" ? @planting.description : "No description given." }
- if can? :edit, @planting
= link_to 'Edit', edit_planting_path(@planting), :class => 'btn btn-mini'
- if @planting.photos.count > 0 or (can? :edit, @planting and can? :create, Photo)
%h2 Pictures
- c = 0
%ul.thumbnails
.row
- @planting.photos.each do |p|
- c += 1
%li.span2
.thumbnail(style='height: 220px')
= link_to image_tag(p.thumbnail_url, :alt => p.title, :class => 'img-rounded'), p
%p
= link_to p.title, p
by
= link_to p.owner, p.owner
- if (c % 6) == 0
.row
- if can? :create, Photo and can? :edit, @planting
%li.span2
.thumbnail(style='height: 220px')
%p{:style => 'text-align: center; padding-top: 50px'}
= link_to "Add photo", new_photo_path(:planting_id => @planting.id), :class => 'btn btn-primary'

View File

@@ -1,8 +1,8 @@
%a{:name => "comments"}
- if @comments
- if post.comments
%h2
=pluralize(@comments.length, "comment")
- @comments.each do |c|
=pluralize(post.comments.length, "comment")
- post.comments.post_order.each do |c|
= render :partial => "comments/single", :locals => { :comment => c }
- else

View File

@@ -1,18 +0,0 @@
xml.instruct! :xml, :version => "1.0"
xml.rss :version => "2.0" do
xml.channel do
xml.title "#{Growstuff::Application.config.site_name} - Recent posts from all members"
xml.link posts_url
for post in @recent_posts
xml.item do
xml.author post.author.login_name
xml.title post.subject
xml.description post.body
xml.pubDate post.created_at.to_s(:rfc822)
xml.link post_url(post)
xml.guid post_url(post)
end
end
end
end

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
%rss{:version => 2.0}
%channel
%title #{Growstuff::Application.config.site_name} - Recent posts from all members
%link= posts_url
- @posts.each do |post|
%item
%author= post.author.login_name
%title= post.subject
%description
:escaped_markdown
#{ strip_tags post.body }
%pubDate= post.created_at.to_s(:rfc822)
%link= post_url(post)
%guid= post_url(post)

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
%rss{:version => 2.0}
%channel
%title #{Growstuff::Application.config.site_name} - Recent comments on #{@post.subject}
%link= post_url(@post)
- @post.comments.each do |comment|
%item
%title Comment by #{comment.author.login_name} on #{comment.created_at.to_s}
%author= comment.author.login_name
%description
:escaped
<p>
Comment on
#{ link_to @post.subject, post_url(@post) }
</p>
:escaped_markdown
#{ strip_tags comment.body }
%pubDate= comment.created_at.to_s(:rfc822)
%link= post_url(@post)
%guid= comment_url(comment)

View File

@@ -0,0 +1,30 @@
= form_for @product do |f|
- if @product.errors.any?
#error_explanation
%h2= "#{pluralize(@product.errors.count, "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 => 'input-block-level'
.field
= f.label :description
= f.text_area :description, :class => 'input-block-level'
.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
.control-group
.actions
= f.submit 'Save'

View File

@@ -0,0 +1,7 @@
%h1 Editing product
= render 'form'
= link_to 'Show', @product
\|
= link_to 'Back', products_path

View File

@@ -0,0 +1,29 @@
%h1 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

View File

@@ -0,0 +1,5 @@
%h1 New product
= render 'form'
= link_to 'Back', products_path

View File

@@ -0,0 +1,25 @@
%p#notice= notice
%p
%b Name:
= @product.name
%p
%b Description:
:markdown
#{@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

View File

@@ -0,0 +1,13 @@
%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
- if ! current_member.is_paid?
= link_to "Upgrade and support #{Growstuff::Application.config.site_name}", shop_path, :class => 'btn btn-primary'

Some files were not shown because too many files have changed in this diff Show More