Compare commits

...

325 Commits

Author SHA1 Message Date
Skud
d6b83454fe Merge pull request #732 from Growstuff/dev
Production push (release 8): request crops, search sci/alt names, garden photos, and more
2015-05-20 09:55:34 +10:00
Skud
d7ef598654 Merge pull request #726 from maco/approved_crops
Crop accept/reject notification improvements
2015-03-18 12:42:06 +11:00
Mackenzie Morgan
bd0da36d63 reverse the rejection_explanation logic to not use != 2015-03-17 21:23:54 -04:00
Mackenzie Morgan
6dedf1b030 add test for crop.rejection_explanation function 2015-03-16 23:07:17 -04:00
Mackenzie Morgan
920ca2948b add helper function for crop rejection explanation and use it on both notifier and status message 2015-03-09 00:50:34 -04:00
Mackenzie Morgan
9e53105f43 make language for crop accept/reject friendlier and if reason for rejection is 'other', give the rejection notes 2015-03-04 22:02:35 -05:00
Mackenzie
6505254e6c Merge pull request #724 from tygriffin/pending-rejected-sci-alt-names
Pending rejected sci alt names
2015-03-04 20:17:33 -05:00
Taylor Griffin
ead9a250af test that status message appears when rejected / pending 2015-02-27 07:56:30 +11:00
Taylor Griffin
3a9ec8cf6d include crop approval status in sci and alt names 2015-02-27 07:39:07 +11:00
pozorvlak
c76e9ccbf6 Merge pull request #722 from maco/approved_crops
remove pending/rejected crops from browse and test that, change links on...
2015-02-25 20:18:26 +00:00
Mackenzie Morgan
1b62c5cb97 remove pending/rejected crops from browse and test that, change links on wrangling page to go directly to crop edit and update tests for that 2015-02-25 00:05:56 -05:00
Mackenzie
7bca5c8845 Merge pull request #715 from Skud/requestcrops
Improvements to crop requests
2015-02-20 22:11:28 -05:00
Mackenzie
017df0484c Merge pull request #716 from oshiho3/PT80956846_crop_search
exclude unapproved crops from search
2015-02-20 22:04:53 -05:00
Shiho Takagi
d338bab82b travis to test both with and without elasticsearch 2015-02-18 16:18:24 +11:00
Shiho Takagi
35f8c126b6 using scope for searching only approved records 2015-02-18 15:38:28 +11:00
Shiho Takagi
eafe90e295 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-02-18 11:37:30 +11:00
Shiho Takagi
7b911034b8 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-02-18 11:37:11 +11:00
Shiho Takagi
798b89db11 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-02-18 11:36:21 +11:00
Shiho Takagi
506e3e550c update sql search to excludes unapproved crops 2015-02-18 11:26:14 +11:00
Shiho Takagi
8ab3167a28 update sql search to excludes unapproved crops 2015-02-18 11:15:15 +11:00
Shiho Takagi
436e7e3c59 Merge branch 'dev' of https://github.com/Growstuff/growstuff into PT80956846_crop_search 2015-02-18 10:33:48 +11:00
Skud
9f1091a1c8 Merge pull request #717 from maco/cms
change footer section names to generic footer1, footer2, footer3
2015-02-18 08:20:58 +11:00
Mackenzie Morgan
3b1e855da3 change footer section names to generic footer1, footer2, footer3 because we're going to CMS mode 2015-02-17 13:51:06 -05:00
Mackenzie
d7f8bff17a Merge pull request #714 from Skud/search_tweaks
Fixed various problems with searches
2015-02-17 09:15:25 -05:00
Shiho Takagi
a7caa2fbaa Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	spec/models/crop_spec.rb
2015-02-18 00:49:21 +11:00
Shiho Takagi
b215ef03c7 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	spec/models/crop_spec.rb
2015-02-18 00:47:46 +11:00
Shiho Takagi
3cbbbc79fb Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	spec/models/crop_spec.rb
2015-02-18 00:39:56 +11:00
Shiho Takagi
eb5e9e926b fixing Travis CI error 2015-02-18 00:37:58 +11:00
Shiho Takagi
ef2d1eb683 fixing Travis CI error 2015-02-18 00:17:53 +11:00
Shiho Takagi
965f87393d Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	spec/models/crop_spec.rb
2015-02-17 23:56:26 +11:00
Shiho Takagi
023333b15f exclude unapproved crops from search 2015-02-17 23:52:02 +11:00
Shiho Takagi
2241a760c2 exclude unapproved crops from search 2015-02-17 23:33:39 +11:00
Skud
e4dabd1725 Fix action links in sidebar - can't do stuff if not approved 2015-02-17 20:54:16 +11:00
Skud
1dfac3fb2f Improving crop request form 2015-02-17 20:44:24 +11:00
Skud
d0f856d389 Fixed various problems with search matching 2015-02-17 19:20:25 +11:00
Mackenzie
ac6aa730c1 Merge pull request #711 from maco/cms
move cms admin to /admin/cms at skud's request
2015-02-17 00:30:38 -05:00
Mackenzie Morgan
cd12412b46 move cms admin to /admin/cms at skud's request 2015-02-16 23:19:25 -05:00
Taylor Griffin
28288c51fe Merge pull request #707 from oshiho3/PT80956846_crop_search
fixing issue with 1)paginating crop search and 2)crop name autocomplete
2015-02-13 06:11:29 +11:00
Shiho Takagi
70cdab96c4 fixing issue with 1)paginating crop search and 2)crop name autocomplete 2015-02-12 23:00:04 +11:00
Taylor Griffin
e906d293a2 Merge pull request #702 from tygriffin/request-crop-links
Request crop links
2015-02-12 22:25:54 +11:00
Taylor Griffin
abdc43ef40 Merge pull request #705 from oshiho3/PT80956846_crop_search
Fixes and improvement
2015-02-12 22:25:08 +11:00
Shiho Takagi
3ed7edbfbf merge 2015-02-12 21:09:42 +11:00
Shiho Takagi
7e9f18e89e Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-02-12 16:42:55 +11:00
Shiho Takagi
e09f050088 updated the crop search query for more accurate search 2015-02-12 16:42:36 +11:00
Shiho Takagi
5bfab90b5b updated the crop search query for more accurate search 2015-02-12 16:31:57 +11:00
Taylor Griffin
3289e7b950 Merge branch 'dev' of https://github.com/Growstuff/growstuff into fix-request-new-crop 2015-02-10 22:12:40 +11:00
Taylor Griffin
102763f2ab link to new crop request form 2015-02-10 22:12:22 +11:00
Skud
09a78d4661 Merge pull request #701 from Skud/search_tweaks
Search tweaks
2015-02-10 20:57:32 +11:00
Skud
e0d8126514 Merge pull request #694 from maco/cms
Add comfortable mexican sofa CMS to growstuff & make footer use it
2015-02-10 20:53:50 +11:00
Skud
5cceb2c4ff Merge pull request #699 from tygriffin/fix-request-new-crop
Fix request new crop
2015-02-10 20:52:37 +11:00
Skud
66fcad69fa Paginate search results, make sexy subtitles 2015-02-10 20:48:36 +11:00
Taylor Griffin
2ab73d3df6 call site name from inside signature partial 2015-02-10 19:59:42 +11:00
Taylor Griffin
623dbdd418 fix search deleting crops 2015-02-10 19:58:43 +11:00
Skud
78c4fc36b1 Paginate search results
... and include total number in subtitle
2015-02-10 19:26:07 +11:00
Skud
9ccef5471f Added search form to crop search result page 2015-02-10 19:18:57 +11:00
Skud
0fc4c3cb4d Made search result page show a suitable title 2015-02-10 19:07:50 +11:00
Taylor Griffin
c61f7b8e72 pass locals into signature partial properly 2015-02-10 18:52:24 +11:00
Taylor Griffin
b81e034254 tweak permissions for alternate names just like sci names 2015-02-10 18:38:32 +11:00
Taylor Griffin
07f7572b13 extract email signature into partial 2015-02-10 18:33:54 +11:00
Taylor Griffin
2697fea249 tests back to green 2015-02-09 22:41:35 +11:00
Taylor Griffin
cbb4f9d7ac add rejection notes 2015-02-09 22:17:32 +11:00
Taylor Griffin
0dbc2e1964 prevent users from seeing sci names of crops unless approved 2015-02-09 21:52:52 +11:00
Taylor Griffin
319fc12ebb add crop must be approved validation 2015-02-09 21:13:25 +11:00
Taylor Griffin
2db7bf638b improve copy for new request email 2015-02-09 20:41:28 +11:00
Skud
497121a221 Merge pull request #695 from sksavant/member_sort
Functionality to sort members by recently joined : Issue #550
2015-02-09 17:53:11 +11:00
Savant Krishna
e17a3a2ab1 Addition to Contributors list 2015-02-09 17:47:31 +11:00
Savant Krishna
49a5a26f17 Functionality to sort members by recently joined : Issue #550 2015-02-09 17:47:25 +11:00
Mackenzie Morgan
b66b8263c1 resolving schema merge 2015-02-09 00:06:18 -05:00
Mackenzie Morgan
c3429cc0f3 adding admin access test for cms, and changing the cms admin path, and adding a link for it to the admin page, and updating the navbar so i can actually target the sign-in link in the test. also removing sample fixture gencode from cms installation 2015-02-09 00:05:02 -05:00
Skud
f7a2ec2054 Merge pull request #676 from pozorvlak/seed_properties
New seed properties: days until maturity, organic, GMO, heirloom
2015-02-09 14:07:20 +11:00
Skud
95ecdad024 Merge pull request #650 from robertlandreaux/add-crop-wrangling-link
add wrangle crop button to browse crops page
2015-02-09 14:06:28 +11:00
Miles Gould
e6cbbb3e3d Use fieldset instead of abusing .input-group.
As discussed in
https://github.com/Growstuff/growstuff/pull/676#issuecomment-73072087
and following comments by @maco and @Skud.
2015-02-07 13:23:31 +00:00
robertlandreaux
b78ccaa097 fix crop_wrangling_button_spec.rb 2015-02-06 21:57:47 -05:00
robertlandreaux
593d6e7ec1 Merge branch 'dev' of https://github.com/Growstuff/growstuff into add-crop-wrangling-link 2015-02-06 21:29:18 -05:00
Skud
4c6b96e590 Merge pull request #687 from tygriffin/crop-request
Crop request
2015-02-06 13:55:08 +11:00
Taylor Griffin
8631c78f9a Merge branch 'dev' of https://github.com/Growstuff/growstuff into crop-request 2015-02-06 07:36:52 +11:00
Taylor Griffin
a69ad34359 add link to search crops 2015-02-06 07:36:43 +11:00
Taylor Griffin
1099e4c9fe update copy for new / edit crop form 2015-02-06 07:34:01 +11:00
Skud
3a53f4f8a8 Merge pull request #686 from yoongkang/mydev
Allow the planting reminder spec to test links in emails properly
2015-02-05 13:53:17 +11:00
Taylor Griffin
076a6cc1df catch up with upstream dev 2015-02-04 21:41:42 +11:00
Taylor Griffin
b842bff9cb wip: fix misc tests 2015-02-04 18:36:14 +11:00
Taylor Griffin
80a28085f1 make pending crops unviewable to regular members 2015-02-04 14:44:12 +11:00
Taylor Griffin
0dd8cbccf0 refactor default scope on crop 2015-02-04 14:21:35 +11:00
Taylor Griffin
abece6473b make rejected and pending crops viewable on wrangle crops page 2015-02-04 14:18:10 +11:00
Taylor Griffin
ff1b941690 validate that a crop hasn't already been rejected or approved 2015-02-04 06:56:51 +11:00
Skud
85a6eb6195 Merge pull request #693 from maco/standard_weights
make the one-off save the si weight
2015-02-03 20:10:37 +11:00
Mackenzie Morgan
87bfceb035 make the one-off save the si weight 2015-02-02 23:49:07 -05:00
Mackenzie Morgan
b95975d632 swap footer over to CMS snippets and set CMS to use Devise for auth 2015-02-02 23:47:53 -05:00
Mackenzie Morgan
075cdb8272 Merge branch 'dev' of github.com:growstuff/growstuff into cms 2015-02-02 23:11:51 -05:00
Taylor Griffin
7db4dee61a add alert on crop show when rejected 2015-02-03 13:30:21 +11:00
Taylor Griffin
0993917dc6 define approval status options in model 2015-02-03 13:28:44 +11:00
Taylor Griffin
d6cb20e2c4 make reasons for rejection a select input 2015-02-03 13:27:41 +11:00
Taylor Griffin
3e65656c7b add meta data to crop pending alert 2015-02-03 13:25:14 +11:00
Taylor Griffin
47dc94f820 reason_for_rejection is required if marked as rejected 2015-02-03 13:18:59 +11:00
Miles Gould
c1870d46a2 Merge branch 'dev' into seed_properties
Conflicts:
	db/schema.rb
2015-02-02 17:45:49 +00:00
pozorvlak
1988c22626 Merge pull request #692 from Skud/elasticsearch-test-failures
Fixed test failure if elasticsearch isn't present in test env
2015-02-02 17:00:53 +00:00
Yoong Kang Lim
a795d452c6 Remove redundant have_content expectations 2015-02-02 21:15:46 +11:00
Shiho Takagi
656b0e44d8 fixing issue with elasticsearch option false in dev 2015-02-02 18:40:24 +11:00
Skud
af39df5e0c Fixed test failure if elasticsearch isn't present in test env 2015-02-02 18:20:16 +11:00
Mackenzie Morgan
1f23e1a646 merge from upstream 2015-02-01 22:08:28 -05:00
Skud
ca47127197 Merge pull request #684 from maco/standard_weights
Standard weights for harvests
2015-02-02 14:06:39 +11:00
Mackenzie Morgan
7ca89908cd merge from upstream 2015-02-01 22:00:52 -05:00
Mackenzie Morgan
2c94f61843 use %0.3f instead of %0.2f so we get to gram-granularity, and don't duplicate code 2015-02-01 21:59:33 -05:00
Mackenzie Morgan
7326acba81 add cms routes 2015-02-01 21:56:06 -05:00
Skud
77b4b76f14 Merge pull request #648 from oshiho3/PT80956846_crop_search
PT80956846 crop search

Fixes #649 as well.

Notes for deployment:

Edit config/application.yml to include GROWSTUFF_ELASTICSEARCH: "true" for dev and prod

Run:

    figaro heroku:set -e staging --app growstuff-staging
    heroku addons:add bonsai --app growstuff-staging

(or prod as appropriate)
Note: if you get a heap of figaro errors, you probably need to quote the value strings in your application.yml (especially numeric ones).

Now I'm ready to actually merge.  The indexing will happen as part of deploy-tasks.sh.
2015-02-02 11:14:16 +11:00
Miles Gould
eca27d18ea Reword "days until maturity" on seed form. 2015-02-01 18:14:25 +00:00
Taylor Griffin
2f67ffd2f8 fix regressions 2015-02-02 00:01:49 +11:00
Taylor Griffin
40d13fadb3 write feature spec for requesting a crop 2015-02-01 23:29:31 +11:00
Taylor Griffin
3791f4aa6f validate wikipedia url only if crop is approved 2015-02-01 22:43:48 +11:00
Yoong Kang Lim
79c60dc7c7 Allow the planting reminder spec to test links in emails properly 2015-02-01 22:26:44 +11:00
Miles Gould
5035b65883 Fix stupid call-nonexistent-method bug in tests. 2015-02-01 10:11:55 +00:00
Taylor Griffin
4211ebec76 add request notes to crop request 2015-02-01 17:56:51 +11:00
Taylor Griffin
d02edc3dd1 don't show sci name fields to regular users in crop form 2015-02-01 17:42:21 +11:00
Taylor Griffin
e86200b942 requester receives a message when crop request is rejected 2015-02-01 17:32:49 +11:00
Taylor Griffin
776b5450f9 requester receives email when crop request is approved 2015-02-01 17:20:48 +11:00
Taylor Griffin
c80b42d9bc change from approved boolean to approval_status string 2015-02-01 16:52:31 +11:00
Mackenzie Morgan
6aa37e6e26 adding CMS via comfortable mexican sofa gem 2015-02-01 00:27:04 -05:00
Miles Gould
089a3d5c24 Merge branch 'dev' into seed_properties
Conflicts:
	db/schema.rb
2015-02-01 00:03:10 +00:00
Miles Gould
1741567e19 Add tests for display of date ranges.
They fail for me with the error

