Compare commits

...

255 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
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
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
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
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
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
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
127 changed files with 2247 additions and 384 deletions

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

@@ -52,4 +52,6 @@ submit the change with your pull request.
- 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)

15
Gemfile
View File

@@ -31,6 +31,9 @@ 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 'comfortable_mexican_sofa', '~> 1.12.0' # content management system
# vendored activemerchant for testing- needed for bogus paypal
# gateway monkeypatch
@@ -76,6 +79,12 @@ 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 :production, :staging do
@@ -83,6 +92,7 @@ group :production, :staging do
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
@@ -93,6 +103,7 @@ group :development do
gem 'better_errors'
gem 'binding_of_caller'
gem 'letter_opener'
gem 'quiet_assets'
end
group :development, :test do
@@ -109,3 +120,7 @@ group :development, :test do
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

@@ -33,6 +33,8 @@ GEM
activesupport (= 4.1.9)
builder (~> 3.1)
erubis (~> 2.7.0)
active_link_to (1.0.2)
actionpack
activemodel (4.1.9)
activesupport (= 4.1.9)
builder (~> 3.1)
@@ -48,6 +50,9 @@ GEM
tzinfo (~> 1.1)
addressable (2.3.6)
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)
@@ -56,8 +61,13 @@ 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)
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)
@@ -73,7 +83,13 @@ GEM
capybara-email (2.4.0)
capybara (~> 2.4)
mail
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 (4.1.0)
coffee-script (>= 2.2.0)
@@ -83,6 +99,21 @@ GEM
execjs
coffee-script-source (1.8.0)
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)
coveralls (0.7.1)
multi_json (~> 1.3)
@@ -109,13 +140,29 @@ GEM
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)
@@ -136,6 +183,9 @@ GEM
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)
hpricot (0.8.6)
@@ -167,6 +217,7 @@ GEM
sprockets-rails
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)
@@ -191,6 +242,7 @@ GEM
minitest (5.5.1)
multi_json (1.10.1)
multi_xml (0.5.5)
multipart-post (2.0.0)
netrc (0.10.0)
newrelic_rpm (3.9.8.273)
nokogiri (1.6.5)
@@ -208,7 +260,14 @@ 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)
@@ -218,6 +277,8 @@ GEM
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
quiet_assets (1.1.0)
railties (>= 3.1, < 5.0)
rack (1.5.2)
rack-test (0.6.3)
rack (>= 1.0)
@@ -231,6 +292,9 @@ GEM
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
@@ -269,6 +333,7 @@ GEM
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)
@@ -335,6 +400,7 @@ DEPENDENCIES
better_errors
binding_of_caller
bluecloth
bonsai-elasticsearch-rails
bootstrap-datepicker-rails
bundler (>= 1.1.5)
byebug
@@ -342,11 +408,14 @@ DEPENDENCIES
capybara
capybara-email
coffee-rails (~> 4.1.0)
comfortable_mexican_sofa (~> 1.12.0)
coveralls
csv_shaper
dalli
database_cleaner (~> 1.3.0)
devise (~> 3.4.1)
elasticsearch-model
elasticsearch-rails
factory_girl_rails (~> 4.5.0)
figaro
flickraw
@@ -356,6 +425,7 @@ DEPENDENCIES
gravatar-ultimate
haml
haml-rails
heroku-api
i18n-tasks
jquery-rails
jquery-ui-rails (~> 5.0.2)
@@ -375,11 +445,13 @@ DEPENDENCIES
pg
poltergeist (~> 1.5.1)
pry
quiet_assets
rails (= 4.1.9)
rails_12factor
rake (>= 10.0.0)
rspec-activemodel-mocks
rspec-rails (~> 3.1.0)
ruby-units
sass-rails (~> 4.0.4)
therubyracer (~> 0.12)
uglifier (~> 2.5.3)

View File

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

View File

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

View File

