mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-05-25 01:13:03 -04:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9cdf2e899f | ||
|
|
2eacf346a8 | ||
|
|
aab91e2fa9 | ||
|
|
2217d87b5a | ||
|
|
44b2251896 | ||
|
|
f5e20cd2d2 | ||
|
|
42de726405 | ||
|
|
65b4c7dbc1 | ||
|
|
6b6ed7e31c | ||
|
|
564901f93f | ||
|
|
f8127eeec3 | ||
|
|
ab56a3c6b3 | ||
|
|
44ba29137d | ||
|
|
ed2fcc2ada | ||
|
|
54c880a66c | ||
|
|
0699677d05 | ||
|
|
3c411f15b8 | ||
|
|
dcf5286275 | ||
|
|
7e1e2bef91 | ||
|
|
5cda14f87a | ||
|
|
88da0da616 | ||
|
|
a69afd87e7 | ||
|
|
24931381af | ||
|
|
742c7e30a9 | ||
|
|
502a20cf10 | ||
|
|
b2cf022522 | ||
|
|
767477df66 | ||
|
|
7f87ee1018 | ||
|
|
093a948922 | ||
|
|
be1553410f | ||
|
|
caf41e80c9 | ||
|
|
2eff7d6716 | ||
|
|
df5006c61c | ||
|
|
1e0565dd9b | ||
|
|
3453a648fa | ||
|
|
e8d9314cff | ||
|
|
92e56cfc1e | ||
|
|
3dc356eb29 | ||
|
|
56ed61b2b3 | ||
|
|
16ad5384d1 | ||
|
|
cf93489af7 | ||
|
|
86b9a3650b | ||
|
|
625a035f44 | ||
|
|
196d37dee9 | ||
|
|
6f613635d2 | ||
|
|
46267b2a1d | ||
|
|
8c8d549cb1 | ||
|
|
d9cc1dcae8 | ||
|
|
9db4736229 | ||
|
|
04a7c41f63 | ||
|
|
78b8be1fc2 | ||
|
|
b6e9539127 | ||
|
|
33276874a8 | ||
|
|
9adb3d1e4e | ||
|
|
3391f6c392 | ||
|
|
a13acbe087 | ||
|
|
0c8240d4e8 | ||
|
|
5ea7ae8af0 | ||
|
|
eb1b890eec | ||
|
|
4821bf3b07 | ||
|
|
b83db1d4e7 | ||
|
|
dea7ce241b | ||
|
|
8d166f1fe6 | ||
|
|
49253b59ee | ||
|
|
ca16b2c407 | ||
|
|
427a0187e1 | ||
|
|
b1096cd021 | ||
|
|
020d024e4b | ||
|
|
070a4605d0 | ||
|
|
1f8413bf3e | ||
|
|
59c3edcf82 | ||
|
|
1bf05f81ab | ||
|
|
e6e88fa0c7 | ||
|
|
308e834713 | ||
|
|
121deb4f48 | ||
|
|
4b65f28461 | ||
|
|
87708f1765 | ||
|
|
2cf335a064 | ||
|
|
b205f35399 | ||
|
|
a4c06207e3 | ||
|
|
580fac6aa1 | ||
|
|
4a696af9ba | ||
|
|
d2a060ad49 | ||
|
|
d898f926d5 | ||
|
|
49444edc61 | ||
|
|
a4c7de381e | ||
|
|
61408d7e4e | ||
|
|
9906036faf | ||
|
|
e009d9532a | ||
|
|
9f1c064900 | ||
|
|
8d3d8f3c91 | ||
|
|
0feed2d359 |
@@ -42,3 +42,4 @@ exclude_paths:
|
||||
- spec/
|
||||
- public/
|
||||
- app/assets/stylesheets/bootstrap-accessibility.css
|
||||
- app/assets/javascripts/bootstrap*
|
||||
|
||||
1
.esignore
Normal file
1
.esignore
Normal file
@@ -0,0 +1 @@
|
||||
app/assets/javascripts/bootstrap-accessibility.min.js
|
||||
11
.eslintrc.json
Normal file
11
.eslintrc.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "google",
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
"rules": {
|
||||
"no-var": "off",
|
||||
"max-len": ["error", { "code": 120, "tabWidth": 4 }]
|
||||
}
|
||||
}
|
||||
@@ -8,3 +8,6 @@ scss:
|
||||
config_file: .scss-lint.yml
|
||||
eslint:
|
||||
config_file: .eslintrc
|
||||
ignore_file: .esignore
|
||||
jshint:
|
||||
enabled: false
|
||||
|
||||
@@ -46,7 +46,9 @@ PreCommit:
|
||||
required_executable: 'npm'
|
||||
HamlLint:
|
||||
enabled: true
|
||||
command: ['bundle', 'exec', 'haml-lint', 'app/views']
|
||||
include:
|
||||
- 'app/views/**'
|
||||
command: ['bundle', 'exec', 'haml-lint']
|
||||
JsonSyntax:
|
||||
enabled: true
|
||||
BundleOutdated:
|
||||
@@ -55,13 +57,13 @@ PreCommit:
|
||||
BundleAudit:
|
||||
enabled: true
|
||||
on_warn: warn
|
||||
JsHint:
|
||||
EsLint:
|
||||
enabled: true
|
||||
exclude:
|
||||
- 'app/assets/**'
|
||||
- 'spec/javascripts/support/vendor/**'
|
||||
- '**/bootstrap*'
|
||||
command: ['npm', 'run', 'jshint']
|
||||
command: ['./node_modules/.bin/eslint']
|
||||
required_executable: 'npm'
|
||||
ScssLint:
|
||||
enabled: true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --no-offense-counts`
|
||||
# on 2017-12-06 11:20:15 +1300 using RuboCop version 0.49.1.
|
||||
# on 2018-02-05 14:37:22 +1300 using RuboCop version 0.49.1.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
@@ -39,7 +39,6 @@ Rails/SkipsModelValidations:
|
||||
# SupportedStyles: strict, flexible
|
||||
Rails/TimeZone:
|
||||
Exclude:
|
||||
- 'spec/controllers/accounts_controller_spec.rb'
|
||||
- 'spec/factories/member.rb'
|
||||
- 'spec/factories/post.rb'
|
||||
- 'spec/models/post_spec.rb'
|
||||
@@ -60,7 +59,6 @@ Style/AsciiComments:
|
||||
# SupportedStyles: nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/orders_controller.rb'
|
||||
- 'lib/actions/oauth_signup_action.rb'
|
||||
- 'lib/haml/filters/escaped_markdown.rb'
|
||||
|
||||
@@ -68,24 +66,11 @@ Style/IdenticalConditionalBranches:
|
||||
Exclude:
|
||||
- 'app/controllers/follows_controller.rb'
|
||||
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: line_count_dependent, lambda, literal
|
||||
Style/Lambda:
|
||||
Exclude:
|
||||
- 'spec/controllers/member_controller_spec.rb'
|
||||
- 'spec/models/photo_spec.rb'
|
||||
|
||||
# Cop supports --auto-correct.
|
||||
Style/MultilineIfModifier:
|
||||
Exclude:
|
||||
- 'spec/rails_helper.rb'
|
||||
|
||||
# Cop supports --auto-correct.
|
||||
Style/MutableConstant:
|
||||
Exclude:
|
||||
- 'app/models/planting.rb'
|
||||
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: predicate, comparison
|
||||
@@ -96,11 +81,6 @@ Style/NumericPredicate:
|
||||
- 'app/helpers/plantings_helper.rb'
|
||||
- 'lib/tasks/growstuff.rake'
|
||||
|
||||
# Cop supports --auto-correct.
|
||||
Style/ParallelAssignment:
|
||||
Exclude:
|
||||
- 'app/mailers/notifier.rb'
|
||||
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
|
||||
# SupportedStyles: slashes, percent_r, mixed
|
||||
|
||||
@@ -56,6 +56,7 @@ deploy:
|
||||
secure: "WrQxf0fEKkCdXrjcejurobOnNNz3he4dDwjBbToXbQTQNDObPp7NetJrLsfM8FiUFEeOuvhIHHiDQtMvY720zGGAGxDptvgFS+0QHCUqoTRZA/yFfUmHlG2jROXTzk5uVK0AE4k6Ion5kX8+mM0EnMT/7u+MTFiukrJctSiEXfg="
|
||||
on:
|
||||
repo: Growstuff/growstuff
|
||||
condition: "$RSPEC_TAG = elasticsearch"
|
||||
app:
|
||||
dev: growstuff-staging
|
||||
master: growstuff-prod
|
||||
|
||||
@@ -8,14 +8,15 @@ 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)
|
||||
- Taylor Griffin / [tygriffin](https://github.com/tygriffin)
|
||||
- Mackenzie Morgan / [maco](https://github.com/maco)
|
||||
- Brenda Wallace / [br3nda](https://github.com/br3nda)
|
||||
|
||||
## Contributors
|
||||
|
||||
- Alex Bayley / [Skud](https://github.com/Skud)
|
||||
- Taylor Griffin / [tygriffin](https://github.com/tygriffin)
|
||||
- Joseph Caudle / [jcaudle](https://github.com/jcaudle)
|
||||
- Ricky Amianym / [amianym](https://github.com/amianym)
|
||||
- Juliet Kemp / [julietk](https://github.com/julietk)
|
||||
@@ -73,7 +74,6 @@ submit the change with your pull request.
|
||||
- Lucas Nogueira / [lucasnogueira](https://github.com/lucasnogueira)
|
||||
- Charley Lewittes / [ctlewitt](https://github.com/ctlewitt)
|
||||
- Kristine Nicole Polvoriza / [polveenomials](https://github.com/polveenomials)
|
||||
- Brenda Wallace / [br3nda](https://github.com/br3nda)
|
||||
- Jim Stallings / [jestallin](https://github.com/jestallin)
|
||||
- Alyssa Ransbury / [alran](https://github.com/alran)
|
||||
- Thomas Countz / [thomascountz](https://github.com/thomascountz)
|
||||
@@ -82,6 +82,7 @@ submit the change with your pull request.
|
||||
- Harry Brodsky / [hbrodsk1](https://github.com/hbrodsk1)
|
||||
- Jeff Kingswood / [ancyentmariner](https://github.com/ancyentmariner)
|
||||
- Logan Gingerich / [logangingerich](https://github.com/logangingerich)
|
||||
- Mark Taffman / [mftaff](https://github.com/mftaff)
|
||||
|
||||
## Bots
|
||||
|
||||
|
||||
7
Gemfile
7
Gemfile
@@ -38,7 +38,7 @@ gem 'gibbon', '~>1.2.0' # for Mailchimp newsletter subscriptions
|
||||
gem 'leaflet-rails'
|
||||
gem 'rails-assets-leaflet.markercluster', source: 'https://rails-assets.org'
|
||||
|
||||
gem 'pg'
|
||||
gem 'pg', '< 1.0.0' # Upstream bug, see https://github.com/Growstuff/growstuff/pull/1539
|
||||
gem 'ruby-units' # for unit conversion
|
||||
gem 'unicorn' # http server
|
||||
|
||||
@@ -48,7 +48,6 @@ gem 'bootstrap-kaminari-views' # bootstrap views for kaminari
|
||||
gem 'kaminari' # pagination
|
||||
|
||||
gem 'active_utils'
|
||||
gem 'activemerchant'
|
||||
gem 'sidekiq'
|
||||
|
||||
# Markdown formatting for updates etc
|
||||
@@ -78,8 +77,7 @@ gem 'omniauth-facebook'
|
||||
gem 'omniauth-flickr', '>= 0.0.15'
|
||||
gem 'omniauth-twitter'
|
||||
|
||||
# For charting data
|
||||
gem 'd3-rails', '~> 3.5' # 4.* produces Error: <spyOn> : could not find an object to spy upon for linear() - see https://travis-ci.org/Growstuff/growstuff/jobs/204461482
|
||||
gem "chartkick"
|
||||
|
||||
# client for Elasticsearch. Elasticsearch is a flexible
|
||||
# and powerful, distributed, real-time search and analytics engine.
|
||||
@@ -126,7 +124,6 @@ group :development do
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
gem "active_merchant-paypal-bogus-gateway"
|
||||
gem 'bullet' # performance tuning by finding unnecesary queries
|
||||
gem 'byebug' # debugging
|
||||
gem 'capybara' # integration tests
|
||||
|
||||
112
Gemfile.lock
112
Gemfile.lock
@@ -26,19 +26,12 @@ GEM
|
||||
addressable
|
||||
active_median (0.1.4)
|
||||
activerecord
|
||||
active_merchant-paypal-bogus-gateway (0.1.0)
|
||||
activemerchant
|
||||
active_utils (3.3.9)
|
||||
activesupport (>= 3.2, < 5.2.0)
|
||||
i18n
|
||||
activejob (4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
globalid (>= 0.3.0)
|
||||
activemerchant (1.75.0)
|
||||
activesupport (>= 3.2.14, < 6.x)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
activemodel (4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
builder (~> 3.1)
|
||||
@@ -57,15 +50,15 @@ GEM
|
||||
addressable (2.5.2)
|
||||
public_suffix (>= 2.0.2, < 4.0)
|
||||
arel (6.0.4)
|
||||
ast (2.3.0)
|
||||
autoprefixer-rails (7.2.3)
|
||||
ast (2.4.0)
|
||||
autoprefixer-rails (7.2.5)
|
||||
execjs
|
||||
bcrypt (3.1.11)
|
||||
better_errors (2.2.0)
|
||||
coderay (>= 1.0.0)
|
||||
erubis (>= 2.6.6)
|
||||
rack (>= 0.9.0)
|
||||
binding_of_caller (0.7.3)
|
||||
binding_of_caller (0.8.0)
|
||||
debug_inspector (>= 0.0.1)
|
||||
bluecloth (2.2.0)
|
||||
bonsai-elasticsearch-rails (0.2.0)
|
||||
@@ -81,24 +74,25 @@ GEM
|
||||
sass (>= 3.3.4)
|
||||
bootstrap_form (2.7.0)
|
||||
builder (3.2.3)
|
||||
bullet (5.7.0)
|
||||
bullet (5.7.2)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.10.0)
|
||||
byebug (9.1.0)
|
||||
cancancan (2.1.2)
|
||||
capybara (2.16.1)
|
||||
uniform_notifier (~> 1.11.0)
|
||||
byebug (10.0.0)
|
||||
cancancan (2.1.3)
|
||||
capybara (2.17.0)
|
||||
addressable
|
||||
mini_mime (>= 0.1.3)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
xpath (>= 2.0, < 4.0)
|
||||
capybara-email (2.5.0)
|
||||
capybara (~> 2.4)
|
||||
mail
|
||||
capybara-screenshot (1.0.18)
|
||||
capybara (>= 1.0, < 3)
|
||||
launchy
|
||||
chartkick (2.2.5)
|
||||
childprocess (0.8.0)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
climate_control (0.2.0)
|
||||
@@ -143,12 +137,10 @@ GEM
|
||||
crass (1.0.3)
|
||||
csv_shaper (1.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
d3-rails (3.5.17)
|
||||
railties (>= 3.1)
|
||||
dalli (2.7.6)
|
||||
database_cleaner (1.6.2)
|
||||
debug_inspector (0.0.3)
|
||||
devise (4.3.0)
|
||||
devise (4.4.1)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 4.1.0, < 5.2)
|
||||
@@ -156,8 +148,7 @@ GEM
|
||||
warden (~> 1.2.3)
|
||||
diff-lcs (1.3)
|
||||
docile (1.1.5)
|
||||
easy_translate (0.5.0)
|
||||
json
|
||||
easy_translate (0.5.1)
|
||||
thread
|
||||
thread_safe
|
||||
elasticsearch (2.0.2)
|
||||
@@ -181,11 +172,11 @@ GEM
|
||||
factory_bot_rails (4.8.2)
|
||||
factory_bot (~> 4.8.2)
|
||||
railties (>= 3.0.0)
|
||||
faker (1.8.5)
|
||||
i18n (~> 0.9.1)
|
||||
faker (1.8.7)
|
||||
i18n (>= 0.7)
|
||||
faraday (0.12.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.18)
|
||||
ffi (1.9.21)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
flickraw (0.9.9)
|
||||
@@ -203,10 +194,10 @@ GEM
|
||||
gravatar-ultimate (2.0.0)
|
||||
activesupport (>= 2.3.14)
|
||||
rack
|
||||
guard (2.14.1)
|
||||
guard (2.14.2)
|
||||
formatador (>= 0.2.4)
|
||||
listen (>= 2.7, < 4.0)
|
||||
lumberjack (~> 1.0)
|
||||
lumberjack (>= 1.0.12, < 2.0)
|
||||
nenv (~> 0.1)
|
||||
notiffany (~> 0.0)
|
||||
pry (>= 0.9.12)
|
||||
@@ -238,7 +229,7 @@ GEM
|
||||
rake (>= 10, < 13)
|
||||
rubocop (>= 0.49.0)
|
||||
sysexits (~> 1.1)
|
||||
hashie (3.5.6)
|
||||
hashie (3.5.7)
|
||||
heroics (0.0.24)
|
||||
erubis (~> 2.0)
|
||||
excon
|
||||
@@ -252,7 +243,7 @@ GEM
|
||||
ruby_parser (~> 3.5)
|
||||
httparty (0.15.6)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (0.9.1)
|
||||
i18n (0.9.3)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-tasks (0.9.12)
|
||||
activesupport (>= 4.0.2)
|
||||
@@ -264,19 +255,19 @@ GEM
|
||||
parser (>= 2.2.3.0)
|
||||
term-ansicolor (>= 1.3.2)
|
||||
terminal-table (>= 1.5.1)
|
||||
jasmine (2.8.0)
|
||||
jasmine-core (>= 2.8.0, < 3.0.0)
|
||||
jasmine (2.9.0)
|
||||
jasmine-core (>= 2.9.0, < 3.0.0)
|
||||
phantomjs
|
||||
rack (>= 1.2.1)
|
||||
rake
|
||||
jasmine-core (2.8.0)
|
||||
jasmine-core (2.99.0)
|
||||
jquery-rails (4.3.1)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
jquery-ui-rails (5.0.5)
|
||||
railties (>= 3.2.16)
|
||||
js-routes (1.4.2)
|
||||
js-routes (1.4.3)
|
||||
railties (>= 3.2)
|
||||
sprockets-rails
|
||||
json (2.1.0)
|
||||
@@ -297,13 +288,13 @@ GEM
|
||||
activerecord
|
||||
kaminari-core (= 1.1.1)
|
||||
kaminari-core (1.1.1)
|
||||
kgio (2.11.1)
|
||||
kgio (2.11.2)
|
||||
kramdown (1.16.2)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
leaflet-rails (1.2.0)
|
||||
leaflet-rails (1.3.1)
|
||||
rails (>= 4.2.0)
|
||||
letter_opener (1.4.1)
|
||||
letter_opener (1.6.0)
|
||||
launchy (~> 2.2)
|
||||
listen (3.1.5)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
@@ -323,14 +314,14 @@ GEM
|
||||
mimemagic (0.3.2)
|
||||
mini_mime (1.0.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.10.3)
|
||||
minitest (5.11.3)
|
||||
moneta (0.8.1)
|
||||
multi_json (1.11.3)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
nenv (0.3.0)
|
||||
newrelic_rpm (4.6.0.338)
|
||||
nokogiri (1.8.1)
|
||||
newrelic_rpm (4.8.0.341)
|
||||
nokogiri (1.8.2)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
notiffany (0.1.1)
|
||||
nenv (~> 0.1)
|
||||
@@ -342,7 +333,7 @@ GEM
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
omniauth (1.7.1)
|
||||
omniauth (1.8.1)
|
||||
hashie (>= 3.4.6, < 3.6.0)
|
||||
rack (>= 1.6.2, < 3)
|
||||
omniauth-facebook (4.0.0)
|
||||
@@ -360,7 +351,7 @@ GEM
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
orm_adapter (0.5.0)
|
||||
paperclip (5.1.0)
|
||||
paperclip (5.2.1)
|
||||
activemodel (>= 4.2.0)
|
||||
activesupport (>= 4.2.0)
|
||||
cocaine (~> 0.5.5)
|
||||
@@ -403,13 +394,13 @@ GEM
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.10)
|
||||
sprockets-rails
|
||||
rails-assets-leaflet (1.2.0)
|
||||
rails-assets-leaflet.markercluster (1.2.0)
|
||||
rails-assets-leaflet (1.3.1)
|
||||
rails-assets-leaflet.markercluster (1.3.0)
|
||||
rails-assets-leaflet (>= 1.0.3)
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.8)
|
||||
activesupport (>= 4.2.0.beta, < 5.0)
|
||||
rails-dom-testing (1.0.9)
|
||||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
@@ -445,7 +436,7 @@ GEM
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
rspec-mocks (>= 2.99, < 4.0)
|
||||
rspec-core (3.7.0)
|
||||
rspec-core (3.7.1)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-expectations (3.7.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
@@ -461,7 +452,7 @@ GEM
|
||||
rspec-expectations (~> 3.7.0)
|
||||
rspec-mocks (~> 3.7.0)
|
||||
rspec-support (~> 3.7.0)
|
||||
rspec-support (3.7.0)
|
||||
rspec-support (3.7.1)
|
||||
rubocop (0.49.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.3.3.1, < 3.0)
|
||||
@@ -475,7 +466,7 @@ GEM
|
||||
ruby_parser (3.10.1)
|
||||
sexp_processor (~> 4.9)
|
||||
rubyzip (1.2.1)
|
||||
sass (3.5.4)
|
||||
sass (3.5.5)
|
||||
sass-listen (~> 4.0.0)
|
||||
sass-listen (4.0.0)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
@@ -486,12 +477,12 @@ GEM
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
selenium-webdriver (3.8.0)
|
||||
selenium-webdriver (3.9.0)
|
||||
childprocess (~> 0.5)
|
||||
rubyzip (~> 1.0)
|
||||
rubyzip (~> 1.2)
|
||||
sexp_processor (4.10.0)
|
||||
shellany (0.0.1)
|
||||
sidekiq (5.0.5)
|
||||
sidekiq (5.1.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
rack-protection (>= 1.5.0)
|
||||
@@ -523,15 +514,15 @@ GEM
|
||||
timecop (0.9.1)
|
||||
tins (1.16.3)
|
||||
trollop (1.16.2)
|
||||
tzinfo (1.2.4)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.0.2)
|
||||
uglifier (4.1.5)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (1.3.0)
|
||||
unicorn (5.3.1)
|
||||
unicorn (5.4.0)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
uniform_notifier (1.10.0)
|
||||
uniform_notifier (1.11.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
webrat (0.7.3)
|
||||
@@ -543,17 +534,15 @@ GEM
|
||||
websocket-extensions (0.1.3)
|
||||
will_paginate (3.1.6)
|
||||
xmlrpc (0.3.0)
|
||||
xpath (2.1.0)
|
||||
nokogiri (~> 1.3)
|
||||
xpath (3.0.0)
|
||||
nokogiri (~> 1.8)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
active_median
|
||||
active_merchant-paypal-bogus-gateway
|
||||
active_utils
|
||||
activemerchant
|
||||
acts_as_paranoid (~> 0.5.0)
|
||||
better_errors (~> 2.2.0)
|
||||
binding_of_caller
|
||||
@@ -569,12 +558,12 @@ DEPENDENCIES
|
||||
capybara
|
||||
capybara-email
|
||||
capybara-screenshot
|
||||
chartkick
|
||||
codeclimate-test-reporter
|
||||
coffee-rails
|
||||
comfortable_mexican_sofa
|
||||
coveralls
|
||||
csv_shaper
|
||||
d3-rails (~> 3.5)
|
||||
dalli
|
||||
database_cleaner
|
||||
devise
|
||||
@@ -612,7 +601,7 @@ DEPENDENCIES
|
||||
omniauth-facebook
|
||||
omniauth-flickr (>= 0.0.15)
|
||||
omniauth-twitter
|
||||
pg
|
||||
pg (< 1.0.0)
|
||||
platform-api
|
||||
poltergeist
|
||||
pry
|
||||
@@ -638,9 +627,8 @@ DEPENDENCIES
|
||||
will_paginate
|
||||
xmlrpc
|
||||
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.4.1p111
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.0
|
||||
1.16.1
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
||||
// GO AFTER THE REQUIRES BELOW.
|
||||
//
|
||||
//= require leaflet
|
||||
//= require leaflet.markercluster
|
||||
//= require js-routes
|
||||
//= require jquery
|
||||
//= require jquery_ujs
|
||||
//= require jquery-ui/autocomplete
|
||||
//= require bootstrap-sprockets
|
||||
//= require bootstrap-datepicker
|
||||
//= require_tree .
|
||||
// = require leaflet
|
||||
// = require leaflet.markercluster
|
||||
// = require js-routes
|
||||
// = require jquery
|
||||
// = require jquery_ujs
|
||||
// = require jquery-ui/autocomplete
|
||||
// = require bootstrap-sprockets
|
||||
// = require bootstrap-datepicker
|
||||
// = require_tree .
|
||||
|
||||
File diff suppressed because one or more lines are too long
2
app/assets/javascripts/charts.js
Normal file
2
app/assets/javascripts/charts.js
Normal file
@@ -0,0 +1,2 @@
|
||||
// = require Chart.bundle
|
||||
// = require chartkick
|
||||
@@ -1,37 +1,27 @@
|
||||
//= require graphs/horizontal_bar_graph
|
||||
|
||||
if (document.getElementById("cropmap") !== null) {
|
||||
mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>";
|
||||
mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>";
|
||||
mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token;
|
||||
|
||||
L.Icon.Default.imagePath = '/assets'
|
||||
|
||||
cropmap = L.map('cropmap').setView([0.0, -0.0], 2);
|
||||
showCropMap(cropmap);
|
||||
}
|
||||
|
||||
function showCropMap(cropmap) {
|
||||
var mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>";
|
||||
var mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>";
|
||||
var mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token;
|
||||
|
||||
L.tileLayer(mapbox_base_url, {
|
||||
attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors under <a href="http://www.openstreetmap.org/copyright">ODbL</a> | Map imagery © <a href="http://mapbox.com">Mapbox</a>',
|
||||
maxZoom: 18
|
||||
}).addTo(cropmap);
|
||||
markers = new L.MarkerClusterGroup({showCoverageOnHover: false, maxClusterRadius: 20 });
|
||||
var markers = new L.MarkerClusterGroup({showCoverageOnHover: false, maxClusterRadius: 20 });
|
||||
|
||||
things_to_map = location.pathname + '.json';
|
||||
var things_to_map = location.pathname + '.json';
|
||||
$.getJSON(things_to_map, function(crop) {
|
||||
$.each(crop.plantings, function(i, planting) {
|
||||
owner = planting.owner;
|
||||
var owner = planting.owner;
|
||||
if (owner.latitude && owner.longitude) {
|
||||
marker = new L.Marker(new L.LatLng(owner.latitude, owner.longitude));
|
||||
var marker = new L.Marker(new L.LatLng(owner.latitude, owner.longitude));
|
||||
|
||||
planting_url = "/plantings/" + planting.id;
|
||||
planting_link = "<a href='" + planting_url + "'>" + owner.login_name + "'s " + crop.name + "</a>";
|
||||
var planting_url = "/plantings/" + planting.id;
|
||||
var planting_link = "<a href='" + planting_url + "'>" + owner.login_name + "'s " + crop.name + "</a>";
|
||||
|
||||
where = "<p><i>" + owner.location + "</i></p>";
|
||||
var where = "<p><i>" + owner.location + "</i></p>";
|
||||
|
||||
details = "<p>";
|
||||
var details = "<p>";
|
||||
if (planting.quantity) {
|
||||
details = details + "Quantity: " + planting.quantity + "<br/>";
|
||||
}
|
||||
@@ -51,41 +41,17 @@ function showCropMap(cropmap) {
|
||||
cropmap.addLayer(markers);
|
||||
}
|
||||
|
||||
function plantingStats(crop) {
|
||||
var sunniness_counts = { 'empty': 0, 'sun': 0, 'semi-shade': 0, 'shade': 0 };
|
||||
$.each(crop.plantings, function(i, planting) {
|
||||
if (planting.sunniness) {
|
||||
sunniness_counts[planting.sunniness]++;
|
||||
} else {
|
||||
sunniness_counts['Empty']++;
|
||||
}
|
||||
$(document).ready(function() {
|
||||
|
||||
if (document.getElementById("cropmap") !== null) {
|
||||
|
||||
L.Icon.Default.imagePath = '/assets';
|
||||
|
||||
var cropmap = L.map('cropmap').setView([0.0, -0.0], 2);
|
||||
showCropMap(cropmap);
|
||||
}
|
||||
|
||||
$('.btn.toggle.crop-hierarchy').click(function () {
|
||||
$('.toggle.crop-hierarchy').toggleClass('hide');
|
||||
});
|
||||
return [
|
||||
{name: 'Empty', value: sunniness_counts['empty']},
|
||||
{name: 'Sun', value: sunniness_counts['sun']},
|
||||
{name: 'Semi-shade', value: sunniness_counts['semi-shade']},
|
||||
{name: 'Shade', value: sunniness_counts['shade']}
|
||||
];
|
||||
}
|
||||
|
||||
if ($("#sunchart")[0] !== null) {
|
||||
var HorizontalBarGraph = growstuff.HorizontalBarGraph;
|
||||
$.getJSON(location.pathname + '.json', function (crop) {
|
||||
data = {
|
||||
bars: plantingStats(crop),
|
||||
bar_color: 'steelblue',
|
||||
width: {size: 300, scale: 'linear'},
|
||||
height: {size: 100, scale: 'ordinal'},
|
||||
//left is used to shift the bars over so that there is
|
||||
//room for the labels
|
||||
margin: {top: 0, right: 0, bottom: 0, left: 100}
|
||||
};
|
||||
|
||||
var graph = new HorizontalBarGraph(data);
|
||||
graph.render(d3.select($('#sunchart')[0]));
|
||||
});
|
||||
}
|
||||
|
||||
$('.btn.toggle.crop-hierarchy').click(function () {
|
||||
$('.toggle.crop-hierarchy').toggleClass('hide');
|
||||
});
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
//= require graphs/width_scale
|
||||
//= require graphs/height_scale
|
||||
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
This represents bars for a bar graph.
|
||||
Currently these are used for HorizontalBarGraph.
|
||||
*/
|
||||
|
||||
var growstuff = (window.growstuff = window.growstuff || {});
|
||||
var WidthScale = growstuff.WidthScale;
|
||||
var HeightScale = growstuff.HeightScale;
|
||||
|
||||
function BarGroup(data) {
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
BarGroup.prototype.render = function(root){
|
||||
|
||||
var data = this._data;
|
||||
var bars = this._data.bars;
|
||||
var widthScale = new WidthScale(data).render();
|
||||
var heightScale = new HeightScale(data).render();
|
||||
|
||||
return root.append('g')
|
||||
.attr("class", "bar")
|
||||
.selectAll("rect")
|
||||
.data(bars.map(function(bar) { return bar.value; }))
|
||||
.enter()
|
||||
.append("rect")
|
||||
.attr("y", function(d, i){
|
||||
return heightScale(i);
|
||||
|
||||
})
|
||||
.attr("height", heightScale.rangeBand())
|
||||
.attr("fill", data.bar_color)
|
||||
.attr("width", function(d){
|
||||
return widthScale(d);
|
||||
})
|
||||
.append("title")
|
||||
.text(function(d){
|
||||
return 'This value is ' + d + '.';
|
||||
});
|
||||
};
|
||||
|
||||
growstuff.BarGroup = BarGroup;
|
||||
|
||||
}());
|
||||
@@ -1,40 +0,0 @@
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
This file draws the labels to the left of each bar.
|
||||
*/
|
||||
|
||||
var growstuff = (window.growstuff = window.growstuff || {});
|
||||
|
||||
function BarLabelGroup(data) {
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
BarLabelGroup.prototype.render = function(d3){
|
||||
var bars = this._data.bars;
|
||||
//vvcopy pasta from spike vv -- this is a good candidate for refactor
|
||||
var barHeight = 40;
|
||||
|
||||
return d3.append('g')
|
||||
.attr("class", "bar-label")
|
||||
.selectAll("text")
|
||||
.data(bars.map(function(bar){ return bar.name;}))
|
||||
.enter()
|
||||
.append("text")
|
||||
.attr('x', -80)
|
||||
.attr('y', function(d, i){
|
||||
//shrink the margin between each label to give them an even spread with
|
||||
//bars
|
||||
var barLabelSpread = 2/3;
|
||||
//move them downward to line up with bars
|
||||
var barLabelTopEdge = 17;
|
||||
return i * barHeight * (barLabelSpread) + barLabelTopEdge;
|
||||
})
|
||||
.text(function(d){return d;});
|
||||
|
||||
};
|
||||
|
||||
growstuff.BarLabelGroup = BarLabelGroup;
|
||||
|
||||
}());
|
||||
@@ -1,29 +0,0 @@
|
||||
//=require d3
|
||||
|
||||
/*
|
||||
Height Scale is used to map the number of bars to the display size of
|
||||
the svg
|
||||
*/
|
||||
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
var growstuff = (window.growstuff = window.growstuff || {});
|
||||
|
||||
function HeightScale(data){
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
HeightScale.prototype.render = function(){
|
||||
var data = this._data;
|
||||
var scaleType = data.height.scale;
|
||||
var axisSize = data.height.size;
|
||||
|
||||
return d3.scale[scaleType]()
|
||||
.domain(d3.range(data.bars.length))
|
||||
.rangeRoundBands([0, data.height.size], 0.05, 0);
|
||||
};
|
||||
|
||||
growstuff.HeightScale = HeightScale;
|
||||
|
||||
}());
|
||||
@@ -1,51 +0,0 @@
|
||||
//= require d3
|
||||
//= require graphs/bar_group
|
||||
//= require graphs/bar_label_group
|
||||
|
||||
/*
|
||||
Horizontal Bar Graph represents sum total of the graph including all of the parts:
|
||||
Bars
|
||||
Bar Labels
|
||||
|
||||
The main dimensions of the graph are rendered here.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var growstuff = (window.growstuff = window.growstuff || {});
|
||||
var BarGroup = growstuff.BarGroup;
|
||||
var BarLabelGroup = growstuff.BarLabelGroup;
|
||||
|
||||
function HorizontalBarGraph(data) {
|
||||
this._data = data;
|
||||
this._d3 = d3;
|
||||
}
|
||||
|
||||
HorizontalBarGraph.prototype.render = function(root) {
|
||||
var bars = this._data.bars;
|
||||
var width = this._data.width;
|
||||
var height = this._data.height;
|
||||
|
||||
var barLabelGroup = new BarLabelGroup(this._data);
|
||||
var margin = this._data.margin;
|
||||
|
||||
var barGroup = new BarGroup(this._data);
|
||||
|
||||
var svg = root
|
||||
.append("svg")
|
||||
.attr("width", width.size + margin.left + margin.right)
|
||||
.attr("height", height.size + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("class","bar-graph")
|
||||
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
|
||||
barGroup.render(svg);
|
||||
barLabelGroup.render(svg);
|
||||
|
||||
return svg;
|
||||
};
|
||||
|
||||
growstuff.HorizontalBarGraph = HorizontalBarGraph;
|
||||
}());
|
||||
@@ -1,33 +0,0 @@
|
||||
//=require d3
|
||||
|
||||
/*
|
||||
Width scale is used to map the value for the length of each bar
|
||||
to the display size of the svg
|
||||
*/
|
||||
|
||||
(function(){
|
||||
'use strict';
|
||||
|
||||
var growstuff = (window.growstuff = window.growstuff || {});
|
||||
|
||||
function WidthScale (data){
|
||||
this._data = data;
|
||||
}
|
||||
|
||||
WidthScale.prototype.render = function() {
|
||||
var data = this._data;
|
||||
var scaleType = data.width.scale;
|
||||
var axisSize = data.width.size;
|
||||
|
||||
return d3.scale[scaleType]()
|
||||
.domain([0, this.getMaxValue()])
|
||||
.range([0, axisSize]);
|
||||
};
|
||||
|
||||
WidthScale.prototype.getMaxValue = function(){
|
||||
return d3.max(this._data.bars.map(function(bar) { return bar.value; }));
|
||||
};
|
||||
|
||||
growstuff.WidthScale = WidthScale;
|
||||
|
||||
}());
|
||||
@@ -1,25 +1,24 @@
|
||||
if (document.getElementById("membermap") !== null) {
|
||||
mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>";
|
||||
mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>";
|
||||
mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token;
|
||||
|
||||
L.Icon.Default.imagePath = '/assets'
|
||||
var mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>";
|
||||
var mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>";
|
||||
var mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token;
|
||||
|
||||
L.Icon.Default.imagePath = '/assets';
|
||||
|
||||
$.getJSON(location.pathname + '.json', function(member) {
|
||||
if (member.latitude && member.longitude) {
|
||||
membermap = L.map('membermap').setView([member.latitude, member.longitude], 4);
|
||||
var membermap = L.map('membermap').setView([member.latitude, member.longitude], 4);
|
||||
|
||||
L.tileLayer(mapbox_base_url, {
|
||||
attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors under <a href="http://www.openstreetmap.org/copyright">ODbL</a> | Map imagery © <a href="http://mapbox.com">Mapbox</a>',
|
||||
maxZoom: 18
|
||||
}).addTo(membermap);
|
||||
marker = new L.Marker(new L.LatLng(member.latitude, member.longitude));
|
||||
var marker = new L.Marker(new L.LatLng(member.latitude, member.longitude));
|
||||
|
||||
member_url = "/members/" + member.slug;
|
||||
member_link = "<a href='" + member_url + "'>" + member.login_name + "</a>";
|
||||
var member_url = "/members/" + member.slug;
|
||||
var member_link = "<a href='" + member_url + "'>" + member.login_name + "</a>";
|
||||
|
||||
where = "<p><i>" + member.location + "</i></p>";
|
||||
var where = "<p><i>" + member.location + "</i></p>";
|
||||
|
||||
marker.bindPopup(member_link + where).openPopup();
|
||||
marker.addTo(membermap);
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
$(document).ready(function () {
|
||||
$(document).ready(function() {
|
||||
$('.post-like').show();
|
||||
|
||||
$('.post-like').on('ajax:success', function(event, data) {
|
||||
var like_control = $('#post-' + data.id + ' .post-like');
|
||||
var likeControl = $('#post-' + data.id + ' .post-like');
|
||||
|
||||
$('#post-' + data.id + ' .like-count').text(data.description);
|
||||
if (data.liked_by_member) {
|
||||
like_control.data("method", "delete");
|
||||
like_control.attr("href", data.url);
|
||||
like_control.text("Unlike");
|
||||
likeControl.data('method', 'delete');
|
||||
likeControl.attr('href', data.url);
|
||||
likeControl.text('Unlike');
|
||||
} else {
|
||||
like_control.data("method", "post");
|
||||
like_control.attr("href", '/likes.json?post_id=' + data.id);
|
||||
like_control.text("Like");
|
||||
likeControl.data('method', 'post');
|
||||
likeControl.attr('href', '/likes.json?post_id=' + data.id);
|
||||
likeControl.text('Like');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,3 +5,4 @@
|
||||
@import 'custom_bootstrap/custom_bootstrap'
|
||||
@import 'overrides'
|
||||
@import 'graphs'
|
||||
@import 'predictions'
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -13,6 +13,7 @@ $blue: #2f4365
|
||||
$red: #8e4d43
|
||||
$orange: #ffa500
|
||||
$yellow: #b2935c
|
||||
$white: #ffffff
|
||||
|
||||
$body-bg: $beige
|
||||
$text-color: $brown
|
||||
|
||||
@@ -3,37 +3,18 @@
|
||||
@import "custom_bootstrap/variables"
|
||||
// this padding needs to be done before the responsive stuff is imported
|
||||
body
|
||||
// modifying this for our promotional banner. can be replaced after if
|
||||
// needed.
|
||||
// padding-top: $navbar-height + 15px
|
||||
padding-top: $navbar-height
|
||||
|
||||
|
||||
//@import "bootstrap/responsive"
|
||||
|
||||
// Font Awesome
|
||||
@import "font-awesome-sprockets"
|
||||
@import "font-awesome"
|
||||
|
||||
// Glyphicons
|
||||
//@import "bootstrap/glyphicons"
|
||||
|
||||
|
||||
.list-inline > li.first
|
||||
padding-left: 0px
|
||||
|
||||
h2
|
||||
font-size: 150%
|
||||
|
||||
|
||||
//#subtitle
|
||||
// color: lighten($brown, 30%)
|
||||
// font-style: italic
|
||||
// font-weight: normal
|
||||
// margin-top: 0px
|
||||
// padding-left: 1em
|
||||
// padding-top: 0px
|
||||
|
||||
h3
|
||||
font-size: 120%
|
||||
|
||||
|
||||
11
app/assets/stylesheets/predictions.sass
Normal file
11
app/assets/stylesheets/predictions.sass
Normal file
@@ -0,0 +1,11 @@
|
||||
.predictions
|
||||
.metric
|
||||
height: 180px
|
||||
border: 1px solid lighten($green, 20%)
|
||||
background: $white
|
||||
margin: 4px
|
||||
strong
|
||||
font-size: 250%
|
||||
font-align: center
|
||||
h3
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
30
app/controllers/charts/crops_controller.rb
Normal file
30
app/controllers/charts/crops_controller.rb
Normal file
@@ -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
|
||||
16
app/controllers/charts/gardens_controller.rb
Normal file
16
app/controllers/charts/gardens_controller.rb
Normal file
@@ -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
|
||||
@@ -51,9 +51,9 @@ 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_to do |format|
|
||||
format.html # show.html.haml
|
||||
format.html
|
||||
format.json { render json: @crop.to_json(crop_json_fields) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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
|
||||
@@ -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: Growstuff::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: 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
|
||||
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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ 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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -37,17 +37,20 @@ class Notifier < ActionMailer::Base
|
||||
end
|
||||
|
||||
def new_crop_request(member, request)
|
||||
@member, @request = member, request
|
||||
@member = member
|
||||
@request = request
|
||||
mail(to: @member.email, subject: "#{@request.requester.login_name} has requested #{@request.name} as a new crop")
|
||||
end
|
||||
|
||||
def crop_request_approved(member, crop)
|
||||
@member, @crop = member, crop
|
||||
@member = member
|
||||
@crop = crop
|
||||
mail(to: @member.email, subject: "#{crop.name.capitalize} has been approved")
|
||||
end
|
||||
|
||||
def crop_request_rejected(member, crop)
|
||||
@member, @crop = member, crop
|
||||
@member = member
|
||||
@crop = crop
|
||||
mail(to: @member.email, subject: "#{crop.name.capitalize} has been rejected")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,17 +15,18 @@ class Ability
|
||||
can :view_follows, Member
|
||||
can :view_followers, Member
|
||||
|
||||
# Everyone can see the charts
|
||||
can :timeline, Garden
|
||||
can :sunniness, Crop
|
||||
can :planted_from, Crop
|
||||
can :harvested_for, Crop
|
||||
|
||||
# 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
|
||||
@@ -114,20 +115,6 @@ class Ability
|
||||
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 }
|
||||
|
||||
# following/unfollowing permissions
|
||||
can :create, Follow
|
||||
cannot :create, Follow, followed_id: member.id # can't follow yourself
|
||||
@@ -142,12 +129,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|
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
class Account < ActiveRecord::Base
|
||||
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
|
||||
"forever"
|
||||
elsif account_type.is_paid
|
||||
paid_until.to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,13 +0,0 @@
|
||||
class AccountType < ActiveRecord::Base
|
||||
#
|
||||
# Relationships
|
||||
has_many :products
|
||||
|
||||
#
|
||||
# Validations
|
||||
validates :name, presence: true, uniqueness: true
|
||||
|
||||
def to_s
|
||||
name
|
||||
end
|
||||
end
|
||||
@@ -46,7 +46,7 @@ class CsvImporter
|
||||
|
||||
names_to_add.each do |name|
|
||||
sciname = ScientificName.find_by(name: name, crop: @crop)
|
||||
sciname = ScientificName.create!(name: name, crop: @crop, creator: cropbot) unless sciname
|
||||
sciname ||= ScientificName.create!(name: name, crop: @crop, creator: cropbot)
|
||||
@crop.scientific_names << sciname
|
||||
end
|
||||
end
|
||||
@@ -56,15 +56,15 @@ class CsvImporter
|
||||
return if alternate_names.blank?
|
||||
alternate_names.split(/,\s*/).each do |name|
|
||||
altname = AlternateName.find_by(name: name, crop: @crop)
|
||||
altname = AlternateName.create! name: name, crop: @crop, creator: cropbot unless altname
|
||||
altname ||= AlternateName.create! name: name, crop: @crop, creator: cropbot
|
||||
@crop.alternate_names << altname
|
||||
end
|
||||
end
|
||||
|
||||
def cropbot
|
||||
@cropbot = Member.find_by!(login_name: 'cropbot') unless @cropbot
|
||||
@cropbot ||= Member.find_by!(login_name: 'cropbot')
|
||||
@cropbot
|
||||
rescue
|
||||
rescue StandardError
|
||||
raise "cropbot account not found: run rake db:seed"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ class Member < ActiveRecord::Base
|
||||
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 < ActiveRecord::Base
|
||||
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
|
||||
@@ -79,11 +76,9 @@ class Member < ActiveRecord::Base
|
||||
after_save :update_newsletter_subscription
|
||||
|
||||
# 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
|
||||
after_create { |member| Garden.create(name: "Garden", owner_id: member.id) }
|
||||
after_create { |member| Account.find_or_create_by(member_id: member.id) }
|
||||
|
||||
# allow login via either login_name or email address
|
||||
def self.find_first_by_auth_conditions(warden_conditions)
|
||||
@@ -101,34 +96,6 @@ class Member < ActiveRecord::Base
|
||||
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
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
class Order < ActiveRecord::Base
|
||||
#
|
||||
# Relationships
|
||||
belongs_to :member, with_deleted: true
|
||||
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
|
||||
@@ -1,12 +0,0 @@
|
||||
class OrderItem < ActiveRecord::Base
|
||||
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
|
||||
@@ -27,7 +27,8 @@ class Photo < ActiveRecord::Base
|
||||
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 < ActiveRecord::Base
|
||||
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
|
||||
|
||||
@@ -4,12 +4,12 @@ class Planting < ActiveRecord::Base
|
||||
friendly_id :planting_slug, use: %i(slugged finders)
|
||||
|
||||
# Constants
|
||||
SUNNINESS_VALUES = %w(sun semi-shade shade)
|
||||
SUNNINESS_VALUES = %w(sun semi-shade shade).freeze
|
||||
PLANTED_FROM_VALUES = [
|
||||
'seed', 'seedling', 'cutting', 'root division', 'runner',
|
||||
'bulb', 'root/tuber', 'bare root plant', 'advanced plant',
|
||||
'graft', 'layering'
|
||||
]
|
||||
].freeze
|
||||
|
||||
##
|
||||
## Triggers
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
class Product < ActiveRecord::Base
|
||||
#
|
||||
# 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
|
||||
@@ -16,8 +16,6 @@ class Seed < ActiveRecord::Base
|
||||
#
|
||||
# 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 +36,10 @@ class Seed < ActiveRecord::Base
|
||||
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 +47,10 @@ class Seed < ActiveRecord::Base
|
||||
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
|
||||
|
||||
@@ -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'
|
||||
@@ -1,7 +0,0 @@
|
||||
- content_for :title, "Editing account type"
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Show', @account_type
|
||||
\|
|
||||
= link_to 'Back', account_types_path
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
- content_for :title, "New account type"
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Back', account_types_path
|
||||
@@ -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
|
||||
@@ -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'
|
||||
@@ -1,7 +0,0 @@
|
||||
- content_for :title, "Editing account"
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Show', @account
|
||||
\|
|
||||
= link_to 'Back', accounts_path
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
- content_for :title, "New account"
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Back', accounts_path
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
@@ -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'
|
||||
@@ -1,3 +0,0 @@
|
||||
- content_for :title, 'Admin Orders'
|
||||
|
||||
= render "admin/orders/searchform"
|
||||
@@ -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'
|
||||
@@ -51,7 +51,8 @@
|
||||
.form-group
|
||||
= f.label :parent_id, 'Parent crop', class: 'control-label col-md-2'
|
||||
.col-md-8
|
||||
= collection_select(:crop, :parent_id, Crop.all, :id, :name, { include_blank: true }, class: 'form-control')
|
||||
= collection_select(:crop, :parent_id, Crop.all.order(:name), :id, :name,
|
||||
{ include_blank: true }, class: 'form-control')
|
||||
%span.help-block Optional. For setting up crop hierarchies for varieties etc.
|
||||
|
||||
|
||||
|
||||
@@ -1,29 +1,35 @@
|
||||
- unless crop.perennial.nil?
|
||||
%p
|
||||
#{crop.name} is
|
||||
- if crop.perennial == true
|
||||
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
|
||||
a perennial crop
|
||||
(living more than two years)
|
||||
- elsif crop.perennial == false
|
||||
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
|
||||
an annual crop
|
||||
(living and reproducing in a single year or less)
|
||||
.predictions
|
||||
- unless crop.perennial.nil?
|
||||
.row
|
||||
.col-md-12
|
||||
%p
|
||||
#{crop.name} is
|
||||
- if crop.perennial == true
|
||||
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
|
||||
a perennial crop
|
||||
(living more than two years)
|
||||
- elsif crop.perennial == false
|
||||
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
|
||||
an annual crop
|
||||
(living and reproducing in a single year or less)
|
||||
|
||||
- if crop.annual? && crop.median_lifespan.present?
|
||||
%p
|
||||
Median lifespan of #{crop.name} plants is
|
||||
%strong= crop.median_lifespan
|
||||
days
|
||||
.row
|
||||
- if crop.annual? && crop.median_lifespan.present?
|
||||
.metric.col-md-3.col-xs-5
|
||||
%h3 Median lifespan
|
||||
%strong= crop.median_lifespan
|
||||
%span days
|
||||
|
||||
- if crop.median_days_to_first_harvest.present?
|
||||
%p
|
||||
First harvest expected
|
||||
%strong= crop.median_days_to_first_harvest
|
||||
days after planting
|
||||
- if crop.median_days_to_first_harvest.present?
|
||||
.metric.col-md-3.col-xs-5
|
||||
%h3 First harvest expected
|
||||
%strong= crop.median_days_to_first_harvest
|
||||
%span days
|
||||
after planting
|
||||
|
||||
- if crop.annual? && crop.median_days_to_last_harvest.present?
|
||||
%p
|
||||
Last harvest expected
|
||||
%strong= crop.median_days_to_last_harvest
|
||||
days after planting
|
||||
- if crop.annual? && crop.median_days_to_last_harvest.present?
|
||||
.metric.col-md-3.col-xs-5
|
||||
%h3 Last harvest expected
|
||||
%strong= crop.median_days_to_last_harvest
|
||||
%span days
|
||||
after planting
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
= tag("meta", property: "og:url", content: request.original_url)
|
||||
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
|
||||
|
||||
- content_for :scripts do
|
||||
= javascript_include_tag "charts"
|
||||
|
||||
= render partial: 'approval_status_message', locals: { crop: @crop }
|
||||
|
||||
- if @crop.approved?
|
||||
@@ -23,37 +26,51 @@
|
||||
|
||||
.row
|
||||
.col-md-9
|
||||
- if member_signed_in?
|
||||
= display_seed_availability(@current_member, @crop)
|
||||
= link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug)
|
||||
.row
|
||||
.col-md-12
|
||||
- if member_signed_in?
|
||||
= display_seed_availability(@current_member, @crop)
|
||||
= link_to "View your seeds", seeds_by_owner_path(owner: current_member.slug)
|
||||
|
||||
%h2 Predictions
|
||||
= render 'predictions', crop: @crop
|
||||
%h2
|
||||
- if !@crop.plantings.empty?
|
||||
= @crop.name.titleize
|
||||
has been planted
|
||||
= pluralize(@crop.plantings.size, "time")
|
||||
by #{ENV['GROWSTUFF_SITE_NAME']} members.
|
||||
- else
|
||||
Nobody is growing this yet. You could be the first!
|
||||
|
||||
%p= render 'crops/photos', crop: @crop
|
||||
|
||||
%h2
|
||||
- if !@crop.plantings.empty?
|
||||
= @crop.name.titleize
|
||||
has been planted
|
||||
= pluralize(@crop.plantings.size, "time")
|
||||
by #{ENV['GROWSTUFF_SITE_NAME']} members.
|
||||
- else
|
||||
Nobody is growing this yet. You could be the first!
|
||||
.row
|
||||
.col-md-12
|
||||
%h2 Predictions
|
||||
= render 'predictions', crop: @crop
|
||||
|
||||
%h2
|
||||
Sunniness Chart
|
||||
.row
|
||||
.col-md-12
|
||||
%h2 Photos
|
||||
%p= render 'crops/photos', crop: @crop
|
||||
.row
|
||||
.col-md-3
|
||||
%h2 Sunniness
|
||||
= pie_chart crop_sunniness_path(@crop), legend: "bottom"
|
||||
|
||||
#sunchart
|
||||
.col-md-3
|
||||
%h2 Planted from
|
||||
= pie_chart crop_planted_from_path(@crop), legend: "bottom"
|
||||
.col-md-3
|
||||
%h2 Harvested for
|
||||
= pie_chart crop_harvested_for_path(@crop), legend: "bottom"
|
||||
|
||||
%h2
|
||||
Crop Map
|
||||
%p
|
||||
Only plantings by members who have set their locations are shown on this map.
|
||||
- if current_member && current_member.location.blank?
|
||||
= link_to "Set your location.", edit_member_registration_path
|
||||
|
||||
#cropmap
|
||||
.row
|
||||
.col-md-12
|
||||
%h2 Crop Map
|
||||
%p
|
||||
Only plantings by members who have set their locations are shown on this map.
|
||||
- if current_member && current_member.location.blank?
|
||||
= link_to "Set your location.", edit_member_registration_path
|
||||
#cropmap
|
||||
|
||||
%a{ name: 'posts' }
|
||||
%h2 What people are saying about #{@crop.name.pluralize}
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
= tag("meta", property: "og:type", content: "website")
|
||||
= 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"
|
||||
= javascript_include_tag "https://www.gstatic.com/charts/loader.js"
|
||||
|
||||
.row
|
||||
.col-md-9
|
||||
%p.btn-group= render 'gardens/actions', garden: @garden
|
||||
@@ -32,7 +37,11 @@
|
||||
Why not
|
||||
= link_to 'tell us more.', edit_garden_path(@garden)
|
||||
|
||||
%h3 What's planted here?
|
||||
%h3 Garden timeline
|
||||
.row
|
||||
= timeline garden_timeline_path(@garden), adapter: "google"
|
||||
|
||||
%h3 Current plantings in garden
|
||||
.row
|
||||
- if @current_plantings.size.positive?
|
||||
- @current_plantings.each do |planting|
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
!!! 5
|
||||
%html{ lang: "en", prefix: "og: http://ogp.me/ns#" }
|
||||
= yield :scripts
|
||||
= render partial: "layouts/meta"
|
||||
%body
|
||||
= render partial: "layouts/header"
|
||||
@@ -27,5 +28,4 @@
|
||||
\==================================================
|
||||
/ Placed at the end of the document so the pages load faster
|
||||
= javascript_include_tag "application"
|
||||
|
||||
!= Growstuff::Application.config.analytics_code
|
||||
|
||||
@@ -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
|
||||
9
app/views/members/_roles.html.haml
Normal file
9
app/views/members/_roles.html.haml
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -21,7 +21,7 @@
|
||||
= 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')
|
||||
|
||||
@@ -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'
|
||||
@@ -1,7 +0,0 @@
|
||||
- content_for :title, "Editing product"
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Show', @product
|
||||
\|
|
||||
= link_to 'Back', products_path
|
||||
@@ -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
|
||||
@@ -1,5 +0,0 @@
|
||||
- content_for :title, "New product"
|
||||
|
||||
= render 'form'
|
||||
|
||||
= link_to 'Back', products_path
|
||||
@@ -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
|
||||
@@ -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'
|
||||
@@ -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.
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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: ""
|
||||
|
||||
@@ -63,17 +63,6 @@ Growstuff::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
|
||||
|
||||
@@ -91,16 +91,5 @@ Growstuff::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
|
||||
end
|
||||
|
||||
@@ -89,16 +89,5 @@ Growstuff::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
|
||||
|
||||
@@ -51,13 +51,6 @@ Growstuff::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)
|
||||
|
||||
15
config/initializers/assets.rb
Normal file
15
config/initializers/assets.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# Be sure to restart your server when you modify this file.
|
||||
|
||||
# Version of your assets, change this if you want to expire all your assets.
|
||||
Rails.application.config.assets.version = '1.0'
|
||||
|
||||
# Add additional assets to the asset load path.
|
||||
# Rails.application.config.assets.paths << Emoji.images_path
|
||||
# Add Yarn node_modules folder to the asset load path.
|
||||
Rails.application.config.assets.paths << Rails.root.join('node_modules')
|
||||
|
||||
# Precompile additional assets.
|
||||
# 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)
|
||||
@@ -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}.
|
||||
|
||||
@@ -27,7 +27,9 @@ Growstuff::Application.routes.draw do
|
||||
get '/plantings/owner/:owner' => 'plantings#index', as: 'plantings_by_owner'
|
||||
get '/plantings/crop/:crop' => 'plantings#index', as: 'plantings_by_crop'
|
||||
|
||||
resources :gardens
|
||||
resources :gardens do
|
||||
get 'timeline' => 'charts/gardens#timeline'
|
||||
end
|
||||
get '/gardens/owner/:owner' => 'gardens#index', as: 'gardens_by_owner'
|
||||
|
||||
resources :seeds
|
||||
@@ -50,6 +52,9 @@ Growstuff::Application.routes.draw do
|
||||
get 'crops/search' => 'crops#search', as: 'crops_search'
|
||||
resources :crops do
|
||||
get 'photos' => 'photos#index'
|
||||
get 'sunniness' => 'charts/crops#sunniness'
|
||||
get 'planted_from' => 'charts/crops#planted_from'
|
||||
get 'harvested_for' => 'charts/crops#harvested_for'
|
||||
end
|
||||
|
||||
resources :comments
|
||||
@@ -67,17 +72,6 @@ Growstuff::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"
|
||||
@@ -86,15 +80,11 @@ Growstuff::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'
|
||||
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'
|
||||
|
||||
20
db/migrate/20180118112809_add_datetaken_to_photos.rb
Normal file
20
db/migrate/20180118112809_add_datetaken_to_photos.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
class AddDatetakenToPhotos < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :photos, :date_taken, :datetime
|
||||
update_flickr_metadata
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :photos, :date_taken
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_flickr_metadata
|
||||
# Fetch from flickr, the photos updated the longest ago will be fetched first
|
||||
Photo.all.order(:updated_at).each do |photo|
|
||||
say "Fetch flickr data for #{photo}"
|
||||
photo.set_flickr_metadata!
|
||||
end
|
||||
end
|
||||
end
|
||||
9
db/migrate/20180205000612_remove_shop.rb
Normal file
9
db/migrate/20180205000612_remove_shop.rb
Normal file
@@ -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
|
||||
49
db/schema.rb
49
db/schema.rb
@@ -11,27 +11,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: 20180205000612) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
create_table "account_types", 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", 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", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.integer "crop_id", null: false
|
||||
@@ -359,25 +343,6 @@ ActiveRecord::Schema.define(version: 20171129041341) do
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "order_items", 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", 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"
|
||||
@@ -405,6 +370,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|
|
||||
@@ -460,17 +426,6 @@ ActiveRecord::Schema.define(version: 20171129041341) do
|
||||
add_index "posts", ["created_at", "author_id"], name: "index_posts_on_created_at_and_author_id", using: :btree
|
||||
add_index "posts", ["slug"], name: "index_posts_on_slug", unique: true, using: :btree
|
||||
|
||||
create_table "products", 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", force: :cascade do |t|
|
||||
t.string "name", null: false
|
||||
t.text "description"
|
||||
|
||||
52
db/seeds.rb
52
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..."
|
||||
|
||||
@@ -65,7 +48,7 @@ def load_test_users # rubocop:disable Metrics/AbcSize
|
||||
source_path = Rails.root.join('db', 'seeds')
|
||||
begin
|
||||
suburb_file = File.open("#{source_path}/suburbs.csv")
|
||||
rescue
|
||||
rescue StandardError
|
||||
puts "Warning: unable to open suburbs.csv"
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -95,77 +95,6 @@ namespace :growstuff do
|
||||
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
|
||||
|
||||
814
package-lock.json
generated
814
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user