undefined method `days_until_harvest_min=' for #<Seed:0x0000000b8dfcd8>
2015-01-31 23:59:27 +00:00
Mackenzie Morgan
de5b16e384 back to kg for si weight, also now adding si_weight to the csv correctly 2015-01-31 18:35:29 -05:00
Taylor Griffin
a8c203aea0 send emails to all crop wranglers when a new crop is requested 2015-02-01 09:32:50 +11:00
Shiho Takagi
2aa30475e9 merge 2015-02-01 00:14:52 +11:00
Shiho Takagi
9a5e15b292 index when sci name or alt name is updated 2015-01-31 23:59:46 +11:00
Mackenzie Morgan
bb9695b272 add check for nil to set_si_weights and the corresponding deploy script and update test 2015-01-31 00:45:31 -05:00
Mackenzie Morgan
d436fd86f8 use ruby-units to handle conversion. note: the deploy task isn't working and i don't know why 2015-01-31 00:22:35 -05:00
Mackenzie Morgan
3f393b0937 moving si_weight population to one-off 2015-01-30 23:17:42 -05:00
Mackenzie Morgan
fb271633d9 Merge branch 'dev' of github.com:growstuff/growstuff into standard_weights 2015-01-30 22:48:50 -05:00
Taylor Griffin
e40fad76fd exclude pending approval crops from default crops scope 2015-01-31 10:39:17 +11:00
Taylor Griffin
41db12d8d7 pending approval crops appear on crops wrangle page 2015-01-31 10:36:02 +11:00
Taylor Griffin
28d29291a7 any member can create a crop at least provisionally 2015-01-31 10:03:44 +11:00
Taylor Griffin
22e0379769 give crops a requester 2015-01-31 09:54:59 +11:00
pozorvlak
b60bbbcb4e Merge pull request #682 from maco/dev
fixing harvest csv so it doesn't error
2015-01-30 15:54:58 +00:00
Mackenzie Morgan
0da121a48d adding test for harvest csv 2015-01-29 22:27:09 -05:00
Skud
6b6ffd6e58 Merge pull request #653 from rocky-jaiswal/issues/625_add_context_for_logged_out_users
Show friendly message to unregistered users who view posts.
2015-01-30 12:37:48 +11:00
Rocky Jaiswal
21dbf87ab9 Merge branch 'issues/625_add_context_for_logged_out_users' of github.com:rocky-jaiswal/growstuff into issues/625_add_context_for_logged_out_users 2015-01-29 12:03:40 +01:00
Rocky Jaiswal
a5fcd9f860 Merge branch 'dev' of github.com:Growstuff/growstuff into issues/625_add_context_for_logged_out_users 2015-01-29 12:03:27 +01:00
Rocky Jaiswal
2853bf5c70 Merge pull request #1 from Skud/rocky-jaiswal-issues/625_add_context_for_logged_out_users
Rocky jaiswal issues/625 add context for logged out users
2015-01-29 12:02:19 +01:00
Mackenzie Morgan
2d55d88db8 fixing harvest csv so it doesn't error 2015-01-29 00:49:23 -05:00
Mackenzie Morgan
2567e7cd74 adding tests (not passing, need to figure out saving mid-test), fixing before_save, adding CSV column, and adding task to set the si_weight throughout the db 2015-01-29 00:27:53 -05:00
Mackenzie Morgan
e2bac619b7 Merge branch 'dev' of github.com:growstuff/growstuff into standard_weights 2015-01-28 23:10:10 -05:00
Mackenzie Morgan
0bdab0d9fc basics of harvest standardized weights 2015-01-28 23:00:16 -05:00
Skud
e55fe55dc7 Merge pull request #680 from maco/garden_photos
Garden photos
2015-01-29 09:48:39 +11:00
Mackenzie Morgan
5a474d523c merge from upstream 2015-01-27 22:35:19 -05:00
Mackenzie Morgan
d126392ee2 display garden photos on member page garden tabs too 2015-01-27 00:58:44 -05:00
Mackenzie Morgan
c38dc4661d basics of garden photos 2015-01-27 00:54:05 -05:00
Mackenzie Morgan
675ac5a03f add before_save for harvest weight and index for harvest photos 2015-01-26 22:26:21 -05:00
Miles Gould
233f9dfd88 Split "days until maturity" into min and max fields. 2015-01-26 19:20:33 +00:00
Shiho Takagi
b414598b07 adding comments for search options 2015-01-26 22:50:47 +11:00
Shiho Takagi
2c4e768a3a fixing wrong file name 2015-01-26 22:30:19 +11:00
Shiho Takagi
04d61bd040 deployment sript 2015-01-25 16:18:26 +11:00
Shiho Takagi
5a96b7efd6 adding a rake task to generate elasticsearch index 2015-01-25 15:47:40 +11:00
Miles Gould
329e147add Show new seed props in detail page 2015-01-24 12:34:14 +00:00
Miles Gould
334b5bf63f Test new seed properties on detail page 2015-01-24 12:34:09 +00:00
Miles Gould
58940a6765 Add new seed properties to feature. 2015-01-24 12:13:57 +00:00
Miles Gould
2442539e1b Allow feature tests and unicorn to run at the same time 2015-01-24 12:08:02 +00:00
Miles Gould
b56237115e Add form and controller for new seed properties 2015-01-24 12:01:11 +00:00
Miles Gould
038192095d Validate all numeric fields as being >= 0. 2015-01-24 11:54:17 +00:00
Miles Gould
9a18b4b62b Add new properties to seeds
Added days_until_maturity, gmo, organic and heirloom properties; added
validation and tests for the last three.
2015-01-24 11:31:35 +00:00
Skud
c6f5abc036 Made info alerts be green like Growstuff is green 2015-01-24 21:07:41 +11:00
Skud
ad76a04e8f Fixed misnamed feature test 2015-01-24 21:07:27 +11:00
Skud
0b70be4939 Merge branch 'issues/625_add_context_for_logged_out_users' of https://github.com/rocky-jaiswal/growstuff into rocky-jaiswal-issues/625_add_context_for_logged_out_users 2015-01-24 20:45:14 +11:00
pozorvlak
da2590791e Merge pull request #665 from pozorvlak/500_on_follow
Fix the 500 server error when you try to follow another user
2015-01-23 23:45:03 +00:00
Miles Gould
79a7958519 Don't try to load a Follow before it's been created. 2015-01-23 11:39:20 +00:00
Miles Gould
f4d452f3bc Turn on PhantomJS for Follows features. 2015-01-23 11:39:20 +00:00
Miles Gould
d08e2f09db Add feature test for 500-on-follow error
This doesn't actually catch the problem; I'm committing it so other
people can see it and suggest ways of making it stronger.
2015-01-23 11:39:20 +00:00
pozorvlak
d5cc3f300a Merge pull request #664 from pozorvlak/travis_containers
Deployment from Travis containers
2015-01-23 11:00:11 +00:00
Skud
1982cecc31 Merge pull request #673 from tygriffin/sci-names-permitted-params
Sci names permitted params
2015-01-23 13:40:47 +11:00
Taylor Griffin
2f05f1dbdb raise exceptions on unpermitted params in staging 2015-01-23 13:22:52 +11:00
Taylor Griffin
a67a55c599 add scientific name to crops create feature spec 2015-01-23 13:21:47 +11:00
Taylor Griffin
253b5a3f85 define permitted param for nested attribute 2015-01-23 13:20:37 +11:00
Taylor Griffin
45aaf31722 Merge branch 'dev' of https://github.com/Growstuff/growstuff into sci-names-permitted-params 2015-01-23 13:19:33 +11:00
Taylor Griffin
d0b9917e84 Merge pull request #671 from Growstuff/revert-669-sci-names-permitted-params
Revert "Sci names permitted params"
2015-01-23 13:14:42 +11:00
Taylor Griffin
32dcacf9ba copy schema from last known correct version 2015-01-23 13:14:13 +11:00
Taylor Griffin
0e0c309c15 Revert "Sci names permitted params" 2015-01-23 11:42:42 +11:00
pozorvlak
dabfeeea3c Merge pull request #669 from tygriffin/sci-names-permitted-params
Sci names permitted params
2015-01-22 23:46:27 +00:00
Taylor Griffin
20b9996f14 raise exceptions on unpermitted parameters in staging 2015-01-23 10:15:06 +11:00
Taylor Griffin
1ea5257da4 include sci names in create crop feature spec 2015-01-23 09:56:23 +11:00
Taylor Griffin
3c360ab1b8 specify permitted params for nested attributes 2015-01-23 09:22:13 +11:00
pozorvlak
b1c60572ef Merge pull request #668 from cesy/moretests
More tests
2015-01-22 22:01:23 +00:00
Cesy Avon
14ad572f18 Adding test for products 2015-01-22 16:21:10 +00:00
pozorvlak
1481d01cf8 Merge pull request #667 from cesy/moretests
More tests
2015-01-22 15:42:11 +00:00
Cesy Avon
492781ea3d The test that's currently failing on some branches 2015-01-22 14:40:11 +00:00
Cesy Avon
542d978d9c Adding extra tests for crop wrangling 2015-01-22 14:24:03 +00:00
Cesy Avon
c893dcd271 Moving file to sensible location for crop wrangling test 2015-01-22 14:19:47 +00:00
Miles Gould
57552455e3 Get Heroku app from .travis.yml 2015-01-21 09:13:07 +00:00
Skud
fe69e2f11d Merge pull request #663 from rocky-jaiswal/minor/less_verbose_dev_logging
Add quiet_assets to reduce noise in dev environment.
2015-01-21 18:36:33 +11:00
Shiho Takagi
684a3d2229 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-21 16:50:45 +11:00
Shiho Takagi
3d738e1b7c Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-21 16:50:21 +11:00
Shiho Takagi
a5daa156ab Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-21 16:48:59 +11:00
Shiho Takagi
018b2b4711 elasticsearch to be turned off as a default in dev and test 2015-01-21 16:47:22 +11:00
Shiho Takagi
d12ec968c4 elasticsearch to be turned off as a default in dev and test 2015-01-21 16:44:59 +11:00
Miles Gould
531a0bd9ea Roll our own heroku maintenance:(on|off) script
This allows us to use maintenance mode without installing the full
Heroku toolbelt, which we can't do on the (much faster!) container-based
infrastructure.

We add a (temporary) deployment to my sandbox from the travis_containers
branch: muckingabout with one branch for both container-based and
VM-based approaches was starting to get confusing.
2015-01-21 00:36:47 +00:00
Rocky Jaiswal
7950c577e9 Add quiet_assets to reduce noise in dev environment. 2015-01-20 19:45:29 +01:00
Rocky Jaiswal
3bc77f9b09 Merge branch 'dev' of github.com:Growstuff/growstuff into issues/625_add_context_for_logged_out_users 2015-01-20 19:15:23 +01:00
Rocky Jaiswal
05260c05c2 incorporating feedback comments for showing message for logged out users. 2015-01-20 19:14:50 +01:00
Rocky Jaiswal
d0ea54237e increase font-weight for urls in alerts. 2015-01-20 19:14:04 +01:00
Robert Landreaux
f404d54d02 update crop_wrangling_button_spec.rb 2015-01-20 12:08:58 -05:00
Miles Gould
5a2d9eabf4 Turn on Bundler caching on Travis 2015-01-20 09:16:00 +00:00
Miles Gould
1b936100e7 Trying out container-based Travis. 2015-01-20 08:47:06 +00:00
Miles Gould
34ea6eb37f Turning on maintenance mode for deploys, attempt 3 2015-01-20 08:20:44 +00:00
Miles Gould
2c006ec430 Remove stray "app: tranquil-basin" 2015-01-20 08:17:41 +00:00
Shiho Takagi
f541261e43 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-20 13:20:56 +11:00
Shiho Takagi
f910fdfa73 use elasticsearch for auto-suggest 2015-01-20 13:20:13 +11:00
Miles Gould
72f86c4ad0 Don't auto-deploy to production.
We need this to be stable and tested on staging (including environment
variables and maintenance mode) before we turn it on for production.
2015-01-19 23:59:27 +00:00
pozorvlak
0cb192ce36 Merge pull request #647 from Skud/followability
Tidied up authorization around follows
2015-01-19 23:46:55 +00:00
Miles Gould
3aadc5d68f Deploy to different apps based on branch 2015-01-19 23:05:15 +00:00
Miles Gould
1387f381d2 Run migrations and scripts on successful build. 2015-01-19 21:52:38 +00:00
pozorvlak
7257f2e557 Merge pull request #655 from cesy/issue640mincontainer
Issue #640 mincontainer
2015-01-19 21:29:46 +00:00
Miles Gould
025bfdb4b0 Test deployment with Travis. 2015-01-19 21:22:07 +00:00
Robert Landreaux
1a50566328 modify test, still needs work 2015-01-19 11:14:36 -05:00
Cesy Avon
ae914daa0c Whitespace and commenting 2015-01-19 13:56:06 +00:00
Cesy Avon
b984475335 Changing percentage so it doesn't get too tall 2015-01-19 13:54:13 +00:00
Cesy Avon
59f5101858 Issue 640 corrected code 2015-01-19 13:50:32 +00:00
Cesy Avon
e7d3e4d6dd Issue 640 container min-height setting up id 2015-01-19 13:25:16 +00:00
Shiho Takagi
79e1835216 use elasticsearch for auto-suggest 2015-01-19 15:45:59 +11:00
Robert Landreaux
e4072fb395 write 'crop_wrangling_button_spec.rb', fix previous issue 2015-01-18 23:25:38 -05:00
Shiho Takagi
666d6dac48 adding elasticsearch service to Travis 2015-01-19 15:24:11 +11:00
Skud
ea5b340933 Merge pull request #654 from Growstuff/dev
Hotfix: fix CSS for homepage and browse crops
2015-01-19 10:25:48 +11:00
Rocky Jaiswal
534c299383 Show friendly message to unregistered users who view posts.
https://github.com/Growstuff/growstuff/issues/625
2015-01-18 20:28:00 +01:00
Shiho Takagi
99eb33ccbb clearning up the code 2015-01-18 12:23:54 +11:00
Robert Landreaux
760e5ca74e remove failing line and add '- if can? :wrangle, Crop' 2015-01-17 12:21:01 -05:00
Shiho Takagi
cd57c9cd34 updated test so elasticsearch index is deleted before every test 2015-01-18 00:24:51 +11:00
Shiho Takagi
2a184bcb2e updated test spec for improved elasticsearch syncing method 2015-01-18 00:20:50 +11:00
Taylor Griffin
df63819602 Merge pull request #652 from Skud/cropcss
Fixed CSS errors with text wrapping
2015-01-17 23:15:31 +11:00
Skud
628d5b24c1 Fixed CSS errors with text wrapping 2015-01-17 21:27:08 +11:00
Shiho Takagi
8221d5b441 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-17 19:16:04 +11:00
Shiho Takagi
ad7cfdabd0 cleaning up the code 2015-01-17 19:11:07 +11:00
Shiho Takagi
4237dfb269 cleaning up the code 2015-01-17 18:28:45 +11:00
Robert Landreaux
c512b079fa add wrangle crop button to browse crops page 2015-01-17 00:20:11 -05:00
Shiho Takagi
b4cd151a03 merge from upstream 2015-01-17 14:09:45 +11:00
pozorvlak
eab958eac4 Merge pull request #646 from Skud/imgrounded
got rid of all img-rounded classes
2015-01-16 15:34:10 +00:00
Skud
17e94e01d0 Tidied up authorization around follows 2015-01-17 00:57:05 +11:00
Shiho Takagi
6451077d1d Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-17 00:40:02 +11:00
Shiho Takagi
ce265e281a cleaning up the code 2015-01-17 00:37:37 +11:00
Shiho Takagi
f4511c79e6 cleaning up the code 2015-01-17 00:35:57 +11:00
Shiho Takagi
06c7703628 auto-suggest to use existing search 2015-01-17 00:31:01 +11:00
Shiho Takagi
619e8590c8 updated test spec for view change 2015-01-17 00:29:11 +11:00
Shiho Takagi
88efcf4da6 updated test spec for view change 2015-01-17 00:25:34 +11:00
Shiho Takagi
556ba33172 updated crop search view 2015-01-17 00:09:39 +11:00
Skud
9d7b939d42 got rid of all img-rounded classes 2015-01-16 23:24:54 +11:00
Shiho Takagi
0bea278c5c Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-16 23:10:28 +11:00
Shiho Takagi
65814f1ef6 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-16 23:10:08 +11:00
Skud
1a7fc57f66 Merge pull request #643 from Growstuff/dev
Production push: release 7
2015-01-16 22:24:08 +11:00
Shiho Takagi
db0eb3e4da Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-16 22:20:36 +11:00
Skud
175996ce90 Merge pull request #637 from pozorvlak/update_contributors
Update CONTRIBUTORS.md with the current committers
2015-01-16 22:09:42 +11:00
Shiho Takagi
323f635b7b Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-16 22:03:01 +11:00
pozorvlak
f70f82014f Merge pull request #642 from Skud/release7_tweaks
Release7 tweaks
2015-01-16 11:02:31 +00:00
Skud
8756808444 Show members on homepage 3-across (not 2-across) 2015-01-16 21:47:24 +11:00
Skud
bb6e798bce Fix stylesheets for various thumbnail displays 2015-01-16 21:46:44 +11:00
Skud
a5c226d128 Tweaked homepage crop display to match resized columns
- made columns 8/4 rather than 6/6
- show 8 interesting crops, not 12
- show 6 recent plantings, not 4
- use crop thumbnail with visible name/info/etc, rather than popup
version
- tweaked aforementioned thumbnail to have no border, and centre-align
the text
2015-01-16 21:37:15 +11:00
Shiho Takagi
729dba8e0b Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-16 10:30:15 +11:00
Shiho Takagi
85c3e74cdd Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-16 10:29:39 +11:00
Miles Gould
c7bcbf6323 Update CONTRIBUTORS.md with the current committers 2015-01-15 14:49:12 +00:00
pozorvlak
f3302a9e30 Merge pull request #636 from rocky-jaiswal/upgrade/update_rails_4_1_9
Upgrade/update rails 4 1 9
2015-01-15 14:42:31 +00:00
Rocky Jaiswal
1e331fc19d adding rocky jaiswal in contributors. 2015-01-15 15:25:42 +01:00
Rocky Jaiswal
31a7011260 update to latest patch on rails 4.1 2015-01-15 15:25:21 +01:00
pozorvlak
181c36cdc9 Merge pull request #635 from tygriffin/fix-cache-key
Fix cache key
2015-01-15 11:37:24 +00:00
Taylor Griffin
36ac0b75e7 decoy commit to test if travis / phantomjs error was spurious 2015-01-15 22:23:27 +11:00
Shiho Takagi
f9cec41360 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-15 21:44:57 +11:00
Shiho Takagi
19dcf6f3d5 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-15 21:44:04 +11:00
Taylor Griffin
d5aef16860 add comment 2015-01-15 21:35:10 +11:00
Shiho Takagi
1d28c30680 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search 2015-01-15 21:33:22 +11:00
Shiho Takagi
9a3c4e69e8 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	app/models/crop.rb
2015-01-15 21:32:46 +11:00
Taylor Griffin
55ba535353 pass in additional parameters to make a more uniquely identifying cache key 2015-01-15 21:21:40 +11:00
Shiho Takagi
56025d3d33 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	app/models/crop.rb
2015-01-15 19:34:25 +11:00
Shiho Takagi
59cae7a8ce Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	app/models/crop.rb
2015-01-15 19:33:27 +11:00
Shiho Takagi
9a9f859b70 Merge branch 'PT80956846_crop_search' of https://github.com/oshiho3/growstuff into PT80956846_crop_search
Conflicts:
	app/models/crop.rb
2015-01-15 19:31:14 +11:00
Shiho Takagi
ba3a1f6298 Integrate Elasticsearch and implement crop search against scientific_name 2015-01-15 19:28:28 +11:00
Shiho Takagi
10e6e7c3cb Integrate Elasticsearch and implement crop search against scientific_name 2015-01-15 19:05:02 +11:00
Taylor Griffin
a510489570 Merge pull request #631 from Skud/newfooter
New footer
2015-01-14 22:45:41 +11:00
Taylor Griffin
fcbc6002d1 Merge pull request #623 from pozorvlak/seo_crop_detail_page
Add SEO-friendly language to the crop detail page
2015-01-14 22:40:25 +11:00
Skud
eeb48e2ad6 Removed sidebar from homepage.
Also removed extraneous view tests for things we no longer have.
2015-01-13 20:13:33 +11:00
Skud
b114ed2414 Improved sitewide footer (fixes #526) 2015-01-13 20:07:59 +11:00
Skud
1064f39020 Merge pull request #626 from pozorvlak/authentications_page_die_die_die
Remove authentications page and extraneous routes
2015-01-13 10:39:06 +11:00
Skud
b5a460a1b7 Merge pull request #624 from pozorvlak/inflections
Add inflections for irregular plural crop names
2015-01-13 10:38:58 +11:00
pozorvlak
9a961b80e5 Merge pull request #627 from tygriffin/seed-by-env
don't load test and admin users in staging
2015-01-12 13:55:37 +00:00
Taylor Griffin
7bc05fa118 typo 2015-01-12 22:16:42 +11:00
Taylor Griffin
f7af7e649d update comment to reflect code changes 2015-01-12 20:13:00 +11:00
Taylor Griffin
4efb93ea45 don't load test and admin users in staging 2015-01-12 07:48:48 +11:00
Miles Gould
a5edb6497c Display lack-of-posts nicely on crop page. 2015-01-11 12:08:57 +00:00
Miles Gould
d6314ea9a1 SEO: add crop name everywhere 2015-01-11 12:08:57 +00:00
Miles Gould
c244ca672f Add tests for SEO of crop detail page 2015-01-11 12:08:57 +00:00
Miles Gould
401777cc4c Add some irregular plurals. 2015-01-11 12:02:02 +00:00
Miles Gould
7ef8afb1ba Tests for crop inflections 2015-01-11 12:02:02 +00:00
Miles Gould
e25bb5578a Remove extraneous authentication routes. 2015-01-11 11:57:13 +00:00
Miles Gould
401f3e176e Remove the authentications index page 2015-01-11 11:57:13 +00:00
Taylor Griffin
10ae117914 Merge pull request #451 from tygriffin/rails4-upgrade
Rails4 upgrade
2015-01-11 21:12:44 +11:00
Taylor Griffin
86cea2ad9f add current_password to permitted params 2015-01-11 14:55:12 +11:00
Taylor Griffin
ccef46a5cf add more permitted parameters to member update 2015-01-11 14:32:19 +11:00
Taylor Griffin
c803da3dfa fix planted_at on planting create bug 2015-01-11 14:00:51 +11:00
Taylor Griffin
02ff45f705 broaden seeding for staging env 2015-01-11 09:41:04 +11:00
Taylor Griffin
8a05a959c3 remove depricated method 2015-01-10 15:46:36 +11:00
Taylor Griffin
e5d407b1ce replace depricated method 2015-01-10 15:35:54 +11:00
Taylor Griffin
5cd53be5be change post route to get per omniauth docs 2015-01-10 14:59:04 +11:00
Taylor Griffin
c6cc8ee6bb configure devise account update for strong parameters 2014-12-31 18:32:37 +11:00
Taylor Griffin
eaf4ea04ac Merge branch 'dev' of https://github.com/Growstuff/growstuff into rails4-upgrade 2014-12-20 20:45:13 +11:00
Taylor Griffin
007f7112a7 replaced caching using observers with a key-based (and simplified) caching system 2014-12-19 21:17:43 +11:00
Taylor Griffin
f62fd8484a get rid of annoying warning about doubly loaded files when running tests 2014-12-15 21:13:22 +11:00
Taylor Griffin
849bdac81b include module that holds expire_fragment method 2014-12-15 21:02:44 +11:00
Taylor Griffin
c1d2f2c9cc resolve conflicts 2014-12-15 07:17:11 +11:00
Taylor Griffin
d92d22d99c include ActionController::Caching in Sweeper class 2014-12-14 21:03:10 +11:00
Taylor Griffin
8829acba3f removed depricated method 2014-12-14 15:54:43 +11:00
Taylor Griffin
66c4a19ad6 revert to previous smtp settings 2014-12-14 15:41:29 +11:00
Taylor Griffin
a65b78084f change staging smtp settings 2014-12-14 15:36:56 +11:00
Taylor Griffin
cdaa9c03a2 Merge branch 'rails4-upgrade' 2014-12-14 14:51:36 +11:00
Taylor Griffin
a35a573b2b update follow member code to be rails 4 compatible 2014-12-14 14:51:18 +11:00
Taylor Griffin
314cdc687a precompiled assets 2014-12-12 22:00:30 +11:00
Taylor Griffin
df3b300967 remove '/assets' from references to assets 2014-12-12 21:31:22 +11:00
Taylor Griffin
d174f25d03 order messages to be most recent 2014-11-30 16:06:06 +11:00
Taylor Griffin
cf7ead3d84 Merge branch 'dev' of https://github.com/Growstuff/growstuff into rails4-upgrade 2014-11-30 14:36:10 +11:00
Taylor Griffin
18c40809a6 Merge branch 'dev' of https://github.com/Growstuff/growstuff into rails4-upgrade 2014-11-29 22:20:58 +11:00
Taylor Griffin
c83b01bbb7 catch up with dev 2014-11-18 22:59:43 +11:00
Taylor Griffin
fb595de457 edited configuration and dependencies 2014-11-18 22:24:58 +11:00
Taylor Griffin
acbd3f9a9e implement strong parameters instead of protected attributes 2014-11-18 20:08:54 +11:00
Taylor Griffin
98c1680138 handle misc deprications 2014-11-17 07:16:02 +11:00
Taylor Griffin
0ffe9adc86 tests are green 2014-11-16 21:40:43 +11:00
Taylor Griffin
56b4f8a221 mimick old FriendlyId behavior when calling find on a model - therefore, Model.find not Model.friendly.find (this probably needs review) 2014-11-16 20:21:34 +11:00
Taylor Griffin
f1945151c7 update RSpec true / false matchers 2014-11-16 14:40:50 +11:00
Taylor Griffin
cc31e864d5 update webrat and webrat matchers 2014-11-16 14:31:33 +11:00
Taylor Griffin
868e5c2079 upgrade jquery-ui-rails gem and config 2014-11-16 12:41:57 +11:00
Taylor Griffin
70185156aa use lambda instead of just relation in names scope 2014-11-16 12:11:56 +11:00
Taylor Griffin
7fc886f43c implement custom Sweeper class as stop gap against errors when running specs 2014-11-16 12:01:27 +11:00
Taylor Griffin
8e79199766 wip: upgrading rspec 2014-11-15 22:55:37 +11:00
Taylor Griffin
40a88b5b09 tests run but fail like whoa 2014-11-15 21:44:55 +11:00
Taylor Griffin
c6f56a23d6 Adds binstubs for rails and rake 2014-11-13 07:26:10 +11:00
394 changed files with 3839 additions and 1944 deletions

1
.rspec
View File

@@ -1 +1,2 @@
--color
--require spec_helper

View File

@@ -1,12 +1,38 @@
---
sudo: false
language: ruby
env: GROWSTUFF_SITE_NAME="Growstuff (travis)" RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
bundler_args: --without development production staging
cache: bundler
env:
matrix:
- GROWSTUFF_SITE_NAME="Growstuff (travis)" RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' GROWSTUFF_ELASTICSEARCH='true'
- GROWSTUFF_SITE_NAME="Growstuff (travis)" RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' GROWSTUFF_ELASTICSEARCH='false'
global:
secure: "Z5TpM2jEX4UCvNePnk/LwltQX48U2u9BRc+Iypr1x9QW2o228QJhPIOH39a8RMUrepGnkQIq9q3ZRUn98RfrJz1yThtlNFL3NmzdQ57gKgjGwfpa0e4Dwj/ZJqV2D84tDGjvdVYLP7zzaYZxQcwk/cgNpzKf/jq97HLNP7CYuf4="
bundler_args: "--without development production staging"
rvm:
- 2.1.5
- 2.1.5
before_script:
- psql -c 'create database growstuff_test;' -U postgres
- psql -c 'create database growstuff_test;' -U postgres
script:
- bundle exec rake db:migrate --trace
- bundle exec rspec spec/
- bundle exec rake db:migrate --trace
- bundle exec rspec spec/
services:
- elasticsearch
before_deploy:
- bundle exec script/heroku_maintenance.rb on
deploy:
provider: heroku
api_key:
secure: WrQxf0fEKkCdXrjcejurobOnNNz3he4dDwjBbToXbQTQNDObPp7NetJrLsfM8FiUFEeOuvhIHHiDQtMvY720zGGAGxDptvgFS+0QHCUqoTRZA/yFfUmHlG2jROXTzk5uVK0AE4k6Ion5kX8+mM0EnMT/7u+MTFiukrJctSiEXfg=
on:
repo: Growstuff/growstuff
app:
dev: growstuff-staging
travis_deploy: tranquil-basin-3130
travis_containers: tranquil-basin-3130
run:
- "rake db:migrate"
- "script/deploy-tasks.sh"
- restart
after_deploy:
- bundle exec script/heroku_maintenance.rb off

View File

@@ -11,10 +11,11 @@ submit the change with your pull request.
- Alex Bayley / [Skud](https://github.com/Skud)
- Cesy / [cesy](https://github.com/cesy)
- Miles Gould / [pozorvlak](https://github.com/pozorvlak)
- Joseph Caudle / [jcaudle](https://github.com/jcaudle)
- Taylor Griffin / [tygriffin](https://github.com/tygriffin)
## Contributors
- Joseph Caudle / [jcaudle](https://github.com/jcaudle)
- Ricky Amianym / [amianym](https://github.com/amianym)
- Juliet Kemp / [julietk](https://github.com/julietk)
- Federico Mena Quintero / [federicomenaquintero](https://github.com/federicomenaquintero)
@@ -40,7 +41,6 @@ submit the change with your pull request.
- Marty Hines / [martyhines](https://github.com/martyhines)
- Amelia Greenhall / [ameliagreenhall](https://github.com/ameliagreenhall)
- Barb Natali / [barbnatali](https://github.com/barbnatali)
- Taylor Griffin / [tygriffin](https://github.com/tygriffin)
- Marlena Compton / [Marlena](https://github.com/marlena)
- Elizabeth A. Kari / [catfriend](https://github.com/catfriend)
- Cheri Allen / [cherimarie](https://github.com/cherimarie)
@@ -51,4 +51,7 @@ submit the change with your pull request.
- Yoong Kang Lim / [yoongkang](https://github.com/yoongkang)
- Kevin Yang / [kevieyang](https://github.com/kevieyang)
- Justin Hamman / [juzham](https://github.com/juzham)
- Rocky Jaiswal / [rocky-jaiswal](https://github.com/rocky-jaiswal)
- Robert Landreaux / [robertlandreaux](https://github.com/robertlandreaux)
- Savant Krishna / [sksavant](https://github.com/sksavant)

165
Gemfile
View File

@@ -1,92 +1,55 @@
source 'https://rubygems.org'
ruby "2.1.5"
ruby '2.1.5'
gem 'rails', '4.1.9'
gem 'bundler', '>=1.1.5'
gem 'rails', '3.2.13'
gem 'rack', '~>1.4.5'
gem 'json', '~>1.7.7'
gem 'sass-rails', '~> 4.0.4'
gem 'coffee-rails', '~> 4.1.0'
gem 'haml'
# Another CSS preprocessor, used for Bootstrap overrides
gem 'less', '~>2.5.0'
gem 'less-rails', '~> 2.5.0'
# CSS framework
gem 'less-rails-bootstrap', '~> 3.2.0'
gem 'uglifier', '~> 2.5.3' # JavaScript compressor
gem 'jquery-rails'
gem 'jquery-ui-rails', '~> 5.0.2'
gem 'js-routes' # provides access to Rails routes in Javascript
gem 'flickraw'
gem 'leaflet-rails'
gem 'leaflet-markercluster-rails'
gem 'unicorn' # http server
gem 'unicorn' # http server
gem 'pg'
gem 'figaro' # for handling config via ENV variables
gem 'cancancan', '~> 1.9' # for checking member privileges
gem 'gibbon' # for Mailchimp newsletter subscriptions
gem 'csv_shaper' # CSV export
gem 'ruby-units' # for unit conversion
gem 'figaro' # for handling config via ENV variables
gem 'cancan' # for checking member privileges
gem 'gibbon' # for Mailchimp newsletter subscriptions
gem 'csv_shaper' # CSV export
gem 'comfortable_mexican_sofa', '~> 1.12.0' # content management system
# vendored activemerchant for testing- needed for bogus paypal
# gateway monkeypatch
gem 'activemerchant', '1.33.0',
:path => 'vendor/gems/activemerchant-1.33.0',
:path => 'vendor/gems/activemerchant-1.33.0',
:require => 'active_merchant'
gem 'active_utils', '1.0.5',
:path => 'vendor/gems/active_utils-1.0.5'
:path => 'vendor/gems/active_utils-1.0.5'
group :production, :staging do
gem 'newrelic_rpm'
gem 'dalli'
gem 'memcachier'
gem 'rails_12factor' # supresses heroku plugin injection
end
# Gems used only for assets and not required
# in production environments by default.
group :assets do
# CSS preprocessor, used for app/assets/stylesheets/application.css
gem 'sass-rails', '~> 3.2.3'
# CoffeeScript is a Python-like language that compiles to JavaScript
gem 'coffee-rails', '~> 3.2.1'
# less-rails depends on a JavaScript engine; we use therubyracer.
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# long term, we'll probably want node.js for performance, but this will do
# for now as it's easier for new people to install
gem "therubyracer", "~> 0.12", :platforms => :ruby
# libv8 is needed by therubyracer and is a bit finicky
gem 'libv8', '3.16.14.7'
# Another CSS preprocessor, used for Bootstrap overrides
gem "less", '~>2.5.0'
gem "less-rails", '~> 2.5.0'
# CSS framework
gem "less-rails-bootstrap", '~> 3.2.0'
gem 'uglifier', '>= 1.0.3' # JavaScript compressor
gem 'compass-rails', '~> 1.0.3' # Yet Another CSS framework
end
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'js-routes' # provides access to Rails routes in Javascript
gem 'flickraw'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
# To use Jbuilder templates for JSON
# gem 'jbuilder'
# Use unicorn as the app server
# gem 'unicorn'
group :development do
# A debugger and irb alternative. Pry doesn't play nice
# with unicorn, so start a Webrick server when debugging
# with Pry
gem 'pry'
gem 'better_errors'
gem 'binding_of_caller'
gem 'letter_opener'
end
# less-rails depends on a JavaScript engine; we use therubyracer.
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# long term, we'll probably want node.js for performance, but this will do
# for now as it's easier for new people to install
gem 'therubyracer', '~> 0.12', :platforms => :ruby
# libv8 is needed by therubyracer and is a bit finicky
gem 'libv8', '3.16.14.7'
# Markdown formatting for updates etc
gem 'bluecloth'
@@ -95,10 +58,10 @@ gem 'bluecloth'
gem 'will_paginate', '~> 3.0'
# user signup/login/etc
gem 'devise', '~> 3.2.0'
gem 'devise', '~> 3.4.1'
# nicely formatted URLs
gem 'friendly_id', '~> 4.0.10'
gem 'friendly_id', '~> 5.0.4'
# gravatars
gem 'gravatar-ultimate'
@@ -116,18 +79,48 @@ gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-flickr', '>= 0.0.15'
# client for Elasticsearch. Elasticsearch is a flexible
# and powerful, distributed, real-time search and analytics engine.
# An example of the use in the project is fuzzy crop search.
gem "elasticsearch-model"
gem "elasticsearch-rails"
gem 'rake', '>= 10.0.0'
group :development, :test do
gem 'byebug' # debugging
gem 'haml-rails' # HTML templating language
gem 'rspec-rails', '~> 2.12.1' # unit testing framework
gem 'database_cleaner', '~> 1.3.0'
gem 'webrat' # provides HTML matchers for view tests
gem 'factory_girl_rails', '~> 4.0' # for creating test data
gem 'coveralls', require: false # coverage analysis
gem 'capybara' # integration tests
gem 'capybara-email' # integration tests for email
gem 'poltergeist', '~> 1.5.1' # for headless JS testing
gem 'i18n-tasks' # adds tests for finding missing and unused translations
group :production, :staging do
gem 'newrelic_rpm'
gem 'dalli'
gem 'memcachier'
gem 'rails_12factor' # supresses heroku plugin injection
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
end
group :development do
# A debugger and irb alternative. Pry doesn't play nice
# with unicorn, so start a Webrick server when debugging
# with Pry
gem 'pry'
gem 'better_errors'
gem 'binding_of_caller'
gem 'letter_opener'
gem 'quiet_assets'
end
group :development, :test do
gem 'haml-rails' # HTML templating language
gem 'rspec-rails', '~> 3.1.0' # unit testing framework
gem 'rspec-activemodel-mocks'
gem 'byebug' # debugging
gem 'database_cleaner', '~> 1.3.0'
gem 'webrat' # provides HTML matchers for view tests
gem 'factory_girl_rails', '~> 4.5.0' # for creating test data
gem 'coveralls', require: false # coverage analysis
gem 'capybara' # integration tests
gem 'capybara-email' # integration tests for email
gem 'poltergeist', '~> 1.5.1' # for headless JS testing
gem 'i18n-tasks' # adds tests for finding missing and unused translations
end
group :travis do
gem 'heroku-api'
end

View File

@@ -20,35 +20,39 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.13)
actionpack (= 3.2.13)
mail (~> 2.5.3)
actionpack (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
actionmailer (4.1.9)
actionpack (= 4.1.9)
actionview (= 4.1.9)
mail (~> 2.5, >= 2.5.4)
actionpack (4.1.9)
actionview (= 4.1.9)
activesupport (= 4.1.9)
rack (~> 1.5.2)
rack-test (~> 0.6.2)
actionview (4.1.9)
activesupport (= 4.1.9)
builder (~> 3.1)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.5)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
activerecord (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activesupport (3.2.13)
i18n (= 0.6.1)
multi_json (~> 1.0)
active_link_to (1.0.2)
actionpack
activemodel (4.1.9)
activesupport (= 4.1.9)
builder (~> 3.1)
activerecord (4.1.9)
activemodel (= 4.1.9)
activesupport (= 4.1.9)
arel (~> 5.0.0)
activesupport (4.1.9)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1)
tzinfo (~> 1.1)
addressable (2.3.6)
arel (3.0.3)
arel (5.0.1.20140414130214)
autoprefixer-rails (5.1.1)
execjs
json
bcrypt (3.1.9)
better_errors (2.0.0)
coderay (>= 1.0.0)
@@ -57,14 +61,19 @@ GEM
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bluecloth (2.2.0)
bonsai-elasticsearch-rails (0.0.4)
bootstrap-datepicker-rails (1.3.0.2)
railties (>= 3.0)
builder (3.0.4)
bootstrap-sass (3.3.3)
autoprefixer-rails (>= 5.0.0.1)
sass (>= 3.2.19)
bootstrap_form (2.2.0)
builder (3.2.2)
byebug (3.5.1)
columnize (~> 0.8)
debugger-linecache (~> 1.2)
slop (~> 3.6)
cancan (1.6.10)
cancancan (1.9.2)
capybara (2.4.4)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
@@ -74,24 +83,38 @@ GEM
capybara-email (2.4.0)
capybara (~> 2.4)
mail
chunky_png (1.3.3)
climate_control (0.0.3)
activesupport (>= 3.0)
cliver (0.3.2)
cocaine (0.5.5)
climate_control (>= 0.0.3, < 1.0)
codemirror-rails (4.8)
railties (>= 3.0, < 5)
coderay (1.1.0)
coffee-rails (3.2.2)
coffee-rails (4.1.0)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
railties (>= 4.0.0, < 5.0)
coffee-script (2.3.0)
coffee-script-source
execjs
coffee-script-source (1.8.0)
columnize (0.8.9)
columnize (0.9.0)
comfortable_mexican_sofa (1.12.7)
active_link_to (>= 1.0.0)
bootstrap-sass (>= 3.2.0)
bootstrap_form (>= 2.2.0)
codemirror-rails (>= 3.0.0)
coffee-rails (>= 3.1.0)
haml-rails (>= 0.3.0)
jquery-rails (>= 3.0.0)
jquery-ui-rails (>= 5.0.0)
kramdown (>= 1.0.0)
paperclip (>= 4.0.0)
plupload-rails (>= 1.2.1)
rails (>= 4.0.0, < 5)
rails-i18n (>= 4.0.0)
sass-rails (>= 4.0.3)
commonjs (0.2.7)
compass (0.12.7)
chunky_png (~> 1.2)
fssm (>= 0.2.7)
sass (~> 3.2.19)
compass-rails (1.0.3)
compass (>= 0.12.2, < 0.14)
coveralls (0.7.1)
multi_json (~> 1.3)
rest-client
@@ -104,51 +127,77 @@ GEM
database_cleaner (1.3.0)
debug_inspector (0.0.2)
debugger-linecache (1.2.0)
devise (3.2.4)
devise (3.4.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 3.2.6, < 5)
responders
thread_safe (~> 0.1)
warden (~> 1.2.3)
diff-lcs (1.1.3)
diff-lcs (1.2.5)
docile (1.1.5)
easy_translate (0.5.0)
json
thread
thread_safe
elasticsearch (1.0.6)
elasticsearch-api (= 1.0.6)
elasticsearch-transport (= 1.0.6)
elasticsearch-api (1.0.6)
multi_json
elasticsearch-model (0.1.6)
activesupport (> 3)
elasticsearch (> 0.4)
hashie
elasticsearch-rails (0.1.6)
elasticsearch-transport (1.0.6)
faraday
multi_json
erubis (2.7.0)
excon (0.43.0)
execjs (2.2.2)
factory_girl (4.5.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.5.0)
factory_girl (~> 4.5.0)
railties (>= 3.0.0)
faraday (0.9.1)
multipart-post (>= 1.2, < 3)
figaro (1.0.0)
thor (~> 0.14)
flickraw (0.9.8)
friendly_id (4.0.10.1)
activerecord (>= 3.0, < 4.0)
fssm (0.2.10)
friendly_id (5.0.4)
activerecord (>= 4.0.0)
gibbon (1.1.4)
httparty
multi_json (>= 1.3.4)
gravatar-ultimate (2.0.0)
activesupport (>= 2.3.14)
rack
haml (4.0.5)
haml (4.1.0.beta.1)
tilt
haml-rails (0.4)
actionpack (>= 3.1, < 4.1)
activesupport (>= 3.1, < 4.1)
haml (>= 3.1, < 4.1)
railties (>= 3.1, < 4.1)
haml-rails (0.6.0)
actionpack (>= 4.0.1)
activesupport (>= 4.0.1)
haml (>= 3.1, < 5.0)
html2haml (>= 1.0.1)
railties (>= 4.0.1)
hashie (3.3.2)
heroku-api (0.3.22)
excon (~> 0.38)
multi_json (~> 1.8)
highline (1.6.21)
hike (1.2.3)
httparty (0.11.0)
multi_json (~> 1.0)
hpricot (0.8.6)
html2haml (1.0.1)
erubis (~> 2.7.0)
haml (>= 4.0.0.rc.1)
hpricot (~> 0.8.6)
ruby_parser (~> 3.1.1)
httparty (0.13.3)
json (~> 1.8)
multi_xml (>= 0.5.2)
i18n (0.6.1)
i18n (0.7.0)
i18n-tasks (0.7.8)
activesupport
easy_translate (>= 0.5.0)
@@ -158,17 +207,17 @@ GEM
slop (>= 3.5.0)
term-ansicolor
terminal-table
journey (1.0.4)
jquery-rails (3.1.2)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (4.1.2)
railties (>= 3.1.0)
jquery-ui-rails (5.0.3)
railties (>= 3.2.16)
js-routes (0.9.9)
railties (>= 3.2)
sprockets-rails
json (1.7.7)
json (1.8.2)
kgio (2.9.2)
kramdown (1.5.0)
launchy (2.4.3)
addressable (~> 2.3)
leaflet-markercluster-rails (0.7.0)
@@ -181,20 +230,21 @@ GEM
less (~> 2.5.0)
less-rails-bootstrap (3.2.0)
less-rails (~> 2.5.0)
letter_opener (1.2.0)
letter_opener (1.3.0)
launchy (~> 2.2)
libv8 (3.16.14.7)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mail (2.6.3)
mime-types (>= 1.16, < 3)
memcachier (0.0.2)
method_source (0.8.2)
mime-types (1.25.1)
mime-types (2.4.3)
mini_portile (0.6.1)
minitest (5.5.1)
multi_json (1.10.1)
multi_xml (0.5.5)
netrc (0.8.0)
newrelic_rpm (3.9.7.266)
multipart-post (2.0.0)
netrc (0.10.0)
newrelic_rpm (3.9.8.273)
nokogiri (1.6.5)
mini_portile (~> 0.6.0)
oauth (0.4.7)
@@ -210,81 +260,104 @@ GEM
multi_json (~> 1.3)
omniauth-oauth (~> 1.0)
orm_adapter (0.5.0)
paperclip (4.2.1)
activemodel (>= 3.0.0)
activesupport (>= 3.0.0)
cocaine (~> 0.5.3)
mime-types
pg (0.17.1)
plupload-rails (1.2.1)
rails (>= 3.1)
poltergeist (1.5.1)
capybara (~> 2.1)
cliver (~> 0.3.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyglot (0.3.5)
pry (0.10.1)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
rack-ssl (1.3.4)
rack
rack-test (0.6.2)
quiet_assets (1.1.0)
railties (>= 3.1, < 5.0)
rack (1.5.2)
rack-test (0.6.3)
rack (>= 1.0)
rails (3.2.13)
actionmailer (= 3.2.13)
actionpack (= 3.2.13)
activerecord (= 3.2.13)
activeresource (= 3.2.13)
activesupport (= 3.2.13)
bundler (~> 1.0)
railties (= 3.2.13)
rails (4.1.9)
actionmailer (= 4.1.9)
actionpack (= 4.1.9)
actionview (= 4.1.9)
activemodel (= 4.1.9)
activerecord (= 4.1.9)
activesupport (= 4.1.9)
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.9)
sprockets-rails (~> 2.0)
rails-i18n (4.0.3)
i18n (~> 0.6)
railties (~> 4.0)
rails_12factor (0.0.3)
rails_serve_static_assets
rails_stdout_logging
rails_serve_static_assets (0.0.2)
rails_stdout_logging (0.0.3)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
rack-ssl (~> 1.3.2)
railties (4.1.9)
actionpack (= 4.1.9)
activesupport (= 4.1.9)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
thor (>= 0.18.1, < 2.0)
raindrops (0.13.0)
rake (10.4.0)
rdoc (3.12.2)
json (~> 1.4)
rake (10.4.2)
ref (1.0.5)
responders (1.1.2)
railties (>= 3.2, < 4.2)
rest-client (1.7.2)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rspec-core (2.12.2)
rspec-expectations (2.12.1)
diff-lcs (~> 1.1.3)
rspec-mocks (2.12.2)
rspec-rails (2.12.2)
rspec-activemodel-mocks (1.0.1)
activemodel (>= 3.0)
activesupport (>= 3.0)
rspec-mocks (>= 2.99, < 4.0)
rspec-core (3.1.7)
rspec-support (~> 3.1.0)
rspec-expectations (3.1.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.1.0)
rspec-mocks (3.1.3)
rspec-support (~> 3.1.0)
rspec-rails (3.1.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 2.12.0)
rspec-expectations (~> 2.12.0)
rspec-mocks (~> 2.12.0)
rspec-core (~> 3.1.0)
rspec-expectations (~> 3.1.0)
rspec-mocks (~> 3.1.0)
rspec-support (~> 3.1.0)
rspec-support (3.1.2)
ruby-units (1.4.5)
ruby_parser (3.1.3)
sexp_processor (~> 4.1)
sass (3.2.19)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
sass-rails (4.0.5)
railties (>= 4.0.0, < 5.0)
sass (~> 3.2.2)
sprockets (~> 2.8, < 3.0)
sprockets-rails (~> 2.0)
sexp_processor (4.4.4)
simplecov (0.9.1)
docile (~> 1.1.0)
multi_json (~> 1.0)
simplecov-html (~> 0.8.0)
simplecov-html (0.8.0)
slop (3.6.0)
sprockets (2.2.3)
sprockets (2.12.3)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sprockets-rails (0.0.1)
sprockets (>= 1.0.2)
sprockets-rails (2.2.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
term-ansicolor (1.3.0)
tins (~> 1.0)
terminal-table (1.4.5)
@@ -296,13 +369,11 @@ GEM
thread_safe (0.3.4)
tilt (1.4.1)
tins (1.3.3)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.42)
uglifier (2.2.1)
tzinfo (1.2.2)
thread_safe (~> 0.1)
uglifier (2.5.3)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
json (>= 1.8.0)
unicorn (4.8.3)
kgio (~> 2.6)
rack
@@ -313,7 +384,9 @@ GEM
nokogiri (>= 1.2.0)
rack (>= 1.0)
rack-test (>= 0.5.3)
websocket-driver (0.4.0)
websocket-driver (0.5.0)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.0)
will_paginate (3.0.7)
xpath (2.0.0)
nokogiri (~> 1.3)
@@ -327,33 +400,36 @@ DEPENDENCIES
better_errors
binding_of_caller
bluecloth
bonsai-elasticsearch-rails
bootstrap-datepicker-rails
bundler (>= 1.1.5)
byebug
cancan
cancancan (~> 1.9)
capybara
capybara-email
coffee-rails (~> 3.2.1)
compass-rails (~> 1.0.3)
coffee-rails (~> 4.1.0)
comfortable_mexican_sofa (~> 1.12.0)
coveralls
csv_shaper
dalli
database_cleaner (~> 1.3.0)
devise (~> 3.2.0)
factory_girl_rails (~> 4.0)
devise (~> 3.4.1)
elasticsearch-model
elasticsearch-rails
factory_girl_rails (~> 4.5.0)
figaro
flickraw
friendly_id (~> 4.0.10)
friendly_id (~> 5.0.4)
geocoder!
gibbon
gravatar-ultimate
haml
haml-rails
heroku-api
i18n-tasks
jquery-rails
jquery-ui-rails
jquery-ui-rails (~> 5.0.2)
js-routes
json (~> 1.7.7)
leaflet-markercluster-rails
leaflet-rails
less (~> 2.5.0)
@@ -369,14 +445,16 @@ DEPENDENCIES
pg
poltergeist (~> 1.5.1)
pry
rack (~> 1.4.5)
rails (= 3.2.13)
quiet_assets
rails (= 4.1.9)
rails_12factor
rake (>= 10.0.0)
rspec-rails (~> 2.12.1)
sass-rails (~> 3.2.3)
rspec-activemodel-mocks
rspec-rails (~> 3.1.0)
ruby-units
sass-rails (~> 4.0.4)
therubyracer (~> 0.12)
uglifier (>= 1.0.3)
uglifier (~> 2.5.3)
unicorn
webrat
will_paginate (~> 3.0)

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 572 B

After

Width:  |  Height:  |  Size: 613 B

View File

@@ -15,7 +15,7 @@
//= require js-routes
//= require jquery
//= require jquery_ujs
//= require jquery.ui.autocomplete
//= require jquery-ui/autocomplete
//= require twitter/bootstrap
//= require_tree .
//= require bootstrap-datepicker

View File

@@ -0,0 +1 @@
# Custom JS for the admin area

View File

@@ -3,7 +3,7 @@
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*= require jquery.ui.autocomplete
*= require jquery-ui/autocomplete
*= require bootstrap-datepicker
*= require leaflet
*= require leaflet.markercluster

View File

@@ -0,0 +1 @@
// custom CSS for admin area

View File

@@ -122,7 +122,7 @@ p.stats {
color: @brown;
}
.crop-thumbnail {
.photo-thumbnail {
position:relative;
padding:0;
img {
@@ -149,33 +149,55 @@ p.stats {
}
}
.member-thumbnail {
img {
height: 85px;
width: 85px;
max-width: 85px
}
}
.thumbnail {
border: none;
text-align: center;
margin-bottom: 1.5em;
.scientific-name small, .crop-name a {
display: inline-block;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1em;
padding-bottom: 2px;
.member-thumbnail {
text-align: left;
img {
height: 85px;
width: 85px;
max-width: 85px
}
}
.crop-name a {
padding-top: 2px;
}
.crop-thumbnail {
height: 220px;
.cropinfo {
display: inline-block;
max-width: 100%;
white-space: nowrap;
line-height: 1em;
padding-bottom: 2px;
.scientific-name small {
margin-bottom: -2px;
.cropname {
overflow: hidden;
text-overflow: ellipsis;
}
.scientificname {
font-size: small;
font-style: italic;
overflow: hidden;
text-overflow: ellipsis;
}
.plantingcount {
font-size: small;
}
}
.crop-name a {
padding-top: 2px;
}
.scientific-name small {
margin-bottom: -2px;
}
}
}
@@ -192,31 +214,48 @@ li.crop-hierarchy {
margin: 40px 0px 0px 0px !important;
}
// navbar centering
footer .navbar .nav {
float: none;
display: inline-block;
*display: inline;
/* ie7 fix */
*zoom: 1;
/* hasLayout ie7 trigger */
vertical-align: top;
> li {
float: none;
display: inline-block;
*display: inline;
/* ie7 fix */
*zoom: 1;
/* hasLayout ie7 trigger */
vertical-align: top;
// footer
footer {
#footer1, #footer2, #footer3 {
text-align: left;
padding-top: 1em;
padding-bottom: 2em;
ul {
list-style-type: none;
list-style-position: outside;
padding-left: 0px;
margin-left: 0px;
}
a {
color: @navbar-default-link-color;
text-decoration: none;
}
a:hover {
color: @navbar-default-link-hover-color;
}
a:active {
color: @navbar-default-link-active-color;
}
}
.navbar-bottom.navbar {
border-radius: 0;
}
}
.navbar-bottom.navbar {
text-align: center;
border-radius: 0;
// ensure footer is pushed to bottom of browser window
#maincontainer {
min-height: 80%;
}
html, body {
height: 100%;
}
//
.crop-image, .member-image {
width: 100%;
height: 100%;
@@ -244,6 +283,12 @@ footer .navbar .nav {
text-decoration: underline;
}
.alert {
a {
font-weight: 800;
}
}
// Overrides applying only to mobile view. This must be at the end of the overrides file.
@media only screen and (max-width: 767px) {
@@ -261,3 +306,13 @@ footer .navbar .nav {
display: block;
}
}
/* override "info" alert boxes to be green, not blue, on Growstuff */
@state-info-text: darken(@green, 10%);
@state-info-bg: lighten(@green, 50%);
/* and set "success" to be the same, as it was just very slightly
* different because the default bootstrap green is slightly different
* from ours */
@state-success-text: darken(@green, 10%);
@state-success-bg: lighten(@green, 50%);

View File

@@ -36,7 +36,7 @@ class AccountTypesController < ApplicationController
# POST /account_types
def create
@account_type = AccountType.new(params[:account_type])
@account_type = AccountType.new(account_type_params)
respond_to do |format|
if @account_type.save
@@ -52,7 +52,7 @@ class AccountTypesController < ApplicationController
@account_type = AccountType.find(params[:id])
respond_to do |format|
if @account_type.update_attributes(params[:account_type])
if @account_type.update(account_type_params)
format.html { redirect_to @account_type, notice: 'Account type was successfully updated.' }
else
format.html { render action: "edit" }
@@ -69,4 +69,10 @@ class AccountTypesController < ApplicationController
format.html { redirect_to account_types_url, notice: 'Account type was successfully deleted.' }
end
end
private
def account_type_params
params.require(:account_type).permit(:is_paid, :is_permanent_paid, :name)
end
end

View File

@@ -30,7 +30,7 @@ class AccountsController < ApplicationController
@account = Account.find(params[:id])
respond_to do |format|
if @account.update_attributes(params[:account])
if @account.update(params[:account])
format.html { redirect_to @account, notice: 'Account detail was successfully updated.' }
else
format.html { render action: "edit" }
@@ -38,4 +38,10 @@ class AccountsController < ApplicationController
end
end
private
def account_params
params.require(:account).permit(:account_type_id, :member_id, :paid_until)
end
end

View File

@@ -45,7 +45,7 @@ class AlternateNamesController < ApplicationController
# POST /alternate_names.json
def create
params[:alternate_name][:creator_id] = current_member.id
@alternate_name = AlternateName.new(params[:alternate_name])
@alternate_name = AlternateName.new(alternate_name_params)
respond_to do |format|
if @alternate_name.save
@@ -64,7 +64,7 @@ class AlternateNamesController < ApplicationController
@alternate_name = AlternateName.find(params[:id])
respond_to do |format|
if @alternate_name.update_attributes(params[:alternate_name])
if @alternate_name.update(alternate_name_params)
format.html { redirect_to @alternate_name.crop, notice: 'Alternate name was successfully updated.' }
format.json { head :no_content }
else
@@ -88,4 +88,10 @@ class AlternateNamesController < ApplicationController
format.json { head :no_content }
end
end
private
def alternate_name_params
params.require(:alternate_name).permit(:crop_id, :name, :creator_id)
end
end

View File

@@ -43,4 +43,36 @@ class ApplicationController < ActionController::Base
I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil
end
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |member|
member.permit(:login_name, :email, :password, :password_confirmation,
:remember_me, :login,
# terms of service
:tos_agreement,
# profile stuff
:bio, :location, :latitude, :longitude,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder
)
end
devise_parameter_sanitizer.for(:account_update) do |member|
member.permit(:login_name, :email, :password, :password_confirmation,
:remember_me, :login,
# terms of service
:tos_agreement,
# profile stuff
:bio, :location, :latitude, :longitude,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder,
#update password
:current_password
)
end
end
end

View File

@@ -2,15 +2,6 @@ class AuthenticationsController < ApplicationController
before_filter :authenticate_member!
load_and_authorize_resource
# GET /authentications
def index
@authentications = current_member.authentications if member_signed_in?
respond_to do |format|
format.html # index.html.erb
end
end
# POST /authentications
def create
auth = request.env['omniauth.auth']
@@ -27,12 +18,17 @@ class AuthenticationsController < ApplicationController
name = auth['info']['name']
end
@authentication = current_member.authentications.find_or_create_by_provider_and_uid(
:provider => auth['provider'],
:uid => auth['uid'],
@authentication = current_member.authentications
.create_with(
:name => name,
:token => auth['credentials']['token'],
:secret => auth['credentials']['secret'])
:secret => auth['credentials']['secret']
)
.find_or_create_by(
:provider => auth['provider'],
:uid => auth['uid'],
:name => name)
flash[:notice] = "Authentication successful."
else
flash[:notice] = "Authentication failed."

View File

@@ -2,8 +2,6 @@ class CommentsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :comment_sweeper
# GET /comments
# GET /comments.json
def index
@@ -55,11 +53,11 @@ class CommentsController < ApplicationController
# POST /comments.json
def create
params[:comment][:author_id] = current_member.id
@comment = Comment.new(params[:comment])
@comment = Comment.new(comment_params)
respond_to do |format|
if @comment.save
format.html { redirect_to @comment.post, notice: 'Comment was successfully created.' }
format.html { redirect_to @comment.post, notice: "Comment was successfully created." }
format.json { render json: @comment, status: :created, location: @comment }
else
format.html { render action: "new" }
@@ -79,7 +77,7 @@ class CommentsController < ApplicationController
params[:comment].delete("author_id")
respond_to do |format|
if @comment.update_attributes(params[:comment])
if @comment.update(comment_params)
format.html { redirect_to @comment.post, notice: 'Comment was successfully updated.' }
format.json { head :no_content }
else
@@ -101,4 +99,10 @@ class CommentsController < ApplicationController
format.json { head :no_content }
end
end
private
def comment_params
params.require(:comment).permit(:author_id, :body, :post_id)
end
end

View File

@@ -1,20 +1,22 @@
require 'will_paginate/array'
class CropsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :hierarchy, :search, :show]
load_and_authorize_resource
skip_authorize_resource :only => [:hierarchy, :search]
cache_sweeper :crop_sweeper
# GET /crops
# GET /crops.json
def index
@sort = params[:sort]
if @sort == 'alpha'
# alphabetical order
@crops = Crop.includes(:scientific_names, {:plantings => :photos}).paginate(:page => params[:page])
@crops = Crop.includes(:scientific_names, {:plantings => :photos})
@paginated_crops = @crops.approved.paginate(:page => params[:page])
else
# default to sorting by popularity
@crops = Crop.popular.includes(:scientific_names, {:plantings => :photos}).paginate(:page => params[:page])
@crops = Crop.popular.includes(:scientific_names, {:plantings => :photos})
@paginated_crops = @crops.approved.paginate(:page => params[:page])
end
respond_to do |format|
@@ -34,7 +36,18 @@ class CropsController < ApplicationController
# GET /crops/wrangle
def wrangle
@crops = Crop.recent.paginate(:page => params[:page])
@approval_status = params[:approval_status]
case @approval_status
when "pending"
@crops = Crop.pending_approval
when "rejected"
@crops = Crop.rejected
else
@crops = Crop.recent
end
@crops = @crops.paginate(:page => params[:page])
@crop_wranglers = Role.crop_wranglers
respond_to do |format|
format.html
@@ -51,18 +64,13 @@ class CropsController < ApplicationController
# GET /crops/search
def search
@search = params[:search]
@exact_match = Crop.find_by_name(params[:search])
@partial_matches = Crop.search(params[:search])
# exclude exact match from partial match list
@partial_matches.reject!{ |r| @exact_match && r.eql?(@exact_match) }
@fuzzy = Crop.search(params[:term])
@term = params[:term]
@matches = Crop.search(@term)
@paginated_matches = @matches.paginate(:page => params[:page])
respond_to do |format|
format.html
format.json { render :json => @fuzzy }
format.json { render :json => @matches }
end
end
@@ -98,17 +106,35 @@ class CropsController < ApplicationController
# GET /crops/1/edit
def edit
@crop = Crop.find(params[:id])
(3 - @crop.scientific_names.length).times do
@crop.scientific_names.build
end
end
# POST /crops
# POST /crops.json
def create
params[:crop][:creator_id] = current_member.id
@crop = Crop.new(params[:crop])
@crop = Crop.new(crop_params)
if current_member.has_role? :crop_wrangler
@crop.creator = current_member
success_msg = "Crop was successfully created."
else
@crop.requester = current_member
@crop.approval_status = "pending"
success_msg = "Crop was successfully requested."
end
respond_to do |format|
if @crop.save
format.html { redirect_to @crop, notice: 'Crop was successfully created.' }
unless current_member.has_role? :crop_wrangler
Role.crop_wranglers.each do |w|
Notifier.new_crop_request(w, @crop).deliver!
end
end
format.html { redirect_to @crop, notice: success_msg }
format.json { render json: @crop, status: :created, location: @crop }
else
format.html { render action: "new" }
@@ -122,8 +148,18 @@ class CropsController < ApplicationController
def update
@crop = Crop.find(params[:id])
previous_status = @crop.approval_status
@crop.creator = current_member if previous_status == "pending"
respond_to do |format|
if @crop.update_attributes(params[:crop])
if @crop.update(crop_params)
if previous_status == "pending"
requester = @crop.requester
new_status = @crop.approval_status
Notifier.crop_request_approved(requester, @crop).deliver! if new_status == "approved"
Notifier.crop_request_rejected(requester, @crop).deliver! if new_status == "rejected"
end
format.html { redirect_to @crop, notice: 'Crop was successfully updated.' }
format.json { head :no_content }
else
@@ -144,4 +180,10 @@ class CropsController < ApplicationController
format.json { head :no_content }
end
end
private
def crop_params
params.require(:crop).permit(:en_wikipedia_url, :name, :parent_id, :creator_id, :approval_status, :request_notes, :reason_for_rejection, :rejection_notes, :scientific_names_attributes => [:scientific_name, :_destroy, :id])
end
end

View File

@@ -1,8 +1,12 @@
class FollowsController < ApplicationController
before_filter :authenticate_member!
load_and_authorize_resource
skip_load_resource :only => :create
# POST /follows
def create
@follow = current_member.follows.build(:followed_id => params[:followed_id])
@follow = current_member.follows.build(:followed_id => follow_params[:followed_id])
if @follow.save
flash[:notice] = "Followed #{ @follow.followed.login_name }"
@@ -15,11 +19,17 @@ class FollowsController < ApplicationController
# DELETE /follows/1
def destroy
@follow = current_member.follows.find(params[:id])
@follow = current_member.follows.find(follow_params[:id])
unfollowed_name = @follow.followed.login_name
@follow.destroy
flash[:notice] = "Unfollowed #{ unfollowed_name }"
redirect_to root_path
end
private
def follow_params
params.permit(:id, :followed_id, :follower_id, :authenticity_token, :_method)
end
end

View File

@@ -1,8 +1,6 @@
class ForumsController < ApplicationController
load_and_authorize_resource
cache_sweeper :forum_sweeper
# GET /forums
# GET /forums.json
def index
@@ -44,7 +42,7 @@ class ForumsController < ApplicationController
# POST /forums
# POST /forums.json
def create
@forum = Forum.new(params[:forum])
@forum = Forum.new(forum_params)
respond_to do |format|
if @forum.save
@@ -63,7 +61,7 @@ class ForumsController < ApplicationController
@forum = Forum.find(params[:id])
respond_to do |format|
if @forum.update_attributes(params[:forum])
if @forum.update(forum_params)
format.html { redirect_to @forum, notice: 'Forum was successfully updated.' }
format.json { head :no_content }
else
@@ -84,4 +82,10 @@ class ForumsController < ApplicationController
format.json { head :no_content }
end
end
private
def forum_params
params.require(:forum).permit(:description, :name, :owner_id, :slug)
end
end

View File

@@ -1,8 +1,7 @@
class GardensController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :garden_sweeper
# GET /gardens
# GET /gardens.json
@@ -50,12 +49,13 @@ class GardensController < ApplicationController
# POST /gardens.json
def create
params[:garden][:owner_id] = current_member.id
@garden = Garden.new(params[:garden])
@garden = Garden.new(garden_params)
respond_to do |format|
if @garden.save
format.html { redirect_to @garden, notice: 'Garden was successfully created.' }
format.json { render json: @garden, status: :created, location: @garden }
expire_fragment("homepage_stats")
else
format.html { render action: "new" }
format.json { render json: @garden.errors, status: :unprocessable_entity }
@@ -69,7 +69,7 @@ class GardensController < ApplicationController
@garden = Garden.find(params[:id])
respond_to do |format|
if @garden.update_attributes(params[:garden])
if @garden.update(garden_params)
format.html { redirect_to @garden, notice: 'Garden was successfully updated.' }
format.json { head :no_content }
else
@@ -84,10 +84,18 @@ class GardensController < ApplicationController
def destroy
@garden = Garden.find(params[:id])
@garden.destroy
expire_fragment("homepage_stats")
respond_to do |format|
format.html { redirect_to gardens_by_owner_path(:owner => @garden.owner), notice: 'Garden was successfully deleted.' }
format.json { head :no_content }
end
end
private
def garden_params
params.require(:garden).permit(:name, :slug, :owner_id, :description, :active,
:location, :latitude, :longitude, :area, :area_unit)
end
end

View File

@@ -20,7 +20,7 @@ class HarvestsController < ApplicationController
format.html { @harvests = @harvests.paginate(:page => params[:page]) }
format.json { render json: @harvests }
format.csv do
specifics = (@owner ? "#{@owner.name}-" : @crop ? "#{@crop.name}-" : nil)
specifics = (@owner ? "#{@owner.login_name}-" : @crop ? "#{@crop.name}-" : nil)
@filename = "Growstuff-#{specifics}Harvests-#{Time.zone.now.to_s(:number)}.csv"
render :csv => @harvests
end
@@ -62,7 +62,7 @@ class HarvestsController < ApplicationController
def create
params[:harvest][:owner_id] = current_member.id
params[:harvested_at] = parse_date(params[:harvested_at])
@harvest = Harvest.new(params[:harvest])
@harvest = Harvest.new(harvest_params)
respond_to do |format|
if @harvest.save
@@ -81,7 +81,7 @@ class HarvestsController < ApplicationController
@harvest = Harvest.find(params[:id])
respond_to do |format|
if @harvest.update_attributes(params[:harvest])
if @harvest.update(harvest_params)
format.html { redirect_to @harvest, notice: 'Harvest was successfully updated.' }
format.json { head :no_content }
else
@@ -102,4 +102,11 @@ class HarvestsController < ApplicationController
format.json { head :no_content }
end
end
private
def harvest_params
params.require(:harvest).permit(:crop_id, :harvested_at, :description, :owner_id,
:quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug, :si_weight)
end
end

View File

@@ -1,12 +1,17 @@
class MembersController < ApplicationController
load_and_authorize_resource
cache_sweeper :member_sweeper
skip_authorize_resource :only => :nearby
after_action :expire_cache_fragments, :only => :create
def index
@members = Member.confirmed.paginate(:page => params[:page])
@sort = params[:sort]
if @sort == 'recently_joined'
@members = Member.confirmed.recently_joined.paginate(:page => params[:page])
else
@members = Member.confirmed.paginate(:page => params[:page])
end
respond_to do |format|
format.html # index.html.haml
@@ -44,4 +49,10 @@ class MembersController < ApplicationController
@followers = @member.followers.paginate(:page => params[:page])
end
private
def expire_cache_fragments
expire_fragment("homepage_stats")
end
end

View File

@@ -5,7 +5,7 @@ class NotificationsController < ApplicationController
# GET /notifications
def index
@notifications = Notification.find_all_by_recipient_id(current_member)
@notifications = Notification.where(recipient_id: current_member)
respond_to do |format|
format.html # index.html.erb
@@ -49,7 +49,7 @@ class NotificationsController < ApplicationController
# POST /notifications
def create
params[:notification][:sender_id] = current_member.id
@notification = Notification.new(params[:notification])
@notification = Notification.new(notification_params)
@recipient = Member.find_by_id(params[:notification][:recipient_id])
respond_to do |format|
@@ -60,4 +60,10 @@ class NotificationsController < ApplicationController
end
end
end
private
def notification_params
params.require(:notification).permit(:sender_id, :recipient_id, :subject, :body, :post_id, :read)
end
end

View File

@@ -7,7 +7,7 @@ class OrderItemsController < ApplicationController
if params[:order_item][:price]
params[:order_item][:price] = params[:order_item][:price].to_f * 100 # convert to cents
end
@order_item = OrderItem.new(params[:order_item])
@order_item = OrderItem.new(order_item_params)
@order_item.order = current_member.current_order || Order.create(:member_id => current_member.id)
respond_to do |format|
@@ -20,4 +20,10 @@ class OrderItemsController < ApplicationController
end
end
end
private
def order_item_params
params.require(:order_item).permit(:order_id, :price, :product_id, :quantity)
end
end

View File

@@ -4,7 +4,7 @@ class OrdersController < ApplicationController
# GET /orders
def index
@orders = Order.find_all_by_member_id(current_member.id)
@orders = Order.where(member_id: current_member.id)
respond_to do |format|
format.html # index.html.erb

View File

@@ -1,8 +1,6 @@
class PhotosController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :photo_sweeper
# GET /photos
# GET /photos.json
@@ -61,13 +59,13 @@ class PhotosController < ApplicationController
# POST /photos.json
def create
@photo = Photo.find_by_flickr_photo_id(params[:photo][:flickr_photo_id]) ||
Photo.new(params[:photo])
Photo.new(photo_params)
@photo.owner_id = current_member.id
@photo.set_flickr_metadata
# several models can have photos. we need to know what model and the id
# for the entry to attach the photo to
valid_models = ["planting", "harvest"]
valid_models = ["planting", "harvest", "garden"]
if params[:type]
if valid_models.include?(params[:type])
if params[:id]
@@ -111,7 +109,7 @@ class PhotosController < ApplicationController
@photo = Photo.find(params[:id])
respond_to do |format|
if @photo.update_attributes(params[:photo])
if @photo.update(photo_params)
format.html { redirect_to @photo, notice: 'Photo was successfully updated.' }
format.json { head :no_content }
else
@@ -132,4 +130,11 @@ class PhotosController < ApplicationController
format.json { head :no_content }
end
end
private
def photo_params
params.require(:photo).permit(:flickr_photo_id, :owner_id, :title, :license_name,
:license_url, :thumbnail_url, :fullsize_url, :link_url)
end
end

View File

@@ -42,7 +42,7 @@ class PlantPartsController < ApplicationController
# POST /plant_parts
# POST /plant_parts.json
def create
@plant_part = PlantPart.new(params[:plant_part])
@plant_part = PlantPart.new(plant_part_params)
respond_to do |format|
if @plant_part.save
@@ -61,7 +61,7 @@ class PlantPartsController < ApplicationController
@plant_part = PlantPart.find(params[:id])
respond_to do |format|
if @plant_part.update_attributes(params[:plant_part])
if @plant_part.update(plant_part_params)
format.html { redirect_to @plant_part, notice: 'Plant part was successfully updated.' }
format.json { head :no_content }
else
@@ -82,4 +82,10 @@ class PlantPartsController < ApplicationController
format.json { head :no_content }
end
end
private
def plant_part_params
params.require(:plant_part).permit(:name, :slug)
end
end

View File

@@ -1,9 +1,6 @@
class PlantingsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :planting_sweeper
# GET /plantings
# GET /plantings.json
@@ -33,7 +30,7 @@ class PlantingsController < ApplicationController
# GET /plantings/1
# GET /plantings/1.json
def show
@planting = Planting.includes(:owner, :crop, :garden, :photos).find(params[:id])
@planting = Planting.includes(:owner, :crop, :garden, :photos).friendly.find(params[:id])
respond_to do |format|
format.html # show.html.erb
@@ -68,14 +65,15 @@ class PlantingsController < ApplicationController
# POST /plantings
# POST /plantings.json
def create
params[:planting][:owner_id] = current_member.id
params[:planted_at] = parse_date(params[:planted_at])
@planting = Planting.new(params[:planting])
@planting = Planting.new(planting_params)
@planting.owner = current_member
respond_to do |format|
if @planting.save
format.html { redirect_to @planting, notice: 'Planting was successfully created.' }
format.json { render json: @planting, status: :created, location: @planting }
expire_fragment("homepage_stats")
else
format.html { render action: "new" }
format.json { render json: @planting.errors, status: :unprocessable_entity }
@@ -90,7 +88,7 @@ class PlantingsController < ApplicationController
params[:planted_at] = parse_date(params[:planted_at])
respond_to do |format|
if @planting.update_attributes(params[:planting])
if @planting.update(planting_params)
format.html { redirect_to @planting, notice: 'Planting was successfully updated.' }
format.json { head :no_content }
else
@@ -106,10 +104,19 @@ class PlantingsController < ApplicationController
@planting = Planting.find(params[:id])
@garden = @planting.garden
@planting.destroy
expire_fragment("homepage_stats")
respond_to do |format|
format.html { redirect_to @garden }
format.json { head :no_content }
end
end
private
def planting_params
params.require(:planting).permit(:crop_id, :description, :garden_id, :planted_at,
:quantity, :sunniness, :planted_from, :owner_id, :finished,
:finished_at)
end
end

View File

@@ -2,8 +2,6 @@ class PostsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :post_sweeper
# GET /posts
# GET /posts.json
@@ -58,7 +56,7 @@ class PostsController < ApplicationController
# POST /posts.json
def create
params[:post][:author_id] = current_member.id
@post = Post.new(params[:post])
@post = Post.new(post_params)
respond_to do |format|
if @post.save
@@ -77,7 +75,7 @@ class PostsController < ApplicationController
@post = Post.find(params[:id])
respond_to do |format|
if @post.update_attributes(params[:post])
if @post.update(post_params)
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
format.json { head :no_content }
else
@@ -98,4 +96,10 @@ class PostsController < ApplicationController
format.json { head :no_content }
end
end
private
def post_params
params.require(:post).permit(:body, :subject, :author_id, :forum_id)
end
end

View File

@@ -36,7 +36,7 @@ class ProductsController < ApplicationController
# POST /products
def create
@product = Product.new(params[:product])
@product = Product.new(product_params)
respond_to do |format|
if @product.save
@@ -52,7 +52,7 @@ class ProductsController < ApplicationController
@product = Product.find(params[:id])
respond_to do |format|
if @product.update_attributes(params[:product])
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
else
format.html { render action: "edit" }
@@ -69,4 +69,11 @@ class ProductsController < ApplicationController
format.html { redirect_to products_url }
end
end
private
def product_params
params.require(:product).permit(:description, :min_price, :recommended_price, :name,
:account_type_id, :paid_months)
end
end

View File

@@ -1,7 +1,5 @@
class RegistrationsController < Devise::RegistrationsController
cache_sweeper :member_sweeper
def edit
@twitter_auth = current_member.auth('twitter')
@flickr_auth = current_member.auth('flickr')

View File

@@ -36,7 +36,7 @@ class RolesController < ApplicationController
# POST /roles
def create
@role = Role.new(params[:role])
@role = Role.new(role_params)
respond_to do |format|
if @role.save
@@ -52,7 +52,7 @@ class RolesController < ApplicationController
@role = Role.find(params[:id])
respond_to do |format|
if @role.update_attributes(params[:role])
if @role.update(role_params)
format.html { redirect_to @role, notice: 'Role was successfully updated.' }
else
format.html { render action: "edit" }
@@ -69,4 +69,10 @@ class RolesController < ApplicationController
format.html { redirect_to roles_url }
end
end
private
def role_params
params.require(:role).permit(:description, :name, :members, :slug)
end
end

View File

@@ -2,8 +2,6 @@ class ScientificNamesController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :scientific_name_sweeper
# GET /scientific_names
# GET /scientific_names.json
def index
@@ -47,7 +45,7 @@ class ScientificNamesController < ApplicationController
# POST /scientific_names.json
def create
params[:scientific_name][:creator_id] = current_member.id
@scientific_name = ScientificName.new(params[:scientific_name])
@scientific_name = ScientificName.new(scientific_name_params)
respond_to do |format|
if @scientific_name.save
@@ -66,7 +64,7 @@ class ScientificNamesController < ApplicationController
@scientific_name = ScientificName.find(params[:id])
respond_to do |format|
if @scientific_name.update_attributes(params[:scientific_name])
if @scientific_name.update(scientific_name_params)
format.html { redirect_to @scientific_name.crop, notice: 'Scientific name was successfully updated.' }
format.json { head :no_content }
else
@@ -90,4 +88,10 @@ class ScientificNamesController < ApplicationController
format.json { head :no_content }
end
end
private
def scientific_name_params
params.require(:scientific_name).permit(:crop_id, :scientific_name, :creator_id)
end
end

View File

@@ -2,8 +2,6 @@ class SeedsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :show]
load_and_authorize_resource
cache_sweeper :seed_sweeper
# GET /seeds
# GET /seeds.json
def index
@@ -68,7 +66,7 @@ class SeedsController < ApplicationController
# POST /seeds.json
def create
params[:seed][:owner_id] = current_member.id
@seed = Seed.new(params[:seed])
@seed = Seed.new(seed_params)
respond_to do |format|
if @seed.save
@@ -87,7 +85,7 @@ class SeedsController < ApplicationController
@seed = Seed.find(params[:id])
respond_to do |format|
if @seed.update_attributes(params[:seed])
if @seed.update(seed_params)
format.html { redirect_to @seed, notice: 'Seed was successfully updated.' }
format.json { head :no_content }
else
@@ -108,4 +106,13 @@ class SeedsController < ApplicationController
format.json { head :no_content }
end
end
private
def seed_params
params.require(:seed).permit(
:owner_id, :crop_id, :description, :quantity, :plant_before,
:days_until_maturity_min, :days_until_maturity_max, :organic, :gmo,
:heirloom, :tradable_to, :slug)
end
end

View File

@@ -24,5 +24,12 @@ module ApplicationHelper
:target => "_blank"
end
# Produces a cache key for uniquely identifying cached fragments.
def cache_key_for(klass, identifier="all")
count = klass.count
max_updated_at = klass.maximum(:updated_at).try(:utc).try(:to_s, :number)
"#{klass.name.downcase.pluralize}/#{identifier}-#{count}-#{max_updated_at}"
end
end

View File

@@ -19,4 +19,4 @@ module AutoSuggestHelper
}.html_safe
end
end
end

View File

@@ -13,8 +13,8 @@ class Notifier < ActionMailer::Base
def planting_reminder(member)
@member = member
@plantings = @member.plantings.reorder.last(5)
@harvests = @member.harvests.reorder.last(5)
@plantings = @member.plantings.first(5)
@harvests = @member.harvests.first(5)
if @member.send_planting_reminder
mail(:to => @member.email,
@@ -22,4 +22,19 @@ class Notifier < ActionMailer::Base
end
end
def new_crop_request(member, request)
@member, @request = member, 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
mail(:to => @member.email, :subject => "#{crop.name.capitalize} has been approved")
end
def crop_request_rejected(member, crop)
@member, @crop = member, crop
mail(:to => @member.email, :subject => "#{crop.name.capitalize} has been rejected")
end
end

View File

@@ -21,7 +21,24 @@ class Ability
cannot :read, Account
cannot :read, AccountType
# nobody should be able to view unapproved crops unless they
# are wranglers or admins
cannot :read, Crop
can :read, Crop, :approval_status => "approved"
# scientific names should only be viewable if associated crop is approved
cannot :read, ScientificName
can :read, ScientificName do |sn|
sn.crop.approved?
end
# ... same for alternate names
cannot :read, AlternateName
can :read, AlternateName do |an|
an.crop.approved?
end
if member
# members can see even rejected or pending crops if they requested it
can :read, Crop, :requester_id => member.id
# managing your own user settings
can :update, Member, :id => member.id
@@ -45,6 +62,9 @@ class Ability
can :manage, AlternateName
end
# any member can create a crop provisionally
can :create, Crop
# can create & destroy their own authentications against other sites.
can :create, Authentication
can :destroy, Authentication, :member_id => member.id
@@ -94,9 +114,11 @@ class Ability
cannot :destroy, OrderItem, :order => { :member_id => member.id, :completed_at => nil }
# following/unfollowing permissions
can :create, Follow do |f|
!member.already_following?(f.followed) && f.followed_id != member.id
end
can :create, Follow
cannot :create, Follow, :followed_id => member.id # can't follow yourself
can :destroy, Follow
cannot :destroy, Follow, :followed_id => member.id # can't unfollow yourself
if member.has_role? :admin

View File

@@ -1,5 +1,4 @@
class Account < ActiveRecord::Base
attr_accessible :account_type_id, :member_id, :paid_until
belongs_to :member
belongs_to :account_type
@@ -9,7 +8,7 @@ class Account < ActiveRecord::Base
before_create do |account|
unless account.account_type
account.account_type = AccountType.find_or_create_by_name(
account.account_type = AccountType.find_or_create_by(name:
Growstuff::Application.config.default_account_type
)
end

View File

@@ -1,5 +1,4 @@
class AccountType < ActiveRecord::Base
attr_accessible :is_paid, :is_permanent_paid, :name
has_many :products
def to_s

View File

@@ -1,5 +1,5 @@
class AlternateName < ActiveRecord::Base
attr_accessible :crop_id, :name, :creator_id
after_commit { |an| an.crop.__elasticsearch__.index_document if an.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" }
belongs_to :crop
belongs_to :creator, :class_name => 'Member'
end

View File

@@ -1,4 +1,3 @@
class Authentication < ActiveRecord::Base
belongs_to :member
attr_accessible :provider, :uid, :token, :secret, :name
end

View File

@@ -1,10 +1,9 @@
class Comment < ActiveRecord::Base
attr_accessible :author_id, :body, :post_id
belongs_to :author, :class_name => 'Member'
belongs_to :post
default_scope order("created_at DESC")
scope :post_order, reorder("created_at ASC") # for display on post page
default_scope { order("created_at DESC") }
scope :post_order, -> { reorder("created_at ASC") } # for display on post page
after_create do
recipient = self.post.author.id

View File

@@ -1,15 +0,0 @@
class CommentSweeper < ActionController::Caching::Sweeper
observe Comment
def after_create(comment)
expire_fragment('recent_posts')
end
def after_update(comment)
end
def after_destroy(comment)
expire_fragment('recent_posts')
end
end

View File

@@ -1,38 +1,115 @@
class Crop < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
attr_accessible :en_wikipedia_url, :name, :parent_id, :creator_id, :scientific_names_attributes
friendly_id :name, use: [:slugged, :finders]
has_many :scientific_names
has_many :scientific_names, after_add: :update_index, after_remove: :update_index
accepts_nested_attributes_for :scientific_names,
:allow_destroy => true,
:reject_if => :all_blank
has_many :alternate_names
has_many :alternate_names, after_add: :update_index, after_remove: :update_index
has_many :plantings
has_many :photos, :through => :plantings
has_many :seeds
has_many :harvests
has_many :plant_parts, :through => :harvests, :uniq => :true
has_many :plant_parts, -> { uniq }, :through => :harvests
belongs_to :creator, :class_name => 'Member'
belongs_to :requester, :class_name => 'Member'
belongs_to :parent, :class_name => 'Crop'
has_many :varieties, :class_name => 'Crop', :foreign_key => 'parent_id'
has_and_belongs_to_many :posts
before_destroy {|crop| crop.posts.clear}
default_scope { order("lower(name) asc") }
scope :recent, -> { where(:approval_status => "approved").reorder("created_at desc") }
scope :toplevel, -> { where(:approval_status => "approved", :parent_id => nil) }
scope :popular, -> { where(:approval_status => "approved").reorder("plantings_count desc, lower(name) asc") }
scope :randomized, -> { where(:approval_status => "approved").reorder('random()') } # ok on sqlite and psql, but not on mysql
scope :pending_approval, -> { where(:approval_status => "pending") }
scope :approved, -> { where(:approval_status => "approved") }
scope :rejected, -> { where(:approval_status => "rejected") }
default_scope order("lower(name) asc")
scope :recent, reorder("created_at desc")
scope :toplevel, where(:parent_id => nil)
scope :popular, reorder("plantings_count desc, lower(name) asc")
scope :randomized, reorder('random()') # ok on sqlite and psql, but not on mysql
## Wikipedia urls are only necessary when approving a crop
validates :en_wikipedia_url,
:format => {
:with => /^https?:\/\/en\.wikipedia\.org\/wiki/,
:with => /\Ahttps?:\/\/en\.wikipedia\.org\/wiki/,
:message => 'is not a valid English Wikipedia URL'
}
},
:if => :approved?
## Reasons are only necessary when rejecting
validates :reason_for_rejection, :presence => true, :if => :rejected?
## This validation addresses a race condition
validate :approval_status_cannot_be_changed_again
validate :must_be_rejected_if_rejected_reasons_present
validate :must_have_meaningful_reason_for_rejection
####################################
# Elastic search configuration
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
# In order to avoid clashing between different environments,
# use Rails.env as a part of index name (eg. development_growstuff)
index_name [Rails.env, "growstuff"].join('_')
settings index: { number_of_shards: 1 },
analysis: {
tokenizer: {
gs_edgeNGram_tokenizer: {
type: "edgeNGram", # edgeNGram: NGram match from the start of a token
min_gram: 3,
max_gram: 10,
# token_chars: Elasticsearch will split on characters
# that dont belong to any of these classes
token_chars: [ "letter", "digit" ]
}
},
analyzer: {
gs_edgeNGram_analyzer: {
tokenizer: "gs_edgeNGram_tokenizer",
filter: ["lowercase"]
}
},
} do
mappings dynamic: 'false' do
indexes :id, type: 'long'
indexes :name, type: 'string', analyzer: 'gs_edgeNGram_analyzer'
indexes :approval_status, type: 'string'
indexes :scientific_names do
indexes :scientific_name,
type: 'string',
analyzer: 'gs_edgeNGram_analyzer',
# Disabling field-length norm (norm). If the norm option is turned on(by default),
# higher weigh would be given for shorter fields, which in our case is irrelevant.
norms: { enabled: false }
end
indexes :alternate_names do
indexes :name, type: 'string', analyzer: 'gs_edgeNGram_analyzer'
end
end
end
def as_indexed_json(options={})
self.as_json(
only: [:id, :name, :approval_status],
include: {
scientific_names: { only: :scientific_name },
alternate_names: { only: :name }
})
end
# update the Elasticsearch index (only if we're using it in this
# environment)
def update_index(name_obj)
if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
__elasticsearch__.index_document
end
end
# End Elasticsearch section
def to_s
return name
@@ -105,6 +182,26 @@ class Crop < ActiveRecord::Base
return true
end
def pending?
approval_status == "pending"
end
def approved?
approval_status == "approved"
end
def rejected?
approval_status == "rejected"
end
def approval_statuses
[ 'rejected', 'pending', 'approved' ]
end
def reasons_for_rejection
[ "already in database", "not edible", "not enough information", "other" ]
end
# Crop.interesting
# returns a list of interesting crops, for use on the homepage etc
def Crop.interesting
@@ -132,7 +229,7 @@ class Crop < ActiveRecord::Base
cropbot = Member.find_by_login_name('cropbot')
raise "cropbot account not found: run rake db:seed" unless cropbot
crop = Crop.find_or_create_by_name(name)
crop = Crop.find_or_create_by(name: name)
crop.update_attributes(
:en_wikipedia_url => en_wikipedia_url,
:creator_id => cropbot.id
@@ -202,11 +299,76 @@ class Crop < ActiveRecord::Base
end
end
def rejection_explanation
if reason_for_rejection == "other"
return rejection_notes
else
return reason_for_rejection
end
end
# Crop.search(string)
# searches for crops whose names match the string given
# just uses SQL LIKE for now, but can be made fancier later
def self.search(query)
where("name ILIKE ?", "%#{query}%")
if ENV['GROWSTUFF_ELASTICSEARCH'] == "true"
search_str = query.nil? ? "" : query.downcase
response = __elasticsearch__.search( {
# Finds documents which match any field, but uses the _score from
# the best field insead of adding up _score from each field.
query: {
multi_match: {
query: "#{search_str}",
analyzer: "standard",
fields: ["name", "scientific_names.scientific_name", "alternate_names.name"]
}
},
filter: {
term: {approval_status: "approved"}
},
size: 50
}
)
return response.records.to_a
else
# if we don't have elasticsearch, just do a basic SQL query.
# also, make sure it's an actual array not an activerecord
# collection, so it matches what we get from elasticsearch and we can
# manipulate it in the same ways (eg. deleting elements without deleting
# the whole record from the db)
matches = Crop.approved.where("name ILIKE ?", "%#{query}%").to_a
# we want to make sure that exact matches come first, even if not
# using elasticsearch (eg. in development)
exact_match = Crop.approved.find_by_name(query)
if exact_match
matches.delete(exact_match)
matches.unshift(exact_match)
end
return matches
end
end
# Custom validations
def approval_status_cannot_be_changed_again
previous = previous_changes.include?(:approval_status) ? previous_changes.approval_status : {}
if previous.include?(:rejected) || previous.include?(:approved)
errors.add(:approval_status, "has already been set to #{approval_status}")
end
end
def must_be_rejected_if_rejected_reasons_present
unless rejected?
if reason_for_rejection.present? || rejection_notes.present?
errors.add(:approval_status, "must be rejected if a reason for rejection is present")
end
end
end
def must_have_meaningful_reason_for_rejection
if reason_for_rejection == "other" && rejection_notes.blank?
errors.add(:rejection_notes, "must be added if the reason for rejection is \"other\"")
end
end
end

View File

@@ -1,21 +0,0 @@
class CropSweeper < ActionController::Caching::Sweeper
observe Crop
def after_create(crop)
expire_fragment('homepage_stats')
expire_fragment('recent_crops')
expire_fragment('full_crop_hierarchy')
end
def after_update(crop)
expire_fragment("crop_image_#{crop.id}")
end
def after_destroy(crop)
expire_fragment('homepage_stats')
expire_fragment('recent_crops')
expire_fragment('full_crop_hierarchy')
end
end

View File

@@ -1,5 +1,4 @@
class Follow < ActiveRecord::Base
attr_accessible :followed_id, :follower_id
belongs_to :follower, class_name: "Member"
belongs_to :followed, class_name: "Member"
validates :follower_id, uniqueness: { :scope => :followed_id }

View File

@@ -1,7 +1,7 @@
class Forum < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
attr_accessible :description, :name, :owner_id, :slug
friendly_id :name, use: [:slugged, :finders]
has_many :posts
belongs_to :owner, :class_name => "Member"

View File

@@ -1,16 +0,0 @@
class ForumSweeper < ActionController::Caching::Sweeper
observe Forum
def after_create(forum)
expire_fragment('homepage_forums')
end
def after_update(forum)
expire_fragment('homepage_forums')
end
def after_destroy(forum)
expire_fragment('homepage_forums')
end
end

View File

@@ -1,24 +1,32 @@
class Garden < ActiveRecord::Base
include Geocodable
extend FriendlyId
friendly_id :garden_slug, use: :slugged
attr_accessible :name, :slug, :owner_id, :description, :active,
:location, :latitude, :longitude, :area, :area_unit
friendly_id :garden_slug, use: [:slugged, :finders]
belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id'
has_many :plantings, :order => 'created_at DESC', :dependent => :destroy
has_many :plantings, -> { order(created_at: :desc) }, :dependent => :destroy
has_many :crops, :through => :plantings
has_and_belongs_to_many :photos
before_destroy do |garden|
photolist = garden.photos.to_a # save a temp copy of the photo list
garden.photos.clear # clear relationship b/w garden and photo
photolist.each do |photo|
photo.destroy_if_unused
end
end
# set up geocoding
geocoded_by :location
after_validation :geocode
after_validation :empty_unwanted_geocodes
after_save :mark_inactive_garden_plantings_as_finished
default_scope order("lower(name) asc")
scope :active, where(:active => true)
scope :inactive, where(:active => false)
default_scope { order("lower(name) asc") }
scope :active, -> { where(:active => true) }
scope :inactive, -> { where(:active => false) }
validates :name,
:format => {
@@ -26,7 +34,9 @@ class Garden < ActiveRecord::Base
}
validates :area,
:numericality => { :only_integer => false, :greater_than_or_equal_to => 0 },
:numericality => {
:only_integer => false,
:greater_than_or_equal_to => 0 },
:allow_nil => true
AREA_UNITS_VALUES = {
@@ -86,4 +96,8 @@ class Garden < ActiveRecord::Base
end
end
def default_photo
return photos.first
end
end

View File

@@ -1,16 +0,0 @@
class GardenSweeper < ActionController::Caching::Sweeper
observe Garden
def after_create(garden)
expire_fragment('homepage_stats')
expire_fragment('interesting_members') if garden.owner.interesting?
expire_fragment("member_thumbnail_#{garden.owner.id}")
end
def after_destroy(garden)
expire_fragment('homepage_stats')
expire_fragment('interesting_members') if garden.owner.interesting?
expire_fragment("member_thumbnail_#{garden.owner.id}")
end
end

View File

@@ -1,10 +1,7 @@
class Harvest < ActiveRecord::Base
include ActionView::Helpers::NumberHelper
extend FriendlyId
friendly_id :harvest_slug, use: :slugged
attr_accessible :crop_id, :harvested_at, :description, :owner_id,
:quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug
friendly_id :harvest_slug, use: [:slugged, :finders]
belongs_to :crop
belongs_to :owner, :class_name => 'Member'
@@ -21,12 +18,16 @@ class Harvest < ActiveRecord::Base
end
end
default_scope order('created_at DESC')
default_scope { order('created_at DESC') }
validates :crop, :approved => true
validates :crop, :presence => {:message => "must be present and exist in our database"}
validates :quantity,
:numericality => { :only_integer => false },
:numericality => {
:only_integer => false,
:greater_than_or_equal_to => 0 },
:allow_nil => true
UNITS_VALUES = {
@@ -62,6 +63,17 @@ class Harvest < ActiveRecord::Base
after_validation :cleanup_quantities
before_save :set_si_weight
# we're storing the harvest weight in kilograms in the db too
# to make data manipulation easier
def set_si_weight
if self.weight_unit != nil
weight_string = "#{self.weight_quantity} #{self.weight_unit}"
self.si_weight = Unit(weight_string).convert_to("kg").to_s("%0.3f").delete(" kg").to_f
end
end
def cleanup_quantities
if quantity == 0
self.quantity = nil

View File

@@ -2,7 +2,7 @@ class Member < ActiveRecord::Base
include Geocodable
extend FriendlyId
friendly_id :login_name, use: :slugged
friendly_id :login_name, use: [:slugged, :finders]
has_many :posts, :foreign_key => 'author_id'
has_many :comments, :foreign_key => 'author_id'
@@ -27,18 +27,20 @@ class Member < ActiveRecord::Base
has_many :photos
default_scope { order("lower(login_name) asc") }
scope :confirmed, -> { where('confirmed_at IS NOT NULL') }
scope :located, -> { where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") }
scope :recently_signed_in, -> { reorder('updated_at DESC') }
scope :recently_joined, -> { reorder("confirmed_at desc") }
scope :wants_newsletter, -> { where(:newsletter => true) }
has_many :follows, :class_name => "Follow", :foreign_key => "follower_id"
has_many :followed, :through => :follows
has_many :inverse_follows, :class_name => "Follow", :foreign_key => "followed_id"
has_many :followers, :through => :inverse_follows, :source => :follower
default_scope order("lower(login_name) asc")
scope :confirmed, where('confirmed_at IS NOT NULL')
scope :located, where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL")
scope :recently_signed_in, reorder('updated_at DESC')
scope :wants_newsletter, where(:newsletter => true)
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
@@ -46,16 +48,6 @@ class Member < ActiveRecord::Base
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable
# Setup accessible (or protected) attributes for your model
attr_accessible :login_name, :email, :password, :password_confirmation,
:remember_me, :login,
# terms of service
:tos_agreement,
# profile stuff
:bio, :location, :latitude, :longitude,
# email settings
:show_email, :newsletter, :send_notification_email, :send_planting_reminder
# set up geocoding
geocoded_by :location
after_validation :geocode
@@ -80,7 +72,7 @@ class Member < ActiveRecord::Base
:message => "name is reserved"
},
:format => {
:with => /^\w+$/,
:with => /\A\w+\z/,
:message => "may only include letters, numbers, or underscores"
},
:uniqueness => {
@@ -93,7 +85,7 @@ class Member < ActiveRecord::Base
# and an account record (for paid accounts etc)
# we use find_or_create to avoid accidentally creating a second one,
# which can happen sometimes especially with FactoryGirl associations
after_create {|member| Account.find_or_create_by_member_id(:member_id => member.id) }
after_create {|member| Account.find_or_create_by(:member_id => member.id) }
after_save :update_newsletter_subscription
@@ -243,17 +235,19 @@ class Member < ActiveRecord::Base
end
end
def newsletter_subscribe
def newsletter_subscribe(testing=false)
return true if (Rails.env.test? && !testing)
gb = Gibbon::API.new
res = gb.lists.subscribe({
:id => Gibbon::API.api_key,
:email => { :email => email },
:merge_vars => { :login_name => login_name },
:double_optin => false # they alredy confirmed their email with us
:double_optin => false # they already confirmed their email with us
})
end
def newsletter_unsubscribe
def newsletter_unsubscribe(testing=false)
return true if (Rails.env.test? && !testing)
gb = Gibbon::API.new
res = gb.lists.unsubscribe({
:id => ENV['GROWSTUFF_MAILCHIMP_NEWSLETTER_ID'],

View File

@@ -1,23 +0,0 @@
class MemberSweeper < ActionController::Caching::Sweeper
observe Member
def after_create(member)
expire_fragment('homepage_stats')
end
def after_update(member)
expire_fragment('interesting_members') if member.interesting?
expire_fragment("interesting_seeds") if member.seeds.tradable.present?
expire_fragment("member_thumbnail_#{member.id}")
if member.plantings.present?
member.plantings.each do |p|
expire_fragment("plantings_listitem_#{p.id}") if p.interesting?
end
expire_fragment('interesting_plantings')
end
end
end

View File

@@ -1,13 +1,10 @@
class Notification < ActiveRecord::Base
attr_accessible :sender_id, :recipient_id,
:subject, :body, :post_id, :read
belongs_to :sender, :class_name => 'Member'
belongs_to :recipient, :class_name => 'Member'
belongs_to :post
default_scope order('created_at DESC')
scope :unread, where(:read => false)
default_scope { order('created_at DESC') }
scope :unread, -> { where(:read => false) }
before_create :replace_blank_subject
after_create :send_email

View File

@@ -1,10 +1,9 @@
class Order < ActiveRecord::Base
attr_accessible :member_id, :completed_at, :referral_code
belongs_to :member
has_many :order_items, :dependent => :destroy
default_scope order('created_at DESC')
default_scope { order('created_at DESC') }
validates :referral_code, :format => {
:with => /\A[a-zA-Z0-9 ]*\z/,

View File

@@ -1,6 +1,4 @@
class OrderItem < ActiveRecord::Base
attr_accessible :order_id, :price, :product_id, :quantity
belongs_to :order
belongs_to :product

View File

@@ -1,20 +1,20 @@
class Photo < ActiveRecord::Base
attr_accessible :flickr_photo_id, :owner_id, :title, :license_name,
:license_url, :thumbnail_url, :fullsize_url, :link_url
belongs_to :owner, :class_name => 'Member'
has_and_belongs_to_many :plantings
has_and_belongs_to_many :harvests
has_and_belongs_to_many :gardens
before_destroy do |photo|
photo.plantings.clear
photo.harvests.clear
photo.gardens.clear
end
default_scope order("created_at desc")
default_scope { order("created_at desc") }
# remove photos that aren't used by anything
def destroy_if_unused
unless plantings.size > 0 or harvests.size > 0
unless plantings.size > 0 or harvests.size > 0 or gardens.size > 0
self.destroy
end
end

View File

@@ -1,13 +0,0 @@
class PhotoSweeper < ActionController::Caching::Sweeper
observe Photo
def after_create(photo)
expire_fragment('interesting_plantings')
end
def after_destroy(photo)
expire_fragment('interesting_plantings')
end
end

View File

@@ -1,11 +1,9 @@
class PlantPart < ActiveRecord::Base
extend FriendlyId
friendly_id :name, :use => :slugged
friendly_id :name, :use => [:slugged, :finders]
has_many :harvests
has_many :crops, :through => :harvests, :uniq => true
attr_accessible :name, :slug
has_many :crops, -> { uniq }, :through => :harvests
def to_s
return name

View File

@@ -1,10 +1,6 @@
class Planting < ActiveRecord::Base
extend FriendlyId
friendly_id :planting_slug, use: :slugged
attr_accessible :crop_id, :description, :garden_id, :planted_at,
:quantity, :sunniness, :planted_from, :owner_id, :finished,
:finished_at
friendly_id :planting_slug, use: [:slugged, :finders]
belongs_to :garden
belongs_to :owner, :class_name => 'Member', :counter_cache => true
@@ -21,9 +17,9 @@ class Planting < ActiveRecord::Base
end
end
default_scope order("created_at desc")
scope :finished, where(:finished => true)
scope :current, where(:finished => false)
default_scope { order("created_at desc") }
scope :finished, -> { where(:finished => true) }
scope :current, -> { where(:finished => false) }
delegate :name,
:en_wikipedia_url,
@@ -32,12 +28,16 @@ class Planting < ActiveRecord::Base
:to => :crop,
:prefix => true
default_scope order("created_at desc")
default_scope { order("created_at desc") }
validates :crop_id, :presence => {:message => "must be present and exist in our database"}
validates :crop, :approved => true
validates :crop, :presence => {:message => "must be present and exist in our database"}
validates :quantity,
:numericality => { :only_integer => true },
:numericality => {
:only_integer => true,
:greater_than_or_equal_to => 0 },
:allow_nil => true
SUNNINESS_VALUES = %w(sun semi-shade shade)

View File

@@ -1,25 +0,0 @@
class PlantingSweeper < ActionController::Caching::Sweeper
observe Planting
def after_create(planting)
expire_fragment('homepage_stats')
expire_fragment("member_thumbnail_#{planting.owner.id}")
expire_fragment("interesting_members") if planting.owner.interesting?
expire_fragment("crop_image_#{planting.crop.id}")
end
def after_update(planting)
expire_fragment("planting_listitem_#{planting.id}")
expire_fragment("planting_image_#{planting.id}")
expire_fragment("interesting_plantings")
end
def after_destroy(planting)
expire_fragment('homepage_stats')
expire_fragment("crop_image_#{planting.crop.id}")
expire_fragment('interesting_plantings') if planting.interesting?
expire_fragment("interesting_members") if planting.owner.interesting?
end
end

View File

@@ -1,7 +1,6 @@
class Post < ActiveRecord::Base
extend FriendlyId
friendly_id :author_date_subject, use: :slugged
attr_accessible :body, :subject, :author_id, :forum_id
friendly_id :author_date_subject, use: [:slugged, :finders]
belongs_to :author, :class_name => 'Member'
belongs_to :forum
has_many :comments, :dependent => :destroy
@@ -11,7 +10,7 @@ class Post < ActiveRecord::Base
# also has_many notifications, but kinda meaningless to get at them
# from this direction, so we won't set up an association for now.
default_scope order("created_at desc")
default_scope { order("created_at desc") }
validates :subject,
:format => {

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
class Role < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
attr_accessible :description, :name, :members, :slug
friendly_id :name, use: [:slugged, :finders]
has_and_belongs_to_many :members
class << self

View File

@@ -1,5 +1,5 @@
class ScientificName < ActiveRecord::Base
attr_accessible :crop_id, :scientific_name, :creator_id
after_commit { |sn| sn.crop.__elasticsearch__.index_document if sn.crop && ENV['GROWSTUFF_ELASTICSEARCH'] == "true" }
belongs_to :crop
belongs_to :creator, :class_name => 'Member'
end

View File

@@ -1,17 +0,0 @@
class ScientificNameSweeper < ActionController::Caching::Sweeper
observe ScientificName
def after_create(scientific_name)
expire_fragment("crop_image_#{scientific_name.crop.id}")
end
def after_update(scientific_name)
expire_fragment("crop_image_#{scientific_name.crop.id}")
end
def after_destroy(scientific_name)
expire_fragment("crop_image_#{scientific_name.crop.id}")
end
end

View File

@@ -1,21 +1,32 @@
class Seed < ActiveRecord::Base
extend FriendlyId
friendly_id :seed_slug, use: :slugged
attr_accessible :owner_id, :crop_id, :description, :quantity, :plant_before,
:tradable_to, :slug
friendly_id :seed_slug, use: [:slugged, :finders]
belongs_to :crop
belongs_to :owner, :class_name => 'Member', :foreign_key => 'owner_id'
default_scope order("created_at desc")
default_scope { order("created_at desc") }
validates :crop, :approved => true
validates :crop, :presence => {:message => "must be present and exist in our database"}
validates :quantity,
:numericality => { :only_integer => true },
:numericality => {
:only_integer => true,
:greater_than_or_equal_to => 0 },
:allow_nil => true
validates :days_until_maturity_min,
:numericality => {
:only_integer => true,
:greater_than_or_equal_to => 0 },
:allow_nil => true
validates :days_until_maturity_max,
:numericality => {
:only_integer => true,
:greater_than_or_equal_to => 0 },
:allow_nil => true
scope :tradable, where("tradable_to != 'nowhere'")
scope :tradable, -> { where("tradable_to != 'nowhere'") }
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally)
validates :tradable_to, :inclusion => { :in => TRADABLE_TO_VALUES,
@@ -23,6 +34,32 @@ class Seed < ActiveRecord::Base
:allow_nil => false,
:allow_blank => false
ORGANIC_VALUES = [
'certified organic',
'non-certified organic',
'conventional/non-organic',
'unknown']
validates :organic, :inclusion => { :in => ORGANIC_VALUES,
:message => "You must say whether the seeds are organic or not, or that you don't know" },
:allow_nil => false,
:allow_blank => false
GMO_VALUES = [
'certified GMO-free',
'non-certified GMO-free',
'GMO',
'unknown']
validates :gmo, :inclusion => { :in => GMO_VALUES,
:message => "You must say whether the seeds are genetically modified or not, or that you don't know" },
:allow_nil => false,
:allow_blank => false
HEIRLOOM_VALUES = %w(heirloom hybrid unknown)
validates :heirloom, :inclusion => { :in => HEIRLOOM_VALUES,
:message => "You must say whether the seeds are heirloom, hybrid, or unknown" },
:allow_nil => false,
:allow_blank => false
def tradable?
if self.tradable_to == 'nowhere'
return false

View File

@@ -1,26 +0,0 @@
class SeedSweeper < ActionController::Caching::Sweeper
observe Seed
def after_create(seed)
if seed.tradable? && seed.interesting?
expire_fragment('interesting_seeds')
end
expire_fragment('interesting_members') if seed.owner.interesting?
expire_fragment("member_thumbnail_#{seed.owner.id}")
end
def after_update(seed)
expire_fragment('interesting_seeds')
end
def after_destroy(seed)
if seed.tradable? && seed.interesting?
expire_fragment('interesting_seeds')
end
expire_fragment('interesting_members') if seed.owner.interesting?
expire_fragment("member_thumbnail_#{seed.owner.id}")
end
end

View File

@@ -0,0 +1,7 @@
class ApprovedValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless record.crop.try(:approved?)
record.errors[attribute] << (options[:message] || 'must be approved')
end
end
end

View File

@@ -8,6 +8,7 @@
%li= link_to "Roles", roles_path
%li= link_to "Forums", forums_path
%li= link_to "Newsletter subscribers", admin_newsletter_path
%li= link_to "CMS", comfy_admin_cms_path
%h2 Orders

View File

@@ -1,5 +1,7 @@
%p#notice= notice
= render :partial => 'crops/approval_status_message', :locals => { :crop => @alternate_name.crop }
%p
%b Alternate name:
= @alternate_name.name

View File

@@ -1,22 +0,0 @@
- content_for :title, "Linked accounts on other sites"
- if @authentications
- unless @authentications.empty?
.authentications
- @authentications.each do |authentication|
%a{ :href => "http://twitter.com/#{authentication.name}" }
.authentication
= image_tag "#{authentication.provider}_64.png", :size => "64x64"
.provider
= authentication.provider.titleize
.name
= authentication.name
= link_to "X", authentication, :confirm => "Are you sure you want to remove this authentication?", :method => :delete, :class => "remove"
.clear
%p
%strong Link another external account:
- else
%p
%strong Link to an external account:
= link_to image_tag("twitter_64.png", :size => "64x64"), "/auth/twitter", :class => "auth_provider"

View File

@@ -0,0 +1,11 @@
- if crop.pending?
.alert.alert-danger
%b This crop is currently pending approval.
%p This crop was requested by #{crop.requester} #{time_ago_in_words(crop.created_at)} ago.
- unless crop.request_notes.blank?
%p
Request notes: #{crop.request_notes}
- if crop.rejected?
.alert.alert-danger
%b This crop was rejected for the following reason: #{crop.rejection_explanation}

View File

@@ -1,4 +1,4 @@
%h4 Find seeds
%h4 Find #{ crop.name } seeds
- if crop.seeds.empty?
%p
There are no seeds available to trade.
@@ -10,7 +10,8 @@
= render :partial => 'members/location', :locals => { :member => seed.owner }
%p
= link_to "View all #{crop.name} seeds", seeds_by_crop_path(crop)
- if current_member
= link_to "List achiote seeds to trade", new_seed_path(:crop_id => crop.id)
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'list your seeds to trade' }
- if crop.approved?
- if current_member
%p= link_to "List #{crop.name} seeds to trade", new_seed_path(:crop_id => crop.id)
- else
= render :partial => 'shared/signin_signup', :locals => { :to => 'list your seeds to trade' }

View File

@@ -6,30 +6,47 @@
- @crop.errors.full_messages.each do |msg|
%li= msg
%p
%span.help-block
For detailed crop wrangling guidelines, please consult the
=link_to "crop wrangling guide", "http://wiki.growstuff.org/index.php/Crop_wrangling"
on the Growstuff wiki.
-# Handy link to crop wrangling policy/style guide, shown to wranglers only
- if can? :wrangle, @crop
%p
%span.help-block
For detailed crop wrangling guidelines, please consult the
=link_to "crop wrangling guide", "http://wiki.growstuff.org/index.php/Crop_wrangling"
on the Growstuff wiki.
-# Everyone (wranglers and requesters) sees the basic info section
%h2 Basic information
.form-group
= f.label :name, :class => 'control-label col-md-2'
.col-md-8
= f.text_field :name, :class => 'form-control'
%span.help-block Name in US English; singular; capitalize proper nouns only.
%span.help-block
The common name for the crop, in English (required).
- if can? :wrangle, @crop
Wranglers: please ensure this is singular, and capitalize
proper nouns only.
.form-group
= f.label :en_wikipedia_url, 'Wikipedia URL', :class => 'control-label col-md-2'
.col-md-8
= f.text_field :en_wikipedia_url, :class => 'form-control'
%span.help-block Link to this crop's page on the English language Wikipedia.
.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')
%span.help-block Optional. For setting up crop hierarchies for varieties etc.
%p
%span.help-block
You may enter up to 3 scientific names for a crop. Most crops will have only one.
%span.help-block
Link to the crop's page on the English language Wikipedia (required).
-# Only crop wranglers see the crop hierarchy (for now)
- if can? :wrangle, @crop
.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')
%span.help-block Optional. For setting up crop hierarchies for varieties etc.
-# Everyone (wranglers and requesters) gets to add scientific names
%h2 Scientific names
%p You may enter up to 3 scientific names for a crop. Most crops will have only one.
= f.fields_for :scientific_names do |sn|
.form-group
= sn.label :scientific_name, "Scientific name", :class => 'control-label col-md-2'
@@ -40,6 +57,42 @@
%label.checkbox
= sn.check_box :_destroy
= sn.label :_destroy, "Delete"
-# This is used for comments from crop requesters. We need to show it
-# to everyone, but we don't include it on new crops from wranglers.
- if (can? :wrangle, @crop and @crop.requester) or (cannot? :wrangle, @crop and @crop.new_record?)
%h2 Crop request notes
.form-group
= f.label :request_notes, 'Comments', :class => 'control-label col-md-2'
.col-md-8
= f.text_area :request_notes, :rows => 3, :class => 'form-control'
-# A final explanation of what's going to happen next, for crop requesters
- unless can? :wrangle, @crop
%p When you submit this form, your suggestion will be sent to our team of #{link_to 'volunteer crop wranglers', 'http://talk.growstuff.org/c/crop-wrangling'} for review. We'll let you know the outcome as soon as we can.
-# Now, for crop wranglers, let's have approval/rejection at the bottom of the page
- if can? :wrangle, @crop and @crop.requester
%h2 Approve or reject pending crops
.form-group
= f.label :approval_status, 'Approval status', :class=> 'control-label col-md-2'
.col-md-8
= f.select(:approval_status, @crop.approval_statuses, {}, {:class => 'form-control'})
.form-group
= f.label :reason_for_rejection, 'Reason for rejection', :class => 'control-label col-md-2'
.col-md-8
= f.select(:reason_for_rejection, @crop.reasons_for_rejection, {:include_blank => true}, {:class => 'form-control'})
.form-group
= f.label :rejection_notes, 'Rejection notes', :class => 'control-label col-md-2'
.col-md-8
= f.text_area :rejection_notes, :rows => 3, :class => 'form-control'
%span.help-block
Please provide additional notes why this crop request was rejected if the above reasons do not apply.
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit 'Save', :class => 'btn btn-primary'

View File

@@ -1,4 +1,4 @@
%h4 Harvests
%h4 #{ crop.name.capitalize } harvests
- if crop.harvests.empty?
%p
Nobody has harvested this crop yet.
@@ -13,9 +13,9 @@
ago.
%p
= link_to "View all #{crop.name} harvests", harvests_by_crop_path(crop)
- if current_member
%p
= link_to "Harvest #{crop.name}", new_harvest_path(:crop_id => crop.id)
- else
= render :partial => 'shared/signin_signup', :locals => { :to => "track your #{crop.name} harvests" }
- if crop.approved?
- if current_member
%p= link_to "Harvest #{crop.name}", new_harvest_path(:crop_id => crop.id)
- else
= render :partial => 'shared/signin_signup', :locals => { :to => "track your #{crop.name} harvests" }

View File

@@ -1,4 +1,4 @@
- cache "crop_image_#{crop.id}" do
- cache crop do
= link_to |
image_tag( |
crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png', |

View File

@@ -1,7 +1,7 @@
.well
.row
.col-md-4
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded crop-image'), crop
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img crop-image'), crop
.col-md-8
%h3{:style => 'padding-top: 0px; margin-top: 0px'}
= link_to crop, crop

View File

@@ -1,4 +1,4 @@
%h4 Plantings
%h4 See who's planted #{ crop.name.pluralize }
- if crop.plantings.empty?
%p
Nobody has planted this crop yet.
@@ -13,9 +13,9 @@
ago.
%p
= link_to "View all #{crop.name} plantings", plantings_by_crop_path(crop)
- if current_member
%p
= link_to "Plant #{crop.name}", new_planting_path(:crop_id => crop.id)
- else
= render :partial => 'shared/signin_signup', :locals => { :to => "track your #{crop.name} plantings" }
- if crop.approved?
- if current_member
%p= link_to "Plant #{crop.name}", new_planting_path(:crop_id => crop.id)
- else
= render :partial => 'shared/signin_signup', :locals => { :to => "track your #{crop.name} plantings" }

View File

@@ -1,14 +1,13 @@
.thumbnail(style='height: 220px')
- if crop
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => crop.name, :class => 'img-rounded'), crop
%p.crop-name
= link_to crop.name, crop
- if crop.scientific_names.count > 0
%br/
%i.scientific-name
%small
.thumbnail
.crop-thumbnail
- if crop
= link_to image_tag((crop.default_photo ? crop.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => crop.name, :class => 'img'), crop
.cropinfo
.cropname
= link_to crop.name, crop
- if crop.scientific_names.count > 0
.scientificname
= crop.scientific_names.first.scientific_name
%br/
%small
.plantingcount
Planted
= pluralize(crop.plantings.size, "time")

View File

@@ -1,10 +1,19 @@
- content_for :title, "Editing crop"
- content_for :title, "Edit crop: #{@crop.name}"
%p
Added by
= @crop.creator
= distance_of_time_in_words(@crop.created_at, Time.zone.now)
ago.
- if @crop.approval_status == "approved"
- if @crop.requester
%p Requested by #{link_to @crop.requester, @crop.requester} #{distance_of_time_in_words(@crop.created_at, Time.zone.now)} ago.
%p Approved by #{link_to @crop.creator, @crop.creator}.
- else
%p Added by #{link_to @crop.creator, @crop.creator} #{distance_of_time_in_words(@crop.created_at, Time.zone.now)} ago.
- elsif @crop.approval_status == "pending"
.alert.alert-danger
%p Requested by #{link_to @crop.requester, @crop.requester} #{distance_of_time_in_words(@crop.created_at, Time.zone.now)} ago.
%p Status: #{@crop.approval_status}.
- elsif @crop.approval_status == "rejected"
.alert.alert-danger
%p Requested by #{link_to @crop.requester, @crop.requester} #{distance_of_time_in_words(@crop.created_at, Time.zone.now)} ago.
%p Status: #{@crop.approval_status} by #{link_to @crop.creator, @crop.creator}.
= render 'form'

View File

@@ -5,5 +5,5 @@
= succeed "." do
= link_to "crops database", crops_path
- cache("full_crop_hierarchy") do
- cache cache_key_for(Crop) do
= render :partial => "hierarchy", :locals => { :display_crops => @crops }

View File

@@ -1,5 +1,8 @@
- content_for :title, "Crops"
- content_for :title, "Browse crops"
- content_for :subtitle, "#{@crops.size} total"
- if can? :wrangle, Crop
= link_to 'Wrangle Crops', wrangle_crops_path, :class => 'btn btn-primary'
%p
#{ENV['GROWSTUFF_SITE_NAME']} tracks who's growing what, where.
View any crop page to see which of our members have planted it and find
@@ -12,11 +15,10 @@
= submit_tag "Show", :class => 'btn btn-primary'
%div.pagination
= page_entries_info @crops, :model => "crops"
= will_paginate @crops
= will_paginate @paginated_crops
.row
- @crops.each do |crop|
- @paginated_crops.each do |crop|
.col-md-2.six-across
= render :partial => "thumbnail", :locals => { :crop => crop }
@@ -25,8 +27,7 @@
= link_to 'New Crop', new_crop_path, {:class => 'btn btn-primary'}
%div.pagination
= page_entries_info @crops, :model => "crops"
= will_paginate @crops
= will_paginate @paginated_crops
%ul.list-inline

View File

@@ -1,3 +1,14 @@
- content_for :title, "New crop"
- content_for :title, (can?(:wrangle, @crop) ? "New crop" : "Suggest a crop")
- unless can? :wrangler, @crop
%p Thanks for taking the time to suggest a crop! Our crop database is managed by volunteers, and we appreciate your help. Here are some things to consider when suggesting a new crop:
%ul
%li First, you might want to #{link_to 'search our crops', crops_search_path} to make sure we don't have it already, perhaps under an alternate name.
%li The Growstuff database only contains edible crops. In future we hope to support other crops, but for now, if your suggestion is not edible we won't be able to add it.
%li At this time, we are only adding crops which have a Wikipedia page. If you want to add a specific variety of crop that doesn't have its own Wikipedia entry, please use the more general form of the crop instead and put the name of your variety in the notes/description.
= render 'form'

View File

@@ -1,26 +1,35 @@
- content_for :title, "Crops matching #{@search}"
- if @term
- content_for :title, "Crops matching \"#{@term}\""
- if @matches
- content_for :subtitle, "#{@matches.size} total"
- else
- content_for :title, "Crop search"
- unless (@exact_match || @partial_matches.length > 0)
%div
= form_tag crops_search_path, :method => :get, :id => 'crop-search', :class => 'form-inline' do
.form-group
= label_tag :term, "Search crops:", :class => 'sr-only'
= text_field_tag 'term', nil, :class => 'search-query input-medium form-control', :placeholder => 'Search crops', :value => @term
= submit_tag "Search", :class => 'btn btn-primary'
- if @matches.empty?
%h2 No results found
%p
Sorry, we couldn't find any crops that matched your search for "#{@search}".
Sorry, we couldn't find any crops that matched your search for "#{@term}".
%p
Try
= link_to "browsing our crop database", crops_path
instead.
- if @exact_match
%div#exact_match
%h2 Exact match
- else
%div.pagination
= will_paginate @paginated_matches
%div#paginated_matches
.row
.col-md-2.six-across
= render :partial => "thumbnail", :locals => { :crop => @exact_match }
- if ! @partial_matches.empty?
%div#partial_matches
%h2 Partial matches
.row
- @partial_matches.each do |c|
- @paginated_matches.each do |c|
.col-md-2.six-across
= render :partial => "thumbnail", :locals => { :crop => c }
%div.pagination
= will_paginate @paginated_matches

View File

@@ -1,18 +1,24 @@
- content_for :title, @crop.name
- content_for :subtitle, @crop.default_scientific_name
- content_for :buttonbar do
- if can? :create, Planting
= link_to "Plant this", new_planting_path(:crop_id => @crop.id), :class => 'btn btn-default'
- if can? :create, Harvest
= link_to "Harvest this", new_harvest_path(:crop_id => @crop.id), :class => 'btn btn-default'
= render :partial => 'approval_status_message', :locals => { :crop => @crop }
- if can? :create, Seed
= link_to 'Add seeds to stash', new_seed_path(:params => { :crop_id => @crop.id }), :class => 'btn btn-default'
- if @crop.approved?
- content_for :buttonbar do
- if can? :create, Planting
= link_to "Plant this", new_planting_path(:crop_id => @crop.id), :class => 'btn btn-default'
- if can? :create, Harvest
= link_to "Harvest this", new_harvest_path(:crop_id => @crop.id), :class => 'btn btn-default'
- if can? :create, Seed
= link_to 'Add seeds to stash', new_seed_path(:params => { :crop_id => @crop.id }), :class => 'btn btn-default'
.row
.col-md-9
- unless current_member
Learn how to grow #{ @crop.name.pluralize } from growers around the world. #{ ENV['GROWSTUFF_SITE_NAME'] } has tips and advice from real-life growers, including when to plant #{ @crop.name.pluralize }, how to harvest #{ @crop.name.pluralize }, and more.
= render :partial => 'photos', :locals => { :crop => @crop }
@@ -34,37 +40,46 @@
%div#cropmap
%a{:name => 'posts'}
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
%h2 What people are saying about #{ @crop.name.pluralize }
- unless @posts.empty?
- if @posts.empty?
%p
Nobody has posted about #{ @crop.name.pluralize } yet.
%p
- if can? :create, Post
= link_to "Post something", new_post_path, :class => 'btn btn-default'
- else
= render :partial => "shared/signin_signup", :locals => { :to => "post your tips and experiences growing #{ @crop.name.pluralize }" }
- else
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
- @posts.each do |post|
= render :partial => "posts/single", :locals => { :post => post, :subject => true }
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
%div.pagination
= page_entries_info @posts, :model => "posts"
= will_paginate @posts, :params => {:anchor => "posts"}
.col-md-3
= render :partial => 'wrangle', :locals => { :crop => @crop }
= render :partial => 'scientific_names', :locals => { :crop => @crop }
= render :partial => 'alternate_names', :locals => { :crop => @crop }
%h4 Planting advice
%h4 How to grow #{ @crop.name.pluralize }
= render :partial => 'grown_for', :locals => { :crop => @crop }
= render :partial => 'planting_advice', :locals => { :crop => @crop }
%h4 Varieties
= render :partial => 'scientific_names', :locals => { :crop => @crop }
= render :partial => 'alternate_names', :locals => { :crop => @crop }
%h4 #{ @crop.name.capitalize } varieties
= render :partial => 'varieties', :locals => { :crop => @crop }
%h4 More information
%ul
%li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url
= render :partial => 'plantings', :locals => { :crop => @crop }
= render :partial => 'harvests', :locals => { :crop => @crop }
= render :partial => 'find_seeds', :locals => { :crop => @crop }
%h4 Learn more about #{ @crop.name.pluralize }
%ul
%li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url

View File

@@ -15,28 +15,50 @@
%li.crop_wrangler
= link_to crop_wrangler.login_name, crop_wrangler
%h2 Recently added crops
.tabbable
%ul.nav.nav-tabs
%li{:class => @approval_status.blank? ? 'active' : ''}
= link_to "Recently added", wrangle_crops_path
%li{:class => @approval_status == "pending" ? 'active' : ''}
= link_to "Pending approval", wrangle_crops_path(:approval_status => "pending")
%li{:class => @approval_status == "rejected" ? 'active' : ''}
= link_to "Rejected", wrangle_crops_path(:approval_status => "rejected")
%h2
- if @approval_status == "pending"
Requested Crops
- elsif @approval_status == "rejected"
Rejected Crops
- else
Recently added crops
%div.pagination
= page_entries_info @crops, :model => "crops"
= will_paginate @crops
%table.table.table-striped
%table{:class => "table table-striped", :id => @approval_status.blank? ? 'recently-added-crops' : "#{@approval_status}-crops"}
%tr
%th System name
%th English Wikipedia URL
%th Scientific names
%th Added by
%th Requested by
- if @approval_status == "rejected"
%th Rejected by
- if @approval_status != "rejected" && @approval_status != "pending"
%th Added by
%th When
- @crops.each do |c|
%tr
%td= link_to c.name, c
%td= link_to c.name, edit_crop_path(c)
%td= link_to c.en_wikipedia_url, c.en_wikipedia_url
%td
- c.scientific_names.each do |s|
= link_to s.scientific_name, s
%br/
%td= link_to c.creator, c.creator
%td= c.requester.present? ? (link_to c.requester, c.requester) : "N/A"
- unless @approval_status == "pending"
%td= c.creator.present? ? (link_to c.creator, c.creator) : "N/A"
%td
= distance_of_time_in_words(c.created_at, Time.zone.now)
ago.
@@ -44,3 +66,5 @@
%div.pagination
= page_entries_info @crops, :model => "crops"
= will_paginate @crops

View File

@@ -29,6 +29,21 @@
:growstuff_markdown
#{strip_tags @garden.description}
- if @garden.photos.count > 0 or (can? :edit, @garden and can? :create, Photo)
.row
%h2 Photos
%ul.thumbnails
- @garden.photos.each do |p|
.col-md-2.six-across
= render :partial => 'photos/thumbnail', :locals => { :photo => p }
- if can? :create, Photo and can? :edit, @garden
.col-md-2
.thumbnail(style='height: 220px')
%p{:style => 'text-align: center; padding-top: 50px'}
= link_to "Add photo", new_photo_path(:type => "garden", :id => @garden.id), :class => 'btn btn-primary'
%h3
What's planted here?

View File

@@ -14,7 +14,7 @@
= collection_select(:harvest, :plant_part_id, PlantPart.all, :id, :name, { :selected => @harvest.plant_part_id }, { :class => 'form-control' })
%span.help-block.col-md-8
Can't find what you're looking for?
= link_to "Request new crops.", Growstuff::Application.config.new_crops_request_link
= link_to "Request new crops.", new_crop_path
.form-group
= f.label :harvested_at, 'When?', :class => 'control-label col-md-2'

View File

@@ -10,6 +10,7 @@ csv.headers :id,
:unit,
:weight_quantity,
:weight_unit,
:si_weight,
:date_harvested,
:description,
:date_added,
@@ -31,7 +32,7 @@ csv.headers :id,
csv.cell :plant_part_id, h.plant_part ? h.plant_part.id : ''
csv.cell :plant_part_name, h.plant_part ? h.plant_part.to_s : ''
csv.cells :quantity, :unit, :weight_quantity, :weight_unit
csv.cells :quantity, :unit, :weight_quantity, :weight_unit, :si_weight
csv.cell :date_harvested, h.created_at.to_s(:db)

View File

@@ -1,19 +1,24 @@
.row
.col-md-6.hidden-xs
- cache "interesting_crops", :expires_in => 1.day do
.col-md-8
- cache cache_key_for(Crop, 'interesting'), :expires_in => 1.day do
%h2= t('.our_crops')
- Crop.interesting.each do |c|
.col-md-3{:style => 'margin:0px; padding: 3px'}
= render :partial => 'crops/image_with_popover', :locals => { :crop => c }
.hidden-xs
- Crop.interesting.first(8).each do |c|
.col-md-3
= render :partial => 'crops/thumbnail', :locals => { :crop => c }
.visible-xs
- Crop.interesting.first(3).each do |c|
.col-md-3
= render :partial => 'crops/thumbnail', :locals => { :crop => c }
.col-md-6
- cache "interesting_plantings" do
.col-md-4.hidden-xs
- cache cache_key_for(Planting) do
%h2= t('.recently_planted')
= render :partial => 'plantings/list', :locals => { :plantings => Planting.interesting.first(4) }
= render :partial => 'plantings/list', :locals => { :plantings => Planting.interesting.first(6) }
.row
.col-md-12
- cache "recent_crops" do
- cache cache_key_for(Crop, 'recent') do
%p{ :style => 'margin-top: 11.25px' }
%strong
#{t('.recently_added')}:

View File

@@ -1,11 +1,10 @@
%h2= t('.discussion')
- cache "recent_posts" do
- posts = Post.limit(6)
- if posts
=render :partial => "posts/summary", :locals => { :posts => posts, :howmany => 6 }
- posts = Post.limit(6)
- if posts
=render :partial => "posts/summary", :locals => { :posts => posts, :howmany => 6 }
- cache "homepage_forums" do
- cache cache_key_for(Forum) do
- forums = Forum.all
- if forums
%ul.list-inline

View File

@@ -1,17 +0,0 @@
%h2= t('.keep_in_touch')
%p
= link_to(image_tag("twitter_32.png", :alt => ''), 'http://twitter.com/growstufforg', :target => "_blank")
= t('.twitter_html', link: link_to(t('.twitter_linktext'), 'http://twitter.com/growstufforg', :target => "_blank"))
%p
= link_to(image_tag("facebook_32.png", :alt => ''), 'https://www.facebook.com/Growstufforg', :target => "_blank")
= t('.facebook_html', link: link_to(t('.facebook_linktext'), 'https://www.facebook.com/Growstufforg', :target => "_blank"))
%p
= link_to(image_tag("blog_32.png", :alt => ''), 'http://blog.growstuff.org/', :target => "_blank")
= t('.blog_html', link: link_to(t('.blog_linktext'), 'http://blog.growstuff.org/', :target => "_blank"))
%p
= link_to(image_tag("email_32.png", :alt => ''), 'http://blog.growstuff.org/newsletter', :target => "_blank")
= t('.newsletter_html', link: link_to(t('.newsletter_linktext'), 'http://blog.growstuff.org/newsletter', :target => "_blank"))

View File

@@ -1,4 +1,4 @@
- cache "interesting_members" do
- cache cache_key_for(Member) do
.hidden-xs
- members = Member.interesting.first(6)
- if members.present?
@@ -6,7 +6,7 @@
.row
- members.each do |m|
.col-md-6.homepage-members
.col-md-4.homepage-members
= render :partial => "members/thumbnail", :locals => { :member => m }
%p.text-right

View File

@@ -1,29 +0,0 @@
%h2= t('.open_source_title')
%p
= t('.open_source_body_html', why: link_to(t('.why_linktext'), 'http://blog.growstuff.org/2013/02/20/why-growstuff-is-open-source/'),
github: link_to(t('.github_linktext'), 'http://github.com/Growstuff/growstuff'),
site_name: ENV['GROWSTUFF_SITE_NAME'] )
%h2= t('.open_data_title')
%p
= t('.open_data_body_html', creative_commons_link: link_to(t('.creative_commons_linktext'), 'http://creativecommons.org/licenses/by-sa/3.0/'),
wiki_link: link_to(t('.wiki_linktext'), 'http://wiki.growstuff.org/index.php/Open_data'),
api_docs_link: link_to(t('.api_docs_linktext'), 'http://wiki.growstuff.org/index.php/API'))
%h2= t('.get_involved_title')
%p
= t('.get_involved_body_html', talk_link: link_to(t('.talk_linktext'), 'http://talk.growstuff.org/'),
wiki_link: link_to(t('.wiki_linktext'), 'http://wiki.growstuff.org/'))
%h2= t('.support_title')
%p
= t('.support_body_html', ad_free: link_to(t('.ad_free_linktext'), 'http://wiki.growstuff.org/index.php/Why_no_ads%3F'),
buy_account: link_to(t('.buy_account_linktext'), shop_path))

View File

@@ -3,7 +3,7 @@
%h2= t('.title')
- cache "interesting_seeds" do
- cache cache_key_for(Seed) do
- if seeds.length > 0
%table.table.table-striped

View File

@@ -17,13 +17,9 @@
= render :partial => 'blurb'
.visible-xs
= render :partial => 'blurb'
.row
.col-md-8.main
= render :partial => 'crops'
= render :partial => 'seeds'
= render :partial => 'members'
= render :partial => 'discuss'
.col-md-4.sidebar
= render :partial => 'keep_in_touch'
= render :partial => 'open'

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