@@ -1,5 +1,3 @@
@import "twitter/bootstrap/bootstrap";
@import "custom_bootstrap/variables";
// this padding needs to be done before the responsive stuff is imported
@@ -168,16 +166,31 @@ p.stats {
.crop-thumbnail {
height: 220px;
.scientific-name small, .crop-name a {
.cropinfo {
display: inline-block;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1em;
padding-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;
}
@@ -201,8 +214,10 @@ li.crop-hierarchy {
margin: 40px 0px 0px 0px !important;
}
// footer
footer {
#contact, #about-growstuff, #policies {
#footer1, #footer2, #footer3 {
text-align: left;
padding-top: 1em;
padding-bottom: 2em;
@@ -229,6 +244,17 @@ footer {
}
}
// ensure footer is pushed to bottom of browser window
#maincontainer {
min-height: 80%;
}
html, body {
height: 100%;
}
//
.crop-image, .member-image {
width: 100%;
@@ -257,6 +283,12 @@ footer {
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) {
@@ -274,3 +306,13 @@ footer {
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

@@ -1,3 +1,5 @@
require 'will_paginate/array'
class CropsController < ApplicationController
before_filter :authenticate_member!, :except => [:index, :hierarchy, :search, :show]
load_and_authorize_resource
@@ -9,10 +11,12 @@ class CropsController < ApplicationController
@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|
@@ -32,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
@@ -49,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 = @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
@@ -96,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(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" }
@@ -120,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(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
@@ -146,6 +184,6 @@ class CropsController < ApplicationController
private
def crop_params
params.require(:crop).permit(:en_wikipedia_url, :name, :parent_id, :creator_id, :scientific_names_attributes)
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,11 @@
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 => follow_params[:followed_id])
if @follow.save

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
@@ -107,6 +107,6 @@ class HarvestsController < ApplicationController
def harvest_params
params.require(:harvest).permit(:crop_id, :harvested_at, :description, :owner_id,
:quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug)
:quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug, :si_weight)
end
end

View File

@@ -6,7 +6,12 @@ class MembersController < ApplicationController
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

View File

@@ -65,7 +65,7 @@ class PhotosController < ApplicationController
# 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]

View File

@@ -110,7 +110,9 @@ class SeedsController < ApplicationController
private
def seed_params
params.require(:seed).permit(:owner_id, :crop_id, :description, :quantity, :plant_before,
:tradable_to, :slug)
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

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

View File

@@ -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,4 +1,5 @@
class AlternateName < ActiveRecord::Base
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

@@ -2,18 +2,19 @@ class Crop < ActiveRecord::Base
extend FriendlyId
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, -> { 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'
@@ -21,16 +22,94 @@ class Crop < ActiveRecord::Base
before_destroy {|crop| crop.posts.clear}
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
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") }
## Wikipedia urls are only necessary when approving a crop
validates :en_wikipedia_url,
:format => {
: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
@@ -103,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
@@ -200,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

@@ -7,6 +7,17 @@ class Garden < ActiveRecord::Base
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
@@ -23,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 = {
@@ -83,4 +96,8 @@ class Garden < ActiveRecord::Base
end
end
def default_photo
return photos.first
end
end

View File

@@ -20,10 +20,14 @@ class Harvest < ActiveRecord::Base
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 = {
@@ -59,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

@@ -32,6 +32,7 @@ class Member < ActiveRecord::Base
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"

View File

@@ -3,16 +3,18 @@ class Photo < ActiveRecord::Base
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") }
# 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

@@ -30,10 +30,14 @@ class Planting < ActiveRecord::Base
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

@@ -2,8 +2,11 @@ class Product < ActiveRecord::Base
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,4 +1,5 @@
class ScientificName < ActiveRecord::Base
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

@@ -7,9 +7,23 @@ class Seed < ActiveRecord::Base
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'") }
@@ -20,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

@@ -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

@@ -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

@@ -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

@@ -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,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

@@ -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.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
%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

@@ -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,14 +1,18 @@
- 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

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,29 +1,9 @@
.navbar.navbar-default.navbar-bottom
.container
.row
.col-md-4#about-growstuff
%ul
%li= link_to t('about'), "http://wiki.growstuff.org/index.php/About%20Growstuff"
%li= link_to t('our_values'), "http://wiki.growstuff.org/index.php/Values"
%li= link_to t('open_source'), "https://github.com/Growstuff/growstuff"
%li= link_to t('growstuff_team'), "http://wiki.growstuff.org/index.php/Team"
%li= link_to t('get_involved'), "http://wiki.growstuff.org/index.php/Get_involved"
.col-md-4#policies
%ul
%li= link_to t('terms_of_service'), url_for(:controller => '/policy', :action => 'tos')
%li= link_to t('privacy_policy'), url_for(:controller => '/policy', :action => 'privacy')
%li= link_to t('data_use_policy'), url_for(:controller => '/policy', :action => 'api')
%li= link_to t('community_guidelines'), url_for(:controller => '/policy', :action => 'community')
.col-md-4#contact
%ul
%li= link_to t('support_'), url_for(:controller => '/support')
%li= link_to t('contact'), url_for(:controller => '/about', :action => 'contact')
%p
= link_to('http://twitter.com/growstufforg', :target => "_blank") do
= image_tag("twitter_32.png", :alt => 'Twitter: @growstufforg')
&nbsp;
= link_to('https://www.facebook.com/Growstufforg', :target => "_blank") do
= image_tag("facebook_32.png", :alt => 'Facebook')
&nbsp;
= link_to('http://blog.growstuff.org/', :target => "_blank") do
= image_tag("blog_32.png", :alt => 'Growstuff Blog')
.col-md-4#footer1
!= cms_snippet_content(:footer1)
.col-md-4#footer2
!= cms_snippet_content(:footer2)
.col-md-4#footer3
!= cms_snippet_content(:footer3)

View File

@@ -65,12 +65,14 @@
%li= link_to "Sign out", destroy_member_session_path, :method => :delete
- else
%li= link_to 'Sign in', new_member_session_path
%li= link_to 'Sign up', new_member_registration_path
%li= link_to 'Sign in', new_member_session_path, :id => 'navbar-signin'
%li= link_to 'Sign up', new_member_registration_path, :id => 'navbar-signup'
= form_tag crops_search_path, :method => :get, :class => 'navbar-form pull-right' do
= form_tag crops_search_path, :method => :get, :id => 'navbar-search', :class => 'navbar-form pull-right' do
.input
= text_field_tag 'search', nil, :class => 'search-query input-medium form-control', :placeholder => 'Search crops'
= label_tag :term, "Search crop database:", :class => 'sr-only'
= text_field_tag 'term', nil, :class => 'search-query input-medium form-control', :placeholder => 'Search crops'
= submit_tag "Search", :class => 'btn sr-only'
- # anchor tag for accessibility link to skip the navigation menu
%a{:name => 'skipnav'}

View File

@@ -5,7 +5,7 @@
= render :partial => "layouts/header"
= render :partial => "layouts/crowdfunding"
.container
#maincontainer.container
.row
.col-md-12
- if content_for?(:title)

View File

@@ -5,5 +5,5 @@
:size => defined?(size) ? size : 150, |
:default => :identicon }), |
:alt => '', |
:class => 'img-rounded img-responsive avatar' ), |
:class => 'img img-responsive avatar' ), |
member_path(member)

View File

@@ -19,6 +19,20 @@
:growstuff_markdown
#{ strip_tags g.description }
- if g.photos.count > 0 or (can? :edit, g and can? :create, Photo)
.row
%h2 Photos
%ul.thumbnails
- g.photos.each do |p|
.col-md-2.six-across
= render :partial => 'photos/thumbnail', :locals => { :photo => p }
- if can? :create, Photo and can? :edit, g
.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 => g.id), :class => 'btn btn-primary'
%h3 What's planted here?
- g.featured_plantings.each do |p|
= render :partial => "plantings/thumbnail", :locals => { :planting => p, :hide_description => true }

View File

@@ -1,5 +1,11 @@
= content_for :title, "#{ENV['GROWSTUFF_SITE_NAME']} members"
= form_tag(members_path, :method => :get, :class => 'form-inline', :role => 'form') do
.form-group
= label_tag :sort, "Sort by:", :class => 'sr-only'
= select_tag "sort", options_for_select({"Sort alphabetically" => 'alpha', "Sort by recently joined" => "recently_joined"}, @sort || 'alpha'), :class => 'form-control'
= submit_tag "Show", :class => 'btn btn-primary'
%div.pagination
= page_entries_info @members, :model => "members"
= will_paginate @members

View File

@@ -5,14 +5,16 @@
= link_to 'Edit profile', edit_member_registration_path, :class => 'btn btn-default'
- if @member == current_member && !@member.is_paid?
= link_to "Upgrade account", shop_path, :class => 'btn btn-default'
-if can? :create, Notification and current_member != @member
=link_to 'Send message', new_notification_path(:recipient_id => @member.id), :class => 'btn btn-default'
- if can? :create, Follow and current_member != @member
- if !current_member.already_following?(@member)
- if can? :create, Notification and current_member != @member
= link_to 'Send message', new_notification_path(:recipient_id => @member.id), :class => 'btn btn-default'
- if current_member and current_member != @member # must be logged in, can't follow yourself
- follow = current_member.get_follow(@member)
- if !follow and can? :create, Follow # not already following
= link_to 'Follow', follows_path(:followed_id => @member.id), :method => :post, :class => 'btn btn-default'
- else
- follow = current_member.get_follow(@member)
- if follow and can? :destroy, follow # already following
= link_to 'Unfollow', follow_path(follow), :method => :delete, :class => 'btn btn-default'
- content_for :member_rss_login_name, @member.login_name
- content_for :member_rss_slug, @member.slug

View File

@@ -0,0 +1,6 @@
- site_name = ENV['GROWSTUFF_SITE_NAME']
%p
The #{site_name} team.
%br/
=link_to root_url, root_url

View File

@@ -0,0 +1,16 @@
- site_name = ENV['GROWSTUFF_SITE_NAME']
%p Hello #{@member.login_name},
%p
Your request for the new crop: #{link_to @crop.name, crop_url(@crop)} has been approved! Thank you for helping us make our listing ever more complete!
%ul
%li
= link_to "Plant #{@crop.name}", new_planting_url(crop_id: @crop.id)
%li
= link_to "Harvest #{@crop.name}", new_harvest_url(crop_id: @crop.id)
%li
= link_to "Stash seeds for #{@crop.name}", new_seed_url(crop_id: @crop.id)
= render :partial => 'signature'

View File

@@ -0,0 +1,7 @@
- site_name = ENV['GROWSTUFF_SITE_NAME']
%p Hello #{@member.login_name},
%p
We're sorry, but your request for the new crop: #{link_to @crop.name, crop_url(@crop)} has been rejected for the following reason: #{@crop.rejection_explanation}
= render :partial => 'signature'

View File

@@ -0,0 +1,22 @@
- site_name = ENV['GROWSTUFF_SITE_NAME']
%p Hello #{@member.login_name},
%p
#{@request.requester.login_name} has requested a new crop on #{site_name}.
%ul
%li Name: #{@request.name}
%li Wikipedia URL: #{@request.en_wikipedia_url.present? ? @request.en_wikipedia_url : "not specified"}
%li Notes: #{@request.request_notes}
%p
As a crop wrangler, you can #{link_to "approve or reject this request", edit_crop_url(@request)}.
%p
Or, discuss this and other crop wrangling issues in our #{link_to "crop wrangling forum", "http://talk.growstuff.org/c/crop-wrangling"}.
%p
Thanks for your help!
= render :partial => 'signature'

View File

@@ -20,7 +20,4 @@
%br/
= link_to "Turn off these notifications", edit_member_registration_url
%p
The #{site_name} team.
%br/
=link_to root_url, root_url
= render :partial => 'signature'

View File

@@ -59,10 +59,7 @@
%h2
See you soon on #{site_name}!
%p
The #{site_name} team.
%br/
=link_to root_url, root_url
= render :partial => 'signature'
%hr/
%p

View File

@@ -10,7 +10,7 @@
- @photos.each do |p|
.col-md-2.six-across
.thumbnail(style='height: 220px')
= link_to image_tag(p.thumbnail_url, :alt => p.title, :class => 'img-rounded'), p
= link_to image_tag(p.thumbnail_url, :alt => p.title, :class => 'img'), p
%p
= link_to p.title, p
by

View File

@@ -27,7 +27,7 @@
- @photos.each do |p|
.col-md-2.six-across
.thumbnail(style='height: 220px')
= link_to image_tag(FlickRaw.url_q(p), :alt => '', :class => 'img-rounded'), photos_path(:photo => { :flickr_photo_id => p.id }, :type => @type, :id => @id), :method => :post
= link_to image_tag(FlickRaw.url_q(p), :alt => '', :class => 'img'), photos_path(:photo => { :flickr_photo_id => p.id }, :type => @type, :id => @id), :method => :post
%p
=p.title

View File

@@ -27,5 +27,5 @@
.row
.col-md-12
%p= image_tag(@photo.fullsize_url, :alt => @photo.title, :class => 'img-rounded')
%p= image_tag(@photo.fullsize_url, :alt => @photo.title, :class => 'img')

View File

@@ -12,7 +12,7 @@
= auto_suggest @planting, :crop, :class => 'form-control', :default => @crop
%span.help-inline
Can't find what you're looking for?
= link_to "Request new crops.", Growstuff::Application.config.new_crops_request_link
= link_to "Request new crops.", new_crop_path
.form-group
= f.label :garden_id, 'Where did you plant it?', :class => 'control-label col-md-2'
.col-md-8

View File

@@ -1,7 +1,7 @@
.well
.row
.col-md-3
= link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img-rounded'), planting
= link_to image_tag((planting.default_photo ? planting.default_photo.thumbnail_url : 'placeholder_150.png'), :alt => '', :class => 'img'), planting
.col-md-9
%h4

View File

@@ -1,5 +1,19 @@
= content_for :title, @post.subject
- unless current_member
.alert.alert-info
= link_to @post.author.login_name, member_path(@post.author)
is using
= link_to ENV["GROWSTUFF_SITE_NAME"], root_path
to discuss #{ @post.subject } with a community of food gardeners worldwide.
We have advice on growing
= succeed "," do
= link_to 'hundreds of different crops', crops_url
and a community from all around the world.
= render :partial => "shared/signin_signup",
:locals => { :to => "or to start using #{ENV["GROWSTUFF_SITE_NAME"]} to track what you're planting and harvesting" }
= render :partial => "single", :locals => { :post => @post, :subject => false, :hide_comments => true }
- if can? :edit, @post or can? :destroy, @post

View File

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

View File

@@ -0,0 +1,9 @@
- if seed.days_until_maturity_min.blank?
- if seed.days_until_maturity_max.blank?
unknown
- else
= seed.days_until_maturity_max.to_s
- elsif seed.days_until_maturity_max.blank?
= seed.days_until_maturity_min.to_s
- else
!= "#{seed.days_until_maturity_min}&ndash;#{seed.days_until_maturity_max}"

View File

@@ -12,7 +12,7 @@
= auto_suggest @seed, :crop, :class => 'form-control', :default => @crop
%span.help-inline
Can't find what you're looking for?
= link_to "Request new crops.", Growstuff::Application.config.new_crops_request_link
= link_to "Request new crops.", new_crop_path
.form-group
= f.label :quantity, 'Quantity:', :class => 'control-label col-md-2'
.col-md-2
@@ -21,6 +21,29 @@
= f.label :plant_before, 'Plant before:', :class => 'control-label col-md-2'
.col-md-2
= f.text_field :plant_before, :class => 'add-datepicker form-control', :value => @seed.plant_before ? @seed.plant_before.to_s(:ymd) : ''
.form-group
= f.label :days_until_maturity_min, 'Days until maturity:', :class => 'control-label col-md-2'
%fieldset
.col-md-2
= f.number_field :days_until_maturity_min, :class => 'form-control'
.col-md-1
= f.label :days_until_maturity_max, 'to', :class => 'control-label'
.col-md-2
= f.number_field :days_until_maturity_max, :class => 'form-control'
.col-md-1
= f.label :dummy, 'days', :class => 'control-label'
.form-group
= f.label :organic, 'Organic?', :class => 'control-label col-md-2'
.col-md-8
= f.select(:organic, Seed::ORGANIC_VALUES, {}, :class => 'form-control', :default => 'unknown')
.form-group
= f.label :gmo, 'GMO?', :class => 'control-label col-md-2'
.col-md-8
= f.select(:gmo, Seed::GMO_VALUES, {}, :class => 'form-control', :default => 'unknown')
.form-group
= f.label :heirloom, 'Heirloom?', :class => 'control-label col-md-2'
.col-md-8
= f.select(:heirloom, Seed::HEIRLOOM_VALUES, {}, :class => 'form-control', :default => 'unknown')
.form-group
= f.label :description, 'Description:', :class => 'control-label col-md-2'
.col-md-8

View File

@@ -13,6 +13,18 @@
%p
%b Plant before:
= @seed.plant_before.to_s
%p
%b Days until maturity:
= render :partial => 'days_until_maturity', :locals => { :seed => @seed }
%p
%b Organic?
= @seed.organic
%p
%b GMO?
= @seed.gmo
%p
%b Heirloom?
= @seed.heirloom
%p
%b Will trade:
= @seed.tradable_to

View File

@@ -62,6 +62,13 @@ GROWSTUFF_PAYPAL_USERNAME: "dummy"
GROWSTUFF_PAYPAL_PASSWORD: "dummy"
GROWSTUFF_PAYPAL_SIGNATURE: "dummy"
# Elasticsearch is used for flexible search and it requires another component
# to be installed. To make it easy for people who don't need to test this feature
# it's been turned off for test and development environment as a default.
# If you want to test this functionality, install elasticsearch and
# set this flag to "true".
GROWSTUFF_ELASTICSEARCH: "false"
##############################################################################
# Other environments
# You can override the above for staging, production, etc.
@@ -78,6 +85,8 @@ test:
staging:
GROWSTUFF_SITE_NAME: Growstuff (staging)
GROWSTUFF_ELASTICSEARCH: "true"
production:
GROWSTUFF_SITE_NAME: Growstuff
GROWSTUFF_ELASTICSEARCH: "true"

View File

@@ -44,7 +44,6 @@ Growstuff::Application.configure do
# config.action_view.raise_on_missing_translations = true
# Growstuff config
config.new_crops_request_link = "http://example.com/not-a-real-url"
config.action_mailer.default_url_options = { :host => 'localhost:8080' }
config.action_mailer.delivery_method = :letter_opener

View File

@@ -67,7 +67,6 @@ Growstuff::Application.configure do
config.active_record.dump_schema_after_migration = false
# Growstuff configuration
config.new_crops_request_link = "http://growstuff.org/posts/skud-20130319-requests-for-new-crops"
config.action_mailer.default_url_options = { :host => 'growstuff.org' }
config.action_mailer.smtp_settings = {

View File

@@ -1,6 +1,8 @@
Growstuff::Application.configure do
# Settings specified here will take precedence over those in config/application.rb
config.action_controller.action_on_unpermitted_parameters = :raise
# Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better.
@@ -67,7 +69,6 @@ Growstuff::Application.configure do
config.active_record.dump_schema_after_migration = false
# Growstuff configuration
config.new_crops_request_link = "http://example.com/not-a-real-url"
config.action_mailer.default_url_options = { :host => 'staging.growstuff.org' }
config.action_mailer.smtp_settings = {

View File

@@ -40,7 +40,6 @@ Growstuff::Application.configure do
# config.action_view.raise_on_missing_translations = true
# Growstuff config
config.new_crops_request_link = "http://example.com/not-a-real-url"
config.action_mailer.default_url_options = { :host => 'localhost:8080' }
Growstuff::Application.configure do

View File

@@ -0,0 +1,103 @@
# encoding: utf-8
ComfortableMexicanSofa.configure do |config|
# Title of the admin area
# config.cms_title = 'ComfortableMexicanSofa CMS Engine'
# Controller that is inherited from CmsAdmin::BaseController
# config.base_controller = 'ApplicationController'
# Module responsible for authentication. You can replace it with your own.
# It simply needs to have #authenticate method. See http_auth.rb for reference.
config.admin_auth = 'CmsDeviseAuth'
# Module responsible for authorization on admin side. It should have #authorize
# method that returns true or false based on params and loaded instance
# variables available for a given controller.
# config.admin_authorization = 'ComfyAdminAuthorization'
# Module responsible for public authentication. Similar to the above. You also
# will have access to @cms_site, @cms_layout, @cms_page so you can use them in
# your logic. Default module doesn't do anything.
# config.public_auth = 'ComfyPublicAuthentication'
# When arriving at /cms-admin you may chose to redirect to arbirtary path,
# for example '/cms-admin/users'
# config.admin_route_redirect = ''
# File uploads use Paperclip and can support filesystem or s3 uploads. Override
# the upload method and appropriate settings based on Paperclip. For S3 see:
# http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/S3, and for
# filesystem see: http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/Filesystem
# If you are using S3 and HTTPS, pass :s3_protocol => '' to have URLs that use the protocol of the page
# config.upload_file_options = {:url => '/system/:class/:id/:attachment/:style/:filename'}
# Sofa allows you to setup entire site from files. Database is updated with each
# request (if necessary). Please note that database entries are destroyed if there's
# no corresponding file. Fixtures are disabled by default.
# config.enable_fixtures = false
# Path where fixtures can be located.
# config.fixtures_path = File.expand_path('db/cms_fixtures', Rails.root)
# Importing fixtures into Database
# To load fixtures into the database just run this rake task:
# local: $ rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=localhost
# Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=yourapp.herokuapp.com
# From indicates folder the fixtures are in and to is the Site hostname you have defined in the database.
# Exporting fixtures into Files
# If you need to dump database contents into fixture files run:
# local: $ rake comfortable_mexican_sofa:fixtures:export FROM=localhost TO=example.local
# Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:export FROM=yourapp.herokuapp.com TO=example.local
# This will create example.local folder and dump all content from example.com Site.
# Content for Layouts, Pages and Snippets has a revision history. You can revert
# a previous version using this system. You can control how many revisions per
# object you want to keep. Set it to 0 if you wish to turn this feature off.
# config.revisions_limit = 25
# Locale definitions. If you want to define your own locale merge
# {:locale => 'Locale Title'} with this.
# config.locales = {:en => 'English', :es => 'Español'}
# Admin interface will respect the locale of the site being managed. However you can
# force it to English by setting this to `:en`
# config.admin_locale = nil
# A class that is included as a sweeper to admin base controller if it's set
# config.admin_cache_sweeper = nil
# By default you cannot have irb code inside your layouts/pages/snippets.
# Generally this is to prevent putting something like this:
# <% User.delete_all %> but if you really want to allow it...
# config.allow_irb = false
# Whitelist of all helper methods that can be used via {{cms:helper}} tag. By default
# all helpers are allowed except `eval`, `send`, `call` and few others. Empty array
# will prevent rendering of all helpers.
# config.allowed_helpers = nil
# Whitelist of partials paths that can be used via {{cms:partial}} tag. All partials
# are accessible by default. Empty array will prevent rendering of all partials.
# config.allowed_partials = nil
# Site aliases, if you want to have aliases for your site. Good for harmonizing
# production env with dev/testing envs.
# e.g. config.hostname_aliases = {'host.com' => 'host.inv', 'host_a.com' => ['host.lvh.me', 'host.dev']}
# Default is nil (not used)
# config.hostname_aliases = nil
# Reveal partials that can be overwritten in the admin area.
# Default is false.
# config.reveal_cms_partials = false
end
module CmsDeviseAuth
def authenticate
unless current_member && current_member.has_role?(:admin)
redirect_to root_path, :alert => 'Permission denied. Please sign in as an admin user to use the CMS admin area.'
end
end
end

View File

@@ -1,5 +1,6 @@
Growstuff::Application.routes.draw do
resources :plant_parts
devise_for :members, :controllers => { :registrations => "registrations", :passwords => "passwords" }
@@ -78,12 +79,14 @@ Growstuff::Application.routes.draw do
get '/shop' => 'shop#index'
get '/shop/:action' => 'shop#:action'
comfy_route :cms_admin, :path => '/admin/cms'
get '/admin/orders' => 'admin/orders#index'
get '/admin/orders/:action' => 'admin/orders#:action'
get '/admin' => 'admin#index'
get '/admin/newsletter' => 'admin#newsletter', :as => :admin_newsletter
get '/admin/:action' => 'admin#:action'
# CMS stuff -- must remain LAST
comfy_route :cms, :path => '/', :sitemap => false
end

View File

@@ -0,0 +1,9 @@
class AddPropertiesToSeeds < ActiveRecord::Migration
def change
add_column :seeds, :days_until_maturity_min, :integer
add_column :seeds, :days_until_maturity_max, :integer
add_column :seeds, :organic, :text, :default => 'unknown'
add_column :seeds, :gmo, :text, :default => 'unknown'
add_column :seeds, :heirloom, :text, :default => 'unknown'
end
end

View File

@@ -0,0 +1,9 @@
class AddGardensPhotosTable < ActiveRecord::Migration
def change
create_table :gardens_photos, :id => false do |t|
t.integer :photo_id
t.integer :garden_id
end
add_index(:gardens_photos, [:garden_id, :photo_id])
end
end

View File

@@ -0,0 +1,5 @@
class AddSiWeightToHarvest < ActiveRecord::Migration
def change
add_column :harvests, :si_weight, :float
end
end

View File

@@ -0,0 +1,6 @@
class AddRequesterToCrops < ActiveRecord::Migration
def change
add_column :crops, :requester_id, :integer
add_index :crops, :requester_id
end
end

View File

@@ -0,0 +1,140 @@
class CreateCms < ActiveRecord::Migration
def self.up
text_limit = case ActiveRecord::Base.connection.adapter_name
when 'PostgreSQL'
{ }
else
{ :limit => 16777215 }
end
# -- Sites --------------------------------------------------------------
create_table :comfy_cms_sites do |t|
t.string :label, :null => false
t.string :identifier, :null => false
t.string :hostname, :null => false
t.string :path
t.string :locale, :null => false, :default => 'en'
t.boolean :is_mirrored, :null => false, :default => false
end
add_index :comfy_cms_sites, :hostname
add_index :comfy_cms_sites, :is_mirrored
# -- Layouts ------------------------------------------------------------
create_table :comfy_cms_layouts do |t|
t.integer :site_id, :null => false
t.integer :parent_id
t.string :app_layout
t.string :label, :null => false
t.string :identifier, :null => false
t.text :content, text_limit
t.text :css, text_limit
t.text :js, text_limit
t.integer :position, :null => false, :default => 0
t.boolean :is_shared, :null => false, :default => false
t.timestamps
end
add_index :comfy_cms_layouts, [:parent_id, :position]
add_index :comfy_cms_layouts, [:site_id, :identifier], :unique => true
# -- Pages --------------------------------------------------------------
create_table :comfy_cms_pages do |t|
t.integer :site_id, :null => false
t.integer :layout_id
t.integer :parent_id
t.integer :target_page_id
t.string :label, :null => false
t.string :slug
t.string :full_path, :null => false
t.text :content_cache, text_limit
t.integer :position, :null => false, :default => 0
t.integer :children_count, :null => false, :default => 0
t.boolean :is_published, :null => false, :default => true
t.boolean :is_shared, :null => false, :default => false
t.timestamps
end
add_index :comfy_cms_pages, [:site_id, :full_path]
add_index :comfy_cms_pages, [:parent_id, :position]
# -- Page Blocks --------------------------------------------------------
create_table :comfy_cms_blocks do |t|
t.string :identifier, :null => false
t.text :content, text_limit
t.references :blockable, :polymorphic => true
t.timestamps
end
add_index :comfy_cms_blocks, [:identifier]
add_index :comfy_cms_blocks, [:blockable_id, :blockable_type]
# -- Snippets -----------------------------------------------------------
create_table :comfy_cms_snippets do |t|
t.integer :site_id, :null => false
t.string :label, :null => false
t.string :identifier, :null => false
t.text :content, text_limit
t.integer :position, :null => false, :default => 0
t.boolean :is_shared, :null => false, :default => false
t.timestamps
end
add_index :comfy_cms_snippets, [:site_id, :identifier], :unique => true
add_index :comfy_cms_snippets, [:site_id, :position]
# -- Files --------------------------------------------------------------
create_table :comfy_cms_files do |t|
t.integer :site_id, :null => false
t.integer :block_id
t.string :label, :null => false
t.string :file_file_name, :null => false
t.string :file_content_type, :null => false
t.integer :file_file_size, :null => false
t.string :description, :limit => 2048
t.integer :position, :null => false, :default => 0
t.timestamps
end
add_index :comfy_cms_files, [:site_id, :label]
add_index :comfy_cms_files, [:site_id, :file_file_name]
add_index :comfy_cms_files, [:site_id, :position]
add_index :comfy_cms_files, [:site_id, :block_id]
# -- Revisions -----------------------------------------------------------
create_table :comfy_cms_revisions, :force => true do |t|
t.string :record_type, :null => false
t.integer :record_id, :null => false
t.text :data, text_limit
t.datetime :created_at
end
add_index :comfy_cms_revisions, [:record_type, :record_id, :created_at],
:name => 'index_cms_revisions_on_rtype_and_rid_and_created_at'
# -- Categories ---------------------------------------------------------
create_table :comfy_cms_categories, :force => true do |t|
t.integer :site_id, :null => false
t.string :label, :null => false
t.string :categorized_type, :null => false
end
add_index :comfy_cms_categories, [:site_id, :categorized_type, :label], :unique => true,
:name => 'index_cms_categories_on_site_id_and_cat_type_and_label'
create_table :comfy_cms_categorizations, :force => true do |t|
t.integer :category_id, :null => false
t.string :categorized_type, :null => false
t.integer :categorized_id, :null => false
end
add_index :comfy_cms_categorizations, [:category_id, :categorized_type, :categorized_id], :unique => true,
:name => 'index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id'
end
def self.down
drop_table :comfy_cms_sites
drop_table :comfy_cms_layouts
drop_table :comfy_cms_pages
drop_table :comfy_cms_snippets
drop_table :comfy_cms_blocks
drop_table :comfy_cms_files
drop_table :comfy_cms_revisions
drop_table :comfy_cms_categories
drop_table :comfy_cms_categorizations
end
end

View File

@@ -0,0 +1,5 @@
class AddApprovalStatusToCrops < ActiveRecord::Migration
def change
add_column :crops, :approval_status, :string, default: "approved"
end
end

View File

@@ -0,0 +1,5 @@
class AddReasonForRejectionToCrops < ActiveRecord::Migration
def change
add_column :crops, :reason_for_rejection, :text
end
end

View File

@@ -0,0 +1,5 @@
class AddRequestNotesToCrops < ActiveRecord::Migration
def change
add_column :crops, :request_notes, :text
end
end

View File

@@ -0,0 +1,5 @@
class AddRejectionNotesToCrops < ActiveRecord::Migration
def change
add_column :crops, :rejection_notes, :text
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141119130555) do
ActiveRecord::Schema.define(version: 20150209105410) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -53,6 +53,125 @@ ActiveRecord::Schema.define(version: 20141119130555) do
add_index "authentications", ["member_id"], name: "index_authentications_on_member_id", using: :btree
create_table "comfy_cms_blocks", force: true do |t|
t.string "identifier", null: false
t.text "content"
t.integer "blockable_id"
t.string "blockable_type"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "comfy_cms_blocks", ["blockable_id", "blockable_type"], name: "index_comfy_cms_blocks_on_blockable_id_and_blockable_type", using: :btree
add_index "comfy_cms_blocks", ["identifier"], name: "index_comfy_cms_blocks_on_identifier", using: :btree
create_table "comfy_cms_categories", force: true do |t|
t.integer "site_id", null: false
t.string "label", null: false
t.string "categorized_type", null: false
end
add_index "comfy_cms_categories", ["site_id", "categorized_type", "label"], name: "index_cms_categories_on_site_id_and_cat_type_and_label", unique: true, using: :btree
create_table "comfy_cms_categorizations", force: true do |t|
t.integer "category_id", null: false
t.string "categorized_type", null: false
t.integer "categorized_id", null: false
end
add_index "comfy_cms_categorizations", ["category_id", "categorized_type", "categorized_id"], name: "index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id", unique: true, using: :btree
create_table "comfy_cms_files", force: true do |t|
t.integer "site_id", null: false
t.integer "block_id"
t.string "label", null: false
t.string "file_file_name", null: false
t.string "file_content_type", null: false
t.integer "file_file_size", null: false
t.string "description", limit: 2048
t.integer "position", default: 0, null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "comfy_cms_files", ["site_id", "block_id"], name: "index_comfy_cms_files_on_site_id_and_block_id", using: :btree
add_index "comfy_cms_files", ["site_id", "file_file_name"], name: "index_comfy_cms_files_on_site_id_and_file_file_name", using: :btree
add_index "comfy_cms_files", ["site_id", "label"], name: "index_comfy_cms_files_on_site_id_and_label", using: :btree
add_index "comfy_cms_files", ["site_id", "position"], name: "index_comfy_cms_files_on_site_id_and_position", using: :btree
create_table "comfy_cms_layouts", force: true do |t|
t.integer "site_id", null: false
t.integer "parent_id"
t.string "app_layout"
t.string "label", null: false
t.string "identifier", null: false
t.text "content"
t.text "css"
t.text "js"
t.integer "position", default: 0, null: false
t.boolean "is_shared", default: false, null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "comfy_cms_layouts", ["parent_id", "position"], name: "index_comfy_cms_layouts_on_parent_id_and_position", using: :btree
add_index "comfy_cms_layouts", ["site_id", "identifier"], name: "index_comfy_cms_layouts_on_site_id_and_identifier", unique: true, using: :btree
create_table "comfy_cms_pages", force: true do |t|
t.integer "site_id", null: false
t.integer "layout_id"
t.integer "parent_id"
t.integer "target_page_id"
t.string "label", null: false
t.string "slug"
t.string "full_path", null: false
t.text "content_cache"
t.integer "position", default: 0, null: false
t.integer "children_count", default: 0, null: false
t.boolean "is_published", default: true, null: false
t.boolean "is_shared", default: false, null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "comfy_cms_pages", ["parent_id", "position"], name: "index_comfy_cms_pages_on_parent_id_and_position", using: :btree
add_index "comfy_cms_pages", ["site_id", "full_path"], name: "index_comfy_cms_pages_on_site_id_and_full_path", using: :btree
create_table "comfy_cms_revisions", force: true do |t|
t.string "record_type", null: false
t.integer "record_id", null: false
t.text "data"
t.datetime "created_at"
end
add_index "comfy_cms_revisions", ["record_type", "record_id", "created_at"], name: "index_cms_revisions_on_rtype_and_rid_and_created_at", using: :btree
create_table "comfy_cms_sites", force: true do |t|
t.string "label", null: false
t.string "identifier", null: false
t.string "hostname", null: false
t.string "path"
t.string "locale", default: "en", null: false
t.boolean "is_mirrored", default: false, null: false
end
add_index "comfy_cms_sites", ["hostname"], name: "index_comfy_cms_sites_on_hostname", using: :btree
add_index "comfy_cms_sites", ["is_mirrored"], name: "index_comfy_cms_sites_on_is_mirrored", using: :btree
create_table "comfy_cms_snippets", force: true do |t|
t.integer "site_id", null: false
t.string "label", null: false
t.string "identifier", null: false
t.text "content"
t.integer "position", default: 0, null: false
t.boolean "is_shared", default: false, null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "comfy_cms_snippets", ["site_id", "identifier"], name: "index_comfy_cms_snippets_on_site_id_and_identifier", unique: true, using: :btree
add_index "comfy_cms_snippets", ["site_id", "position"], name: "index_comfy_cms_snippets_on_site_id_and_position", using: :btree
create_table "comments", force: true do |t|
t.integer "post_id", null: false
t.integer "author_id", null: false
@@ -62,17 +181,23 @@ ActiveRecord::Schema.define(version: 20141119130555) do
end
create_table "crops", force: true do |t|
t.string "name", null: false
t.string "name", null: false
t.string "en_wikipedia_url"
t.datetime "created_at"
t.datetime "updated_at"
t.string "slug"
t.integer "parent_id"
t.integer "plantings_count", default: 0
t.integer "plantings_count", default: 0
t.integer "creator_id"
t.integer "requester_id"
t.string "approval_status", default: "approved"
t.text "reason_for_rejection"
t.text "request_notes"
t.text "rejection_notes"
end
add_index "crops", ["name"], name: "index_crops_on_name", using: :btree
add_index "crops", ["requester_id"], name: "index_crops_on_requester_id", using: :btree
add_index "crops", ["slug"], name: "index_crops_on_slug", unique: true, using: :btree
create_table "crops_posts", id: false, force: true do |t|
@@ -119,6 +244,13 @@ ActiveRecord::Schema.define(version: 20141119130555) do
add_index "gardens", ["owner_id"], name: "index_gardens_on_owner_id", using: :btree
add_index "gardens", ["slug"], name: "index_gardens_on_slug", unique: true, using: :btree
create_table "gardens_photos", id: false, force: true do |t|
t.integer "photo_id"
t.integer "garden_id"
end
add_index "gardens_photos", ["garden_id", "photo_id"], name: "index_gardens_photos_on_garden_id_and_photo_id", using: :btree
create_table "harvests", force: true do |t|
t.integer "crop_id", null: false
t.integer "owner_id", null: false
@@ -132,6 +264,7 @@ ActiveRecord::Schema.define(version: 20141119130555) do
t.decimal "weight_quantity"
t.string "weight_unit"
t.integer "plant_part_id"
t.float "si_weight"
end
create_table "harvests_photos", id: false, force: true do |t|
@@ -272,6 +405,7 @@ ActiveRecord::Schema.define(version: 20141119130555) do
t.datetime "updated_at"
t.string "slug"
t.integer "forum_id"
t.integer "parent_id"
end
add_index "posts", ["created_at", "author_id"], name: "index_posts_on_created_at_and_author_id", using: :btree
@@ -307,15 +441,20 @@ ActiveRecord::Schema.define(version: 20141119130555) do
end
create_table "seeds", force: true do |t|
t.integer "owner_id", null: false
t.integer "crop_id", null: false
t.integer "owner_id", null: false
t.integer "crop_id", null: false
t.text "description"
t.integer "quantity"
t.date "plant_before"
t.datetime "created_at"
t.datetime "updated_at"
t.string "tradable_to", default: "nowhere"
t.string "tradable_to", default: "nowhere"
t.string "slug"
t.integer "days_until_maturity_min"
t.integer "days_until_maturity_max"
t.text "organic", default: "unknown"
t.text "gmo", default: "unknown"
t.text "heirloom", default: "unknown"
end
add_index "seeds", ["slug"], name: "index_seeds_on_slug", unique: true, using: :btree

View File

@@ -314,6 +314,20 @@ namespace :growstuff do
end
end
end
desc "January 2015: fill in si_weight column"
task :populate_si_weight => :environment do
Harvest.find_each do |h|
h.set_si_weight
h.save
end
end
desc "January 2015: build Elasticsearch index"
task :elasticsearch_create_index => :environment do
Crop.__elasticsearch__.create_index! force: true
Crop.import
end
end # end oneoff section
end

View File

@@ -18,3 +18,9 @@ rake growstuff:import_crops file=db/seeds/crops-15-squashes.csv
echo "2014-12-01 - load alternate names for crops"
rake growstuff:oneoff:add_alternate_names
echo "2015-01-28 - populate the harvest si_weight field"
rake growstuff:oneoff:populate_si_weight
echo "2015-01-30 - build Elasticsearch index"
rake growstuff:oneoff:elasticsearch_create_index

25
script/heroku_maintenance.rb Executable file
View File

@@ -0,0 +1,25 @@
#!/usr/bin/env ruby
require 'heroku-api'
require 'yaml'
heroku = Heroku::API.new(:api_key => ENV['HEROKU_API_KEY'])
branch = ENV['TRAVIS_BRANCH']
travis_config = YAML.load_file('.travis.yml')
if travis_config['deploy']['app'].has_key? branch
app = travis_config['deploy']['app'][branch]
else
abort "No Heroku app found for branch #{branch}"
end
case ARGV[0]
when "on"
maintenance_state = 1
when "off"
maintenance_state = 0
else
abort "usage: #{$0} (on|off)"
end
puts "Turning #{maintenance_state} maintenance mode on app #{app}"
heroku.post_app_maintenance(app, maintenance_state)

View File

@@ -7,7 +7,8 @@ describe CropsController do
def valid_attributes
{
:name => "Tomato",
:en_wikipedia_url => 'http://en.wikipedia.org/wiki/Tomato'
:en_wikipedia_url => 'http://en.wikipedia.org/wiki/Tomato',
:approval_status => 'approved'
}
end

View File

@@ -37,6 +37,11 @@ describe HarvestsController do
assigns(:crop).should eq @maize
assigns(:harvests).should eq [@harvest2]
end
it "generates a csv" do
get :index, {:format => "csv"}
response.status.should eq 200
end
end
describe "GET show" do

View File

@@ -48,6 +48,12 @@ describe PhotosController do
assigns(:type).should eq "harvest"
end
it "assigns a garden id" do
get :new, { :type => "garden", :id => 5 }
assigns(:id).should eq "5"
assigns(:type).should eq "garden"
end
it "assigns the current set as @current_set" do
get :new, { :set => 'foo' }
assigns(:current_set).should eq "foo"

View File

@@ -3,6 +3,7 @@ FactoryGirl.define do
factory :crop do
name "magic bean"
en_wikipedia_url "http://en.wikipedia.org/wiki/Magic_bean"
approval_status "approved"
creator
factory :tomato do
@@ -54,6 +55,21 @@ FactoryGirl.define do
name "Swiss chard"
end
#for testing crop request
factory :crop_request do
name "Ultra berry"
en_wikipedia_url ""
approval_status "pending"
association :requester, factory: :member
request_notes "Please approve this even though it's fake."
end
factory :rejected_crop do
name "Fail bean"
approval_status "rejected"
reason_for_rejection "Totally fake"
end
end
end

View File

@@ -8,6 +8,11 @@ FactoryGirl.define do
quantity 1
plant_before "2013-07-15"
tradable_to 'nowhere'
organic 'unknown'
gmo 'unknown'
heirloom 'unknown'
days_until_maturity_min nil
days_until_maturity_max nil
factory :tradable_seed do
tradable_to "locally"

View File

@@ -0,0 +1,42 @@
require 'rails_helper'
feature "products" do
context "admin user" do
let(:member) { FactoryGirl.create(:admin_member) }
background do
login_as(member)
end
scenario "navigating to product admin" do
visit admin_path
click_link "Products"
current_path.should eq products_path
end
scenario "adding a product" do
visit products_path
click_link "New Product"
current_path.should eq new_product_path
fill_in 'Name', :with => 'Special offer'
# note that failing to fill in a mandatory field has a messy error. This is not a priority defect but should be raised at some point.
fill_in 'Minimum price', :with => '150'
click_button 'Save'
current_path.should eq product_path(Product.last)
page.should have_content 'Product was successfully created'
end
scenario 'editing product' do
p = FactoryGirl.create(:product)
visit product_path(p)
click_link 'Edit'
fill_in 'Name', :with => 'Something else'
click_button 'Save'
current_path.should eq product_path(p)
page.should have_content 'Product was successfully updated'
page.should have_content 'Something else'
end
scenario 'deleting product'
# this isn't possible. Should it be?
end
end

37
spec/features/cms_spec.rb Normal file
View File

@@ -0,0 +1,37 @@
require 'spec_helper'
feature "cms admin" do
before(:each) do
@member = FactoryGirl.create(:member)
@admin_member = FactoryGirl.create(:admin_member)
end
scenario "can't view CMS admin if not signed in" do
visit comfy_admin_cms_path
current_path.should == root_path
page.should have_content("Please sign in as an admin user")
end
scenario "can't view CMS admin if not an admin member" do
# sign in as an ordinary member
visit root_path
click_link 'navbar-signin'
fill_in 'Login', :with => @member.email
fill_in 'Password', :with => @member.password
click_button 'Sign in'
visit comfy_admin_cms_path
current_path.should == root_path
page.should have_content("Please sign in as an admin user")
end
scenario "admin members can view CMS admin area" do
visit root_path
# now we sign in as an admin member
click_link 'navbar-signin'
fill_in 'Login', :with => @admin_member.email
fill_in 'Password', :with => @admin_member.password
click_button 'Sign in'
visit comfy_admin_cms_path
current_path.should match /#{comfy_admin_cms_path}/ # match any CMS admin page
end
end

View File

@@ -1,24 +0,0 @@
require 'rails_helper'
feature "crop wranglers" do
context "signed in member" do
let!(:crop_wranglers) { FactoryGirl.create_list(:crop_wrangling_member, 3) }
let(:member){crop_wranglers.first}
background do
login_as(member)
end
scenario "crop wranglers are listed on the crop wrangler page" do
visit root_path
click_link 'Crop Wrangling'
within '.crop_wranglers' do
expect(page).to have_content 'Crop Wranglers:'
crop_wranglers.each do |crop_wrangler|
page.should have_link crop_wrangler.login_name, :href => member_path(crop_wrangler)
end
end
end
end
end

View File

@@ -69,6 +69,18 @@ feature "Alternate names" do
expect(page).to have_content alternate_eggplant.crop.name
end
context "When alternate name is rejected" do
let(:rejected_crop) { FactoryGirl.create(:rejected_crop) }
let(:pending_alt_name) { FactoryGirl.create(:alternate_name, :crop => rejected_crop) }
scenario "Displays crop rejection message" do
visit alternate_name_path(pending_alt_name)
expect(page).to have_content "This crop was rejected for the following reason: Totally fake"
end
end
end
end

View File

@@ -0,0 +1,30 @@
require 'rails_helper'
feature "browse crops" do
let(:tomato) { FactoryGirl.create(:tomato) }
let(:maize) { FactoryGirl.create(:maize) }
let(:pending_crop) { FactoryGirl.create(:crop_request) }
let(:rejected_crop) { FactoryGirl.create(:rejected_crop) }
scenario "has a form for sorting by" do
visit crops_path
expect(page).to have_css "select#sort"
end
scenario "shows a list of crops" do
crop1 = tomato
visit crops_path
expect(page).to have_content crop1.name
end
scenario "pending crops are not listed" do
visit crops_path
expect(page).not_to have_content pending_crop.name
end
scenario "rejected crops are not listed" do
visit crops_path
expect(page).not_to have_content rejected_crop.name
end
end

View File

@@ -0,0 +1,22 @@
require 'rails_helper'
feature "crop search" do
scenario "search results show the search term in title" do
visit root_path
within "form#navbar-search" do
fill_in "term", with: "tomato"
click_button "Search"
end
expect(page).to have_css "h1", text: "Crops matching \"tomato\""
end
scenario "search page with no search term shows suitable title" do
visit crops_search_path
expect(page).to have_css "h1", text: "Crop search"
end
scenario "search page has a search form on it" do
visit crops_search_path
expect(page).to have_css "form#crop-search"
end
end

View File

@@ -0,0 +1,82 @@
require 'rails_helper'
feature "crop wranglers" do
context "signed in wrangler" do
let!(:crop_wranglers) { FactoryGirl.create_list(:crop_wrangling_member, 3) }
let(:wrangler){crop_wranglers.first}
let!(:crops) { FactoryGirl.create_list(:crop, 2) }
let!(:requested_crop) { FactoryGirl.create(:crop_request) }
let!(:rejected_crop) { FactoryGirl.create(:rejected_crop) }
background do
login_as(wrangler)
end
scenario "sees crop wranglers listed on the crop wrangler page" do
visit root_path
click_link 'Crop Wrangling'
within '.crop_wranglers' do
expect(page).to have_content 'Crop Wranglers:'
crop_wranglers.each do |crop_wrangler|
page.should have_link crop_wrangler.login_name, :href => member_path(crop_wrangler)
end
end
end
scenario "can see list of crops with extra detail of who created a crop" do
visit root_path
click_link 'Crop Wrangling'
within '#recently-added-crops' do
expect(page).to have_content "#{crops.first.creator.login_name}"
end
end
scenario "visiting a crop can see wrangler links" do
visit crop_path(crops.first)
expect(page).to have_content 'You are a CROP WRANGLER'
expect(page).to have_link 'Edit crop'
expect(page).to have_link 'Delete crop'
end
scenario "can create a new crop" do
visit root_path
click_link 'Crop Wrangling'
click_link 'Add Crop'
fill_in 'Name', with: "aubergine"
fill_in 'Wikipedia URL', with: "http://en.wikipedia.org/wiki/Maize"
fill_in 'crop_scientific_names_attributes_0_scientific_name', with: "planticus maximus"
click_on 'Save'
expect(page).to have_content 'Crop was successfully created'
expect(page).to have_content 'planticus maximus'
end
scenario "View pending crops" do
visit crop_path(requested_crop)
expect(page).to have_content "This crop is currently pending approval."
expect(page).to have_content "Please approve this even though it's fake."
end
scenario "View rejected crops" do
visit crop_path(rejected_crop)
expect(page).to have_content "This crop was rejected for the following reason: Totally fake"
end
end
context "signed in non-wrangler" do
let!(:crop_wranglers) { FactoryGirl.create_list(:crop_wrangling_member, 3) }
let(:member) { FactoryGirl.create(:member) }
background do
login_as(member)
end
scenario "can't see wrangling page" do
visit root_path
expect(page).not_to have_link "Crop Wrangling"
end
end
end

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