mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-05-25 09:19:15 -04:00
Compare commits
508 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf8fab8ed9 | ||
|
|
376e6c08d3 | ||
|
|
0cbaac3c75 | ||
|
|
6be9640625 | ||
|
|
1841548936 | ||
|
|
d3b927b44b | ||
|
|
9d68690d86 | ||
|
|
900e7361c6 | ||
|
|
7b0fdcf007 | ||
|
|
9aa4fa8031 | ||
|
|
391111a5bf | ||
|
|
818c8f0c37 | ||
|
|
915030e583 | ||
|
|
832719b01a | ||
|
|
0d8cbc5bf2 | ||
|
|
bac8f5e4cc | ||
|
|
69980d9ec6 | ||
|
|
2129b6480d | ||
|
|
fe860aa1ab | ||
|
|
a382caab48 | ||
|
|
e1e9a52186 | ||
|
|
66c8ce78bc | ||
|
|
e1a2b168c9 | ||
|
|
8763c22284 | ||
|
|
9ec2f76909 | ||
|
|
b94cb2abd6 | ||
|
|
7abafd7b74 | ||
|
|
502862128f | ||
|
|
96b1e78962 | ||
|
|
e077f6c7b1 | ||
|
|
b25a938936 | ||
|
|
0952d7d32f | ||
|
|
9963502026 | ||
|
|
5c2b14376e | ||
|
|
330bc912c1 | ||
|
|
bd46c37f07 | ||
|
|
c08c038df1 | ||
|
|
0fb9ea7a11 | ||
|
|
89c29ea73c | ||
|
|
9c116f5887 | ||
|
|
eb1013f925 | ||
|
|
9bd1484a95 | ||
|
|
7a90c020fc | ||
|
|
0a69ee682c | ||
|
|
8b5c63e898 | ||
|
|
dfe12fd7f8 | ||
|
|
73a2ac87da | ||
|
|
9cce0e39f6 | ||
|
|
10c20c7f91 | ||
|
|
f52b828abe | ||
|
|
c76fb15cfd | ||
|
|
167417a711 | ||
|
|
7fcd3cba8d | ||
|
|
9cb58ab0c9 | ||
|
|
702bbeb724 | ||
|
|
38fbc52a6f | ||
|
|
34e86f5881 | ||
|
|
20c72e1205 | ||
|
|
c02562518d | ||
|
|
723ebff923 | ||
|
|
62e7c716dd | ||
|
|
b17e4eed7d | ||
|
|
19727144d8 | ||
|
|
e62adc297a | ||
|
|
2e46cccd21 | ||
|
|
bbc19a5436 | ||
|
|
4cf0f85ee8 | ||
|
|
d268d2b09e | ||
|
|
200a1c9a84 | ||
|
|
ebacd83dde | ||
|
|
c878baa886 | ||
|
|
564731667e | ||
|
|
bae25cfe8f | ||
|
|
5f3dd04068 | ||
|
|
2eddaf90cf | ||
|
|
91d2998507 | ||
|
|
7eb0ee16b9 | ||
|
|
83392ddda1 | ||
|
|
847f4d88d6 | ||
|
|
fb9a1fdfd3 | ||
|
|
783406d730 | ||
|
|
be67b858b4 | ||
|
|
a796ba904a | ||
|
|
012f2f0cfa | ||
|
|
3e8c61c0c3 | ||
|
|
844f68ef4c | ||
|
|
e95566ed48 | ||
|
|
916fd73071 | ||
|
|
18a8d6c5bf | ||
|
|
37d01e831f | ||
|
|
975deab4b2 | ||
|
|
fb6f1ac0a8 | ||
|
|
069343803e | ||
|
|
36d38fe624 | ||
|
|
0d6680f574 | ||
|
|
dac2343b68 | ||
|
|
f24e02fd11 | ||
|
|
dddc7b020d | ||
|
|
12a9a0b97d | ||
|
|
6a8f48693b | ||
|
|
50a0668c1d | ||
|
|
a7e88a55b3 | ||
|
|
8012d9f6a8 | ||
|
|
73a050df13 | ||
|
|
d0a1a113b6 | ||
|
|
a8bffd3bce | ||
|
|
f6aac07c3d | ||
|
|
72f1d83af4 | ||
|
|
138080c4d4 | ||
|
|
cf70bfebe9 | ||
|
|
5fc1ab9c60 | ||
|
|
6078734136 | ||
|
|
917e33bccf | ||
|
|
6a8b604554 | ||
|
|
2fa282e131 | ||
|
|
810fe14c69 | ||
|
|
f4a26d0580 | ||
|
|
0a54c2d986 | ||
|
|
9c4f011fbc | ||
|
|
951727e266 | ||
|
|
7355061762 | ||
|
|
2872a1c29d | ||
|
|
fd29a94d6e | ||
|
|
5e0cff5b8e | ||
|
|
b3ae03ab7e | ||
|
|
5ec2877577 | ||
|
|
e182247774 | ||
|
|
6bd9bd98d9 | ||
|
|
0475954acf | ||
|
|
0d371593fb | ||
|
|
a6ef100e02 | ||
|
|
adc34b76da | ||
|
|
a91c785543 | ||
|
|
1cac58dadc | ||
|
|
510c31f669 | ||
|
|
bdb057ca0f | ||
|
|
dc5d7a8677 | ||
|
|
1fc1c64f62 | ||
|
|
d49f33476d | ||
|
|
2260f56713 | ||
|
|
eecd54c5ea | ||
|
|
e1f0b649f5 | ||
|
|
9605ec6109 | ||
|
|
b2977d6806 | ||
|
|
d091aecaf1 | ||
|
|
97f0d5fc5d | ||
|
|
2bc9b8c8bb | ||
|
|
e312ee2773 | ||
|
|
c685b970d3 | ||
|
|
621b7e5d29 | ||
|
|
b59ebb7d52 | ||
|
|
ce2141ddb7 | ||
|
|
36c88c3762 | ||
|
|
099b399b24 | ||
|
|
5092c78fba | ||
|
|
199cdf20a7 | ||
|
|
7c1040e7aa | ||
|
|
faf117b002 | ||
|
|
13e491cda7 | ||
|
|
286b7118be | ||
|
|
b2dfe31b5c | ||
|
|
1f005a3d42 | ||
|
|
36c64bd8dc | ||
|
|
277325d58c | ||
|
|
370f407ad6 | ||
|
|
3ea8e2294e | ||
|
|
c6413afa67 | ||
|
|
fe137a11bb | ||
|
|
0fa15161d4 | ||
|
|
aeb8792165 | ||
|
|
c60609d507 | ||
|
|
ad04c07017 | ||
|
|
f3f8326360 | ||
|
|
3798e386ae | ||
|
|
7d3afa005c | ||
|
|
3bfe2329f1 | ||
|
|
29765ebc19 | ||
|
|
b91f0e7f63 | ||
|
|
87352b04f1 | ||
|
|
0f034523e1 | ||
|
|
20b87e596a | ||
|
|
4b7cffad04 | ||
|
|
bcb0a19dea | ||
|
|
4e2311e8d7 | ||
|
|
c7be0f3b0e | ||
|
|
9ab79209ef | ||
|
|
1c3016a31e | ||
|
|
941001c743 | ||
|
|
40cf5ba63a | ||
|
|
9a40449f08 | ||
|
|
049d792053 | ||
|
|
e399085a57 | ||
|
|
18b4a90690 | ||
|
|
a68ffda7eb | ||
|
|
0a722edc88 | ||
|
|
de407608f2 | ||
|
|
ece0fdfe6c | ||
|
|
5008d35614 | ||
|
|
6b470f180c | ||
|
|
4deb895b4c | ||
|
|
5d70d822eb | ||
|
|
90a88cf69d | ||
|
|
044a992d25 | ||
|
|
4b066ec37f | ||
|
|
0dad02343e | ||
|
|
7f6a1a424d | ||
|
|
c2dc2c5836 | ||
|
|
58452204aa | ||
|
|
711ba73d6b | ||
|
|
5354f2732f | ||
|
|
9bbaaa2211 | ||
|
|
93c47d774e | ||
|
|
d8ad697d09 | ||
|
|
7308a7cf9a | ||
|
|
c9c49a7e5e | ||
|
|
dba6b2a291 | ||
|
|
7d3991b295 | ||
|
|
e4c0ecfb5a | ||
|
|
fdb0e842de | ||
|
|
85ff36198b | ||
|
|
e38321aa33 | ||
|
|
d1438d1b2e | ||
|
|
b6f848ef66 | ||
|
|
ff47784aee | ||
|
|
1dba711057 | ||
|
|
6911f7b24b | ||
|
|
1e94abd063 | ||
|
|
3325e1e388 | ||
|
|
4b87977e24 | ||
|
|
dfa28264c6 | ||
|
|
f0c1d6d4c2 | ||
|
|
427b98a157 | ||
|
|
8f5000443f | ||
|
|
7947fd6e91 | ||
|
|
70bf5499b2 | ||
|
|
6b059cb4f4 | ||
|
|
efd112c4b8 | ||
|
|
5c7b760f34 | ||
|
|
81ae473972 | ||
|
|
a8171bb739 | ||
|
|
c803ed4ee6 | ||
|
|
9e41a65749 | ||
|
|
43e7d6f7c2 | ||
|
|
a7539df5b5 | ||
|
|
3950619877 | ||
|
|
7373fd4aa9 | ||
|
|
c3d9885525 | ||
|
|
4b5dee7bdb | ||
|
|
55d846b9e0 | ||
|
|
f2d8349a88 | ||
|
|
7c7dd7c609 | ||
|
|
d8f2c580ee | ||
|
|
2a0602468d | ||
|
|
89a9c18188 | ||
|
|
8b426da149 | ||
|
|
cab98f9750 | ||
|
|
27b7a26fee | ||
|
|
7261fae9f2 | ||
|
|
628ebd6841 | ||
|
|
61bbf7c30d | ||
|
|
e33803343a | ||
|
|
b08a448fdc | ||
|
|
7210ebfb22 | ||
|
|
039978357b | ||
|
|
7ce2481cbc | ||
|
|
5bc6af87c5 | ||
|
|
a5eaf3566e | ||
|
|
58d40e912d | ||
|
|
63d89be698 | ||
|
|
1b7be9f9b0 | ||
|
|
7a53e96d52 | ||
|
|
b28d146de7 | ||
|
|
55c8be8dc5 | ||
|
|
38a273459a | ||
|
|
1b07632c69 | ||
|
|
4a12523793 | ||
|
|
6aa601b8ab | ||
|
|
a66a040207 | ||
|
|
547a408a99 | ||
|
|
8cd224b7fa | ||
|
|
8428e93b47 | ||
|
|
483143f2fe | ||
|
|
1b3d106b6d | ||
|
|
e7be006fa7 | ||
|
|
b9f40151d8 | ||
|
|
fd467acc29 | ||
|
|
e1ad0c31c8 | ||
|
|
ee604dc2b0 | ||
|
|
0620646c6d | ||
|
|
df9cf3f5c4 | ||
|
|
944349760a | ||
|
|
7fe75ee52a | ||
|
|
e3d7bf9a62 | ||
|
|
deaf49c18f | ||
|
|
53543fff4c | ||
|
|
ea5e710a70 | ||
|
|
ad5a52ae74 | ||
|
|
c0cc5ab085 | ||
|
|
cf784cbedd | ||
|
|
5c68830919 | ||
|
|
370aab41c3 | ||
|
|
081f4021bc | ||
|
|
36f846fabf | ||
|
|
f6d094f57c | ||
|
|
9ce097b7d6 | ||
|
|
91991f0c67 | ||
|
|
306cd13723 | ||
|
|
8c624cfacd | ||
|
|
b03ccce575 | ||
|
|
63b8788c80 | ||
|
|
faa3beddbc | ||
|
|
5dbd5bc1d2 | ||
|
|
b8b0d98e07 | ||
|
|
b911ebfd07 | ||
|
|
1ca515bd4e | ||
|
|
905710b6e9 | ||
|
|
12e0f674bc | ||
|
|
18739c2a24 | ||
|
|
f3dc2ff7e5 | ||
|
|
e6209a5906 | ||
|
|
dbf64a4e90 | ||
|
|
a8961c3466 | ||
|
|
6931952688 | ||
|
|
936aa17ecc | ||
|
|
f3d7420b8a | ||
|
|
e419acea6e | ||
|
|
95ae15b780 | ||
|
|
ed468e79fc | ||
|
|
130565af75 | ||
|
|
ad8f360336 | ||
|
|
15775403fd | ||
|
|
e1b83c32af | ||
|
|
3fc7c65247 | ||
|
|
c8d1239b79 | ||
|
|
7885257fae | ||
|
|
a8d22709e6 | ||
|
|
31b7b45ae3 | ||
|
|
681798b582 | ||
|
|
f05ea56179 | ||
|
|
ed4269ea4c | ||
|
|
085fcc958e | ||
|
|
8f33fe3595 | ||
|
|
980a7d79d3 | ||
|
|
9c5c07e087 | ||
|
|
faaf07cad8 | ||
|
|
0e83a230b9 | ||
|
|
c278b36858 | ||
|
|
0805f86b86 | ||
|
|
aad88f1da6 | ||
|
|
7550bc860f | ||
|
|
fc38e1edea | ||
|
|
88a66a705b | ||
|
|
f77fd00931 | ||
|
|
b5c030905a | ||
|
|
2844e13298 | ||
|
|
3e4dc1f9e3 | ||
|
|
259c1e1731 | ||
|
|
870aa674b0 | ||
|
|
b1ab319bf7 | ||
|
|
857422719a | ||
|
|
235314bc13 | ||
|
|
ac1cd88ae1 | ||
|
|
f93ea3c0a1 | ||
|
|
0075040aab | ||
|
|
f9d51e623c | ||
|
|
dcd36dcd67 | ||
|
|
608a921fce | ||
|
|
4bedf1e6ac | ||
|
|
ac14c310f6 | ||
|
|
f979da315a | ||
|
|
a74ef7de6b | ||
|
|
10064121a6 | ||
|
|
f8a1ef6066 | ||
|
|
40d7b11d90 | ||
|
|
1600dd9e0b | ||
|
|
fbf5164eca | ||
|
|
21d86a8c2d | ||
|
|
848c7e117b | ||
|
|
369868672b | ||
|
|
321f3517a7 | ||
|
|
6dd7ec9f95 | ||
|
|
dc00878ff9 | ||
|
|
90f444dc1a | ||
|
|
4fa2e273aa | ||
|
|
df92e0574a | ||
|
|
e2053e2f8b | ||
|
|
31f0052b9d | ||
|
|
b6169778fd | ||
|
|
32b98a7e40 | ||
|
|
5111c2a96b | ||
|
|
2ac901c891 | ||
|
|
ff4466951c | ||
|
|
8f05e254a2 | ||
|
|
5122903139 | ||
|
|
1344f776e4 | ||
|
|
f33367ebac | ||
|
|
3ac42deae5 | ||
|
|
3d04e7c125 | ||
|
|
fa77f11177 | ||
|
|
45c8767234 | ||
|
|
13dc87f368 | ||
|
|
fc0116182f | ||
|
|
bbe9f3f1db | ||
|
|
1009570102 | ||
|
|
47f42d0ffa | ||
|
|
23d21be73f | ||
|
|
25f8d2ca44 | ||
|
|
58d91ec0b0 | ||
|
|
85cc9868cb | ||
|
|
75631da398 | ||
|
|
03c74dae03 | ||
|
|
2089866756 | ||
|
|
8d982c7e3e | ||
|
|
079cecc529 | ||
|
|
b0d90f6fd5 | ||
|
|
58f4ae32d0 | ||
|
|
dd0373a3ee | ||
|
|
170dca7086 | ||
|
|
c930f04b5a | ||
|
|
f41d919ca8 | ||
|
|
8c4583b0d3 | ||
|
|
972518e9fc | ||
|
|
5b38fad85e | ||
|
|
d227601627 | ||
|
|
736e45aec9 | ||
|
|
11e2e86b06 | ||
|
|
58617b5685 | ||
|
|
8c2aa4844f | ||
|
|
8648db5518 | ||
|
|
b5b201b6df | ||
|
|
b601fe40b3 | ||
|
|
d6999b2a8a | ||
|
|
76f152aa35 | ||
|
|
63f8a2c5c0 | ||
|
|
ae482ecab6 | ||
|
|
a8e63ab397 | ||
|
|
a2717ad058 | ||
|
|
083035c924 | ||
|
|
92cce5910e | ||
|
|
ab897f05f9 | ||
|
|
cd8ca02322 | ||
|
|
5104225d11 | ||
|
|
24d6087ea7 | ||
|
|
dc9ee18e96 | ||
|
|
b4060b7903 | ||
|
|
884a3aad2c | ||
|
|
80f826421b | ||
|
|
7872bb48e2 | ||
|
|
7d10101c57 | ||
|
|
d9ed21ba53 | ||
|
|
5e8211172b | ||
|
|
24956255d7 | ||
|
|
55380dab04 | ||
|
|
e7926b6f22 | ||
|
|
fe7d8f73f3 | ||
|
|
47d7f001fe | ||
|
|
23a6722ddb | ||
|
|
23e2b756fd | ||
|
|
8bea05a77b | ||
|
|
d5ac4bac48 | ||
|
|
1af9b2e6db | ||
|
|
daa3c08706 | ||
|
|
29102e3b52 | ||
|
|
8c0fc54344 | ||
|
|
f5b20c2f32 | ||
|
|
79734ff603 | ||
|
|
397bfd8bca | ||
|
|
52dc111210 | ||
|
|
da1375e34d | ||
|
|
79db3c4c1d | ||
|
|
925027f7f0 | ||
|
|
1442a9106c | ||
|
|
fafb421a51 | ||
|
|
f81666da5e | ||
|
|
4a1bc9f6c0 | ||
|
|
0652c40c52 | ||
|
|
a99145b705 | ||
|
|
222f875c42 | ||
|
|
dc983d4863 | ||
|
|
7256c28038 | ||
|
|
021cb4f93b | ||
|
|
00ca01dc33 | ||
|
|
b2f3755196 | ||
|
|
c09b0a0341 | ||
|
|
8a739b31a1 | ||
|
|
afec210219 | ||
|
|
dafee90b24 | ||
|
|
f6790a5f9b | ||
|
|
4983a6dfb3 | ||
|
|
c4c477fdd8 | ||
|
|
20b89f0d2f | ||
|
|
9564866f6d | ||
|
|
994296640b | ||
|
|
9a68c7e1c3 | ||
|
|
ec597d4e6e | ||
|
|
2882e3d1a5 | ||
|
|
86e9cd0ec6 | ||
|
|
3a05f75ab0 | ||
|
|
34b4d30014 | ||
|
|
89b6c47bfb | ||
|
|
70f48108b4 | ||
|
|
df5689ec18 | ||
|
|
22d72b13d5 | ||
|
|
dee7ff34c9 | ||
|
|
07eb305992 | ||
|
|
c7f0076ee6 | ||
|
|
93bc5255e7 | ||
|
|
e8266480e5 |
40
.codeclimate.yml
Normal file
40
.codeclimate.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
engines:
|
||||
rubocop:
|
||||
enabled: true
|
||||
scss-lint:
|
||||
enabled: true
|
||||
shellcheck:
|
||||
enabled: true
|
||||
eslint:
|
||||
enabled: true
|
||||
coffeelint:
|
||||
enabled: true
|
||||
brakeman:
|
||||
enabled: true
|
||||
bundler-audit:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- ruby
|
||||
- javascript
|
||||
fixme:
|
||||
enabled: true
|
||||
exclude_fingerprints: # rubocop_todo filename
|
||||
- 63b8552079d106832fbe281566b6d028
|
||||
- d38afbaaea3ecaa9a4cf046b07a01cec
|
||||
- 57ff3968fd371d3e1f75c237d6c78acf
|
||||
ratings:
|
||||
paths:
|
||||
- "**.rb"
|
||||
- "**.js"
|
||||
- "**.coffee"
|
||||
- "**.sass"
|
||||
- "**.haml"
|
||||
- Gemfile.lock
|
||||
exclude_paths:
|
||||
- config/
|
||||
- db/
|
||||
- spec/
|
||||
- public/
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -8,10 +8,10 @@ coverage
|
||||
*~
|
||||
*.DS_Store
|
||||
config/application.yml
|
||||
config/database.yml
|
||||
credentials*.sh
|
||||
Pathogen:
|
||||
custom_plan.rb
|
||||
zeus.json
|
||||
.bundle
|
||||
config/application.yml
|
||||
.idea/**
|
||||
68
.rubocop.yml
Normal file
68
.rubocop.yml
Normal file
@@ -0,0 +1,68 @@
|
||||
inherit_from: .rubocop_todo.yml
|
||||
AllCops:
|
||||
Include:
|
||||
- 'Rakefile'
|
||||
- 'config.ru'
|
||||
- 'lib/**/*.rake'
|
||||
Exclude:
|
||||
- 'db/schema.rb'
|
||||
- 'vendor/**/*'
|
||||
|
||||
Style/FileName:
|
||||
Exclude:
|
||||
- 'Gemfile'
|
||||
- 'Gemfile.lock'
|
||||
|
||||
Style/StringLiterals:
|
||||
Enabled: false
|
||||
|
||||
Style/MultilineMethodCallIndentation:
|
||||
EnforcedStyle: indented
|
||||
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# SupportedStyles: with_first_parameter, with_fixed_indentation
|
||||
Style/AlignParameters:
|
||||
EnforcedStyle: with_fixed_indentation
|
||||
|
||||
Metrics/MethodLength:
|
||||
Description: 'Avoid methods longer than 30 lines of code.'
|
||||
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods'
|
||||
# Set to 30 once all methods are fixed.
|
||||
# Max: 30
|
||||
Max: 104
|
||||
|
||||
# Remove the following once the code style matches
|
||||
# Offense count: 59
|
||||
Metrics/AbcSize:
|
||||
Max: 115
|
||||
|
||||
# Offense count: 5
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/BlockLength:
|
||||
Max: 62
|
||||
|
||||
# Offense count: 6
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ClassLength:
|
||||
Max: 275
|
||||
|
||||
# Offense count: 6
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 11
|
||||
|
||||
Metrics/LineLength:
|
||||
Max: 120
|
||||
|
||||
# Offense count: 8
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 10
|
||||
|
||||
# See https://github.com/bbatsov/rubocop/issues/3629
|
||||
Rails/HttpPositionalArguments:
|
||||
Enabled: false
|
||||
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: false
|
||||
1088
.rubocop_todo.yml
Normal file
1088
.rubocop_todo.yml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
2.2.4
|
||||
2.3.1
|
||||
|
||||
33
.travis.yml
33
.travis.yml
@@ -1,6 +1,9 @@
|
||||
sudo: false
|
||||
language: ruby
|
||||
cache: bundler
|
||||
cache:
|
||||
bundler: true
|
||||
directories:
|
||||
- travis_phantomjs
|
||||
env:
|
||||
matrix:
|
||||
- GROWSTUFF_SITE_NAME="Growstuff (travis)" RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' GROWSTUFF_ELASTICSEARCH='true'
|
||||
@@ -8,12 +11,27 @@ env:
|
||||
global:
|
||||
secure: "Z5TpM2jEX4UCvNePnk/LwltQX48U2u9BRc+Iypr1x9QW2o228QJhPIOH39a8RMUrepGnkQIq9q3ZRUn98RfrJz1yThtlNFL3NmzdQ57gKgjGwfpa0e4Dwj/ZJqV2D84tDGjvdVYLP7zzaYZxQcwk/cgNpzKf/jq97HLNP7CYuf4="
|
||||
rvm:
|
||||
- 2.2.4
|
||||
- 2.3.1
|
||||
before_install:
|
||||
- export PATH=$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH
|
||||
- >
|
||||
if [ $(phantomjs --version) != '2.1.1' ]; then
|
||||
PHANTOM_URL=https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2;
|
||||
rm -rf $PWD/travis_phantomjs;
|
||||
mkdir -p $PWD/travis_phantomjs;
|
||||
wget $PHANTOM_URL -O $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2;
|
||||
tar -xvf $PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis_phantomjs;
|
||||
fi
|
||||
- phantomjs --version
|
||||
before_script:
|
||||
- psql -c 'create database growstuff_test;' -U postgres
|
||||
- bundle exec rake db:create db:migrate db:test:prepare
|
||||
- bundle exec rake assets:precompile
|
||||
script:
|
||||
- bundle exec rake db:migrate --trace
|
||||
- bundle exec rspec spec/
|
||||
- bundle exec rubocop --display-cop-names --rails
|
||||
- script/gemfile_check
|
||||
- bundle exec script/check_contributors_md
|
||||
- bundle exec rake db:migrate --trace
|
||||
- bundle exec rspec spec/
|
||||
services:
|
||||
- elasticsearch
|
||||
before_deploy:
|
||||
@@ -26,6 +44,7 @@ deploy:
|
||||
repo: Growstuff/growstuff
|
||||
app:
|
||||
dev: growstuff-staging
|
||||
master: growstuff-prod
|
||||
travis_deploy: tranquil-basin-3130
|
||||
travis_containers: tranquil-basin-3130
|
||||
run:
|
||||
@@ -34,4 +53,6 @@ deploy:
|
||||
- restart
|
||||
after_deploy:
|
||||
- bundle exec script/heroku_maintenance.rb off
|
||||
|
||||
addons:
|
||||
code_climate:
|
||||
repo_token: 462e015bbdaabfb20910fc07f2fea253410ecb131444e00f97dbf32dc6789ca6
|
||||
|
||||
7
.yamllint
Normal file
7
.yamllint
Normal file
@@ -0,0 +1,7 @@
|
||||
extends: relaxed
|
||||
|
||||
rules:
|
||||
# 80 chars should be enough, but don't fail if a line is longer
|
||||
line-length:
|
||||
max: 150
|
||||
level: warning
|
||||
@@ -66,3 +66,9 @@ submit the change with your pull request.
|
||||
- Anthony Atkinson / [sha1sum](https://github.com/sha1sum)
|
||||
- Terence Conquest / [twconquest](https://github.com/twconquest)
|
||||
- Daniel O'Connor / [CloCkWeRX](https://github.com/CloCkWeRX)
|
||||
- DV Dasari / [dv2](https://github.com/dv2)
|
||||
- Eric Tillberg / [Thrillberg](https://github.com/Thrillberg)
|
||||
- Lucas Nogueira / [lucasnogueira](https://github.com/lucasnogueira)
|
||||
- Charley Lewittes / [ctlewitt](https://github.com/ctlewitt)
|
||||
- Kristine Nicole Polvoriza / [polveenomials](https://github.com/polveenomials)
|
||||
- Brenda Wallace / [br3nda](https://github.com/br3nda)
|
||||
|
||||
4
Capfile
4
Capfile
@@ -1,4 +0,0 @@
|
||||
load 'deploy'
|
||||
# Uncomment if you are using Rails' asset pipeline
|
||||
# load 'deploy/assets'
|
||||
load 'config/deploy' # remove this line to skip loading any of the default tasks
|
||||
44
Gemfile
44
Gemfile
@@ -1,8 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
source 'https://rubygems.org'
|
||||
|
||||
ruby '2.2.4'
|
||||
ruby '2.3.1'
|
||||
|
||||
gem 'rails', '~> 4.1.11'
|
||||
gem 'rails', '~> 4.2.1'
|
||||
|
||||
gem 'bundler', '>=1.1.5'
|
||||
|
||||
@@ -14,11 +15,11 @@ gem 'haml'
|
||||
gem 'bootstrap-sass', '~> 3.3.6'
|
||||
gem 'font-awesome-sass'
|
||||
|
||||
gem 'uglifier', '~> 2.7.2' # JavaScript compressor
|
||||
gem 'uglifier', '~> 2.7.2' # JavaScript compressor
|
||||
|
||||
gem 'jquery-rails'
|
||||
gem 'jquery-ui-rails', '~> 5.0.2'
|
||||
gem 'js-routes' # provides access to Rails routes in Javascript
|
||||
gem 'js-routes' # provides access to Rails routes in Javascript
|
||||
gem 'flickraw'
|
||||
|
||||
gem 'leaflet-rails'
|
||||
@@ -36,13 +37,9 @@ gem 'comfortable_mexican_sofa', '~> 1.12.0' # content management system
|
||||
gem 'kaminari' # pagination
|
||||
gem 'bootstrap-kaminari-views' # bootstrap views for kaminari
|
||||
|
||||
# vendored activemerchant for testing- needed for bogus paypal
|
||||
# gateway monkeypatch
|
||||
gem 'activemerchant', '1.33.0',
|
||||
:path => 'vendor/gems/activemerchant-1.33.0',
|
||||
:require => 'active_merchant'
|
||||
gem 'active_utils', '1.0.5',
|
||||
:path => 'vendor/gems/active_utils-1.0.5'
|
||||
gem 'activemerchant'
|
||||
gem 'active_utils'
|
||||
gem 'sidekiq'
|
||||
|
||||
# Markdown formatting for updates etc
|
||||
gem 'bluecloth'
|
||||
@@ -51,7 +48,7 @@ gem 'bluecloth'
|
||||
gem 'will_paginate', '~> 3.0'
|
||||
|
||||
# user signup/login/etc
|
||||
gem 'devise', '~> 3.5.0'
|
||||
gem 'devise', '>= 4.0.0'
|
||||
|
||||
# nicely formatted URLs
|
||||
gem 'friendly_id', '~> 5.0.4'
|
||||
@@ -60,9 +57,7 @@ gem 'friendly_id', '~> 5.0.4'
|
||||
gem 'gravatar-ultimate'
|
||||
|
||||
# For geolocation
|
||||
gem 'geocoder',
|
||||
:git => 'https://github.com/alexreisner/geocoder.git',
|
||||
:ref => '104d46'
|
||||
gem 'geocoder'
|
||||
|
||||
# For easy calendar selection
|
||||
gem 'bootstrap-datepicker-rails'
|
||||
@@ -71,9 +66,10 @@ gem 'bootstrap-datepicker-rails'
|
||||
gem 'omniauth'
|
||||
gem 'omniauth-twitter'
|
||||
gem 'omniauth-flickr', '>= 0.0.15'
|
||||
gem 'omniauth-facebook'
|
||||
|
||||
# client for Elasticsearch. Elasticsearch is a flexible
|
||||
# and powerful, distributed, real-time search and analytics engine.
|
||||
# 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"
|
||||
@@ -85,7 +81,8 @@ 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
|
||||
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
|
||||
gem 'sparkpost_rails'
|
||||
end
|
||||
|
||||
group :development do
|
||||
@@ -103,18 +100,25 @@ end
|
||||
|
||||
group :development, :test do
|
||||
gem 'haml-rails' # HTML templating language
|
||||
gem 'rspec-rails', '~> 3.4.0' # unit testing framework
|
||||
gem 'rspec-rails' # unit testing framework
|
||||
gem 'rspec-activemodel-mocks'
|
||||
gem 'byebug' # debugging
|
||||
gem 'database_cleaner', '~> 1.5.0'
|
||||
gem 'webrat' # provides HTML matchers for view tests
|
||||
gem 'factory_girl_rails', '~> 4.5.0' # for creating test data
|
||||
gem 'factory_girl_rails' # for creating test data
|
||||
gem 'coveralls', require: false # coverage analysis
|
||||
gem 'capybara' # integration tests
|
||||
gem 'capybara-email' # integration tests for email
|
||||
gem 'poltergeist', '~> 1.6' # for headless JS testing
|
||||
gem 'capybara-screenshot' # for test debugging
|
||||
gem 'poltergeist' # for headless JS testing
|
||||
gem 'i18n-tasks' # adds tests for finding missing and unused translations
|
||||
gem 'selenium-webdriver'
|
||||
gem "active_merchant-paypal-bogus-gateway"
|
||||
gem 'rubocop', require: false
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'codeclimate-test-reporter', require: false
|
||||
end
|
||||
|
||||
group :travis do
|
||||
|
||||
388
Gemfile.lock
388
Gemfile.lock
@@ -1,57 +1,58 @@
|
||||
GIT
|
||||
remote: https://github.com/alexreisner/geocoder.git
|
||||
revision: 104d466ba7097b7dce5ba19f8e4091b7f69ccdf6
|
||||
ref: 104d46
|
||||
specs:
|
||||
geocoder (1.1.8)
|
||||
|
||||
PATH
|
||||
remote: vendor/gems/active_utils-1.0.5
|
||||
specs:
|
||||
active_utils (1.0.5)
|
||||
activesupport (>= 2.3.11)
|
||||
i18n
|
||||
|
||||
PATH
|
||||
remote: vendor/gems/activemerchant-1.33.0
|
||||
specs:
|
||||
activemerchant (1.33.0)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (4.1.15)
|
||||
actionpack (= 4.1.15)
|
||||
actionview (= 4.1.15)
|
||||
actionmailer (4.2.7.1)
|
||||
actionpack (= 4.2.7.1)
|
||||
actionview (= 4.2.7.1)
|
||||
activejob (= 4.2.7.1)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
actionpack (4.1.15)
|
||||
actionview (= 4.1.15)
|
||||
activesupport (= 4.1.15)
|
||||
rack (~> 1.5.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.7.1)
|
||||
actionview (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
actionview (4.1.15)
|
||||
activesupport (= 4.1.15)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
active_link_to (1.0.3)
|
||||
actionpack
|
||||
activemodel (4.1.15)
|
||||
activesupport (= 4.1.15)
|
||||
active_merchant-paypal-bogus-gateway (0.1.0)
|
||||
activemerchant
|
||||
active_utils (3.2.3)
|
||||
activesupport (>= 3.2, < 5.1.0)
|
||||
i18n
|
||||
activejob (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
globalid (>= 0.3.0)
|
||||
activemerchant (1.61.0)
|
||||
activesupport (>= 3.2.14, < 5.1)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
activemodel (4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.1.15)
|
||||
activemodel (= 4.1.15)
|
||||
activesupport (= 4.1.15)
|
||||
arel (~> 5.0.0)
|
||||
activesupport (4.1.15)
|
||||
i18n (~> 0.6, >= 0.6.9)
|
||||
activerecord (4.2.7.1)
|
||||
activemodel (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.7.1)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.4.0)
|
||||
arel (5.0.1.20140414130214)
|
||||
ast (2.2.0)
|
||||
autoprefixer-rails (6.3.6.1)
|
||||
addressable (2.5.0)
|
||||
public_suffix (~> 2.0, >= 2.0.2)
|
||||
arel (6.0.3)
|
||||
ast (2.3.0)
|
||||
autoprefixer-rails (6.4.0.2)
|
||||
execjs
|
||||
bcrypt (3.1.11)
|
||||
better_errors (2.1.1)
|
||||
@@ -62,19 +63,19 @@ GEM
|
||||
debug_inspector (>= 0.0.1)
|
||||
bluecloth (2.2.0)
|
||||
bonsai-elasticsearch-rails (0.0.4)
|
||||
bootstrap-datepicker-rails (1.6.1.1)
|
||||
bootstrap-datepicker-rails (1.6.4.1)
|
||||
railties (>= 3.0)
|
||||
bootstrap-kaminari-views (0.0.5)
|
||||
kaminari (>= 0.13)
|
||||
rails (>= 3.1)
|
||||
bootstrap-sass (3.3.6)
|
||||
bootstrap-sass (3.3.7)
|
||||
autoprefixer-rails (>= 5.2.1)
|
||||
sass (>= 3.3.4)
|
||||
bootstrap_form (2.3.0)
|
||||
bootstrap_form (2.5.2)
|
||||
builder (3.2.2)
|
||||
byebug (9.0.4)
|
||||
cancancan (1.14.0)
|
||||
capybara (2.7.1)
|
||||
byebug (9.0.6)
|
||||
cancancan (1.15.0)
|
||||
capybara (2.10.1)
|
||||
addressable
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
@@ -84,6 +85,9 @@ GEM
|
||||
capybara-email (2.5.0)
|
||||
capybara (~> 2.4)
|
||||
mail
|
||||
capybara-screenshot (1.0.14)
|
||||
capybara (>= 1.0, < 3)
|
||||
launchy
|
||||
childprocess (0.5.9)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
climate_control (0.0.3)
|
||||
@@ -91,8 +95,10 @@ GEM
|
||||
cliver (0.3.2)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
codemirror-rails (5.11)
|
||||
railties (>= 3.0, < 5)
|
||||
codeclimate-test-reporter (0.6.0)
|
||||
simplecov (>= 0.7.1, < 1.0.0)
|
||||
codemirror-rails (5.16.0)
|
||||
railties (>= 3.0, < 6.0)
|
||||
coderay (1.1.1)
|
||||
coffee-rails (4.1.1)
|
||||
coffee-script (>= 2.2.0)
|
||||
@@ -117,23 +123,23 @@ GEM
|
||||
rails-i18n (>= 4.0.0)
|
||||
sass-rails (>= 4.0.3)
|
||||
concurrent-ruby (1.0.2)
|
||||
coveralls (0.8.13)
|
||||
json (~> 1.8)
|
||||
simplecov (~> 0.11.0)
|
||||
term-ansicolor (~> 1.3)
|
||||
connection_pool (2.2.0)
|
||||
coveralls (0.8.16)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov (~> 0.12.0)
|
||||
term-ansicolor (~> 1.3.0)
|
||||
thor (~> 0.19.1)
|
||||
tins (~> 1.6.0)
|
||||
csv_shaper (1.2.0)
|
||||
tins (>= 1.6.0, < 2)
|
||||
csv_shaper (1.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
dalli (2.7.6)
|
||||
database_cleaner (1.5.3)
|
||||
debug_inspector (0.0.2)
|
||||
devise (3.5.10)
|
||||
devise (4.2.0)
|
||||
bcrypt (~> 3.0)
|
||||
orm_adapter (~> 0.1)
|
||||
railties (>= 3.2.6, < 5)
|
||||
railties (>= 4.1.0, < 5.1)
|
||||
responders
|
||||
thread_safe (~> 0.1)
|
||||
warden (~> 1.2.3)
|
||||
diff-lcs (1.2.5)
|
||||
docile (1.1.5)
|
||||
@@ -141,41 +147,44 @@ GEM
|
||||
json
|
||||
thread
|
||||
thread_safe
|
||||
elasticsearch (1.0.17)
|
||||
elasticsearch-api (= 1.0.17)
|
||||
elasticsearch-transport (= 1.0.17)
|
||||
elasticsearch-api (1.0.17)
|
||||
elasticsearch (2.0.0)
|
||||
elasticsearch-api (= 2.0.0)
|
||||
elasticsearch-transport (= 2.0.0)
|
||||
elasticsearch-api (2.0.0)
|
||||
multi_json
|
||||
elasticsearch-model (0.1.9)
|
||||
activesupport (> 3)
|
||||
elasticsearch (> 0.4)
|
||||
hashie
|
||||
elasticsearch-rails (0.1.9)
|
||||
elasticsearch-transport (1.0.17)
|
||||
elasticsearch-transport (2.0.0)
|
||||
faraday
|
||||
multi_json
|
||||
erubis (2.7.0)
|
||||
excon (0.49.0)
|
||||
excon (0.54.0)
|
||||
execjs (2.7.0)
|
||||
factory_girl (4.5.0)
|
||||
factory_girl (4.7.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.5.0)
|
||||
factory_girl (~> 4.5.0)
|
||||
factory_girl_rails (4.7.0)
|
||||
factory_girl (~> 4.7.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.9.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.10)
|
||||
ffi (1.9.14)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
flickraw (0.9.8)
|
||||
flickraw (0.9.9)
|
||||
font-awesome-sass (4.6.2)
|
||||
sass (>= 3.2)
|
||||
formatador (0.2.5)
|
||||
friendly_id (5.0.5)
|
||||
activerecord (>= 4.0.0)
|
||||
gibbon (1.2.0)
|
||||
geocoder (1.3.7)
|
||||
gibbon (1.2.1)
|
||||
httparty
|
||||
multi_json (>= 1.9.0)
|
||||
globalid (0.3.7)
|
||||
activesupport (>= 4.1.0)
|
||||
gravatar-ultimate (2.0.0)
|
||||
activesupport (>= 2.3.14)
|
||||
rack
|
||||
@@ -189,7 +198,7 @@ GEM
|
||||
shellany (~> 0.0)
|
||||
thor (>= 0.18.1)
|
||||
guard-compat (1.2.1)
|
||||
guard-rspec (4.6.5)
|
||||
guard-rspec (4.7.3)
|
||||
guard (~> 2.1)
|
||||
guard-compat (~> 1.1)
|
||||
rspec (>= 2.99.0, < 4.0)
|
||||
@@ -211,11 +220,10 @@ GEM
|
||||
haml (~> 4.0.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
ruby_parser (~> 3.5)
|
||||
httparty (0.13.3)
|
||||
json (~> 1.8)
|
||||
httparty (0.14.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (0.7.0)
|
||||
i18n-tasks (0.9.5)
|
||||
i18n-tasks (0.9.6)
|
||||
activesupport (>= 4.0.2)
|
||||
ast (>= 2.1.0)
|
||||
easy_translate (>= 0.5.0)
|
||||
@@ -225,20 +233,22 @@ GEM
|
||||
parser (>= 2.2.3.0)
|
||||
term-ansicolor (>= 1.3.2)
|
||||
terminal-table (>= 1.5.1)
|
||||
jquery-rails (3.1.4)
|
||||
railties (>= 3.0, < 5.0)
|
||||
jquery-rails (4.2.1)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
jquery-ui-rails (5.0.5)
|
||||
railties (>= 3.2.16)
|
||||
js-routes (1.2.5)
|
||||
js-routes (1.3.0)
|
||||
railties (>= 3.2)
|
||||
sprockets-rails
|
||||
json (1.8.3)
|
||||
kaminari (0.16.3)
|
||||
jwt (1.5.6)
|
||||
kaminari (0.17.0)
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
kgio (2.10.0)
|
||||
kramdown (1.11.1)
|
||||
kramdown (1.13.1)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
leaflet-markercluster-rails (0.7.0)
|
||||
@@ -250,77 +260,102 @@ GEM
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
ruby_dep (~> 1.2)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
lumberjack (1.0.10)
|
||||
mail (2.6.4)
|
||||
mime-types (>= 1.16, < 4)
|
||||
memcachier (0.0.2)
|
||||
method_source (0.8.2)
|
||||
mime-types (3.0)
|
||||
mime-types (3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2016.0221)
|
||||
mimemagic (0.3.0)
|
||||
mini_portile2 (2.0.0)
|
||||
minitest (5.9.0)
|
||||
mime-types-data (3.2016.0521)
|
||||
mimemagic (0.3.2)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.9.1)
|
||||
multi_json (1.11.3)
|
||||
multi_xml (0.5.5)
|
||||
multipart-post (2.0.0)
|
||||
nenv (0.3.0)
|
||||
newrelic_rpm (3.15.2.317)
|
||||
nokogiri (1.6.7.2)
|
||||
mini_portile2 (~> 2.0.0.rc2)
|
||||
notiffany (0.1.0)
|
||||
newrelic_rpm (3.17.1.326)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
notiffany (0.1.1)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
oauth (0.5.1)
|
||||
oauth2 (1.2.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
jwt (~> 1.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
omniauth (1.3.1)
|
||||
hashie (>= 1.2, < 4)
|
||||
rack (>= 1.0, < 3)
|
||||
omniauth-facebook (3.0.0)
|
||||
omniauth-oauth2 (~> 1.2)
|
||||
omniauth-flickr (0.0.19)
|
||||
multi_json (~> 1.11.0)
|
||||
omniauth-oauth (~> 1.0)
|
||||
omniauth-oauth (1.1.0)
|
||||
oauth
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (1.4.0)
|
||||
oauth2 (~> 1.0)
|
||||
omniauth (~> 1.2)
|
||||
omniauth-twitter (1.2.1)
|
||||
json (~> 1.3)
|
||||
omniauth-oauth (~> 1.1)
|
||||
orm_adapter (0.5.0)
|
||||
paperclip (4.3.6)
|
||||
activemodel (>= 3.2.0)
|
||||
activesupport (>= 3.2.0)
|
||||
paperclip (5.1.0)
|
||||
activemodel (>= 4.2.0)
|
||||
activesupport (>= 4.2.0)
|
||||
cocaine (~> 0.5.5)
|
||||
mime-types
|
||||
mimemagic (= 0.3.0)
|
||||
parser (2.3.1.0)
|
||||
mimemagic (~> 0.3.0)
|
||||
parser (2.3.2.0)
|
||||
ast (~> 2.2)
|
||||
pg (0.18.4)
|
||||
pg (0.19.0)
|
||||
plupload-rails (1.2.1)
|
||||
rails (>= 3.1)
|
||||
poltergeist (1.9.0)
|
||||
poltergeist (1.11.0)
|
||||
capybara (~> 2.1)
|
||||
cliver (~> 0.3.1)
|
||||
multi_json (~> 1.0)
|
||||
websocket-driver (>= 0.2.0)
|
||||
pry (0.10.3)
|
||||
powerpack (0.1.1)
|
||||
pry (0.10.4)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
slop (~> 3.4)
|
||||
public_suffix (2.0.4)
|
||||
quiet_assets (1.1.0)
|
||||
railties (>= 3.1, < 5.0)
|
||||
rack (1.5.5)
|
||||
rack (1.6.5)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.1.15)
|
||||
actionmailer (= 4.1.15)
|
||||
actionpack (= 4.1.15)
|
||||
actionview (= 4.1.15)
|
||||
activemodel (= 4.1.15)
|
||||
activerecord (= 4.1.15)
|
||||
activesupport (= 4.1.15)
|
||||
rails (4.2.7.1)
|
||||
actionmailer (= 4.2.7.1)
|
||||
actionpack (= 4.2.7.1)
|
||||
actionview (= 4.2.7.1)
|
||||
activejob (= 4.2.7.1)
|
||||
activemodel (= 4.2.7.1)
|
||||
activerecord (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.1.15)
|
||||
sprockets-rails (~> 2.0)
|
||||
rails-i18n (4.0.8)
|
||||
railties (= 4.2.7.1)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.7)
|
||||
activesupport (>= 4.2.0.beta, < 5.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
rails-i18n (4.0.9)
|
||||
i18n (~> 0.7)
|
||||
railties (~> 4.0)
|
||||
rails_12factor (0.0.3)
|
||||
@@ -328,87 +363,109 @@ GEM
|
||||
rails_stdout_logging
|
||||
rails_serve_static_assets (0.0.5)
|
||||
rails_stdout_logging (0.0.5)
|
||||
railties (4.1.15)
|
||||
actionpack (= 4.1.15)
|
||||
activesupport (= 4.1.15)
|
||||
railties (4.2.7.1)
|
||||
actionpack (= 4.2.7.1)
|
||||
activesupport (= 4.2.7.1)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
raindrops (0.16.0)
|
||||
rake (11.1.2)
|
||||
rb-fsevent (0.9.7)
|
||||
rainbow (2.1.0)
|
||||
raindrops (0.17.0)
|
||||
rake (11.3.0)
|
||||
rb-fsevent (0.9.8)
|
||||
rb-inotify (0.9.7)
|
||||
ffi (>= 0.5.0)
|
||||
responders (1.1.2)
|
||||
railties (>= 3.2, < 4.2)
|
||||
rspec (3.4.0)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
redis (3.3.2)
|
||||
responders (2.3.0)
|
||||
railties (>= 4.2.0, < 5.1)
|
||||
rspec (3.5.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-activemodel-mocks (1.0.3)
|
||||
activemodel (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
rspec-mocks (>= 2.99, < 4.0)
|
||||
rspec-core (3.4.4)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-expectations (3.4.0)
|
||||
rspec-core (3.5.4)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-expectations (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-mocks (3.4.1)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-mocks (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-rails (3.4.2)
|
||||
actionpack (>= 3.0, < 4.3)
|
||||
activesupport (>= 3.0, < 4.3)
|
||||
railties (>= 3.0, < 4.3)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-support (3.4.1)
|
||||
ruby-units (2.0.0)
|
||||
ruby_dep (1.3.1)
|
||||
ruby_parser (3.8.2)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-rails (3.5.2)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-support (3.5.0)
|
||||
rubocop (0.45.0)
|
||||
parser (>= 2.3.1.1, < 3.0)
|
||||
powerpack (~> 0.1)
|
||||
rainbow (>= 1.99.1, < 3.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
ruby-progressbar (1.8.1)
|
||||
ruby-units (2.0.1)
|
||||
ruby_dep (1.4.0)
|
||||
ruby_parser (3.8.3)
|
||||
sexp_processor (~> 4.1)
|
||||
rubyzip (1.2.0)
|
||||
sass (3.4.22)
|
||||
sass-rails (5.0.4)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass-rails (5.0.6)
|
||||
railties (>= 4.0.0, < 6)
|
||||
sass (~> 3.1)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (>= 2.0, < 4.0)
|
||||
tilt (>= 1.1, < 3)
|
||||
selenium-webdriver (2.53.0)
|
||||
selenium-webdriver (2.53.4)
|
||||
childprocess (~> 0.5)
|
||||
rubyzip (~> 1.0)
|
||||
websocket (~> 1.0)
|
||||
sexp_processor (4.7.0)
|
||||
shellany (0.0.1)
|
||||
simplecov (0.11.2)
|
||||
sidekiq (4.1.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
connection_pool (~> 2.2, >= 2.2.0)
|
||||
redis (~> 3.2, >= 3.2.1)
|
||||
sinatra (>= 1.4.7)
|
||||
simplecov (0.12.0)
|
||||
docile (~> 1.1.0)
|
||||
json (~> 1.8)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.0)
|
||||
sinatra (1.4.7)
|
||||
rack (~> 1.5)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (>= 1.3, < 3)
|
||||
slop (3.6.0)
|
||||
sprockets (3.6.0)
|
||||
sparkpost_rails (1.4.0)
|
||||
rails (>= 4.0, < 5.1)
|
||||
sprockets (3.7.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
sprockets-rails (2.3.3)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sprockets-rails (3.1.1)
|
||||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
term-ansicolor (1.3.2)
|
||||
tins (~> 1.0)
|
||||
terminal-table (1.5.2)
|
||||
thor (0.19.1)
|
||||
terminal-table (1.7.3)
|
||||
unicode-display_width (~> 1.1.1)
|
||||
thor (0.19.3)
|
||||
thread (0.2.2)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.4)
|
||||
tins (1.6.0)
|
||||
tilt (2.0.5)
|
||||
tins (1.13.0)
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.7.2)
|
||||
execjs (>= 0.3.0)
|
||||
json (>= 1.8.0)
|
||||
unicode-display_width (1.1.1)
|
||||
unicorn (5.1.0)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
@@ -430,8 +487,9 @@ PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
active_utils (= 1.0.5)!
|
||||
activemerchant (= 1.33.0)!
|
||||
active_merchant-paypal-bogus-gateway
|
||||
active_utils
|
||||
activemerchant
|
||||
better_errors
|
||||
binding_of_caller
|
||||
bluecloth
|
||||
@@ -444,21 +502,23 @@ DEPENDENCIES
|
||||
cancancan (~> 1.9)
|
||||
capybara
|
||||
capybara-email
|
||||
capybara-screenshot
|
||||
codeclimate-test-reporter
|
||||
coffee-rails (~> 4.1.0)
|
||||
comfortable_mexican_sofa (~> 1.12.0)
|
||||
coveralls
|
||||
csv_shaper
|
||||
dalli
|
||||
database_cleaner (~> 1.5.0)
|
||||
devise (~> 3.5.0)
|
||||
devise (>= 4.0.0)
|
||||
elasticsearch-model
|
||||
elasticsearch-rails
|
||||
factory_girl_rails (~> 4.5.0)
|
||||
factory_girl_rails
|
||||
figaro
|
||||
flickraw
|
||||
font-awesome-sass
|
||||
friendly_id (~> 5.0.4)
|
||||
geocoder!
|
||||
geocoder
|
||||
gibbon (~> 1.2.0)
|
||||
gravatar-ultimate
|
||||
guard
|
||||
@@ -477,27 +537,31 @@ DEPENDENCIES
|
||||
memcachier
|
||||
newrelic_rpm
|
||||
omniauth
|
||||
omniauth-facebook
|
||||
omniauth-flickr (>= 0.0.15)
|
||||
omniauth-twitter
|
||||
pg
|
||||
poltergeist (~> 1.6)
|
||||
poltergeist
|
||||
pry
|
||||
quiet_assets
|
||||
rails (~> 4.1.11)
|
||||
rails (~> 4.2.1)
|
||||
rails_12factor
|
||||
rake (>= 10.0.0)
|
||||
rspec-activemodel-mocks
|
||||
rspec-rails (~> 3.4.0)
|
||||
rspec-rails
|
||||
rubocop
|
||||
ruby-units
|
||||
sass-rails (~> 5.0.4)
|
||||
selenium-webdriver
|
||||
sidekiq
|
||||
sparkpost_rails
|
||||
uglifier (~> 2.7.2)
|
||||
unicorn
|
||||
webrat
|
||||
will_paginate (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 2.1.8p440
|
||||
ruby 2.3.1p112
|
||||
|
||||
BUNDLED WITH
|
||||
1.12.4
|
||||
1.13.6
|
||||
|
||||
21
README.md
21
README.md
@@ -2,6 +2,7 @@
|
||||
|
||||
[](https://travis-ci.org/Growstuff/growstuff)
|
||||
[](https://coveralls.io/r/Growstuff/growstuff)
|
||||
[](https://codeclimate.com/github/Growstuff/growstuff)
|
||||
|
||||
Welcome to the Growstuff project.
|
||||
|
||||
@@ -18,8 +19,9 @@ encourage participation from people of all backgrounds and skill levels.
|
||||
|
||||
* [Issues](http://github.com/Growstuff/growstuff/issues) (features we're
|
||||
working on, known bugs, etc)
|
||||
* [Discussion forums](http://wiki.growstuff.org/index.php/Discussion_forums) (mailing lists, IRC, etc)
|
||||
* [Wiki](http://wiki.growstuff.org/) (general documentation)
|
||||
* [Discussion forums](http://talk.growstuff.org/) (design ideas, planning releases)
|
||||
* [IRC](https://webchat.freenode.net/) growstuff channel (general chat, brainstorming and troubleshooting) or [Gitter](https://gitter.im/Growstuff/growstuff)
|
||||
* [Wiki](https://github.com/Growstuff/growstuff/wiki) (general documentation, etc. Help by migrating from the [old wiki](https://web.archive.org/web/*/wiki.growstuff.org))
|
||||
|
||||
## For coders
|
||||
|
||||
@@ -27,18 +29,10 @@ Growstuff is built in Ruby on Rails and also uses JavaScript for
|
||||
frontend features. We welcome contributions -- see
|
||||
[CONTRIBUTING](CONTRIBUTING.md) for details.
|
||||
|
||||
* To set up your development environment, see [Getting started](http://wiki.growstuff.org/index.php/Development/Getting_Started).
|
||||
* To set up your development environment, see [Getting started](https://github.com/Growstuff/growstuff/wiki/New-contributor-guide).
|
||||
* We encourage [pair programming](http://wiki.growstuff.org/index.php/Pairing), especially for newer developers. [Find a pair programming partner.](http://talk.growstuff.org/t/find-a-pair-programming-partner/13)
|
||||
* Drop in to one of our [discussion forums](http://wiki.growstuff.org/index.php/Discussion_forums) to chat to other developers, get help, etc.
|
||||
* You may also be interested in our [API](http://wiki.growstuff.org/index.php/API).
|
||||
|
||||
The wiki is down right now, so here's what you need to do on Mac OS X to get set up.
|
||||
|
||||
```
|
||||
gem install bundle
|
||||
gem install pg -v '0.18.4' -- --with-pg-config=/Applications/Postgres.app/Contents/Versions/latest/bin/pg_config
|
||||
bundle install
|
||||
```
|
||||
* Drop in to our [discussion forums](http://talk.growstuff.org/), IRC or Gitter to chat to other developers, get help, etc.
|
||||
* You may also be interested in our [API](https://github.com/Growstuff/growstuff/wiki/API).
|
||||
|
||||
## For designers, writers, researchers, data wranglers, and other contributors
|
||||
|
||||
@@ -57,6 +51,7 @@ Here on Github, you might find these useful:
|
||||
* [needs: visual design](https://github.com/Growstuff/growstuff/labels/needs:%20visual design) - tasks requiring visual/graphical design
|
||||
* [needs: documentation](https://github.com/Growstuff/growstuff/labels/needs:%20documentation)
|
||||
* [needs: data](https://github.com/Growstuff/growstuff/labels/needs:%20data) - tasks requiring data entry, data design, data import, or similar
|
||||
* [curated:beginner](https://github.com/Growstuff/growstuff/labels/curated:%20beginner) - tasks that are ideal for beginner programmers or people new to the project
|
||||
|
||||
Feel free to comment on any of the issues you find there, or open up a broader conversation on [Growstuff Talk](http://talk.growstuff.org).
|
||||
|
||||
|
||||
BIN
app/assets/images/facebook-login-splash.png
Normal file
BIN
app/assets/images/facebook-login-splash.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 176 KiB |
BIN
app/assets/images/facebook-thumbnail.png
Normal file
BIN
app/assets/images/facebook-thumbnail.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
BIN
app/assets/images/location-not-set.en.png
Normal file
BIN
app/assets/images/location-not-set.en.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@@ -5,17 +5,15 @@
|
||||
jQuery ->
|
||||
|
||||
el = $('.append-date')
|
||||
|
||||
|
||||
el.datepicker({'format': 'yyyy-mm-dd'})
|
||||
|
||||
href = el.attr('href')
|
||||
|
||||
originalText = el.text()
|
||||
|
||||
el.click (e) ->
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
|
||||
originalText = $(this).text()
|
||||
href = $(this).attr('href')
|
||||
$(this).text('Confirm without date')
|
||||
|
||||
$(this).bind('click.confirm', (e) ->
|
||||
@@ -31,6 +29,8 @@ jQuery ->
|
||||
|
||||
el.one 'changeDate', ->
|
||||
date = $(this).datepicker('getDate')
|
||||
href = $(this).attr('href')
|
||||
|
||||
url = "#{href}&planting[finished_at]=#{date}"
|
||||
|
||||
link = $("<a href='#{url}' data-method='put'></a>")
|
||||
|
||||
4
app/assets/javascripts/bootstrap-accessibility.min.js
vendored
Normal file
4
app/assets/javascripts/bootstrap-accessibility.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
if (document.getElementById("cropmap") !== null) {
|
||||
mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>";
|
||||
mapbox_base_url = "https://c.tiles.mapbox.com/v3/" + mapbox_map_id + "/{z}/{x}/{y}.png";
|
||||
mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>";
|
||||
mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token;
|
||||
|
||||
L.Icon.Default.imagePath = '/assets'
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
if (document.getElementById("membermap") !== null) {
|
||||
mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>";
|
||||
mapbox_base_url = "https://c.tiles.mapbox.com/v3/" + mapbox_map_id + "/{z}/{x}/{y}.png";
|
||||
mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>";
|
||||
mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token;
|
||||
|
||||
L.Icon.Default.imagePath = '/assets'
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
if (document.getElementById("placesmap") !== null) {
|
||||
places_base_path = "/places";
|
||||
mapbox_map_id = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_map_id %>";
|
||||
mapbox_base_url = "https://c.tiles.mapbox.com/v3/" + mapbox_map_id + "/{z}/{x}/{y}.png";
|
||||
mapbox_access_token = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.mapbox_access_token %>";
|
||||
mapbox_base_url = "http://a.tiles.mapbox.com/v4/" + mapbox_map_id + "/{z}/{x}/{y}.png?access_token=" + mapbox_access_token;
|
||||
nominatim_base_url = 'http://nominatim.openstreetmap.org/search/';
|
||||
nominatim_user_agent_email = "<%= Rails.env == 'test' ? 0 : Growstuff::Application.config.user_agent_email %>";
|
||||
|
||||
|
||||
@@ -42,4 +42,3 @@ $ ->
|
||||
element = document.getElementById(tmp)
|
||||
console.log("%s",tmp)
|
||||
element.remove()
|
||||
|
||||
1
app/assets/stylesheets/bootstrap-accessibility.css
vendored
Normal file
1
app/assets/stylesheets/bootstrap-accessibility.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.btn:focus{outline:dotted 2px #000}div.active:focus{outline:dotted 1px #000}a:focus{outline:dotted 1px #000}.close:hover,.close:focus{outline:dotted 1px #000}.nav>li>a:hover,.nav>li>a:focus{outline:dotted 1px #000}.carousel-inner>.item{position:absolute;top:-999999em;display:block;-moz-transition:ease-in-out 0.6s left;-o-transition:ease-in-out 0.6s left;-webkit-transition:ease-in-out 0.6s left;transition:ease-in-out 0.6s left}.carousel-inner>.active{top:0}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{position:relative}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.alert-success{color:#2d4821}.alert-info{color:#214c62}.alert-warning{color:#6c4a00;background-color:#f9f1c6}.alert-danger{color:#d2322d}.alert-danger:hover{color:#a82824}
|
||||
@@ -42,7 +42,7 @@ $navbar-default-bg-highlight: $brown
|
||||
$navbar-default-color: $beige
|
||||
$navbar-default-link-color: darken($beige, 20%)
|
||||
$navbar-default-link-hover-color: $beige
|
||||
$navbar-default-link-active-color: $beige
|
||||
$navbar-default-link-active-color: darken($beige,80%)
|
||||
$navbar-default-brand-color: lighten($green, 20%)
|
||||
|
||||
// Top nav collapse threshold
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@import "bootstrap"
|
||||
@import "custom_bootstrap/variables"
|
||||
// this padding needs to be done before the responsive stuff is imported
|
||||
body
|
||||
body
|
||||
// modifying this for our promotional banner. can be replaced after if
|
||||
// needed.
|
||||
// padding-top: $navbar-height + 15px
|
||||
@@ -19,14 +19,14 @@ body
|
||||
//@import "bootstrap/glyphicons"
|
||||
|
||||
|
||||
.list-inline > li.first
|
||||
.list-inline > li.first
|
||||
padding-left: 0px
|
||||
|
||||
h2
|
||||
h2
|
||||
font-size: 150%
|
||||
|
||||
|
||||
//#subtitle
|
||||
//#subtitle
|
||||
// color: lighten($brown, 30%)
|
||||
// font-style: italic
|
||||
// font-weight: normal
|
||||
@@ -34,36 +34,49 @@ h2
|
||||
// padding-left: 1em
|
||||
// padding-top: 0px
|
||||
|
||||
h3
|
||||
h3
|
||||
font-size: 120%
|
||||
|
||||
.main
|
||||
.main
|
||||
padding-right: 1em
|
||||
|
||||
.navbar .navbar-form
|
||||
padding-top: 0
|
||||
padding-bottom: 0
|
||||
margin-right: 0
|
||||
margin-left: 15px
|
||||
border: 0
|
||||
-webkit-box-shadow: none
|
||||
box-shadow: none
|
||||
|
||||
.img-responsive
|
||||
max-width: 100%
|
||||
height: auto
|
||||
|
||||
.sidebar
|
||||
border-left: 1px solid darken($beige, 10%)
|
||||
margin-left: -1px
|
||||
padding-left: 1em
|
||||
|
||||
// this is used for eg. crops and members index pages
|
||||
.six-across:nth-child(6n+1)
|
||||
.six-across:nth-child(6n+1)
|
||||
margin-left: 0px
|
||||
|
||||
.three-across:nth-child(3n+1)
|
||||
.three-across:nth-child(3n+1)
|
||||
margin-left: 0px
|
||||
clear: both
|
||||
|
||||
// let's condense the hero unit a little
|
||||
.jumbotron
|
||||
.jumbotron
|
||||
padding-top: 30px
|
||||
padding-bottom: 30px
|
||||
|
||||
// info under the main heading on homepage
|
||||
.jumbotron .info
|
||||
.jumbotron .info
|
||||
padding-top: 15px
|
||||
|
||||
// signup widget on homepage
|
||||
.jumbotron .signup
|
||||
.jumbotron .signup
|
||||
background-color: lighten($green, 40%)
|
||||
border: 1px solid lighten($green, 20%)
|
||||
border-radius: 6px
|
||||
@@ -72,19 +85,19 @@ h3
|
||||
text-align: center
|
||||
|
||||
// stats shown on homepage. eg. "999 members..."
|
||||
p.stats
|
||||
p.stats
|
||||
font-weight: bold
|
||||
|
||||
.member-cards
|
||||
.member-cards
|
||||
display: flex
|
||||
flex: none
|
||||
flex-wrap: wrap
|
||||
justify-content: space-between
|
||||
|
||||
.member-thumbnail
|
||||
.member-thumbnail
|
||||
padding: .25em
|
||||
|
||||
div
|
||||
div
|
||||
width: 5em
|
||||
display: inline-block
|
||||
vertical-align: top
|
||||
@@ -93,29 +106,62 @@ p.stats
|
||||
padding-left: 1em
|
||||
width: 15em
|
||||
|
||||
#placesmap, #cropmap
|
||||
.planting
|
||||
dl.planting-attributes
|
||||
font-size: 85%
|
||||
|
||||
dt
|
||||
text-align: left
|
||||
dd
|
||||
margin-left: auto
|
||||
|
||||
@media (min-width: $screen-md-min)
|
||||
.planting-thumbnail
|
||||
dl.planting-attributes
|
||||
font-size: 85%
|
||||
width: 100%
|
||||
|
||||
dt
|
||||
text-align: left
|
||||
width: 80px
|
||||
dd
|
||||
padding-left: 80px
|
||||
margin-left: auto
|
||||
|
||||
.navbar .navbar-form
|
||||
width: 250px
|
||||
|
||||
|
||||
#placesmap, #cropmap
|
||||
height: 500px
|
||||
|
||||
#membermap
|
||||
#membermap
|
||||
height: 250px
|
||||
|
||||
.member-location
|
||||
.location-not-set
|
||||
height: 250px
|
||||
width: 100%
|
||||
background-image: image-url('location-not-set.en.png')
|
||||
background-repeat: no-repeat
|
||||
background-position: center
|
||||
|
||||
.member-location
|
||||
font-size: small
|
||||
font-style: italic
|
||||
|
||||
|
||||
.member-location a
|
||||
.member-location a
|
||||
color: $brown
|
||||
|
||||
|
||||
.photo-thumbnail
|
||||
.photo-thumbnail
|
||||
padding: 0
|
||||
position: relative
|
||||
|
||||
img
|
||||
width: 100%
|
||||
|
||||
.text
|
||||
|
||||
.text
|
||||
display: none
|
||||
color: #000
|
||||
position: absolute
|
||||
@@ -123,140 +169,132 @@ p.stats
|
||||
background: rgba(0, 0, 0, 0.8)
|
||||
width: 100%
|
||||
margin: 0
|
||||
|
||||
p
|
||||
|
||||
p
|
||||
padding: 5px
|
||||
margin: 0
|
||||
color: #fff
|
||||
|
||||
&:hover
|
||||
.text
|
||||
|
||||
&:hover
|
||||
.text
|
||||
display: block
|
||||
|
||||
.thumbnail
|
||||
.thumbnail
|
||||
border: none
|
||||
text-align: center
|
||||
margin-bottom: 1.5em
|
||||
|
||||
.member-thumbnail
|
||||
.member-thumbnail
|
||||
text-align: left
|
||||
img
|
||||
img
|
||||
height: 85px
|
||||
width: 85px
|
||||
max-width: 85px
|
||||
|
||||
.crop-thumbnail
|
||||
.crop-thumbnail
|
||||
height: 220px
|
||||
.cropinfo
|
||||
.cropinfo
|
||||
display: inline-block
|
||||
max-width: 100%
|
||||
white-space: nowrap
|
||||
line-height: 1em
|
||||
padding-bottom: 2px
|
||||
|
||||
.cropname
|
||||
.cropname
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
|
||||
.scientificname
|
||||
.scientificname
|
||||
font-size: small
|
||||
font-style: italic
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
|
||||
.plantingcount
|
||||
.plantingcount
|
||||
font-size: small
|
||||
|
||||
.crop-name a
|
||||
.crop-name a
|
||||
padding-top: 2px
|
||||
|
||||
.scientific-name small
|
||||
.scientific-name small
|
||||
margin-bottom: -2px
|
||||
|
||||
li.crop-hierarchy
|
||||
li.crop-hierarchy
|
||||
list-style-type: disc
|
||||
|
||||
.navbar-brand
|
||||
.navbar-brand
|
||||
margin: 0px
|
||||
padding: 0px
|
||||
|
||||
.navbar-bottom
|
||||
.navbar-bottom
|
||||
margin: 40px 0px 0px 0px !important
|
||||
|
||||
// footer
|
||||
footer
|
||||
#footer1, #footer2, #footer3
|
||||
footer
|
||||
#footer1, #footer2, #footer3
|
||||
text-align: left
|
||||
padding-top: 1em
|
||||
padding-bottom: 2em
|
||||
ul
|
||||
ul
|
||||
list-style-type: none
|
||||
list-style-position: outside
|
||||
padding-left: 0px
|
||||
margin-left: 0px
|
||||
|
||||
a
|
||||
|
||||
a
|
||||
color: $navbar-default-link-color
|
||||
text-decoration: none
|
||||
|
||||
a:hover
|
||||
|
||||
a:hover
|
||||
color: $navbar-default-link-hover-color
|
||||
|
||||
a:active
|
||||
|
||||
a:active
|
||||
color: $navbar-default-link-active-color
|
||||
|
||||
.navbar-bottom.navbar
|
||||
.navbar-bottom.navbar
|
||||
border-radius: 0
|
||||
|
||||
// ensure footer is pushed to bottom of browser window
|
||||
|
||||
#maincontainer
|
||||
#maincontainer
|
||||
min-height: 80%
|
||||
|
||||
html, body
|
||||
html, body
|
||||
height: 100%
|
||||
|
||||
.crop-image, .member-image
|
||||
.crop-image, .member-image
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
// Autosuggest
|
||||
|
||||
.ui-autocomplete
|
||||
.ui-autocomplete
|
||||
background: white
|
||||
z-index: $zindex-tooltip
|
||||
|
||||
// Crowdfunding campaign, Sep-Oct 2014
|
||||
|
||||
.crowdfunding-banner
|
||||
text-align: center
|
||||
font-weight: bold
|
||||
background-color: lighten($green, 30%)
|
||||
margin-top: 0px
|
||||
margin-bottom: 5px
|
||||
padding: 15px
|
||||
|
||||
.crowdfunding-banner a
|
||||
color: $brown
|
||||
text-decoration: underline
|
||||
|
||||
.alert
|
||||
a
|
||||
.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)
|
||||
.sidebar
|
||||
@media only screen and (max-width: 767px)
|
||||
.sidebar
|
||||
margin-left: 0
|
||||
border-left: none
|
||||
padding-left: 0
|
||||
|
||||
#map
|
||||
#map
|
||||
height: 300px
|
||||
|
||||
.navbar .nav > li
|
||||
.navbar .nav > li
|
||||
display: block
|
||||
|
||||
.navbar .navbar-form
|
||||
width: 185px
|
||||
padding-left: 0
|
||||
padding-right: 0
|
||||
|
||||
/* override "info" alert boxes to be green, not blue, on Growstuff */
|
||||
$state-info-text: darken($green, 10%)
|
||||
$state-info-bg: lighten($green, 50%)
|
||||
@@ -267,7 +305,7 @@ $state-info-bg: lighten($green, 50%)
|
||||
$state-success-text: darken($green, 10%)
|
||||
$state-success-bg: lighten($green, 50%)
|
||||
|
||||
.hide
|
||||
.hide
|
||||
display: none
|
||||
|
||||
#add-sci_name-row, #remove-sci_name-row, #add-alt_name-row, #remove-alt_name-row
|
||||
@@ -276,15 +314,25 @@ $state-success-bg: lighten($green, 50%)
|
||||
.panel-footer
|
||||
height: 6em
|
||||
|
||||
.panel
|
||||
.dl-horizontal
|
||||
text-overflow: ellipsis
|
||||
overflow: hidden
|
||||
|
||||
#gardens_panel_body
|
||||
height: 20em
|
||||
|
||||
.form-group.required .control-label:before
|
||||
.form-group.required .control-label:before
|
||||
content: "* "
|
||||
color: red
|
||||
|
||||
.margin-bottom
|
||||
.margin-bottom
|
||||
margin-bottom: 1em
|
||||
|
||||
.red
|
||||
.red
|
||||
color: red
|
||||
|
||||
.truncate
|
||||
overflow: hidden
|
||||
text-overflow: ellipsis
|
||||
white-space: nowrap
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
class AboutController < ApplicationController
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
class AccountTypesController < ApplicationController
|
||||
before_filter :authenticate_member!
|
||||
load_and_authorize_resource
|
||||
|
||||
|
||||
# GET /account_types
|
||||
def index
|
||||
@account_types = AccountType.all
|
||||
@@ -70,7 +70,7 @@ class AccountTypesController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def account_type_params
|
||||
params.require(:account_type).permit(:is_paid, :is_permanent_paid, :name)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class AccountsController < ApplicationController
|
||||
before_filter :authenticate_member!
|
||||
load_and_authorize_resource
|
||||
|
||||
|
||||
# GET /accounts
|
||||
def index
|
||||
@accounts = Account.all
|
||||
@@ -43,5 +43,4 @@ class AccountsController < ApplicationController
|
||||
def account_params
|
||||
params.require(:account).permit(:account_type_id, :member_id, :paid_until)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ class Admin::OrdersController < ApplicationController
|
||||
|
||||
def search
|
||||
authorize! :manage, :all
|
||||
@orders = Order.search({by: params[:search_by], for: params[:search_text]})
|
||||
@orders = Order.search({ by: params[:search_by], for: params[:search_text] })
|
||||
|
||||
if @orders.empty?
|
||||
flash[:alert] = "Couldn't find order with #{params[:search_by]} = #{params[:search_text]}"
|
||||
@@ -17,6 +17,5 @@ class Admin::OrdersController < ApplicationController
|
||||
respond_to do |format|
|
||||
format.html # index.html.haml
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,17 +13,6 @@ class AlternateNamesController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# GET /alternate_names/1
|
||||
# GET /alternate_names/1.json
|
||||
def show
|
||||
@alternate_name = AlternateName.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.haml
|
||||
format.json { render json: @alternate_name }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /alternate_names/new
|
||||
# GET /alternate_names/new.json
|
||||
def new
|
||||
|
||||
@@ -14,7 +14,7 @@ class ApplicationController < ActionController::Base
|
||||
request.path != "/members/confirmation" &&
|
||||
request.path != "/members/sign_out" &&
|
||||
!request.xhr?)
|
||||
store_location_for(:member, request.fullpath)
|
||||
store_location_for(:member, request.fullpath)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -52,7 +52,7 @@ class ApplicationController < ActionController::Base
|
||||
protected
|
||||
|
||||
def configure_permitted_parameters
|
||||
devise_parameter_sanitizer.for(:sign_up) do |member|
|
||||
devise_parameter_sanitizer.permit(:sign_up) do |member|
|
||||
member.permit(:login_name, :email, :password, :password_confirmation,
|
||||
:remember_me, :login,
|
||||
# terms of service
|
||||
@@ -64,7 +64,7 @@ class ApplicationController < ActionController::Base
|
||||
)
|
||||
end
|
||||
|
||||
devise_parameter_sanitizer.for(:account_update) do |member|
|
||||
devise_parameter_sanitizer.permit(:account_update) do |member|
|
||||
member.permit(:login_name, :email, :password, :password_confirmation,
|
||||
:remember_me, :login,
|
||||
# terms of service
|
||||
@@ -73,10 +73,9 @@ class ApplicationController < ActionController::Base
|
||||
:bio, :location, :latitude, :longitude,
|
||||
# email settings
|
||||
:show_email, :newsletter, :send_notification_email, :send_planting_reminder,
|
||||
#update password
|
||||
# update password
|
||||
:current_password
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -7,27 +7,18 @@ class AuthenticationsController < ApplicationController
|
||||
auth = request.env['omniauth.auth']
|
||||
@authentication = nil
|
||||
if auth
|
||||
|
||||
name = ''
|
||||
case auth['provider']
|
||||
when 'twitter'
|
||||
name = auth['info']['nickname']
|
||||
when 'flickr'
|
||||
name = auth['info']['name']
|
||||
else
|
||||
name = auth['info']['name']
|
||||
end
|
||||
name = Growstuff::OauthSignupAction.new.determine_name(auth)
|
||||
|
||||
@authentication = current_member.authentications
|
||||
.create_with(
|
||||
name: name,
|
||||
token: auth['credentials']['token'],
|
||||
secret: auth['credentials']['secret']
|
||||
)
|
||||
.find_or_create_by(
|
||||
provider: auth['provider'],
|
||||
uid: auth['uid'],
|
||||
name: name)
|
||||
.create_with(
|
||||
name: name,
|
||||
token: auth['credentials']['token'],
|
||||
secret: auth['credentials']['secret']
|
||||
)
|
||||
.find_or_create_by(
|
||||
provider: auth['provider'],
|
||||
uid: auth['uid'],
|
||||
name: name)
|
||||
|
||||
flash[:notice] = "Authentication successful."
|
||||
else
|
||||
|
||||
@@ -14,17 +14,6 @@ class CommentsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# GET /comments/1
|
||||
# GET /comments/1.json
|
||||
def show
|
||||
@comment = Comment.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.json { render json: @comment }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /comments/new
|
||||
# GET /comments/new.json
|
||||
def new
|
||||
@@ -100,7 +89,7 @@ class CommentsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def comment_params
|
||||
params.require(:comment).permit(:author_id, :body, :post_id)
|
||||
|
||||
@@ -11,11 +11,11 @@ class CropsController < ApplicationController
|
||||
@sort = params[:sort]
|
||||
if @sort == 'alpha'
|
||||
# alphabetical order
|
||||
@crops = Crop.includes(:scientific_names, {plantings: :photos})
|
||||
@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})
|
||||
@crops = Crop.popular.includes(:scientific_names, { plantings: :photos })
|
||||
@paginated_crops = @crops.approved.paginate(page: params[:page])
|
||||
end
|
||||
|
||||
@@ -37,14 +37,14 @@ class CropsController < ApplicationController
|
||||
# GET /crops/wrangle
|
||||
def wrangle
|
||||
@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 = case @approval_status
|
||||
when "pending"
|
||||
Crop.pending_approval
|
||||
when "rejected"
|
||||
Crop.rejected
|
||||
else
|
||||
Crop.recent
|
||||
end
|
||||
|
||||
@crops = @crops.paginate(page: params[:page])
|
||||
|
||||
@@ -77,15 +77,23 @@ class CropsController < ApplicationController
|
||||
# GET /crops/1
|
||||
# GET /crops/1.json
|
||||
def show
|
||||
@crop = Crop.includes(:scientific_names, {plantings: :photos}).find(params[:id])
|
||||
@crop = Crop.includes(:scientific_names, { plantings: :photos }).find(params[:id])
|
||||
@posts = @crop.posts.paginate(page: params[:page])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.haml
|
||||
format.json do
|
||||
# TODO RABL or similar one day to avoid presentation logic here
|
||||
owner_structure = {
|
||||
owner: {
|
||||
only: [:id, :login_name, :location, :latitude, :longitude]
|
||||
}
|
||||
}
|
||||
render json: @crop.to_json(include: {
|
||||
plantings: { include: { owner: { only: [:id, :login_name, :location, :latitude, :longitude] }}}
|
||||
})
|
||||
plantings: {
|
||||
include: owner_structure
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -108,13 +116,11 @@ class CropsController < ApplicationController
|
||||
@crop = Crop.find(params[:id])
|
||||
@crop.alternate_names.build if @crop.alternate_names.blank?
|
||||
@crop.scientific_names.build if @crop.scientific_names.blank?
|
||||
|
||||
end
|
||||
|
||||
# POST /crops
|
||||
# POST /crops.json
|
||||
def create
|
||||
|
||||
@crop = Crop.new(crop_params)
|
||||
|
||||
if current_member.has_role? :crop_wrangler
|
||||
@@ -129,14 +135,14 @@ class CropsController < ApplicationController
|
||||
respond_to do |format|
|
||||
if @crop.save
|
||||
params[:alt_name].each do |index, value|
|
||||
@crop.alternate_names.create(name: value, creator_id: current_member.id)
|
||||
create_name('alternate', value)
|
||||
end
|
||||
params[:sci_name].each do |index, value|
|
||||
@crop.scientific_names.create(scientific_name: value, creator_id: current_member.id)
|
||||
create_name('scientific', value)
|
||||
end
|
||||
unless current_member.has_role? :crop_wrangler
|
||||
Role.crop_wranglers.each do |w|
|
||||
Notifier.new_crop_request(w, @crop).deliver!
|
||||
Notifier.new_crop_request(w, @crop).deliver_later!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -160,28 +166,14 @@ class CropsController < ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
if @crop.update(crop_params)
|
||||
if !params[:alt_name].nil?
|
||||
@crop.alternate_names.each do |alt_name|
|
||||
alt_name.destroy
|
||||
end
|
||||
recreate_names('alt_name', 'alternate')
|
||||
recreate_names('sci_name', 'scientific')
|
||||
|
||||
params[:alt_name].each do |index, value|
|
||||
alt_name = @crop.alternate_names.create(name: value, creator_id: current_member.id)
|
||||
end
|
||||
|
||||
@crop.scientific_names.each do |sci_name|
|
||||
sci_name.destroy
|
||||
end
|
||||
params[:sci_name].each do |index, value|
|
||||
sci_name = @crop.scientific_names.create(scientific_name: value, creator_id: current_member.id)
|
||||
end
|
||||
end
|
||||
|
||||
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"
|
||||
Notifier.crop_request_approved(requester, @crop).deliver_later! if new_status == "approved"
|
||||
Notifier.crop_request_rejected(requester, @crop).deliver_later! if new_status == "rejected"
|
||||
end
|
||||
format.html { redirect_to @crop, notice: 'Crop was successfully updated.' }
|
||||
format.json { head :no_content }
|
||||
@@ -206,7 +198,34 @@ class CropsController < ApplicationController
|
||||
|
||||
private
|
||||
|
||||
def recreate_names(param_name, name_type)
|
||||
return unless params[param_name].present?
|
||||
destroy_names(name_type)
|
||||
params[param_name].each do |index, value|
|
||||
create_name(name_type, value)
|
||||
end
|
||||
end
|
||||
|
||||
def destroy_names(name_type)
|
||||
@crop.send("#{name_type}_names").each do |alt_name|
|
||||
alt_name.destroy
|
||||
end
|
||||
end
|
||||
|
||||
def create_name(name_type, value)
|
||||
@crop.send("#{name_type}_names").create(name: value, creator_id: current_member.id)
|
||||
end
|
||||
|
||||
def crop_params
|
||||
params.require(:crop).permit(:en_wikipedia_url, :name, :parent_id, :creator_id, :approval_status, :request_notes, :reason_for_rejection, :rejection_notes, scientific_names_attributes: [:scientific_name, :_destroy, :id])
|
||||
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
|
||||
|
||||
@@ -5,11 +5,10 @@ class FollowsController < ApplicationController
|
||||
|
||||
# POST /follows
|
||||
def create
|
||||
|
||||
@follow = current_member.follows.build(followed_id: follow_params[:followed_id])
|
||||
|
||||
if @follow.save
|
||||
flash[:notice] = "Followed #{ @follow.followed.login_name }"
|
||||
flash[:notice] = "Followed #{@follow.followed.login_name}"
|
||||
redirect_to :back
|
||||
else
|
||||
flash[:error] = "Already following or error while following."
|
||||
@@ -23,7 +22,7 @@ class FollowsController < ApplicationController
|
||||
unfollowed_name = @follow.followed.login_name
|
||||
@follow.destroy
|
||||
|
||||
flash[:notice] = "Unfollowed #{ unfollowed_name }"
|
||||
flash[:notice] = "Unfollowed #{unfollowed_name}"
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ class GardensController < ApplicationController
|
||||
before_filter :authenticate_member!, except: [:index, :show]
|
||||
load_and_authorize_resource
|
||||
|
||||
|
||||
# GET /gardens
|
||||
# GET /gardens.json
|
||||
def index
|
||||
@@ -87,7 +86,9 @@ class GardensController < ApplicationController
|
||||
expire_fragment("homepage_stats")
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to gardens_by_owner_path(owner: @garden.owner), notice: 'Garden was successfully deleted.' }
|
||||
format.html do
|
||||
redirect_to gardens_by_owner_path(owner: @garden.owner), notice: 'Garden was successfully deleted.'
|
||||
end
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
@@ -96,6 +97,6 @@ class GardensController < ApplicationController
|
||||
|
||||
def garden_params
|
||||
params.require(:garden).permit(:name, :slug, :owner_id, :description, :active,
|
||||
:location, :latitude, :longitude, :area, :area_unit)
|
||||
:location, :latitude, :longitude, :area, :area_unit)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
class HarvestsController < ApplicationController
|
||||
before_filter :authenticate_member!, except: [:index, :show]
|
||||
load_and_authorize_resource
|
||||
|
||||
|
||||
# GET /harvests
|
||||
# GET /harvests.json
|
||||
def index
|
||||
@owner = Member.find_by_slug(params[:owner])
|
||||
@crop = Crop.find_by_slug(params[:crop])
|
||||
if @owner
|
||||
@harvests = @owner.harvests.includes(:owner, :crop)
|
||||
elsif @crop
|
||||
@harvests = @crop.harvests.includes(:owner, :crop)
|
||||
else
|
||||
@harvests = Harvest.includes(:owner, :crop)
|
||||
end
|
||||
@harvests = if @owner
|
||||
@owner.harvests.includes(:owner, :crop)
|
||||
elsif @crop
|
||||
@crop.harvests.includes(:owner, :crop)
|
||||
else
|
||||
Harvest.includes(:owner, :crop)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html { @harvests = @harvests.paginate(page: params[:page]) }
|
||||
@@ -27,24 +26,13 @@ class HarvestsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# GET /harvests/1
|
||||
# GET /harvests/1.json
|
||||
def show
|
||||
@harvest = Harvest.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.json { render json: @harvest }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /harvests/new
|
||||
# GET /harvests/new.json
|
||||
def new
|
||||
@harvest = Harvest.new('harvested_at' => Date.today)
|
||||
|
||||
# using find_by_id here because it returns nil, unlike find
|
||||
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
|
||||
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
@@ -107,6 +95,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, :si_weight)
|
||||
:quantity, :unit, :weight_quantity, :weight_unit, :plant_part_id, :slug, :si_weight)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,6 @@ class HomeController < ApplicationController
|
||||
skip_authorize_resource
|
||||
|
||||
def index
|
||||
|
||||
# we were previously generating a lot of instance variables like
|
||||
# @members_count and @interesting_crops in here, but now we call
|
||||
# the relevant class methods directly in the view, so that fragment
|
||||
@@ -12,5 +11,4 @@ class HomeController < ApplicationController
|
||||
format.html # index.html.haml
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,37 +1,46 @@
|
||||
class MembersController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
|
||||
skip_authorize_resource only: [:nearby, :unsubscribe]
|
||||
skip_authorize_resource only: [:nearby, :unsubscribe, :finish_signup]
|
||||
|
||||
after_action :expire_cache_fragments, only: :create
|
||||
|
||||
def index
|
||||
@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
|
||||
@members = if @sort == 'recently_joined'
|
||||
Member.confirmed.recently_joined.paginate(page: params[:page])
|
||||
else
|
||||
Member.confirmed.paginate(page: params[:page])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.haml
|
||||
format.json { render json: @members.to_json(only: [:id, :login_name, :slug, :bio, :created_at, :location, :latitude, :longitude]) }
|
||||
format.json {
|
||||
render json: @members.to_json(only: [
|
||||
:id, :login_name, :slug, :bio, :created_at, :location, :latitude, :longitude
|
||||
])
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@member = Member.confirmed.find(params[:id])
|
||||
@twitter_auth = @member.auth('twitter')
|
||||
@flickr_auth = @member.auth('flickr')
|
||||
@posts = @member.posts
|
||||
@member = Member.confirmed.find(params[:id])
|
||||
@twitter_auth = @member.auth('twitter')
|
||||
@flickr_auth = @member.auth('flickr')
|
||||
@facebook_auth = @member.auth('facebook')
|
||||
@posts = @member.posts
|
||||
# The garden form partial is called from the "New Garden" tab;
|
||||
# it requires a garden to be passed in @garden.
|
||||
# The new garden is not persisted unless Garden#save is called.
|
||||
@garden = Garden.new
|
||||
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.haml
|
||||
format.json { render json: @member.to_json(only: [:id, :login_name, :bio, :created_at, :slug, :location, :latitude, :longitude]) }
|
||||
format.json {
|
||||
render json: @member.to_json(only: [
|
||||
:id, :login_name, :bio, :created_at, :slug, :location, :latitude, :longitude
|
||||
])
|
||||
}
|
||||
format.rss { render(
|
||||
layout: false,
|
||||
locals: { member: @member }
|
||||
@@ -70,10 +79,27 @@ class MembersController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def finish_signup
|
||||
@member = current_member
|
||||
if request.patch? && params[:member]
|
||||
if @member.update(member_params)
|
||||
@member.skip_reconfirmation!
|
||||
bypass_sign_in(@member)
|
||||
redirect_to root_path, notice: 'Welcome.'
|
||||
else
|
||||
flash[:alert] = 'Failed to complete signup'
|
||||
@show_errors = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def expire_cache_fragments
|
||||
expire_fragment("homepage_stats")
|
||||
end
|
||||
|
||||
def member_params
|
||||
params.require(:member).permit(:login_name, :tos_agreement, :email, :newsletter)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -46,7 +46,6 @@ class NotificationsController < ApplicationController
|
||||
@subject = @sender_notification.subject =~ /^Re: / ?
|
||||
@sender_notification.subject :
|
||||
"Re: " + @sender_notification.subject
|
||||
|
||||
|
||||
respond_to do |format|
|
||||
format.html # reply.html.haml
|
||||
|
||||
52
app/controllers/omniauth_callbacks_controller.rb
Normal file
52
app/controllers/omniauth_callbacks_controller.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
require './lib/actions/oauth_signup_action'
|
||||
|
||||
#
|
||||
# Handle signup or signin
|
||||
# from various oauth providers
|
||||
#
|
||||
# Heavily overlaps with Authentications controller
|
||||
#
|
||||
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
||||
def facebook
|
||||
create
|
||||
end
|
||||
|
||||
def failure
|
||||
flash[:alert] = "Authentication failed."
|
||||
redirect_to request.env['omniauth.origin'] || "/"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create
|
||||
auth = request.env['omniauth.auth']
|
||||
action = Growstuff::OauthSignupAction.new
|
||||
|
||||
@authentication = nil
|
||||
if auth
|
||||
member = action.find_or_create_from_authorization(auth)
|
||||
@authentication = action.establish_authentication(auth, member)
|
||||
|
||||
unless action.member_created?
|
||||
sign_in_and_redirect member, event: :authentication # this will throw if @user is not activated
|
||||
set_flash_message(:notice, :success, kind: auth['provider']) if is_navigational_format?
|
||||
else
|
||||
raise "Invalid provider" unless ['facebook', 'twitter', 'flickr'].index(auth['provider'].to_s)
|
||||
|
||||
session["devise.#{auth['provider']}_data"] = request.env["omniauth.auth"]
|
||||
sign_in member
|
||||
redirect_to finish_signup_url(member)
|
||||
end
|
||||
else
|
||||
redirect_to request.env['omniauth.origin'] || edit_member_registration_path
|
||||
end
|
||||
end
|
||||
|
||||
def after_sign_in_path_for(resource)
|
||||
if resource.tos_agreement
|
||||
super resource
|
||||
else
|
||||
finish_signup_path(resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -49,7 +49,6 @@ class OrdersController < ApplicationController
|
||||
format.html { render action: "show" }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def complete
|
||||
@@ -78,7 +77,6 @@ class OrdersController < ApplicationController
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def cancel
|
||||
|
||||
6
app/controllers/pages_controller.rb
Normal file
6
app/controllers/pages_controller.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
class PagesController < ApplicationController
|
||||
def letsencrypt
|
||||
# use your code here, not mine
|
||||
render text: "y9KNck8wqkoQLnlr2RgA2TVwWtyYb4PeY_hzGNx0Tfs.dlIPqFhMDCLyQEccczY3roHZ1UWu6UqVeyb9mkRxheU"
|
||||
end
|
||||
end
|
||||
@@ -1,7 +1,7 @@
|
||||
class PasswordsController < Devise::PasswordsController
|
||||
protected
|
||||
|
||||
protected
|
||||
def after_resetting_password_path_for(resource)
|
||||
root_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class PhotosController < ApplicationController
|
||||
before_filter :authenticate_member!, except: [:index, :show]
|
||||
before_action :authenticate_member!, except: [:index, :show]
|
||||
load_and_authorize_resource
|
||||
|
||||
# GET /photos
|
||||
@@ -13,17 +13,6 @@ class PhotosController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# GET /photos/1
|
||||
# GET /photos/1.json
|
||||
def show
|
||||
@photo = Photo.find(params[:id])
|
||||
|
||||
respond_to do |format|
|
||||
format.html # show.html.erb
|
||||
format.json { render json: @photo }
|
||||
end
|
||||
end
|
||||
|
||||
# GET /photos/new
|
||||
# GET /photos/new.json
|
||||
def new
|
||||
@@ -58,43 +47,12 @@ class PhotosController < ApplicationController
|
||||
# POST /photos
|
||||
# POST /photos.json
|
||||
def create
|
||||
@photo = Photo.find_by_flickr_photo_id(params[:photo][:flickr_photo_id]) ||
|
||||
Photo.new(photo_params)
|
||||
@photo.owner_id = current_member.id
|
||||
@photo.set_flickr_metadata
|
||||
find_or_create_photo_from_flickr_photo
|
||||
add_photo_to_collection
|
||||
|
||||
# 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", "garden"]
|
||||
if params[:type]
|
||||
if valid_models.include?(params[:type])
|
||||
if params[:id]
|
||||
item = params[:type].camelcase.constantize.find_by_id(params[:id])
|
||||
if item
|
||||
if item.owner.id == current_member.id
|
||||
# This syntax is weird, so just know that it means this:
|
||||
# @photo.harvests << item unless @photo.harvests.include?(item)
|
||||
# but with the correct many-to-many relationship automatically referenced
|
||||
(@photo.send "#{params[:type]}s") << item unless (@photo.send "#{params[:type]}s").include?(item)
|
||||
else
|
||||
flash[:alert] = "You must own both the #{params[:type]} and the photo."
|
||||
end
|
||||
else
|
||||
flash[:alert] = "Couldn't find #{params[:type]} to connect to photo."
|
||||
end
|
||||
else
|
||||
flash[:alert] = "Missing id parameter"
|
||||
end
|
||||
else
|
||||
flash[:alert] = "Cannot attach photos to #{params[:type]}"
|
||||
end
|
||||
else
|
||||
flash[:alert] = "Missing type parameter"
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
if @photo.save
|
||||
format.html { redirect_to @photo, notice: 'Photo was successfully added.' }
|
||||
if @photo.present? && @photo.save
|
||||
format.html { redirect_to photo_path(@photo), notice: 'Photo was successfully added.' }
|
||||
format.json { render json: @photo, status: :created, location: @photo }
|
||||
else
|
||||
format.html { render action: "new" }
|
||||
@@ -125,7 +83,7 @@ class PhotosController < ApplicationController
|
||||
@photo = Photo.find(params[:id])
|
||||
@photo.destroy
|
||||
flash[:alert] = "Photo successfully deleted."
|
||||
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to photos_url }
|
||||
format.json { head :no_content }
|
||||
@@ -134,8 +92,57 @@ class PhotosController < ApplicationController
|
||||
|
||||
private
|
||||
|
||||
def item_id?
|
||||
params.key? :id
|
||||
end
|
||||
|
||||
def flickr_photo_id_param
|
||||
params[:photo][:flickr_photo_id]
|
||||
end
|
||||
|
||||
def photo_params
|
||||
params.require(:photo).permit(:flickr_photo_id, :owner_id, :title, :license_name,
|
||||
:license_url, :thumbnail_url, :fullsize_url, :link_url)
|
||||
:license_url, :thumbnail_url, :fullsize_url, :link_url)
|
||||
end
|
||||
|
||||
def find_or_create_photo_from_flickr_photo
|
||||
@photo = Photo.find_by(flickr_photo_id: flickr_photo_id_param)
|
||||
@photo = Photo.new(photo_params) unless @photo
|
||||
@photo.owner_id = current_member.id
|
||||
@photo.set_flickr_metadata
|
||||
@photo
|
||||
end
|
||||
|
||||
def which_collection?
|
||||
case params[:type]
|
||||
when "garden" then @photo.gardens
|
||||
when "harvest" then @photo.harvests
|
||||
when "planting" then @photo.plantings
|
||||
else raise "Invalid type"
|
||||
end
|
||||
end
|
||||
|
||||
def add_photo_to_collection
|
||||
collection = which_collection?
|
||||
|
||||
unless collection && item_id?
|
||||
flash[:alert] = "Missing or invalid type or id parameter"
|
||||
return
|
||||
end
|
||||
|
||||
item = find_item_for_photo!
|
||||
collection << item unless collection.include?(item)
|
||||
rescue
|
||||
flash[:alert] = "Could not find this item owned by you"
|
||||
end
|
||||
|
||||
def find_item_for_photo!
|
||||
item_class = case params[:type]
|
||||
when "garden" then Garden
|
||||
when "harvest" then Harvest
|
||||
when "planting" then Planting
|
||||
else raise "Invalid type"
|
||||
end
|
||||
item_class.find_by!(id: params[:id], owner_id: current_member.id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,11 @@ class PlacesController < ApplicationController
|
||||
respond_to do |format|
|
||||
format.html
|
||||
# json response is whatever we want to map here
|
||||
format.json { render json: Member.located.to_json(only: [:id, :login_name, :slug, :location, :latitude, :longitude]) }
|
||||
format.json do
|
||||
render json: Member.located.to_json(only: [
|
||||
:id, :login_name, :slug, :location, :latitude, :longitude
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,7 +20,11 @@ class PlacesController < ApplicationController
|
||||
@nearby_members = Member.nearest_to(params[:place])
|
||||
respond_to do |format|
|
||||
format.html # show.html.haml
|
||||
format.json { render json: @nearby_members.to_json(only: [:id, :login_name, :slug, :location, :latitude, :longitude]) }
|
||||
format.json do
|
||||
render json: @nearby_members.to_json(only: [
|
||||
:id, :login_name, :slug, :location, :latitude, :longitude
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -35,5 +43,4 @@ class PlacesController < ApplicationController
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -7,18 +7,18 @@ class PlantingsController < ApplicationController
|
||||
def index
|
||||
@owner = Member.find_by_slug(params[:owner])
|
||||
@crop = Crop.find_by_slug(params[:crop])
|
||||
if @owner
|
||||
@plantings = @owner.plantings.includes(:owner, :crop, :garden).paginate(page: params[:page])
|
||||
elsif @crop
|
||||
@plantings = @crop.plantings.includes(:owner, :crop, :garden).paginate(page: params[:page])
|
||||
else
|
||||
@plantings = Planting.includes(:owner, :crop, :garden).paginate(page: params[:page])
|
||||
end
|
||||
@plantings = if @owner
|
||||
@owner.plantings.includes(:owner, :crop, :garden).paginate(page: params[:page])
|
||||
elsif @crop
|
||||
@crop.plantings.includes(:owner, :crop, :garden).paginate(page: params[:page])
|
||||
else
|
||||
Planting.includes(:owner, :crop, :garden).paginate(page: params[:page])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html { @plantings = @plantings.paginate(page: params[:page]) }
|
||||
format.json { render json: @plantings }
|
||||
format.rss { render layout: false } #index.rss.builder
|
||||
format.rss { render layout: false } # index.rss.builder
|
||||
format.csv do
|
||||
specifics = (@owner ? "#{@owner.login_name}-" : @crop ? "#{@crop.name}-" : nil)
|
||||
@filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@@ -71,7 +71,8 @@ class PlantingsController < ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
if @planting.save
|
||||
@planting.update_attribute(:days_before_maturity, update_days_before_maturity(@planting, planting_params[:crop_id]))
|
||||
@planting.update_attribute(:days_before_maturity,
|
||||
update_days_before_maturity(@planting, planting_params[:crop_id]))
|
||||
format.html { redirect_to @planting, notice: 'Planting was successfully created.' }
|
||||
format.json { render json: @planting, status: :created, location: @planting }
|
||||
expire_fragment("homepage_stats")
|
||||
@@ -90,7 +91,8 @@ class PlantingsController < ApplicationController
|
||||
|
||||
respond_to do |format|
|
||||
if @planting.update(planting_params)
|
||||
@planting.update_attribute(:days_before_maturity, update_days_before_maturity(@planting, planting_params[:crop_id]))
|
||||
@planting.update_attribute(:days_before_maturity,
|
||||
update_days_before_maturity(@planting, planting_params[:crop_id]))
|
||||
format.html { redirect_to @planting, notice: 'Planting was successfully updated.' }
|
||||
format.json { head :no_content }
|
||||
else
|
||||
@@ -118,8 +120,8 @@ class PlantingsController < ApplicationController
|
||||
|
||||
def planting_params
|
||||
params.require(:planting).permit(:crop_id, :description, :garden_id, :planted_at,
|
||||
:quantity, :sunniness, :planted_from, :owner_id, :finished,
|
||||
:finished_at)
|
||||
:quantity, :sunniness, :planted_from, :owner_id, :finished,
|
||||
:finished_at)
|
||||
end
|
||||
|
||||
def update_days_before_maturity(planting, crop_id)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
class PolicyController < ApplicationController
|
||||
end
|
||||
@@ -7,16 +7,16 @@ class PostsController < ApplicationController
|
||||
|
||||
def index
|
||||
@author = Member.find_by_slug(params[:author])
|
||||
if @author
|
||||
@posts = @author.posts.includes(:author, { comments: :author }).paginate(page: params[:page])
|
||||
else
|
||||
@posts = Post.includes(:author, { comments: :author }).paginate(page: params[:page])
|
||||
end
|
||||
@posts = if @author
|
||||
@author.posts.includes(:author, { comments: :author }).paginate(page: params[:page])
|
||||
else
|
||||
Post.includes(:author, { comments: :author }).paginate(page: params[:page])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.haml
|
||||
format.json { render json: @posts }
|
||||
format.rss { render layout: false } #index.rss.builder
|
||||
format.rss { render layout: false } # index.rss.builder
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -74,6 +74,6 @@ class ProductsController < ApplicationController
|
||||
|
||||
def product_params
|
||||
params.require(:product).permit(:description, :min_price, :recommended_price, :name,
|
||||
:account_type_id, :paid_months)
|
||||
:account_type_id, :paid_months)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,28 +1,29 @@
|
||||
class RegistrationsController < Devise::RegistrationsController
|
||||
respond_to :json
|
||||
|
||||
def edit
|
||||
@twitter_auth = current_member.auth('twitter')
|
||||
@flickr_auth = current_member.auth('flickr')
|
||||
@twitter_auth = current_member.auth('twitter')
|
||||
@flickr_auth = current_member.auth('flickr')
|
||||
@facebook_auth = current_member.auth('facebook')
|
||||
render "edit"
|
||||
end
|
||||
|
||||
# we need this subclassed method so that Devise doesn't force people to
|
||||
# change their password every time they want to edit their settings.
|
||||
# we also check that they give their current password to change their password.
|
||||
# Code copied from
|
||||
# https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-account-without-providing-a-password
|
||||
# we need this subclassed method so that Devise doesn't force people to
|
||||
# change their password every time they want to edit their settings.
|
||||
# we also check that they give their current password to change their password.
|
||||
# Code copied from
|
||||
# https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-account-without-providing-a-password
|
||||
|
||||
def update
|
||||
|
||||
@member = Member.find(current_member.id)
|
||||
|
||||
successfully_updated = if needs_password?(@member, params)
|
||||
@member.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
|
||||
if needs_password?(@member, params)
|
||||
successfully_updated = @member.update_with_password(devise_parameter_sanitizer.sanitize(:account_update))
|
||||
else
|
||||
# remove the virtual current_password attribute
|
||||
# update_without_password doesn't know how to ignore it
|
||||
params[:member].delete(:current_password)
|
||||
@member.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
|
||||
successfully_updated = @member.update_without_password(devise_parameter_sanitizer.sanitize(:account_update))
|
||||
end
|
||||
|
||||
if successfully_updated
|
||||
@@ -33,12 +34,11 @@ class RegistrationsController < Devise::RegistrationsController
|
||||
else
|
||||
render "edit"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# check if we need the current password to update fields
|
||||
def needs_password?(member, params)
|
||||
params[:member][:password].present? ||
|
||||
params[:member][:password_confirmation].present?
|
||||
params[:member][:password_confirmation].present?
|
||||
end
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
class RobotsController < ApplicationController
|
||||
|
||||
DEFAULT_FILENAME = 'config/robots.txt'.freeze
|
||||
|
||||
def robots
|
||||
filename = if subdomain && subdomain != 'www'
|
||||
"config/robots.#{ subdomain }.txt"
|
||||
end
|
||||
|
||||
file_to_render = File.exists?(filename.to_s) ? filename : DEFAULT_FILENAME
|
||||
|
||||
filename = "config/robots.#{subdomain}.txt" if subdomain && subdomain != 'www'
|
||||
file_to_render = File.exist?(filename.to_s) ? filename : DEFAULT_FILENAME
|
||||
render file: file_to_render, layout: false, content_type: 'text/plain'
|
||||
end
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
class RolesController < ApplicationController
|
||||
before_filter :authenticate_member!
|
||||
load_and_authorize_resource
|
||||
|
||||
|
||||
# GET /roles
|
||||
def index
|
||||
@roles = Role.all
|
||||
|
||||
@@ -92,6 +92,6 @@ class ScientificNamesController < ApplicationController
|
||||
private
|
||||
|
||||
def scientific_name_params
|
||||
params.require(:scientific_name).permit(:crop_id, :scientific_name, :creator_id)
|
||||
params.require(:scientific_name).permit(:crop_id, :name, :creator_id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,18 +7,18 @@ class SeedsController < ApplicationController
|
||||
def index
|
||||
@owner = Member.find_by_slug(params[:owner])
|
||||
@crop = Crop.find_by_slug(params[:crop])
|
||||
if @owner
|
||||
@seeds = @owner.seeds.includes(:owner, :crop).paginate(page: params[:page])
|
||||
elsif @crop
|
||||
@seeds = @crop.seeds.includes(:owner, :crop).paginate(page: params[:page])
|
||||
else
|
||||
@seeds = Seed.includes(:owner, :crop).paginate(page: params[:page])
|
||||
end
|
||||
@seeds = if @owner
|
||||
@owner.seeds.includes(:owner, :crop).paginate(page: params[:page])
|
||||
elsif @crop
|
||||
@crop.seeds.includes(:owner, :crop).paginate(page: params[:page])
|
||||
else
|
||||
Seed.includes(:owner, :crop).paginate(page: params[:page])
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html # index.html.erb
|
||||
format.json { render json: @seeds }
|
||||
format.rss { render layout: false } #index.rss.builder
|
||||
format.rss { render layout: false } # index.rss.builder
|
||||
format.csv do
|
||||
if @owner
|
||||
@filename = "Growstuff-#{@owner}-Seeds-#{Time.zone.now.to_s(:number)}.csv"
|
||||
@@ -49,7 +49,7 @@ class SeedsController < ApplicationController
|
||||
@seed = Seed.new
|
||||
|
||||
# using find_by_id here because it returns nil, unlike find
|
||||
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
|
||||
@crop = Crop.find_by_id(params[:crop_id]) || Crop.new
|
||||
|
||||
respond_to do |format|
|
||||
format.html # new.html.erb
|
||||
|
||||
11
app/controllers/sessions_controller.rb
Normal file
11
app/controllers/sessions_controller.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class SessionsController < Devise::SessionsController
|
||||
respond_to :json
|
||||
|
||||
def create
|
||||
super do |resource|
|
||||
if Crop.pending_approval.present? && current_member.has_role?(:crop_wrangler)
|
||||
flash[:alert] = "There are crops waiting to be wrangled."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,2 +0,0 @@
|
||||
class SupportController < ApplicationController
|
||||
end
|
||||
@@ -1,5 +1,4 @@
|
||||
module ApplicationHelper
|
||||
|
||||
def price_in_dollars(price)
|
||||
return sprintf('%.2f', price / 100.0)
|
||||
end
|
||||
@@ -7,7 +6,7 @@ module ApplicationHelper
|
||||
# 999 cents becomes 9.99 AUD -- for products/orders/etc
|
||||
def price_with_currency(price)
|
||||
return sprintf('%.2f %s', price / 100.0,
|
||||
Growstuff::Application.config.currency)
|
||||
Growstuff::Application.config.currency)
|
||||
end
|
||||
|
||||
def parse_date(str)
|
||||
@@ -19,13 +18,27 @@ module ApplicationHelper
|
||||
pid = price_in_dollars(price)
|
||||
currency = Growstuff::Application.config.currency
|
||||
link = "http://www.wolframalpha.com/input/?i=#{pid}+#{currency}"
|
||||
return link_to "(convert)",
|
||||
link,
|
||||
target: "_blank"
|
||||
end
|
||||
|
||||
link_to "(convert)", link, target: "_blank", rel: "noopener noreferrer"
|
||||
end
|
||||
|
||||
def build_alert_classes(alert_type = :info)
|
||||
classes = 'alert alert-dismissable '
|
||||
case alert_type.to_sym
|
||||
when :alert, :danger, :error, :validation_errors
|
||||
classes += 'alert-danger'
|
||||
when :warning, :todo
|
||||
classes += 'alert-warning'
|
||||
when :notice, :success
|
||||
classes += 'alert-success'
|
||||
when :info
|
||||
classes += 'alert-info'
|
||||
end
|
||||
classes
|
||||
end
|
||||
|
||||
# Produces a cache key for uniquely identifying cached fragments.
|
||||
def cache_key_for(klass, identifier="all")
|
||||
def cache_key_for(klass, identifier = "all")
|
||||
count = klass.count
|
||||
max_updated_at = klass.maximum(:updated_at).try(:utc).try(:to_s, :number)
|
||||
"#{klass.name.downcase.pluralize}/#{identifier}-#{count}-#{max_updated_at}"
|
||||
@@ -43,12 +56,32 @@ module ApplicationHelper
|
||||
# Falls back to Gravatar
|
||||
#
|
||||
def avatar_uri(member, size = 150)
|
||||
return member.preferred_avatar_uri if member.preferred_avatar_uri.present?
|
||||
if member.preferred_avatar_uri.present?
|
||||
# Some avatars support different sizes
|
||||
# http://graph.facebook.com/12345678/picture?width=150&height=150
|
||||
uri = URI.parse(member.preferred_avatar_uri)
|
||||
|
||||
if uri.host == 'graph.facebook.com'
|
||||
uri.query = "&width=#{size}&height=#{size}"
|
||||
end
|
||||
|
||||
# TODO: Assess twitter - https://dev.twitter.com/overview/general/user-profile-images-and-banners
|
||||
# TODO: Assess flickr - https://www.flickr.com/services/api/misc.buddyicons.html
|
||||
|
||||
return uri.to_s
|
||||
end
|
||||
|
||||
Gravatar.new(member.email).image_url({
|
||||
size: size,
|
||||
default: :identicon
|
||||
})
|
||||
size: size,
|
||||
default: :identicon
|
||||
})
|
||||
end
|
||||
|
||||
# Returns a string with the quantity and the right pluralization for a
|
||||
# given collection and model.
|
||||
def localize_plural(collection, model)
|
||||
size = collection.size
|
||||
model_name = model.model_name.human(count: size)
|
||||
"#{size} #{model_name}"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
module AutoSuggestHelper
|
||||
|
||||
def auto_suggest(resource, source, options={})
|
||||
def auto_suggest(resource, source, options = {})
|
||||
if options[:default] && !options[:default].new_record?
|
||||
default = options[:default]
|
||||
default_id = options[:default].try(:id)
|
||||
@@ -13,10 +12,14 @@ module AutoSuggestHelper
|
||||
source_path = Rails.application.routes.url_helpers.send("#{source}s_search_path")
|
||||
|
||||
%Q{
|
||||
<input id="#{source}" class="auto-suggest #{options[:class]}" type="text" value="#{default}" data-source-url="#{source_path}", placeholder="e.g. lettuce">
|
||||
<noscript class="text-warning">Warning: Javascript must be available to search and match crops</noscript>
|
||||
<input id="#{resource}_#{source}_id" class="auto-suggest-id" type="hidden" name="#{resource}[#{source}_id]" value="#{default_id}">
|
||||
<input id="#{source}" class="auto-suggest #{options[:class]}"
|
||||
type="text" value="#{default}" data-source-url="#{source_path}",
|
||||
placeholder="e.g. lettuce">
|
||||
<noscript class="text-warning">
|
||||
Warning: Javascript must be available to search and match crops
|
||||
</noscript>
|
||||
<input id="#{resource}_#{source}_id" class="auto-suggest-id"
|
||||
type="hidden" name="#{resource}[#{source}_id]" value="#{default_id}">
|
||||
}.html_safe
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
module CropsHelper
|
||||
def display_seed_availability(member, crop)
|
||||
total_quantity = 0
|
||||
member.seeds.each do |seed|
|
||||
if seed.crop.name == crop.name
|
||||
total_quantity = total_quantity + seed.quantity
|
||||
end
|
||||
|
||||
seeds = member.seeds.select { |seed| seed.crop.name == crop.name }
|
||||
|
||||
seeds.each do |seed|
|
||||
total_quantity = total_quantity + seed.quantity if seed.quantity
|
||||
end
|
||||
|
||||
if !seeds.any?
|
||||
return "You don't have any seeds of this crop."
|
||||
end
|
||||
|
||||
if (total_quantity != 0)
|
||||
"You have #{pluralize(total_quantity, "seed")} of this crop."
|
||||
"You have #{total_quantity} #{Seed.model_name.human(count: total_quantity)} of this crop."
|
||||
else
|
||||
"You don't have any seeds of this crop."
|
||||
"You have an unknown quantity of seeds of this crop."
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
module GardensHelper
|
||||
|
||||
def display_garden_description(garden)
|
||||
if garden.description.nil?
|
||||
"no description provided."
|
||||
else
|
||||
truncate(garden.description, length: 130, separator: ' ', omission: '... ') { link_to "Read more", garden_path(garden) }
|
||||
truncate(garden.description, length: 130, separator: ' ', omission: '... ') do
|
||||
link_to "Read more", garden_path(garden)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
module HarvestsHelper
|
||||
|
||||
def display_quantity(harvest)
|
||||
human_quantity = display_human_quantity(harvest)
|
||||
weight = display_weight(harvest)
|
||||
@@ -16,10 +15,10 @@ module HarvestsHelper
|
||||
end
|
||||
|
||||
def display_human_quantity(harvest)
|
||||
if ! harvest.quantity.blank? && harvest.quantity > 0
|
||||
if !harvest.quantity.blank? && harvest.quantity > 0
|
||||
if harvest.unit == 'individual' # just the number
|
||||
number_to_human(harvest.quantity, strip_insignificant_zeros: true)
|
||||
elsif ! harvest.unit.blank? # pluralize anything else
|
||||
elsif !harvest.unit.blank? # pluralize anything else
|
||||
return pluralize(number_to_human(harvest.quantity, strip_insignificant_zeros: true), harvest.unit)
|
||||
else
|
||||
return "#{number_to_human(harvest.quantity, strip_insignificant_zeros: true)} #{harvest.unit}"
|
||||
@@ -30,7 +29,7 @@ module HarvestsHelper
|
||||
end
|
||||
|
||||
def display_weight(harvest)
|
||||
if ! harvest.weight_quantity.blank? && harvest.weight_quantity > 0
|
||||
if !harvest.weight_quantity.blank? && harvest.weight_quantity > 0
|
||||
return "#{number_to_human(harvest.weight_quantity, strip_insignificant_zeros: true)} #{harvest.weight_unit}"
|
||||
else
|
||||
return nil
|
||||
@@ -41,8 +40,7 @@ module HarvestsHelper
|
||||
if harvest.description.empty?
|
||||
"No description provided."
|
||||
else
|
||||
truncate(harvest.description, length: 130, separator: ' ', omission: '... ') { link_to "Read more", harvest_path(harvest) }
|
||||
harvest.description
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
module PlantingsHelper
|
||||
|
||||
def display_days_before_maturity(planting)
|
||||
if planting.finished?
|
||||
0
|
||||
elsif !planting.finished_at.nil?
|
||||
((p = planting.finished_at - DateTime.now).to_i) <= 0 ? 0 : p.to_i
|
||||
elsif planting.days_before_maturity.nil?
|
||||
elsif planting.planted_at.nil? || planting.days_before_maturity.nil?
|
||||
"unknown"
|
||||
else
|
||||
((p = (planting.planted_at + planting.days_before_maturity) - DateTime.now).to_i <= 0) ? 0 : p.to_i
|
||||
@@ -41,5 +40,4 @@ module PlantingsHelper
|
||||
return "#{planting.owner}."
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
module SeedsHelper
|
||||
|
||||
def display_seed_description(seed)
|
||||
if seed.description.nil?
|
||||
"no description provided."
|
||||
if seed.description.nil?
|
||||
"no description provided."
|
||||
else
|
||||
truncate(seed.description, length: 130, separator: ' ', omission: '... ') { link_to "Read more", seed_path(seed) }
|
||||
truncate(seed.description, length: 130, separator: ' ', omission: '... ') { link_to "Read more", seed_path(seed) }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,19 +2,20 @@ class Notifier < ActionMailer::Base
|
||||
include NotificationsHelper
|
||||
default from: "Growstuff <noreply@growstuff.org>"
|
||||
|
||||
def verifier()
|
||||
if ENV['RAILS_SECRET_TOKEN']
|
||||
return ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN'])
|
||||
else
|
||||
raise "RAILS_SECRET_TOKEN environment variable not set - have you created config/application.yml?"
|
||||
def verifier
|
||||
unless ENV['RAILS_SECRET_TOKEN']
|
||||
raise "RAILS_SECRET_TOKEN environment variable"\
|
||||
"not set - have you created config/application.yml?"
|
||||
end
|
||||
|
||||
return ActiveSupport::MessageVerifier.new(ENV['RAILS_SECRET_TOKEN'])
|
||||
end
|
||||
|
||||
def notify(notification)
|
||||
@notification = notification
|
||||
@reply_link = reply_link(@notification)
|
||||
|
||||
# Encrypting
|
||||
# Encrypting
|
||||
@signed_message = verifier.generate ({ member_id: @notification.recipient.id, type: :send_notification_email })
|
||||
|
||||
mail(to: @notification.recipient.email,
|
||||
@@ -27,18 +28,18 @@ class Notifier < ActionMailer::Base
|
||||
@plantings = @member.plantings.first(5)
|
||||
@harvests = @member.harvests.first(5)
|
||||
|
||||
# Encrypting
|
||||
# Encrypting
|
||||
@signed_message = verifier.generate ({ member_id: @member.id, type: :send_planting_reminder })
|
||||
|
||||
if @member.send_planting_reminder
|
||||
mail(to: @member.email,
|
||||
subject: "What have you planted lately?")
|
||||
subject: "What have you planted lately?")
|
||||
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")
|
||||
mail(to: @member.email, subject: "#{@request.requester.login_name} has requested #{@request.name} as a new crop")
|
||||
end
|
||||
|
||||
def crop_request_approved(member, crop)
|
||||
@@ -50,5 +51,4 @@ class Notifier < ActionMailer::Base
|
||||
@member, @crop = member, crop
|
||||
mail(to: @member.email, subject: "#{crop.name.capitalize} has been rejected")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ class Ability
|
||||
cannot :read, AccountType
|
||||
|
||||
# nobody should be able to view unapproved crops unless they
|
||||
# are wranglers or admins
|
||||
# are wranglers or admins
|
||||
cannot :read, Crop
|
||||
can :read, Crop, approval_status: "approved"
|
||||
# scientific names should only be viewable if associated crop is approved
|
||||
@@ -108,7 +108,7 @@ class Ability
|
||||
can :cancel, Order, member_id: member.id, completed_at: nil
|
||||
can :destroy, Order, member_id: member.id, completed_at: nil
|
||||
|
||||
can :create, OrderItem
|
||||
can :create, OrderItem
|
||||
# for now, let's not let people mess with individual order items
|
||||
cannot :read, OrderItem, order: { member_id: member.id }
|
||||
cannot :update, OrderItem, order: { member_id: member.id, completed_at: nil }
|
||||
|
||||
@@ -8,7 +8,7 @@ class Account < ActiveRecord::Base
|
||||
|
||||
before_create do |account|
|
||||
unless account.account_type
|
||||
account.account_type = AccountType.find_or_create_by(name:
|
||||
account.account_type = AccountType.find_or_create_by(name:
|
||||
Growstuff::Application.config.default_account_type
|
||||
)
|
||||
end
|
||||
@@ -21,5 +21,4 @@ class Account < ActiveRecord::Base
|
||||
return paid_until.to_s
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -19,5 +19,4 @@ class Comment < ActiveRecord::Base
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
class Crop < ActiveRecord::Base
|
||||
class Crop < ActiveRecord::Base # rubocop:disable Metrics/ClassLength
|
||||
extend FriendlyId
|
||||
friendly_id :name, use: [:slugged, :finders]
|
||||
|
||||
@@ -19,13 +19,22 @@ class Crop < ActiveRecord::Base
|
||||
belongs_to :parent, class_name: 'Crop'
|
||||
has_many :varieties, class_name: 'Crop', foreign_key: 'parent_id'
|
||||
has_and_belongs_to_many :posts
|
||||
before_destroy {|crop| crop.posts.clear}
|
||||
before_destroy { |crop| crop.posts.clear }
|
||||
|
||||
default_scope { order("lower(name) asc") }
|
||||
scope :recent, -> { where(approval_status: "approved").reorder("created_at desc") }
|
||||
scope :toplevel, -> { where(approval_status: "approved", parent_id: nil) }
|
||||
scope :popular, -> { where(approval_status: "approved").reorder("plantings_count desc, lower(name) asc") }
|
||||
scope :randomized, -> { where(approval_status: "approved").reorder('random()') } # ok on sqlite and psql, but not on mysql
|
||||
scope :recent, lambda {
|
||||
where(approval_status: "approved").reorder("created_at desc")
|
||||
}
|
||||
scope :toplevel, lambda {
|
||||
where(approval_status: "approved", parent_id: nil)
|
||||
}
|
||||
scope :popular, lambda {
|
||||
where(approval_status: "approved").reorder("plantings_count desc, lower(name) asc")
|
||||
}
|
||||
scope :randomized, lambda {
|
||||
# ok on sqlite and psql, but not on mysql
|
||||
where(approval_status: "approved").reorder('random()')
|
||||
}
|
||||
scope :pending_approval, -> { where(approval_status: "pending") }
|
||||
scope :approved, -> { where(approval_status: "approved") }
|
||||
scope :rejected, -> { where(approval_status: "rejected") }
|
||||
@@ -33,7 +42,7 @@ class Crop < ActiveRecord::Base
|
||||
## Wikipedia urls are only necessary when approving a crop
|
||||
validates :en_wikipedia_url,
|
||||
format: {
|
||||
with: /\Ahttps?:\/\/en\.wikipedia\.org\/wiki/,
|
||||
with: /\Ahttps?:\/\/en\.wikipedia\.org\/wiki\/[[:alnum:]%_]+\z/,
|
||||
message: 'is not a valid English Wikipedia URL'
|
||||
},
|
||||
if: :approved?
|
||||
@@ -50,55 +59,57 @@ class Crop < ActiveRecord::Base
|
||||
|
||||
####################################
|
||||
# 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 don’t 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
|
||||
if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
|
||||
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 don’t 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 :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
|
||||
end
|
||||
|
||||
def as_indexed_json(options={})
|
||||
def as_indexed_json(options = {})
|
||||
self.as_json(
|
||||
only: [:id, :name, :approval_status],
|
||||
include: {
|
||||
scientific_names: { only: :scientific_name },
|
||||
scientific_names: { only: :name },
|
||||
alternate_names: { only: :name }
|
||||
})
|
||||
})
|
||||
end
|
||||
|
||||
# update the Elasticsearch index (only if we're using it in this
|
||||
@@ -112,14 +123,12 @@ class Crop < ActiveRecord::Base
|
||||
# End Elasticsearch section
|
||||
|
||||
def to_s
|
||||
return name
|
||||
name
|
||||
end
|
||||
|
||||
def default_scientific_name
|
||||
if scientific_names.size > 0
|
||||
return scientific_names.first.scientific_name
|
||||
else
|
||||
return nil
|
||||
scientific_names.first.name
|
||||
end
|
||||
end
|
||||
|
||||
@@ -128,7 +137,11 @@ class Crop < ActiveRecord::Base
|
||||
# later we can choose a default photo based on different criteria,
|
||||
# eg. popularity
|
||||
def default_photo
|
||||
return photos.first
|
||||
return photos.first if photos.any?
|
||||
|
||||
# Crop has no photos? Look for the most recent harvest with a photo.
|
||||
harvest_with_photo = Harvest.where(crop_id: id).joins(:photos).order('harvests.id DESC').limit(1).first
|
||||
harvest_with_photo.photos.first if harvest_with_photo
|
||||
end
|
||||
|
||||
# crop.sunniness
|
||||
@@ -137,13 +150,7 @@ class Crop < ActiveRecord::Base
|
||||
# key: sunniness (eg. 'sun')
|
||||
# value: count of how many times it's been used by plantings
|
||||
def sunniness
|
||||
sunniness = Hash.new(0)
|
||||
plantings.each do |p|
|
||||
if !p.sunniness.blank?
|
||||
sunniness[p.sunniness] += 1
|
||||
end
|
||||
end
|
||||
return sunniness
|
||||
count_uses_of_property 'sunniness'
|
||||
end
|
||||
|
||||
# crop.planted_from
|
||||
@@ -151,13 +158,7 @@ class Crop < ActiveRecord::Base
|
||||
# key: propagation method (eg. 'seed')
|
||||
# value: count of how many times it's been used by plantings
|
||||
def planted_from
|
||||
planted_from = Hash.new(0)
|
||||
plantings.each do |p|
|
||||
if !p.planted_from.blank?
|
||||
planted_from[p.planted_from] += 1
|
||||
end
|
||||
end
|
||||
return planted_from
|
||||
count_uses_of_property 'planted_from'
|
||||
end
|
||||
|
||||
# crop.popular_plant_parts
|
||||
@@ -195,18 +196,18 @@ class Crop < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def approval_statuses
|
||||
[ 'rejected', 'pending', 'approved' ]
|
||||
['rejected', 'pending', 'approved']
|
||||
end
|
||||
|
||||
def reasons_for_rejection
|
||||
[ "already in database", "not edible", "not enough information", "other" ]
|
||||
["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
|
||||
howmany = 12 # max number to find
|
||||
interesting_crops = Array.new
|
||||
howmany = 12 # max number to find
|
||||
interesting_crops = []
|
||||
Crop.includes(:photos).randomized.each do |c|
|
||||
break if interesting_crops.size == howmany
|
||||
next unless c.interesting?
|
||||
@@ -215,16 +216,16 @@ class Crop < ActiveRecord::Base
|
||||
return interesting_crops
|
||||
end
|
||||
|
||||
# Crop.create_from_csv(row)
|
||||
# used by db/seeds.rb and rake growstuff:import_crops
|
||||
# CSV fields:
|
||||
# - name (required)
|
||||
# - en_wikipedia_url (required)
|
||||
# - parent (name, optional)
|
||||
# - scientific name (optional, can be picked up from parent if it has one)
|
||||
# Crop.create_from_csv(row)
|
||||
# used by db/seeds.rb and rake growstuff:import_crops
|
||||
# CSV fields:
|
||||
# - name (required)
|
||||
# - en_wikipedia_url (required)
|
||||
# - parent (name, optional)
|
||||
# - scientific name (optional, can be picked up from parent if it has one)
|
||||
|
||||
def Crop.create_from_csv(row)
|
||||
name,en_wikipedia_url,parent,scientific_names,alternate_names = row
|
||||
name, en_wikipedia_url, parent, scientific_names, alternate_names = row
|
||||
|
||||
cropbot = Member.find_by_login_name('cropbot')
|
||||
raise "cropbot account not found: run rake db:seed" unless cropbot
|
||||
@@ -246,56 +247,37 @@ class Crop < ActiveRecord::Base
|
||||
|
||||
crop.add_scientific_names_from_csv(scientific_names)
|
||||
crop.add_alternate_names_from_csv(alternate_names)
|
||||
|
||||
end
|
||||
|
||||
def add_scientific_names_from_csv(scientific_names)
|
||||
names_to_add = []
|
||||
if ! scientific_names.blank? # i.e. we actually passed something in, which isn't a given
|
||||
if !scientific_names.blank? # i.e. we actually passed something in, which isn't a given
|
||||
names_to_add = scientific_names.split(%r{,\s*})
|
||||
elsif parent && parent.scientific_names.size > 0 # pick up from parent
|
||||
names_to_add = parent.scientific_names.map{|s| s.scientific_name}
|
||||
names_to_add = parent.scientific_names.map { |s| s.name }
|
||||
else
|
||||
logger.warn("Warning: no scientific name (not even on parent crop) for #{self}")
|
||||
end
|
||||
|
||||
cropbot = Member.find_by_login_name('cropbot')
|
||||
|
||||
if names_to_add.size > 0
|
||||
cropbot = Member.find_by_login_name('cropbot')
|
||||
raise "cropbot account not found: run rake db:seed" unless cropbot
|
||||
|
||||
names_to_add.each do |n|
|
||||
if self.scientific_names.exists?(scientific_name: n)
|
||||
logger.warn("Warning: skipping duplicate scientific name #{n} for #{self}")
|
||||
else
|
||||
|
||||
self.scientific_names.create(
|
||||
scientific_name: n,
|
||||
creator_id: cropbot.id
|
||||
)
|
||||
end
|
||||
end
|
||||
add_names_to_list(names_to_add, 'scientific')
|
||||
end
|
||||
end
|
||||
|
||||
def add_alternate_names_from_csv(alternate_names)
|
||||
cropbot = Member.find_by_login_name('cropbot')
|
||||
|
||||
names_to_add = []
|
||||
if ! alternate_names.blank? # i.e. we actually passed something in, which isn't a given
|
||||
cropbot = Member.find_by_login_name('cropbot')
|
||||
|
||||
if !alternate_names.blank? # i.e. we actually passed something in, which isn't a given
|
||||
raise "cropbot account not found: run rake db:seed" unless cropbot
|
||||
|
||||
names_to_add = alternate_names.split(%r{,\s*})
|
||||
|
||||
names_to_add.each do |n|
|
||||
if self.alternate_names.exists?(name: n)
|
||||
logger.warn("Warning: skipping duplicate alternate name #{n} for #{self}")
|
||||
else
|
||||
self.alternate_names.create(
|
||||
name: n,
|
||||
creator_id: cropbot.id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
add_names_to_list(names_to_add, 'alternate')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -311,21 +293,23 @@ class Crop < ActiveRecord::Base
|
||||
def self.search(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
|
||||
}
|
||||
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
|
||||
@@ -348,6 +332,41 @@ class Crop < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_names_to_list(names_to_add, list_name)
|
||||
names_to_add.each do |n|
|
||||
if name_already_exists(list_name, n)
|
||||
logger.warn("Warning: skipping duplicate #{list_name} name #{n} for #{self}")
|
||||
else
|
||||
create_crop_in_list(list_name, n)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def create_crop_in_list(list_name, name)
|
||||
cropbot = Member.find_by_login_name('cropbot')
|
||||
create_hash = {
|
||||
creator_id: "#{cropbot.id}",
|
||||
name: name
|
||||
}
|
||||
self.send("#{list_name}_names").create(create_hash)
|
||||
end
|
||||
|
||||
def name_already_exists(list_name, name)
|
||||
self.send("#{list_name}_names").exists?(name: name)
|
||||
end
|
||||
|
||||
def count_uses_of_property(col_name)
|
||||
data = Hash.new(0)
|
||||
plantings.each do |p|
|
||||
if !p.send("#{col_name}").blank?
|
||||
data[p.send("#{col_name}")] += 1
|
||||
end
|
||||
end
|
||||
data
|
||||
end
|
||||
|
||||
# Custom validations
|
||||
|
||||
def approval_status_cannot_be_changed_again
|
||||
@@ -370,5 +389,4 @@ class Crop < ActiveRecord::Base
|
||||
errors.add(:rejection_notes, "must be added if the reason for rejection is \"other\"")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -11,6 +11,4 @@ class Follow < ActiveRecord::Base
|
||||
body: "#{self.follower.login_name} just followed you on #{ENV["GROWSTUFF_SITE_NAME"]}. "
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -8,5 +8,4 @@ class Forum < ActiveRecord::Base
|
||||
def to_s
|
||||
return name
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -9,14 +9,14 @@ class Garden < ActiveRecord::Base
|
||||
|
||||
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
|
||||
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
|
||||
photolist.each do |photo|
|
||||
photo.destroy_if_unused
|
||||
end
|
||||
end
|
||||
|
||||
# set up geocoding
|
||||
geocoded_by :location
|
||||
@@ -33,7 +33,7 @@ class Garden < ActiveRecord::Base
|
||||
|
||||
validates :name,
|
||||
format: {
|
||||
with: /\S/
|
||||
with: /\A\w+[\w ]+\z/
|
||||
},
|
||||
length: { maximum: 255 }
|
||||
|
||||
@@ -50,9 +50,9 @@ class Garden < ActiveRecord::Base
|
||||
"acres" => "acre"
|
||||
}
|
||||
validates :area_unit, inclusion: { in: AREA_UNITS_VALUES.values,
|
||||
message: "%{value} is not a valid area unit" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
message: "%{value} is not a valid area unit" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
|
||||
after_validation :cleanup_area
|
||||
|
||||
@@ -76,7 +76,7 @@ class Garden < ActiveRecord::Base
|
||||
seen_crops = []
|
||||
|
||||
plantings.each do |p|
|
||||
if (! seen_crops.include?(p.crop))
|
||||
if (!seen_crops.include?(p.crop))
|
||||
unique_plantings.push(p)
|
||||
seen_crops.push(p.crop)
|
||||
end
|
||||
@@ -103,5 +103,4 @@ class Garden < ActiveRecord::Base
|
||||
def default_photo
|
||||
return photos.first
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -22,9 +22,9 @@ class Harvest < ActiveRecord::Base
|
||||
|
||||
validates :crop, approved: true
|
||||
|
||||
validates :crop, presence: {message: "must be present and exist in our database"}
|
||||
validates :crop, presence: { message: "must be present and exist in our database" }
|
||||
|
||||
validates :plant_part, presence: {message: "must be present and exist in our database"}
|
||||
validates :plant_part, presence: { message: "must be present and exist in our database" }
|
||||
|
||||
validates :quantity,
|
||||
numericality: {
|
||||
@@ -45,9 +45,9 @@ class Harvest < ActiveRecord::Base
|
||||
"bushels" => "bushel"
|
||||
}
|
||||
validates :unit, inclusion: { in: UNITS_VALUES.values,
|
||||
message: "%{value} is not a valid unit" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
message: "%{value} is not a valid unit" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
|
||||
validates :weight_quantity,
|
||||
numericality: { only_integer: false },
|
||||
@@ -59,15 +59,15 @@ class Harvest < ActiveRecord::Base
|
||||
"oz" => "oz"
|
||||
}
|
||||
validates :weight_unit, inclusion: { in: WEIGHT_UNITS_VALUES.values,
|
||||
message: "%{value} is not a valid unit" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
message: "%{value} is not a valid unit" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
|
||||
after_validation :cleanup_quantities
|
||||
|
||||
before_save :set_si_weight
|
||||
|
||||
# we're storing the harvest weight in kilograms in the db too
|
||||
# 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
|
||||
@@ -105,34 +105,32 @@ class Harvest < ActiveRecord::Base
|
||||
string = ''
|
||||
if self.quantity
|
||||
string += "#{number_to_human(self.quantity.to_s, strip_insignificant_zeros: true)} "
|
||||
if self.unit == 'individual'
|
||||
string += 'individual '
|
||||
else
|
||||
if self.quantity == 1
|
||||
string += "#{self.unit} of "
|
||||
else
|
||||
string += "#{self.unit.pluralize} of "
|
||||
end
|
||||
end
|
||||
string += if self.unit == 'individual'
|
||||
'individual '
|
||||
elsif self.quantity == 1
|
||||
"#{self.unit} of "
|
||||
else
|
||||
"#{self.unit.pluralize} of "
|
||||
end
|
||||
end
|
||||
|
||||
if self.unit != 'individual' # buckets of apricot*s*
|
||||
string += "#{self.crop.name.pluralize}"
|
||||
elsif self.quantity == 1
|
||||
string += "#{self.crop.name}"
|
||||
else
|
||||
string += "#{self.crop.name.pluralize}"
|
||||
end
|
||||
string += if self.unit != 'individual' # buckets of apricot*s*
|
||||
"#{self.crop.name.pluralize}"
|
||||
elsif self.quantity == 1
|
||||
"#{self.crop.name}"
|
||||
else
|
||||
"#{self.crop.name.pluralize}"
|
||||
end
|
||||
|
||||
if self.weight_quantity
|
||||
string += " weighing #{number_to_human(self.weight_quantity, strip_insignificant_zeros: true)} #{self.weight_unit}"
|
||||
string += " weighing #{number_to_human(self.weight_quantity, strip_insignificant_zeros: true)}"\
|
||||
" #{self.weight_unit}"
|
||||
end
|
||||
|
||||
return string
|
||||
end
|
||||
|
||||
def default_photo
|
||||
return photos.first
|
||||
return photos.first || crop.default_photo
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ class Member < ActiveRecord::Base
|
||||
|
||||
friendly_id :login_name, use: [:slugged, :finders]
|
||||
|
||||
has_many :posts, foreign_key: 'author_id'
|
||||
has_many :posts, foreign_key: 'author_id'
|
||||
has_many :comments, foreign_key: 'author_id'
|
||||
has_many :forums, foreign_key: 'owner_id'
|
||||
|
||||
@@ -27,7 +27,6 @@ class Member < ActiveRecord::Base
|
||||
|
||||
has_many :photos
|
||||
|
||||
|
||||
default_scope { order("lower(login_name) asc") }
|
||||
scope :confirmed, -> { where('confirmed_at IS NOT NULL') }
|
||||
scope :located, -> { where("location <> '' and latitude IS NOT NULL and longitude IS NOT NULL") }
|
||||
@@ -45,8 +44,8 @@ class Member < ActiveRecord::Base
|
||||
# :token_authenticatable, :confirmable,
|
||||
# :lockable, :timeoutable and :omniauthable
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :trackable, :validatable,
|
||||
:confirmable, :lockable, :timeoutable
|
||||
:recoverable, :rememberable, :trackable, :validatable,
|
||||
:confirmable, :lockable, :timeoutable, :omniauthable
|
||||
|
||||
# set up geocoding
|
||||
geocoded_by :location
|
||||
@@ -58,8 +57,8 @@ class Member < ActiveRecord::Base
|
||||
attr_accessor :login
|
||||
|
||||
# Requires acceptance of the Terms of Service
|
||||
validates_acceptance_of :tos_agreement, allow_nil: false,
|
||||
accept: true
|
||||
validates_acceptance_of :tos_agreement, allow_nil: true,
|
||||
accept: true
|
||||
|
||||
validates :login_name,
|
||||
length: {
|
||||
@@ -80,12 +79,12 @@ class Member < ActiveRecord::Base
|
||||
}
|
||||
|
||||
# Give each new member a default garden
|
||||
after_create {|member| Garden.create(name: "Garden", owner_id: member.id) }
|
||||
after_create { |member| Garden.create(name: "Garden", owner_id: member.id) }
|
||||
|
||||
# and an account record (for paid accounts etc)
|
||||
# we use find_or_create to avoid accidentally creating a second one,
|
||||
# which can happen sometimes especially with FactoryGirl associations
|
||||
after_create {|member| Account.find_or_create_by(member_id: member.id) }
|
||||
after_create { |member| Account.find_or_create_by(member_id: member.id) }
|
||||
|
||||
after_save :update_newsletter_subscription
|
||||
|
||||
@@ -130,7 +129,7 @@ class Member < ActiveRecord::Base
|
||||
def is_paid?
|
||||
if account.account_type.is_permanent_paid
|
||||
return true
|
||||
elsif account.account_type.is_paid and account.paid_until >= Time.zone.now
|
||||
elsif account.account_type.is_paid && account.paid_until >= Time.zone.now
|
||||
return true
|
||||
else
|
||||
return false
|
||||
@@ -159,21 +158,21 @@ class Member < ActiveRecord::Base
|
||||
# Fetches a collection of photos from Flickr
|
||||
# Returns a [[page of photos], total] pair.
|
||||
# Total is needed for pagination.
|
||||
def flickr_photos(page_num=1, set=nil)
|
||||
def flickr_photos(page_num = 1, set = nil)
|
||||
result = false
|
||||
if set
|
||||
result = flickr.photosets.getPhotos(
|
||||
photoset_id: set,
|
||||
page: page_num,
|
||||
per_page: 30
|
||||
)
|
||||
else
|
||||
result = flickr.people.getPhotos(
|
||||
user_id: 'me',
|
||||
page: page_num,
|
||||
per_page: 30
|
||||
)
|
||||
end
|
||||
result = if set
|
||||
flickr.photosets.getPhotos(
|
||||
photoset_id: set,
|
||||
page: page_num,
|
||||
per_page: 30
|
||||
)
|
||||
else
|
||||
flickr.people.getPhotos(
|
||||
user_id: 'me',
|
||||
page: page_num,
|
||||
per_page: 30
|
||||
)
|
||||
end
|
||||
if result
|
||||
return [result.photo, result.total]
|
||||
else
|
||||
@@ -183,7 +182,7 @@ class Member < ActiveRecord::Base
|
||||
|
||||
# Returns a hash of Flickr photosets' ids and titles
|
||||
def flickr_sets
|
||||
sets = Hash.new
|
||||
sets = Hash.new
|
||||
flickr.photosets.getList.each do |p|
|
||||
sets[p.title] = p.id
|
||||
end
|
||||
@@ -200,7 +199,7 @@ class Member < ActiveRecord::Base
|
||||
|
||||
def Member.interesting
|
||||
howmany = 12 # max number to find
|
||||
interesting_members = Array.new
|
||||
interesting_members = []
|
||||
Member.confirmed.located.recently_signed_in.each do |m|
|
||||
break if interesting_members.size == howmany
|
||||
if m.interesting?
|
||||
@@ -213,7 +212,7 @@ class Member < ActiveRecord::Base
|
||||
def Member.nearest_to(place)
|
||||
nearby_members = []
|
||||
if place
|
||||
latitude, longitude = Geocoder.coordinates(place, params: {limit: 1})
|
||||
latitude, longitude = Geocoder.coordinates(place, params: { limit: 1 })
|
||||
if latitude && longitude
|
||||
nearby_members = Member.located.sort_by { |x| x.distance_from([latitude, longitude]) }
|
||||
end
|
||||
@@ -222,7 +221,7 @@ class Member < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def update_newsletter_subscription
|
||||
if confirmed_at_changed? and newsletter # just signed up
|
||||
if confirmed_at_changed? && newsletter # just signed up
|
||||
newsletter_subscribe
|
||||
elsif confirmed_at # i.e. after member's confirmed their account
|
||||
if newsletter_changed? # edited member settings
|
||||
@@ -235,24 +234,24 @@ class Member < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def newsletter_subscribe(testing=false)
|
||||
def newsletter_subscribe(testing = false)
|
||||
return true if (Rails.env.test? && !testing)
|
||||
gb = Gibbon::API.new
|
||||
res = gb.lists.subscribe({
|
||||
id: Gibbon::API.api_key,
|
||||
email: { email: email },
|
||||
merge_vars: { login_name: login_name },
|
||||
double_optin: false # they already confirmed their email with us
|
||||
})
|
||||
id: Growstuff::Application.config.newsletter_list_id,
|
||||
email: { email: email },
|
||||
merge_vars: { login_name: login_name },
|
||||
double_optin: false # they already confirmed their email with us
|
||||
})
|
||||
end
|
||||
|
||||
def newsletter_unsubscribe(testing=false)
|
||||
def newsletter_unsubscribe(testing = false)
|
||||
return true if (Rails.env.test? && !testing)
|
||||
gb = Gibbon::API.new
|
||||
res = gb.lists.unsubscribe({
|
||||
id: ENV['GROWSTUFF_MAILCHIMP_NEWSLETTER_ID'],
|
||||
email: { email: email }
|
||||
})
|
||||
id: Growstuff::Application.config.newsletter_list_id,
|
||||
email: { email: email }
|
||||
})
|
||||
end
|
||||
|
||||
def already_following?(member)
|
||||
@@ -262,5 +261,4 @@ class Member < ActiveRecord::Base
|
||||
def get_follow(member)
|
||||
self.follows.where(followed_id: member.id).first if already_following?(member)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -23,8 +23,7 @@ class Notification < ActiveRecord::Base
|
||||
|
||||
def send_email
|
||||
if self.recipient.send_notification_email
|
||||
Notifier.notify(self).deliver
|
||||
Notifier.notify(self).deliver_later
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -17,7 +17,7 @@ class Order < ActiveRecord::Base
|
||||
sum = 0
|
||||
for i in order_items do
|
||||
subtotal = i.price * i.quantity
|
||||
sum += subtotal
|
||||
sum += subtotal
|
||||
end
|
||||
return sum
|
||||
end
|
||||
@@ -27,10 +27,10 @@ class Order < ActiveRecord::Base
|
||||
items = []
|
||||
order_items.each do |i|
|
||||
items.push({
|
||||
name: i.product.name,
|
||||
quantity: i.quantity,
|
||||
amount: i.price
|
||||
})
|
||||
name: i.product.name,
|
||||
quantity: i.quantity,
|
||||
amount: i.price
|
||||
})
|
||||
end
|
||||
return items
|
||||
end
|
||||
@@ -62,35 +62,34 @@ class Order < ActiveRecord::Base
|
||||
# search orders (used by admin/orders)
|
||||
# usage: Order.search({ :by => 'member', :for => 'Skud' })
|
||||
# can search by: member, order_id, paypal_token, paypal_payer_id,
|
||||
def Order.search(args={})
|
||||
def Order.search(args = {})
|
||||
if args[:for]
|
||||
case args[:by]
|
||||
when "member"
|
||||
member = Member.find_by_login_name(args[:for])
|
||||
if member
|
||||
return member.orders
|
||||
end
|
||||
when "order_id"
|
||||
order = Order.find_by_id(args[:for])
|
||||
if order
|
||||
return [order]
|
||||
end
|
||||
when "paypal_token"
|
||||
order = Order.find_by_paypal_express_token(args[:for])
|
||||
if order
|
||||
return [order]
|
||||
end
|
||||
when "paypal_payer_id"
|
||||
order = Order.find_by_paypal_express_payer_id(args[:for])
|
||||
if order
|
||||
return [order]
|
||||
end
|
||||
when "referral_code"
|
||||
# coerce to uppercase
|
||||
return Order.where(referral_code: args[:for].upcase)
|
||||
when "member"
|
||||
member = Member.find_by_login_name(args[:for])
|
||||
if member
|
||||
return member.orders
|
||||
end
|
||||
when "order_id"
|
||||
order = Order.find_by_id(args[:for])
|
||||
if order
|
||||
return [order]
|
||||
end
|
||||
when "paypal_token"
|
||||
order = Order.find_by_paypal_express_token(args[:for])
|
||||
if order
|
||||
return [order]
|
||||
end
|
||||
when "paypal_payer_id"
|
||||
order = Order.find_by_paypal_express_payer_id(args[:for])
|
||||
if order
|
||||
return [order]
|
||||
end
|
||||
when "referral_code"
|
||||
# coerce to uppercase
|
||||
return Order.where(referral_code: args[:for].upcase)
|
||||
end
|
||||
end
|
||||
return []
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -34,11 +34,9 @@ class Photo < ActiveRecord::Base
|
||||
fullsize_url: FlickRaw.url_z(info),
|
||||
link_url: FlickRaw.url_photopage(info)
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
def set_flickr_metadata
|
||||
self.update_attributes(flickr_metadata)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -20,5 +20,4 @@ class PlantPart < ActiveRecord::Base
|
||||
def crops
|
||||
return super.reorder('name')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ class Planting < ActiveRecord::Base
|
||||
|
||||
validates :crop, approved: true
|
||||
|
||||
validates :crop, presence: {message: "must be present and exist in our database"}
|
||||
validates :crop, presence: { message: "must be present and exist in our database" }
|
||||
|
||||
validates :quantity,
|
||||
numericality: {
|
||||
@@ -42,9 +42,9 @@ class Planting < ActiveRecord::Base
|
||||
|
||||
SUNNINESS_VALUES = %w(sun semi-shade shade)
|
||||
validates :sunniness, inclusion: { in: SUNNINESS_VALUES,
|
||||
message: "%{value} is not a valid sunniness value" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
message: "%{value} is not a valid sunniness value" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
|
||||
PLANTED_FROM_VALUES = [
|
||||
'seed',
|
||||
@@ -60,15 +60,15 @@ class Planting < ActiveRecord::Base
|
||||
'layering'
|
||||
]
|
||||
validates :planted_from, inclusion: { in: PLANTED_FROM_VALUES,
|
||||
message: "%{value} is not a valid planting method" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
message: "%{value} is not a valid planting method" },
|
||||
allow_nil: true,
|
||||
allow_blank: true
|
||||
|
||||
validate :finished_must_be_after_planted
|
||||
|
||||
# check that any finished_at date occurs after planted_at
|
||||
def finished_must_be_after_planted
|
||||
return unless planted_at and finished_at # only check if we have both
|
||||
return unless planted_at && finished_at # only check if we have both
|
||||
errors.add(:finished_at, "must be after the planting date") unless planted_at < finished_at
|
||||
end
|
||||
|
||||
@@ -97,15 +97,15 @@ class Planting < ActiveRecord::Base
|
||||
def calculate_days_before_maturity(planting, crop)
|
||||
p_crop = Planting.where(crop_id: crop).where.not(id: planting)
|
||||
differences = p_crop.collect do |p|
|
||||
if p.finished and !p.finished_at.nil?
|
||||
if p.finished && !p.finished_at.nil?
|
||||
(p.finished_at - p.planted_at).to_i
|
||||
end
|
||||
end
|
||||
|
||||
if differences.compact.empty?
|
||||
nil
|
||||
else
|
||||
differences.compact.sum/differences.compact.size
|
||||
else
|
||||
differences.compact.sum / differences.compact.size
|
||||
end
|
||||
end
|
||||
|
||||
@@ -120,7 +120,7 @@ class Planting < ActiveRecord::Base
|
||||
|
||||
return 0 if current_date < planted_at
|
||||
return 100 if days > days_before_maturity
|
||||
percent = (days/days_before_maturity*100).to_i
|
||||
percent = (days / days_before_maturity * 100).to_i
|
||||
|
||||
if percent >= 100
|
||||
percent = 100
|
||||
@@ -132,8 +132,8 @@ class Planting < ActiveRecord::Base
|
||||
# return a list of interesting plantings, for the homepage etc.
|
||||
# we can't do this via a scope (as far as we know) so sadly we have to
|
||||
# do it this way.
|
||||
def Planting.interesting(howmany=12, require_photo=true)
|
||||
interesting_plantings = Array.new
|
||||
def Planting.interesting(howmany = 12, require_photo = true)
|
||||
interesting_plantings = []
|
||||
seen_owners = Hash.new(false) # keep track of which owners we've seen already
|
||||
|
||||
Planting.includes(:photos).each do |p|
|
||||
|
||||
@@ -5,26 +5,26 @@ class Post < ActiveRecord::Base
|
||||
belongs_to :forum
|
||||
has_many :comments, dependent: :destroy
|
||||
has_and_belongs_to_many :crops
|
||||
before_destroy {|post| post.crops.clear}
|
||||
before_destroy { |post| post.crops.clear }
|
||||
after_save :update_crops_posts_association
|
||||
# also has_many notifications, but kinda meaningless to get at them
|
||||
# from this direction, so we won't set up an association for now.
|
||||
|
||||
after_create do
|
||||
recipients = Array.new
|
||||
sender = self.author.id
|
||||
recipients = []
|
||||
sender = self.author.id
|
||||
self.body.scan(Haml::Filters::GrowstuffMarkdown::MEMBER_REGEX) do |m|
|
||||
# find member case-insensitively and add to list of recipients
|
||||
member = Member.where('lower(login_name) = ?', $1.downcase).first
|
||||
recipients << member if member and not recipients.include?(member)
|
||||
recipients << member if member && !recipients.include?(member)
|
||||
end
|
||||
self.body.scan(Haml::Filters::GrowstuffMarkdown::MEMBER_AT_REGEX) do |m|
|
||||
# find member case-insensitively and add to list of recipients
|
||||
member = Member.where('lower(login_name) = ?', $1[1..-1].downcase).first
|
||||
recipients << member if member and not recipients.include?(member)
|
||||
recipients << member if member && !recipients.include?(member)
|
||||
end
|
||||
# don't send notifications to yourself
|
||||
recipients.map{ |r| r.id }.each do |recipient|
|
||||
recipients.map { |r| r.id }.each do |recipient|
|
||||
if recipient != sender
|
||||
Notification.create(
|
||||
recipient_id: recipient,
|
||||
@@ -44,7 +44,6 @@ class Post < ActiveRecord::Base
|
||||
},
|
||||
length: { maximum: 255 }
|
||||
|
||||
|
||||
def author_date_subject
|
||||
# slugs are created before created_at is set
|
||||
time = created_at || Time.zone.now
|
||||
@@ -64,20 +63,21 @@ class Post < ActiveRecord::Base
|
||||
|
||||
# return posts sorted by recent activity
|
||||
def Post.recently_active
|
||||
Post.all.sort do |a,b|
|
||||
Post.all.sort do |a, b|
|
||||
b.recent_activity <=> a.recent_activity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def update_crops_posts_association
|
||||
self.crops.destroy_all
|
||||
# look for crops mentioned in the post. eg. [tomato](crop)
|
||||
self.body.scan(Haml::Filters::GrowstuffMarkdown::CROP_REGEX) do |m|
|
||||
# find crop case-insensitively
|
||||
crop = Crop.where('lower(name) = ?', $1.downcase).first
|
||||
# create association
|
||||
self.crops << crop if crop and not self.crops.include?(crop)
|
||||
end
|
||||
|
||||
def update_crops_posts_association
|
||||
self.crops.destroy_all
|
||||
# look for crops mentioned in the post. eg. [tomato](crop)
|
||||
self.body.scan(Haml::Filters::GrowstuffMarkdown::CROP_REGEX) do |m|
|
||||
# find crop case-insensitively
|
||||
crop = Crop.where('lower(name) = ?', $1.downcase).first
|
||||
# create association
|
||||
self.crops << crop if crop && !self.crops.include?(crop)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,5 +11,4 @@ class Product < ActiveRecord::Base
|
||||
def to_s
|
||||
name
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ class Seed < ActiveRecord::Base
|
||||
|
||||
validates :crop, approved: true
|
||||
|
||||
validates :crop, presence: {message: "must be present and exist in our database"}
|
||||
validates :crop, presence: { message: "must be present and exist in our database" }
|
||||
validates :quantity,
|
||||
numericality: {
|
||||
only_integer: true,
|
||||
@@ -30,9 +30,10 @@ class Seed < ActiveRecord::Base
|
||||
|
||||
TRADABLE_TO_VALUES = %w(nowhere locally nationally internationally)
|
||||
validates :tradable_to, inclusion: { in: TRADABLE_TO_VALUES,
|
||||
message: "You may only trade seed nowhere, locally, nationally, or internationally" },
|
||||
allow_nil: false,
|
||||
allow_blank: false
|
||||
message: "You may only trade seed nowhere, "\
|
||||
"locally, nationally, or internationally" },
|
||||
allow_nil: false,
|
||||
allow_blank: false
|
||||
|
||||
ORGANIC_VALUES = [
|
||||
'certified organic',
|
||||
@@ -40,9 +41,10 @@ class Seed < ActiveRecord::Base
|
||||
'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
|
||||
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',
|
||||
@@ -50,15 +52,16 @@ class Seed < ActiveRecord::Base
|
||||
'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
|
||||
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
|
||||
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'
|
||||
@@ -79,7 +82,7 @@ class Seed < ActiveRecord::Base
|
||||
# returns a list of interesting seeds, for use on the homepage etc
|
||||
def Seed.interesting
|
||||
howmany = 12 # max number to find
|
||||
interesting_seeds = Array.new
|
||||
interesting_seeds = []
|
||||
|
||||
Seed.tradable.each do |s|
|
||||
break if interesting_seeds.size == howmany
|
||||
@@ -89,7 +92,6 @@ class Seed < ActiveRecord::Base
|
||||
end
|
||||
|
||||
return interesting_seeds
|
||||
|
||||
end
|
||||
|
||||
def seed_slug
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
-content_for :title, 'Contact'
|
||||
|
||||
%dl
|
||||
%dt General contact email
|
||||
%dd= link_to 'info@growstuff.org', 'mailto:info@growstuff.org'
|
||||
%dl
|
||||
%dt
|
||||
Support and accounts enquiries (not covered by the
|
||||
=succeed ")" do
|
||||
=link_to 'FAQ', url_for(:controller => '/support')
|
||||
%dd= link_to 'support@growstuff.org', 'mailto:support@growstuff.org'
|
||||
%dl
|
||||
%dt Media/Press enquiries
|
||||
%dd= link_to 'media@growstuff.org', 'mailto:media@growstuff.org'
|
||||
%dl
|
||||
%dt Twitter
|
||||
%dd= link_to '@growstufforg', 'http://twitter.com/growstufforg'
|
||||
@@ -21,7 +21,7 @@
|
||||
= f.label :name, :class => 'control-label col-md-2'
|
||||
.col-md-8
|
||||
= f.text_field :name, :class => 'form-control'
|
||||
|
||||
|
||||
.form-group
|
||||
.form-actions.col-md-offset-2.col-md-8
|
||||
= f.submit 'Save', :class => 'btn btn-primary'
|
||||
@@ -1,3 +1,10 @@
|
||||
= content_for :title, @alternate_name.name
|
||||
- content_for :opengraph do
|
||||
= tag("meta", property: "og:title", content: @alternate_name.name)
|
||||
= tag("meta", property: "og:type", content: "website")
|
||||
= tag("meta", property: "og:url", content: request.original_url)
|
||||
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
|
||||
|
||||
%p#notice= notice
|
||||
|
||||
= render :partial => 'crops/approval_status_message', :locals => { :crop => @alternate_name.crop }
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
= render :partial => "members/avatar", :locals => { :member => comment.author }
|
||||
.col-md-11
|
||||
.comment-meta
|
||||
= (comment.created_at == comment.updated_at) ? 'Posted by' : 'Edited by'
|
||||
Posted by
|
||||
= link_to comment.author.login_name, member_path(comment.author)
|
||||
on
|
||||
= (comment.created_at == comment.updated_at) ? comment.created_at : comment.updated_at
|
||||
= comment.created_at
|
||||
- if comment.updated_at > comment.created_at
|
||||
and edited at
|
||||
= comment.updated_at
|
||||
|
||||
.comment-body
|
||||
:growstuff_markdown
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
= content_for :title, "Recent comments"
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @comments, :model => "comments"
|
||||
= page_entries_info @comments
|
||||
= will_paginate @comments
|
||||
|
||||
- @comments.each do |comment|
|
||||
@@ -11,7 +11,7 @@
|
||||
= render :partial => "single", :locals => { :comment => comment }
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @comments, :model => "comments"
|
||||
= page_entries_info @comments
|
||||
= will_paginate @comments
|
||||
|
||||
%p
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
= content_for :title, @comment.post.subject
|
||||
- content_for :opengraph do
|
||||
= tag("meta", property: "og:image", content: avatar_uri(@comment.post.author, 200))
|
||||
= tag("meta", property: "og:image:user_generated", content: "true")
|
||||
= tag("meta", property: "og:title", content: @comment.post.subject)
|
||||
= tag("meta", property: "og:description", content: strip_tags(@comment.post.body).split(' ')[0..20].join(' '))
|
||||
= tag("meta", property: "og:type", content: "website")
|
||||
= tag("meta", property: "og:url", content: request.original_url)
|
||||
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
|
||||
|
||||
= render :partial => "posts/single", :locals => { :post => @comment.post }
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%h4 Find #{ crop.name } seeds
|
||||
- if crop.seeds.empty?
|
||||
%p
|
||||
There are no seeds available to trade.
|
||||
There are no seeds available to trade on Growstuff right now.
|
||||
- else
|
||||
%ul
|
||||
- crop.seeds.tradable.each do |seed|
|
||||
@@ -10,6 +10,8 @@
|
||||
= render :partial => 'members/location', :locals => { :member => seed.owner }
|
||||
%p
|
||||
= link_to "View all #{crop.name} seeds", seeds_by_crop_path(crop)
|
||||
%p
|
||||
= link_to "Purchase seeds via Ebay", "http://rover.ebay.com/rover/1/705-53470-19255-0/1?icep_ff3=9&pub=5575213277&toolid=10001&campid=5337940151&customid=&icep_uq=#{URI.escape crop.name}&icep_sellerId=&icep_ex_kw=&icep_sortBy=12&icep_catId=181003&icep_minPrice=&icep_maxPrice=&ipn=psmain&icep_vectorid=229515&kwid=902099&mtid=824&kw=lg", target: "_blank", rel: "noopener noreferrer"
|
||||
- if crop.approved?
|
||||
- if current_member
|
||||
%p= link_to "List #{crop.name} seeds to trade", new_seed_path(:crop_id => crop.id)
|
||||
|
||||
@@ -48,14 +48,14 @@
|
||||
Scientific names
|
||||
= button_tag "+", :id => "add-sci_name-row", :type => "button"
|
||||
= button_tag "-", :id => "remove-sci_name-row", :type => "button"
|
||||
|
||||
|
||||
.form-group#scientific_names
|
||||
- @crop.scientific_names.each.with_index do |sci, index|
|
||||
.template.col-md-12{ :id => "sci_template[#{index+1}]" }
|
||||
.col-md-2
|
||||
= label_tag :scientific_names, "Scientific name #{index+1}:", :class => 'control-label'
|
||||
.col-md-8
|
||||
= text_field_tag "sci_name[#{index+1}]", sci.scientific_name, :id => "sci_name[#{index+1}]", :class => 'form-control'
|
||||
= text_field_tag "sci_name[#{index+1}]", sci.name, :id => "sci_name[#{index+1}]", :class => 'form-control'
|
||||
%span.help-block Scientific name of crop.
|
||||
.col-md-2
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
= button_tag "+", :id => "add-alt_name-row", :type => "button"
|
||||
= button_tag "-", :id => "remove-alt_name-row", :type => "button"
|
||||
|
||||
.form-group#alternate_names
|
||||
.form-group#alternate_names
|
||||
- @crop.alternate_names.each.with_index do |alt, index|
|
||||
.template.col-md-12{ :id => "alt_template[#{index+1}]" }
|
||||
.col-md-2
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%small
|
||||
- if crop.scientific_names.size > 0
|
||||
%i
|
||||
= crop.scientific_names.first.scientific_name
|
||||
= crop.scientific_names.first.name
|
||||
%br/
|
||||
Planted
|
||||
= pluralize(crop.plantings.size, "time")
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
%ul
|
||||
- crop.scientific_names.each do |sn|
|
||||
%li
|
||||
= sn.scientific_name
|
||||
= sn.name
|
||||
- if can? :edit, sn
|
||||
= link_to 'Edit', edit_scientific_name_path(sn), { :class => 'btn btn-default btn-xs' }
|
||||
- if can? :destroy, sn
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
= link_to crop.name, crop
|
||||
- if crop.scientific_names.size > 0
|
||||
.scientificname
|
||||
= crop.scientific_names.first.scientific_name
|
||||
= crop.scientific_names.first.name
|
||||
.plantingcount
|
||||
Planted
|
||||
= pluralize(crop.plantings.size, "time")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
- content_for :title, (can?(:wrangle, @crop) ? "New crop" : "Suggest a 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
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
- content_for :title, @crop.name
|
||||
- content_for :subtitle, @crop.default_scientific_name
|
||||
- content_for :opengraph do
|
||||
- @crop.photos.each do |photo|
|
||||
= tag("meta", property: "og:image", content: photo.fullsize_url)
|
||||
= tag("meta", property: "og:title", content: @crop.name)
|
||||
= tag("meta", property: "og:type", content: "website")
|
||||
= tag("meta", property: "og:url", content: request.original_url)
|
||||
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
|
||||
|
||||
= render :partial => 'approval_status_message', :locals => { :crop => @crop }
|
||||
|
||||
@@ -54,13 +61,13 @@
|
||||
= render :partial => "shared/signin_signup", :locals => { :to => "post your tips and experiences growing #{ @crop.name.pluralize }" }
|
||||
- else
|
||||
%div.pagination
|
||||
= page_entries_info @posts, :model => "posts"
|
||||
= page_entries_info @posts
|
||||
= will_paginate @posts, :params => {:anchor => "posts"}
|
||||
- @posts.each do |post|
|
||||
= render :partial => "posts/single", :locals => { :post => post, :subject => true }
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @posts, :model => "posts"
|
||||
= page_entries_info @posts
|
||||
= will_paginate @posts, :params => {:anchor => "posts"}
|
||||
|
||||
.col-md-3
|
||||
@@ -84,4 +91,11 @@
|
||||
|
||||
%h4 Learn more about #{ @crop.name.pluralize }
|
||||
%ul
|
||||
%li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url
|
||||
%li= link_to 'Wikipedia (English)', @crop.en_wikipedia_url, target: "_blank", rel: "noopener noreferrer"
|
||||
%li
|
||||
= link_to "OpenFarm - Growing guide", "https://openfarm.cc/en/crops/#{URI.escape @crop.name}", target: "_blank", rel: "noopener noreferrer"
|
||||
%li
|
||||
= link_to "Gardenate - Planting reminders", "http://www.gardenate.com/plant/#{URI.escape @crop.name}", target: "_blank", rel: "noopener noreferrer"
|
||||
- if current_member && current_member.location
|
||||
%li
|
||||
= link_to "Google", "http://www.google.com/search?q=#{URI.escape ["Growing", @crop.name, current_member.location].join(" ")}", target: "_blank", rel: "noopener noreferrer"
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
%li{:class => @approval_status == "rejected" ? 'active' : ''}
|
||||
= link_to "Rejected", wrangle_crops_path(:approval_status => "rejected")
|
||||
|
||||
%h2
|
||||
%h2
|
||||
- if @approval_status == "pending"
|
||||
Requested Crops
|
||||
- elsif @approval_status == "rejected"
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @crops, :model => "crops"
|
||||
= page_entries_info @crops
|
||||
= will_paginate @crops
|
||||
|
||||
%table{:class => "table table-striped", :id => @approval_status.blank? ? 'recently-added-crops' : "#{@approval_status}-crops"}
|
||||
@@ -54,7 +54,7 @@
|
||||
%td= link_to c.en_wikipedia_url, c.en_wikipedia_url
|
||||
%td
|
||||
- c.scientific_names.each do |s|
|
||||
= link_to s.scientific_name, s
|
||||
= link_to s.name, s
|
||||
%br/
|
||||
%td= c.requester.present? ? (link_to c.requester, c.requester) : "N/A"
|
||||
- unless @approval_status == "pending"
|
||||
@@ -64,7 +64,7 @@
|
||||
ago.
|
||||
|
||||
%div.pagination
|
||||
= page_entries_info @crops, :model => "crops"
|
||||
= page_entries_info @crops
|
||||
= will_paginate @crops
|
||||
|
||||
|
||||
|
||||
@@ -13,4 +13,6 @@
|
||||
.form-actions.col-md-offset-2.col-md-8
|
||||
= f.submit "Resend confirmation instructions", :class => 'btn btn-primary'
|
||||
|
||||
= render "devise/shared/links"
|
||||
.form-group
|
||||
.col-md-offset-2.col-md-8
|
||||
= render "devise/shared/links"
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
%p
|
||||
We'd also appreciate it if you'd read our
|
||||
= succeed "," do
|
||||
= link_to 'Community Guidelines', url_for(:controller => '/policy', :action => 'community', :only_path => false)
|
||||
= link_to 'Community Guidelines', "#{root_url}/policy/community"
|
||||
and make sure you follow them. We want #{site_name} to be a
|
||||
friendly, welcoming environment for everyone, and we hope you'll
|
||||
help us keep it that way.
|
||||
|
||||
@@ -11,4 +11,6 @@
|
||||
.form-actions.col-md-offset-2.col-md-8
|
||||
= f.submit "Send me reset password instructions", :class => 'btn btn-primary'
|
||||
|
||||
= render "devise/shared/links"
|
||||
.form-group
|
||||
.col-md-offset-2.col-md-8
|
||||
= render "devise/shared/links"
|
||||
|
||||
@@ -25,3 +25,15 @@
|
||||
= link_to "Disconnect", @flickr_auth, :confirm => "Are you sure you want to remove this connection?", :method => :delete, :class => "remove"
|
||||
- else
|
||||
=link_to 'Connect to Flickr', '/auth/flickr'
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
%p
|
||||
= image_tag "facebook_32.png", :size => "32x32", :alt => 'Facebook logo'
|
||||
- if @facebook_auth
|
||||
You are connected to Facebook as
|
||||
= succeed "." do
|
||||
=link_to @facebook_auth.name, "http://facebook.com/profile/#{@facebook_auth.uid}"
|
||||
= link_to "Disconnect", @facebook_auth, :confirm => "Are you sure you want to remove this connection?", :method => :delete, :class => "remove"
|
||||
- else
|
||||
=link_to 'Connect to Facebook', '/auth/facebook'
|
||||
@@ -18,11 +18,12 @@
|
||||
Profile picture
|
||||
.col-md-8
|
||||
= render :partial => "members/avatar", :locals => { :member => @member }
|
||||
%p
|
||||
%br/
|
||||
To change your profile picture, visit
|
||||
= succeed "." do
|
||||
= link_to 'gravatar.com', "http://gravatar.com/"
|
||||
- unless @member.preferred_avatar_uri.present?
|
||||
%p
|
||||
%br/
|
||||
To change your profile picture, visit
|
||||
= succeed "." do
|
||||
= link_to 'gravatar.com', "http://gravatar.com/"
|
||||
|
||||
.form-group
|
||||
.form-actions.col-md-offset-2.col-md-8
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user