Merge pull request #2006 from Growstuff/dev

Release 55
This commit is contained in:
Brenda Wallace
2019-07-07 08:38:57 +12:00
committed by GitHub
284 changed files with 4255 additions and 3570 deletions

View File

@@ -1,7 +1,7 @@
engines:
rubocop:
enabled: true
channel: "rubocop-0-70"
channel: "rubocop-0-71"
scss-lint:
enabled: true
shellcheck:
@@ -44,3 +44,4 @@ exclude_paths:
- public/
- app/assets/stylesheets/bootstrap-accessibility.css
- app/assets/javascripts/bootstrap*
- app/assets/stylesheets/leaflet_overrides.scss

1
.gitignore vendored
View File

@@ -28,3 +28,4 @@ config/database.yml
cc-test-reporter
elasticsearch-*.deb
elasticsearch-*.deb.sha512

View File

@@ -1,13 +0,0 @@
---
fail_on_violations: true
ruby:
config_file: .rubocop.yml
haml:
config_file: .haml-lint.yml
scss:
config_file: .scss-lint.yml
eslint:
config_file: .eslintrc
ignore_file: .esignore
jshint:
enabled: false

View File

@@ -1,3 +0,0 @@
{
"userBlacklist": ["tygriffin","oshiho3"]
}

View File

@@ -22,7 +22,7 @@ PreCommit:
problem_on_unmodified_line: warn
RuboCop:
enabled: true
command: ['bundle', 'exec', 'rubocop', '-D', '--rails']
command: ['bundle', 'exec', 'rubocop', '-D']
TrailingWhitespace:
enabled: true
exclude:

View File

@@ -1,4 +1,5 @@
inherit_from: .rubocop_todo.yml
require: rubocop-rails
AllCops:
Exclude:
- 'db/schema.rb'
@@ -56,7 +57,7 @@ Metrics/BlockLength:
- 'config/**/*.rb'
Metrics/LineLength:
Max: 120
Max: 140
# Remove the following once the code style matches
Metrics/MethodLength:
@@ -75,4 +76,4 @@ Metrics/PerceivedComplexity:
Rails/SkipsModelValidations:
Exclude:
- 'db/migrate/20190317023129_finished_boolean.rb'
- 'db/seeds.rb'
- 'db/seeds.rb'

View File

@@ -1 +1 @@
2.6.0
2.6.3

View File

@@ -3,21 +3,26 @@ language: ruby
cache:
bundler: true
directories:
- travis_phantomjs
- tmp/cache/assets/test/sprockets
addons:
apt:
packages:
- chromium-chromedriver
- google-chrome-stable
code_climate:
repo_token:
secure: "PfhLGBKRgNqhKuYCJsK+VPhdAzcgWFGeeOyxC/eS8gtlvIISVdgyZE+r30uIei0DFI6zEiN62eW4d+xtT4j7/e2ZcAcx7U52mza/SnQNuu3nCGQDJB8VOvV5NbnwXfi8vfr4e889Mt7k3ocd2c4gqB4UtRqrzhygj7HN+B/GfEk="
env:
matrix:
- GROWSTUFF_ELASTICSEARCH=true RSPEC_TAG=elasticsearch COVERAGE=true PERCY_CHECKS=true
- GROWSTUFF_ELASTICSEARCH=true RSPEC_TAG=elasticsearch COVERAGE=true
- GROWSTUFF_ELASTICSEARCH=false RSPEC_TAG=~elasticsearch COVERAGE=false
- STATIC_CHECKS=true
- STATIC_CHECKS=true PERCY_CHECKS=true
global:
- secure: "Z5TpM2jEX4UCvNePnk/LwltQX48U2u9BRc+Iypr1x9QW2o228QJhPIOH39a8RMUrepGnkQIq9q3ZRUn98RfrJz1yThtlNFL3NmzdQ57gKgjGwfpa0e4Dwj/ZJqV2D84tDGjvdVYLP7zzaYZxQcwk/cgNpzKf/jq97HLNP7CYuf4="
- GROWSTUFF_EMAIL="noreply@test.growstuff.org"
- GROWSTUFF_SITE_NAME="Growstuff (travis)"
- RAILS_SECRET_TOKEN='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
before_install:
- ./script/install_phantomjs.sh
- export PATH=$PWD/travis_phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH
- ./script/install_codeclimate.sh
- ./script/install_linters.sh
- VERSION="6.2.3" ./script/install_elasticsearch.sh
@@ -33,9 +38,9 @@ script:
./script/check_static.rb
else
set +e;
RAILS_ENV=test bundle exec rake db:create db:migrate search:create;
RAILS_ENV=test bundle exec rake db:create db:migrate search:reindex;
bundle exec rake assets:precompile;
bundle exec rspec --tag $RSPEC_TAG spec/;
bundle exec rspec -fd --tag $RSPEC_TAG spec/;
fi;
- set +e
after_script:
@@ -67,7 +72,3 @@ deploy:
- restart
after_deploy:
- bundle exec script/heroku_maintenance.rb off
addons:
code_climate:
repo_token:
secure: "PfhLGBKRgNqhKuYCJsK+VPhdAzcgWFGeeOyxC/eS8gtlvIISVdgyZE+r30uIei0DFI6zEiN62eW4d+xtT4j7/e2ZcAcx7U52mza/SnQNuu3nCGQDJB8VOvV5NbnwXfi8vfr4e889Mt7k3ocd2c4gqB4UtRqrzhygj7HN+B/GfEk="

33
Gemfile
View File

@@ -2,7 +2,7 @@
source 'https://rubygems.org'
ruby '2.6.0'
ruby '2.6.3'
gem 'rails', '5.2.2.1'
@@ -16,7 +16,13 @@ gem 'sass-rails'
gem 'jsonapi-resources'
# CSS framework
gem 'bootstrap-sass'
gem "bootstrap", ">= 4.3.1"
gem 'material-sass', '4.1.1'
# Icons used by bootstrap/material-sass
gem 'material_icons'
# icons
gem 'font-awesome-sass'
gem 'uglifier' # JavaScript compressor
@@ -26,15 +32,13 @@ gem 'oj' # Speeds up json
# planting and harvest predictions
# based on median values for the crop
gem 'active_median', '0.1.4' # needs postgresql update https://github.com/Growstuff/growstuff/issues/1757
gem 'active_record_union'
gem 'flickraw'
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'js-routes' # provides access to Rails routes in Javascript
# Boostrap friendly layout for photo galleries
gem 'isotope-rails'
gem 'cancancan' # for checking member privileges
gem 'csv_shaper' # CSV export
gem 'figaro' # for handling config via ENV variables
@@ -61,6 +65,7 @@ gem 'bluecloth'
# Pagination
gem 'will_paginate'
gem 'will_paginate-bootstrap4'
# user signup/login/etc
gem 'devise'
@@ -77,6 +82,9 @@ gem 'geocoder', '1.4.9' # TODO: Fails on version 1.5.0. Needs investigation
# For easy calendar selection
gem 'bootstrap-datepicker-rails'
# DRY-er easier bootstrap 4 forms
gem "bootstrap_form", ">= 4.2.0"
# For connecting to other services (eg Twitter)
gem 'omniauth', '~> 1.3'
gem 'omniauth-facebook'
@@ -87,6 +95,7 @@ gem 'omniauth-twitter'
gem "chartkick"
# clever elastic search
gem 'elasticsearch', '< 7.0.0'
gem 'searchkick'
gem "hashie", ">= 3.5.3"
@@ -103,6 +112,9 @@ gem 'xmlrpc' # fixes rake error - can be removed if not needed later
gem 'puma'
gem 'loofah', '>= 2.2.1'
gem 'rack-protection', '>= 2.0.1'
group :production do
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
gem 'dalli'
@@ -132,13 +144,12 @@ group :development, :test do
gem 'haml-i18n-extractor'
gem 'haml-rails' # HTML templating language
gem 'haml_lint', '>= 0.25.1' # Checks haml files for goodness
gem 'i18n-tasks' # adds tests for finding missing and unused translations
gem 'poltergeist' # for headless JS testing
gem 'i18n-tasks' # adds tests for finding missing and unused translations
gem 'rspec-activemodel-mocks'
gem 'rspec-rails' # unit testing framework
gem 'rubocop', '~> 0.70'
gem 'rubocop', '~> 0.71'
gem 'rubocop-rails'
gem 'rubocop-rspec'
gem 'selenium-webdriver'
gem 'webrat' # provides HTML matchers for view tests
end
@@ -146,11 +157,11 @@ group :test do
gem 'codeclimate-test-reporter', require: false
gem 'percy-capybara', '~> 4.0.0'
gem 'rails-controller-testing'
gem 'selenium-webdriver'
gem 'timecop'
gem 'webdrivers'
end
group :travis do
gem 'platform-api'
end
gem 'loofah', '>= 2.2.1'
gem 'rack-protection', '>= 2.0.1'

View File

@@ -30,6 +30,8 @@ GEM
addressable
active_median (0.1.4)
activerecord
active_record_union (1.3.0)
activerecord (>= 4.0)
active_utils (3.3.16)
activesupport (>= 4.2)
i18n
@@ -55,9 +57,9 @@ GEM
public_suffix (>= 2.0.2, < 4.0)
arel (9.0.0)
ast (2.4.0)
autoprefixer-rails (9.4.7)
autoprefixer-rails (9.6.0)
execjs
bcrypt (3.1.12)
bcrypt (3.1.13)
better_errors (2.5.1)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
@@ -66,21 +68,25 @@ GEM
bonsai-elasticsearch-rails (7.0.1)
elasticsearch-model (< 8)
elasticsearch-rails (< 8)
bootstrap (4.3.1)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 1.14.3, < 2)
sassc-rails (>= 2.0.0)
bootstrap-datepicker-rails (1.8.0.1)
railties (>= 3.0)
bootstrap-kaminari-views (0.0.5)
kaminari (>= 0.13)
rails (>= 3.1)
bootstrap-sass (3.4.1)
autoprefixer-rails (>= 5.2.1)
sassc (>= 2.0.0)
bootstrap_form (4.2.0)
actionpack (>= 5.0)
activemodel (>= 5.0)
builder (3.2.3)
bullet (6.0.0)
bullet (6.0.1)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.0.1)
cancancan (3.0.1)
capybara (3.24.0)
capybara (3.25.0)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
@@ -97,7 +103,6 @@ GEM
chartkick (3.2.0)
childprocess (1.0.1)
rake (< 13.0)
cliver (0.3.2)
codeclimate-test-reporter (1.0.9)
simplecov (<= 0.13)
coderay (1.1.2)
@@ -123,12 +128,12 @@ GEM
rails (>= 5.0.0)
concurrent-ruby (1.1.5)
connection_pool (2.2.2)
coveralls (0.8.19)
json (>= 1.8, < 3)
simplecov (~> 0.12.0)
term-ansicolor (~> 1.3)
thor (~> 0.19.1)
tins (~> 1.6)
coveralls (0.7.1)
multi_json (~> 1.3)
rest-client
simplecov (>= 0.7)
term-ansicolor
thor
crass (1.0.4)
csv_shaper (1.3.0)
activesupport (>= 3.0.0)
@@ -142,33 +147,35 @@ GEM
warden (~> 1.2.3)
diff-lcs (1.3)
docile (1.1.5)
elasticsearch (7.1.0)
elasticsearch-api (= 7.1.0)
elasticsearch-transport (= 7.1.0)
elasticsearch-api (7.1.0)
domain_name (0.5.20180417)
unf (>= 0.0.5, < 1.0.0)
elasticsearch (6.8.0)
elasticsearch-api (= 6.8.0)
elasticsearch-transport (= 6.8.0)
elasticsearch-api (6.8.0)
multi_json
elasticsearch-model (6.0.0)
activesupport (> 3)
elasticsearch (> 1)
hashie
elasticsearch-rails (6.0.0)
elasticsearch-transport (7.1.0)
elasticsearch-transport (6.8.0)
faraday
multi_json
erubi (1.8.0)
erubis (2.7.0)
excon (0.62.0)
excon (0.64.0)
execjs (2.7.0)
factory_bot (4.11.1)
activesupport (>= 3.0.0)
factory_bot_rails (4.11.1)
factory_bot (~> 4.11.1)
railties (>= 3.0.0)
faker (1.9.3)
factory_bot (5.0.2)
activesupport (>= 4.2.0)
factory_bot_rails (5.0.2)
factory_bot (~> 5.0.2)
railties (>= 4.2.0)
faker (1.9.5)
i18n (>= 0.7)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
ffi (1.10.0)
ffi (1.11.1)
figaro (1.1.1)
thor (~> 0.14)
flickraw (0.9.10)
@@ -212,13 +219,15 @@ GEM
excon
moneta
multi_json (>= 1.9.2)
highline (2.0.1)
highline (2.0.2)
html2haml (2.2.0)
erubis (~> 2.7.0)
haml (>= 4.0, < 6)
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
httparty (0.16.3)
http-cookie (1.0.3)
domain_name (~> 0.5)
httparty (0.17.0)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
i18n (1.6.0)
@@ -233,25 +242,22 @@ GEM
rails-i18n
rainbow (>= 2.2.2, < 4.0)
terminal-table (>= 1.5.1)
isotope-rails (2.2.2)
jquery-rails
rails (>= 4.0)
jaro_winkler (1.5.2)
jaro_winkler (1.5.3)
jquery-rails (4.3.5)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (6.0.1)
railties (>= 3.2.16)
js-routes (1.4.6)
js-routes (1.4.7)
railties (>= 4)
sprockets-rails
json (2.1.0)
jsonapi-resources (0.9.8)
json (2.2.0)
jsonapi-resources (0.9.9)
activerecord (>= 4.1)
concurrent-ruby
railties (>= 4.1)
jwt (2.1.0)
jwt (2.2.1)
kaminari (1.1.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.1.1)
@@ -268,7 +274,7 @@ GEM
kramdown (2.1.0)
launchy (2.4.3)
addressable (~> 2.3)
leaflet-rails (1.4.0)
leaflet-rails (1.5.1)
rails (>= 4.2.0)
letter_opener (1.7.0)
launchy (~> 2.2)
@@ -283,11 +289,16 @@ GEM
mini_mime (>= 0.1.1)
marcel (0.3.3)
mimemagic (~> 0.3.2)
material-sass (4.1.1)
autoprefixer-rails (>= 6.0.3)
sass (>= 3.5.2)
material_icons (2.2.1)
railties (>= 3.2)
memcachier (0.0.2)
method_source (0.9.2)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mime-types-data (3.2019.0331)
mimemagic (0.3.3)
mini_magick (4.9.3)
mini_mime (1.0.1)
@@ -297,7 +308,8 @@ GEM
multi_json (1.11.3)
multi_xml (0.6.0)
multipart-post (2.1.1)
newrelic_rpm (6.4.0.356)
netrc (0.11.0)
newrelic_rpm (6.5.0.357)
nio4r (2.3.1)
nokogiri (1.10.3)
mini_portile2 (~> 2.4.0)
@@ -337,12 +349,10 @@ GEM
platform-api (2.2.0)
heroics (~> 0.0.25)
moneta (~> 1.0.0)
poltergeist (1.18.1)
capybara (>= 2.1, < 4)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
public_suffix (3.1.0)
puma (3.12.1)
popper_js (1.14.5)
public_suffix (3.1.1)
puma (4.0.0)
nio4r (~> 2.0)
rack (2.0.7)
rack-protection (2.0.5)
rack
@@ -361,7 +371,7 @@ GEM
bundler (>= 1.3.0)
railties (= 5.2.2.1)
sprockets-rails (>= 2.0.0)
rails-assets-leaflet (1.3.4)
rails-assets-leaflet (1.5.1)
rails-assets-leaflet.markercluster (1.4.1)
rails-assets-leaflet (>= 1.3.1)
rails-controller-testing (1.0.4)
@@ -393,21 +403,25 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
redis (4.1.0)
redis (4.1.2)
regexp_parser (1.5.1)
responders (2.4.1)
actionpack (>= 4.2.0, < 6.0)
railties (>= 4.2.0, < 6.0)
responders (3.0.0)
actionpack (>= 5.0)
railties (>= 5.0)
rest-client (2.0.2)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rspec-activemodel-mocks (1.1.0)
activemodel (>= 3.0)
activesupport (>= 3.0)
rspec-mocks (>= 2.99, < 4.0)
rspec-core (3.8.0)
rspec-core (3.8.1)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
rspec-expectations (3.8.4)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
rspec-mocks (3.8.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.2)
@@ -418,14 +432,17 @@ GEM
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.0)
rubocop (0.71.0)
rspec-support (3.8.2)
rubocop (0.72.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-rails (2.1.0)
rack (>= 1.1)
rubocop (>= 0.72.0)
rubocop-rspec (1.33.0)
rubocop (>= 0.60.0)
ruby-progressbar (1.10.1)
@@ -433,8 +450,8 @@ GEM
ruby_dep (1.5.0)
ruby_parser (3.13.1)
sexp_processor (~> 4.9)
rubyzip (1.2.2)
sass (3.7.3)
rubyzip (1.2.3)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
@@ -448,13 +465,13 @@ GEM
sassc (2.0.1)
ffi (~> 1.9)
rake
sassc-rails (2.1.0)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
scout_apm (2.4.24)
scout_apm (2.5.1)
searchkick (4.0.2)
activemodel (>= 5)
elasticsearch (>= 6)
@@ -462,13 +479,13 @@ GEM
selenium-webdriver (3.142.3)
childprocess (>= 0.5, < 2.0)
rubyzip (~> 1.2, >= 1.2.2)
sexp_processor (4.12.0)
sexp_processor (4.12.1)
sidekiq (5.2.7)
connection_pool (~> 2.2, >= 2.2.2)
rack (>= 1.5.0)
rack-protection (>= 1.5.0)
redis (>= 3.3.5, < 5)
simplecov (0.12.0)
simplecov (0.13.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
@@ -482,20 +499,23 @@ GEM
sprockets (>= 3.0.0)
sysexits (1.2.0)
temple (0.8.1)
term-ansicolor (1.7.0)
term-ansicolor (1.7.1)
tins (~> 1.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thor (0.19.4)
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.9)
timecop (0.9.1)
tins (1.20.2)
tins (1.20.3)
trollop (1.16.2)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (4.1.20)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.6)
unicode-display_width (1.6.0)
unicorn (5.5.1)
kgio (~> 2.6)
@@ -503,14 +523,20 @@ GEM
uniform_notifier (1.12.1)
warden (1.2.8)
rack (>= 2.0.6)
webdrivers (4.1.0)
nokogiri (~> 1.6)
rubyzip (~> 1.0)
selenium-webdriver (>= 3.0, < 4.0)
webrat (0.7.3)
nokogiri (>= 1.2.0)
rack (>= 1.0)
rack-test (>= 0.5.3)
websocket-driver (0.7.0)
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
websocket-extensions (0.1.4)
will_paginate (3.1.7)
will_paginate-bootstrap4 (0.2.2)
will_paginate (~> 3.0, >= 3.0.0)
xmlrpc (0.3.0)
xpath (3.2.0)
nokogiri (~> 1.8)
@@ -520,13 +546,15 @@ PLATFORMS
DEPENDENCIES
active_median (= 0.1.4)
active_record_union
active_utils
better_errors
bluecloth
bonsai-elasticsearch-rails
bootstrap (>= 4.3.1)
bootstrap-datepicker-rails
bootstrap-kaminari-views
bootstrap-sass
bootstrap_form (>= 4.2.0)
bullet
bundler (>= 1.1.5)
byebug
@@ -543,6 +571,7 @@ DEPENDENCIES
dalli
database_cleaner
devise
elasticsearch (< 7.0.0)
factory_bot_rails
faker
figaro
@@ -558,7 +587,6 @@ DEPENDENCIES
haml_lint (>= 0.25.1)
hashie (>= 3.5.3)
i18n-tasks
isotope-rails
jquery-rails
jquery-ui-rails
js-routes
@@ -568,6 +596,8 @@ DEPENDENCIES
letter_opener
listen
loofah (>= 2.2.1)
material-sass (= 4.1.1)
material_icons
memcachier
newrelic_rpm
oj
@@ -579,7 +609,6 @@ DEPENDENCIES
percy-capybara (~> 4.0.0)
pg (< 1.0.0)
platform-api
poltergeist
puma
rack-protection (>= 2.0.1)
rails (= 5.2.2.1)
@@ -590,7 +619,8 @@ DEPENDENCIES
responders
rspec-activemodel-mocks
rspec-rails
rubocop (~> 0.70)
rubocop (~> 0.71)
rubocop-rails
rubocop-rspec
ruby-units
sass-rails
@@ -601,12 +631,14 @@ DEPENDENCIES
timecop
uglifier
unicorn
webdrivers
webrat
will_paginate
will_paginate-bootstrap4
xmlrpc
RUBY VERSION
ruby 2.6.0p0
ruby 2.6.3p62
BUNDLED WITH
1.17.2
1.17.3

View File

@@ -6,6 +6,8 @@
Welcome to the Growstuff project.
You can find our app at https://www.growstuff.org
Growstuff is an open source/open data project to create a website for
food gardeners. We crowdsource information on what our members are
growing and harvesting, aggregate it, and make it available as open data

View File

@@ -3,7 +3,7 @@
"stack": "heroku-18",
"description": "Open data project for small-scale food growers",
"scripts": {
"postdeploy": "bundle exec rails db:migrate db:seed"
"postdeploy": "bundle exec rails db:seed"
},
"env": {
"GROWSTUFF_ELASTICSEARCH": {

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" version="1.1" width="96px" height="96px">
<g id="surface1">
<path style=" fill:#9FA8DA;" d="M 12 13 L 12 38 C 12 40.210938 13.789063 42 16 42 L 32 42 C 34.210938 42 36 40.210938 36 38 L 36 13 Z "/>
<path style=" fill:#7986CB;" d="M 23 15 L 25 15 L 25 38 L 23 38 Z "/>
<path style=" fill:#7986CB;" d="M 29 15 L 31 15 L 31 38 L 29 38 Z "/>
<path style=" fill:#7986CB;" d="M 17 15 L 19 15 L 19 38 L 17 38 Z "/>
<path style=" fill:#5C6BC0;" d="M 10 11 L 38 11 L 38 15 L 10 15 Z "/>
<path style=" fill:#5C6BC0;" d="M 21.800781 13.027344 C 21.308594 12.492188 21 11.785156 21 11 C 21 9.34375 22.34375 8 24 8 C 25.65625 8 27 9.34375 27 11 C 27 11.785156 26.691406 12.492188 26.199219 13.027344 L 28.5625 13.027344 C 28.839844 12.40625 29 11.722656 29 11 C 29 8.238281 26.761719 6 24 6 C 21.238281 6 19 8.238281 19 11 C 19 11.722656 19.160156 12.40625 19.4375 13.027344 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1022 B

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" version="1.1" width="96px" height="96px">
<g id="surface1">
<path style=" fill:#CFD8DC;" d="M 5 38 L 5 14 L 43 14 L 43 38 C 43 40.199219 41.199219 42 39 42 L 9 42 C 6.800781 42 5 40.199219 5 38 Z "/>
<path style=" fill:#F44336;" d="M 43 10 L 43 16 L 5 16 L 5 10 C 5 7.800781 6.800781 6 9 6 L 39 6 C 41.199219 6 43 7.800781 43 10 Z "/>
<path style=" fill:#B71C1C;" d="M 36 10 C 36 11.65625 34.65625 13 33 13 C 31.34375 13 30 11.65625 30 10 C 30 8.34375 31.34375 7 33 7 C 34.65625 7 36 8.34375 36 10 Z "/>
<path style=" fill:#B71C1C;" d="M 18 10 C 18 11.65625 16.65625 13 15 13 C 13.34375 13 12 11.65625 12 10 C 12 8.34375 13.34375 7 15 7 C 16.65625 7 18 8.34375 18 10 Z "/>
<path style=" fill:#B0BEC5;" d="M 33 3 C 31.898438 3 31 3.898438 31 5 L 31 10 C 31 11.101563 31.898438 12 33 12 C 34.101563 12 35 11.101563 35 10 L 35 5 C 35 3.898438 34.101563 3 33 3 Z "/>
<path style=" fill:#B0BEC5;" d="M 15 3 C 13.898438 3 13 3.898438 13 5 L 13 10 C 13 11.101563 13.898438 12 15 12 C 16.101563 12 17 11.101563 17 10 L 17 5 C 17 3.898438 16.101563 3 15 3 Z "/>
<path style=" fill:#90A4AE;" d="M 13 20 L 17 20 L 17 24 L 13 24 Z "/>
<path style=" fill:#90A4AE;" d="M 19 20 L 23 20 L 23 24 L 19 24 Z "/>
<path style=" fill:#90A4AE;" d="M 25 20 L 29 20 L 29 24 L 25 24 Z "/>
<path style=" fill:#90A4AE;" d="M 31 20 L 35 20 L 35 24 L 31 24 Z "/>
<path style=" fill:#90A4AE;" d="M 13 26 L 17 26 L 17 30 L 13 30 Z "/>
<path style=" fill:#90A4AE;" d="M 19 26 L 23 26 L 23 30 L 19 30 Z "/>
<path style=" fill:#90A4AE;" d="M 25 26 L 29 26 L 29 30 L 25 30 Z "/>
<path style=" fill:#90A4AE;" d="M 31 26 L 35 26 L 35 30 L 31 30 Z "/>
<path style=" fill:#90A4AE;" d="M 13 32 L 17 32 L 17 36 L 13 36 Z "/>
<path style=" fill:#90A4AE;" d="M 19 32 L 23 32 L 23 36 L 19 36 Z "/>
<path style=" fill:#90A4AE;" d="M 25 32 L 29 32 L 29 36 L 25 36 Z "/>
<path style=" fill:#90A4AE;" d="M 31 32 L 35 32 L 35 36 L 31 36 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,26 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" version="1.1" width="100" height="100" fill="000000">
<g id="surface1">
<path style=" fill:#2E7D32;" d="M 30 11.5 C 30 14.539063 27.539063 17 24.5 17 C 21.460938 17 19 14.539063 19 11.5 C 19 8.460938 21.460938 6 24.5 6 C 27.539063 6 30 8.460938 30 11.5 Z "/>
<path style=" fill:#2E7D32;" d="M 41 16.5 C 41 18.984375 38.984375 21 36.5 21 C 34.015625 21 32 18.984375 32 16.5 C 32 14.015625 34.015625 12 36.5 12 C 38.984375 12 41 14.015625 41 16.5 Z "/>
<path style=" fill:#388E3C;" d="M 22 14 C 22 16.761719 19.761719 19 17 19 C 14.238281 19 12 16.761719 12 14 C 12 11.238281 14.238281 9 17 9 C 19.761719 9 22 11.238281 22 14 Z "/>
<path style=" fill:#388E3C;" d="M 12 19.5 C 12 21.433594 10.433594 23 8.5 23 C 6.566406 23 5 21.433594 5 19.5 C 5 17.566406 6.566406 16 8.5 16 C 10.433594 16 12 17.566406 12 19.5 Z "/>
<path style=" fill:#388E3C;" d="M 43 19.5 C 43 21.433594 41.433594 23 39.5 23 C 37.566406 23 36 21.433594 36 19.5 C 36 17.566406 37.566406 16 39.5 16 C 41.433594 16 43 17.566406 43 19.5 Z "/>
<path style=" fill:#388E3C;" d="M 35 14 C 35 16.761719 32.761719 19 30 19 C 27.238281 19 25 16.761719 25 14 C 25 11.238281 27.238281 9 30 9 C 32.761719 9 35 11.238281 35 14 Z "/>
<path style=" fill:#4CAF50;" d="M 26 19 C 26 21.761719 23.761719 24 21 24 C 18.238281 24 16 21.761719 16 19 C 16 16.238281 18.238281 14 21 14 C 23.761719 14 26 16.238281 26 19 Z "/>
<path style=" fill:#4CAF50;" d="M 18 17 C 18 19.761719 15.761719 22 13 22 C 10.238281 22 8 19.761719 8 17 C 8 14.238281 10.238281 12 13 12 C 15.761719 12 18 14.238281 18 17 Z "/>
<path style=" fill:#4CAF50;" d="M 38 20 C 38 22.210938 36.210938 24 34 24 C 31.789063 24 30 22.210938 30 20 C 30 17.789063 31.789063 16 34 16 C 36.210938 16 38 17.789063 38 20 Z "/>
<path style=" fill:#9CCC65;" d="M 31 19.5 C 31 21.433594 29.433594 23 27.5 23 C 25.566406 23 24 21.433594 24 19.5 C 24 17.566406 25.566406 16 27.5 16 C 29.433594 16 31 17.566406 31 19.5 Z "/>
<path style=" fill:#9CCC65;" d="M 18 18.5 C 18 19.878906 16.878906 21 15.5 21 C 14.121094 21 13 19.878906 13 18.5 C 13 17.121094 14.121094 16 15.5 16 C 16.878906 16 18 17.121094 18 18.5 Z "/>
<path style=" fill:#795548;" d="M 5 20 L 43 20 L 43 42 L 5 42 Z "/>
<path style=" fill:#4E342E;" d="M 5 26 L 43 26 L 43 28 L 5 28 Z "/>
<path style=" fill:#4E342E;" d="M 5 34 L 43 34 L 43 36 L 5 36 Z "/>
<path style=" fill:#8D6E63;" d="M 9 20 L 13 20 L 13 42 L 9 42 Z "/>
<path style=" fill:#8D6E63;" d="M 35 20 L 39 20 L 39 42 L 35 42 Z "/>
<path style=" fill:#6D4C41;" d="M 7 20 L 9 20 L 9 42 L 7 42 Z "/>
<path style=" fill:#6D4C41;" d="M 33 20 L 35 20 L 35 42 L 33 42 Z "/>
<path style=" fill:#3E2723;" d="M 7 26 L 9 26 L 9 28 L 7 28 Z "/>
<path style=" fill:#3E2723;" d="M 7 34 L 9 34 L 9 36 L 7 36 Z "/>
<path style=" fill:#3E2723;" d="M 33 26 L 35 26 L 35 28 L 33 28 Z "/>
<path style=" fill:#3E2723;" d="M 33 34 L 35 34 L 35 36 L 33 36 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" version="1.1" width="100" height="100" fill="000000">
<g id="surface1">
<path style=" " d="M 7.304688 4 L 4.664063 11.042969 L 6.804688 11.042969 L 8.695313 6 L 23.308594 6 L 25.199219 11.042969 L 27.332031 11.042969 L 24.691406 4 Z M 2 12 L 2 18 L 3.257813 18 L 6.257813 28 L 25.746094 28 L 28.746094 18 L 30 18 L 30 12 Z M 4 14 L 28 14 L 28 16 L 27.253906 16 L 24.253906 26 L 7.742188 26 L 4.742188 16 L 4 16 Z M 11 17 L 11 24 L 13 24 L 13 17 Z M 15 17 L 15 24 L 17 24 L 17 17 Z M 19 17 L 19 24 L 21 24 L 21 17 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 633 B

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" version="1.1" width="100" height="100" fill="000000">
<g id="surface1">
<path style=" " d="M 16 2.59375 L 15.28125 3.28125 L 2.28125 16.28125 L 3.71875 17.71875 L 5 16.4375 L 5 28 L 14 28 L 14 18 L 18 18 L 18 28 L 27 28 L 27 16.4375 L 28.28125 17.71875 L 29.71875 16.28125 L 16.71875 3.28125 Z M 16 5.4375 L 25 14.4375 L 25 26 L 20 26 L 20 16 L 12 16 L 12 26 L 7 26 L 7 14.4375 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 498 B

View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="100" height="100" fill="000000">
<path d="M 12.457031 4 C 12.303766 4.0054531 12.180109 4.0547969 12.099609 4.1542969 C 11.777609 4.5522969 12.255016 5.5897031 13.166016 6.4707031 C 14.077016 7.3517031 15.076437 7.7427031 15.398438 7.3457031 C 15.720438 6.9477031 15.243031 5.9102969 14.332031 5.0292969 C 13.648781 4.3685469 12.916828 3.9836406 12.457031 4 z M 18.273438 7.0078125 C 17.745498 7.0965566 17.100062 7.9065781 16.742188 8.9863281 C 16.333187 10.220328 16.453766 11.339375 17.009766 11.484375 C 17.565766 11.629375 18.348813 10.745719 18.757812 9.5117188 C 19.166812 8.2777187 19.046234 7.160625 18.490234 7.015625 C 18.420734 6.9975 18.348857 6.9951348 18.273438 7.0078125 z M 10.966797 9.0019531 C 10.493797 8.9824531 10.145656 9.0859531 10.035156 9.3144531 C 9.8141562 9.7714531 10.626609 10.561125 11.849609 11.078125 C 13.072609 11.595125 14.243844 11.643547 14.464844 11.185547 C 14.685844 10.728547 13.873391 9.938875 12.650391 9.421875 C 12.038891 9.163375 11.439797 9.0214531 10.966797 9.0019531 z M 3 14 L 3 16 L 9.203125 16 C 9.709475 19.363146 12.49988 22 16 22 C 19.50012 22 22.290525 19.363146 22.796875 16 L 29 16 L 29 14 L 21 14 L 21 15 C 21 17.773666 18.773666 20 16 20 C 13.226334 20 11 17.773666 11 15 L 11 14 L 3 14 z M 15.830078 14.001953 A 2.5 0.99900001 0.361 0 0 13.5 14.984375 A 2.5 0.99900001 0.361 0 0 15.994141 15.998047 A 2.5 0.99900001 0.361 0 0 18.5 15.015625 A 2.5 0.99900001 0.361 0 0 16.005859 14.001953 A 2.5 0.99900001 0.361 0 0 15.830078 14.001953 z M 7 17 A 1 1 0 0 0 6 18 A 1 1 0 0 0 7 19 A 1 1 0 0 0 8 18 A 1 1 0 0 0 7 17 z M 25 17 A 1 1 0 0 0 24 18 A 1 1 0 0 0 25 19 A 1 1 0 0 0 26 18 A 1 1 0 0 0 25 17 z M 4 20 A 1 1 0 0 0 3 21 A 1 1 0 0 0 4 22 A 1 1 0 0 0 5 21 A 1 1 0 0 0 4 20 z M 10 20 A 1 1 0 0 0 9 21 A 1 1 0 0 0 10 22 A 1 1 0 0 0 11 21 A 1 1 0 0 0 10 20 z M 22 20 A 1 1 0 0 0 21 21 A 1 1 0 0 0 22 22 A 1 1 0 0 0 23 21 A 1 1 0 0 0 22 20 z M 28 20 A 1 1 0 0 0 27 21 A 1 1 0 0 0 28 22 A 1 1 0 0 0 29 21 A 1 1 0 0 0 28 20 z M 7 23 A 1 1 0 0 0 6 24 A 1 1 0 0 0 7 25 A 1 1 0 0 0 8 24 A 1 1 0 0 0 7 23 z M 13 23 A 1 1 0 0 0 12 24 A 1 1 0 0 0 13 25 A 1 1 0 0 0 14 24 A 1 1 0 0 0 13 23 z M 19 23 A 1 1 0 0 0 18 24 A 1 1 0 0 0 19 25 A 1 1 0 0 0 20 24 A 1 1 0 0 0 19 23 z M 25 23 A 1 1 0 0 0 24 24 A 1 1 0 0 0 25 25 A 1 1 0 0 0 26 24 A 1 1 0 0 0 25 23 z M 4 26 A 1 1 0 0 0 3 27 A 1 1 0 0 0 4 28 A 1 1 0 0 0 5 27 A 1 1 0 0 0 4 26 z M 10 26 A 1 1 0 0 0 9 27 A 1 1 0 0 0 10 28 A 1 1 0 0 0 11 27 A 1 1 0 0 0 10 26 z M 16 26 A 1 1 0 0 0 15 27 A 1 1 0 0 0 16 28 A 1 1 0 0 0 17 27 A 1 1 0 0 0 16 26 z M 22 26 A 1 1 0 0 0 21 27 A 1 1 0 0 0 22 28 A 1 1 0 0 0 23 27 A 1 1 0 0 0 22 26 z M 28 26 A 1 1 0 0 0 27 27 A 1 1 0 0 0 28 28 A 1 1 0 0 0 29 27 A 1 1 0 0 0 28 26 z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" version="1.1" width="100" height="100" fill="000000">
<g id="surface1">
<path style=" " d="M 23.398438 14.023438 C 23.058594 14.042969 22.835938 13.933594 22.808594 13.914063 L 21.121094 14.992188 C 21.492188 15.574219 22.257813 15.96875 23.117188 16.019531 C 23.183594 16.023438 23.25 16.023438 23.316406 16.023438 C 24.445313 16.023438 25.554688 15.453125 26.394531 14.4375 C 27.828125 12.695313 28.835938 10.847656 28.878906 10.769531 L 29.332031 9.929688 L 28.515625 9.4375 C 23.984375 6.714844 21.394531 8.007813 20.492188 8.691406 C 19.328125 9.574219 18.796875 11.019531 19.089844 12.429688 C 18.160156 13.023438 17.234375 13.773438 16.496094 14.6875 C 16.070313 13.691406 15.40625 12.796875 14.632813 12.007813 C 14.703125 11.824219 14.75 11.644531 14.78125 11.511719 C 14.796875 11.441406 14.8125 11.375 14.832031 11.316406 C 15.34375 9.601563 14.640625 7.601563 13.082031 6.34375 C 11.972656 5.449219 8.820313 3.683594 3.519531 6.605469 L 2.835938 6.980469 L 3.03125 7.730469 C 3.070313 7.882813 4.015625 11.445313 5.894531 13.53125 C 6.707031 14.433594 7.726563 14.941406 8.847656 14.996094 C 8.917969 15 8.988281 15 9.054688 15 C 10.3125 15 11.390625 14.441406 11.828125 14.042969 L 10.484375 12.5625 C 10.46875 12.574219 8.789063 13.753906 7.382813 12.191406 C 6.292969 10.984375 5.550781 9.046875 5.199219 7.984375 C 8.984375 6.160156 11.078125 7.296875 11.824219 7.898438 C 12.699219 8.605469 13.132813 9.648438 12.953125 10.554688 C 10.800781 8.960938 8.558594 8.070313 8.378906 8.003906 L 7.65625 9.867188 C 9.699219 10.65625 15 13.484375 15 17 L 15 20.144531 C 14.238281 20.34375 13.542969 20.753906 13.019531 21.34375 C 12.550781 21.117188 12.035156 21 11.5 21 C 10.070313 21 8.839844 21.859375 8.296875 23.09375 C 8.035156 23.03125 7.769531 23 7.5 23 C 5.570313 23 4 24.570313 4 26.5 L 4 27 L 6 27 L 6 26.5 C 6 25.671875 6.671875 25 7.5 25 C 7.902344 25 8.210938 25.167969 8.398438 25.308594 L 10 24.511719 L 10 24.496094 C 10.003906 23.671875 10.675781 23 11.5 23 C 11.902344 23 12.28125 23.160156 12.566406 23.449219 L 14.1875 23.167969 C 14.515625 22.457031 15.226563 22 16 22 C 16.726563 22 17.398438 22.40625 17.75 23.0625 L 19.328125 23.304688 C 19.527344 23.109375 19.792969 23 20.070313 23 C 20.65625 23 21.136719 23.480469 21.136719 24.066406 C 21.136719 24.183594 21.113281 24.300781 21.066406 24.429688 L 22.671875 25.519531 C 22.9375 25.28125 23.382813 25 24 25 C 25.101563 25 26 25.898438 26 27 L 28 27 C 28 24.792969 26.207031 23 24 23 C 23.65625 23 23.316406 23.046875 22.992188 23.132813 C 22.59375 21.894531 21.433594 21 20.070313 21 C 19.652344 21 19.253906 21.082031 18.878906 21.238281 C 18.367188 20.703125 17.714844 20.332031 17 20.144531 L 17 19 L 17.003906 19 L 17.003906 18.671875 C 17.003906 14.519531 23.535156 12.53125 23.601563 12.511719 L 23.039063 10.59375 C 22.9375 10.621094 22.121094 10.871094 21.046875 11.363281 C 21.125 10.949219 21.339844 10.5625 21.703125 10.289063 C 22.761719 9.484375 24.558594 9.636719 26.617188 10.675781 C 26.214844 11.332031 25.589844 12.273438 24.851563 13.167969 C 24.300781 13.835938 23.757813 14.003906 23.398438 14.023438 Z M 13.484375 10.820313 L 13.496094 10.976563 C 13.445313 10.9375 13.390625 10.898438 13.339844 10.855469 C 13.386719 10.84375 13.429688 10.824219 13.484375 10.820313 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" version="1.1" width="96px" height="96px">
<g id="surface1">
<path style=" " d="M 2 5 L 2 21 L 6 21 L 6 26.09375 L 7.625 24.78125 L 12.34375 21 L 22 21 L 22 5 Z M 4 7 L 20 7 L 20 19 L 11.65625 19 L 11.375 19.21875 L 8 21.90625 L 8 19 L 4 19 Z M 24 9 L 24 11 L 28 11 L 28 23 L 24 23 L 24 25.90625 L 20.34375 23 L 12.84375 23 L 10.34375 25 L 19.65625 25 L 26 30.09375 L 26 25 L 30 25 L 30 9 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 548 B

View File

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 48 48" version="1.1" width="100" height="100" fill="000000">
<g id="surface1">
<path style=" fill:#E0AC6E;" d="M 36 20 L 16 6 L 4 23 L 25 37 L 31 37 L 38.070313 25.394531 Z "/>
<path style=" fill:#5D4037;" d="M 36.484375 35.726563 C 37.742188 36.925781 39.226563 37.355469 39.78125 36.679688 C 40.34375 36 39.773438 34.476563 38.515625 33.273438 C 37.253906 32.074219 35.777344 31.644531 35.214844 32.320313 C 34.652344 32.996094 35.226563 34.523438 36.484375 35.726563 Z "/>
<path style=" fill:#5D4037;" d="M 30.359375 38.433594 C 31.976563 39.203125 33.578125 39.183594 33.929688 38.390625 C 34.285156 37.597656 33.257813 36.328125 31.640625 35.5625 C 30.023438 34.796875 28.421875 34.8125 28.070313 35.605469 C 27.714844 36.398438 28.742188 37.664063 30.359375 38.433594 Z "/>
<path style=" fill:#5D4037;" d="M 29.484375 31.726563 C 30.742188 32.925781 32.226563 33.355469 32.78125 32.679688 C 33.34375 32 32.773438 30.476563 31.515625 29.273438 C 30.253906 28.074219 28.777344 27.644531 28.214844 28.320313 C 27.652344 28.996094 28.226563 30.523438 29.484375 31.726563 Z "/>
<path style=" fill:#5D4037;" d="M 43 41.5 C 43 40.671875 41.65625 40 40 40 C 38.34375 40 37 40.671875 37 41.5 C 37 42.328125 38.34375 43 40 43 C 41.65625 43 43 42.328125 43 41.5 Z "/>
<path style=" fill:#FFCC80;" d="M 16 6 L 18.214844 11.652344 L 10 23 L 4 23 L 25 37 L 36 20 Z "/>
<path style=" fill:#558B2F;" d="M 28 23 C 28 26.316406 25.316406 29 22 29 C 18.683594 29 16 26.316406 16 23 C 16 19.683594 18.683594 17 22 17 C 25.316406 17 28 19.683594 28 23 "/>
<path style=" fill:#FFFFFF;" d="M 20.535156 19.941406 C 20.535156 19.113281 21.191406 18.445313 22 18.445313 C 22.808594 18.445313 23.464844 19.113281 23.464844 19.941406 C 23.464844 20.773438 22 22.945313 22 22.945313 C 22 22.945313 20.535156 20.773438 20.535156 19.941406 "/>
<path style=" fill:#FFFFFF;" d="M 23.464844 25.945313 C 23.464844 26.777344 22.808594 27.445313 22 27.445313 C 21.191406 27.445313 20.535156 26.777344 20.535156 25.945313 C 20.535156 25.113281 22 22.945313 22 22.945313 C 22 22.945313 23.464844 25.113281 23.464844 25.945313 "/>
<path style=" fill:#FFFFFF;" d="M 18.730469 22.742188 C 18.03125 22.328125 17.792969 21.414063 18.195313 20.695313 C 18.597656 19.976563 19.496094 19.730469 20.195313 20.148438 C 20.894531 20.5625 22 22.945313 22 22.945313 C 22 22.945313 19.433594 23.15625 18.730469 22.742188 "/>
<path style=" fill:#FFFFFF;" d="M 25.269531 23.144531 C 25.96875 23.5625 26.207031 24.476563 25.804688 25.195313 C 25.402344 25.914063 24.503906 26.160156 23.804688 25.742188 C 23.101563 25.328125 22 22.945313 22 22.945313 C 22 22.945313 24.566406 22.730469 25.269531 23.144531 "/>
<path style=" fill:#FFFFFF;" d="M 25.269531 22.742188 C 25.96875 22.328125 26.207031 21.414063 25.804688 20.695313 C 25.402344 19.976563 24.503906 19.730469 23.804688 20.148438 C 23.101563 20.5625 22 22.945313 22 22.945313 C 22 22.945313 24.566406 23.15625 25.269531 22.742188 "/>
<path style=" fill:#FFFFFF;" d="M 18.730469 23.144531 C 18.03125 23.5625 17.792969 24.476563 18.195313 25.195313 C 18.597656 25.914063 19.496094 26.160156 20.195313 25.742188 C 20.894531 25.328125 22 22.945313 22 22.945313 C 22 22.945313 19.433594 22.730469 18.730469 23.144531 "/>
<path style=" fill:#FFC107;" d="M 23.5 23 C 23.5 23.828125 22.828125 24.5 22 24.5 C 21.171875 24.5 20.5 23.828125 20.5 23 C 20.5 22.171875 21.171875 21.5 22 21.5 C 22.828125 21.5 23.5 22.171875 23.5 23 "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" version="1.1" width="100" height="100" fill="000000">
<g id="surface1">
<path style=" " d="M 10.84375 2 L 10.28125 2.8125 L 2.53125 14.46875 L 1.96875 15.3125 L 2.8125 15.84375 L 8.84375 19.875 L 13.5 22.9375 L 15.03125 22.25 C 15.148438 21.535156 15.746094 21 16.5 21 C 16.777344 21 17.265625 21.195313 17.5 21.375 L 19.09375 20.5625 C 19.09375 19.667969 19.691406 19 20.5 19 C 20.832031 19 21.117188 19.121094 21.375 19.3125 L 22.8125 19.0625 L 24.46875 16.59375 L 26.5 13.5625 L 27.03125 12.71875 L 26.21875 12.15625 L 11.6875 2.53125 Z M 11.40625 4.78125 L 24.25 13.28125 L 22.8125 15.46875 L 21.5625 17.34375 C 21.207031 17.21875 20.898438 17 20.5 17 C 19 17 17.820313 18.003906 17.34375 19.3125 C 17.046875 19.230469 16.828125 19 16.5 19 C 15.285156 19 14.375 19.738281 13.75 20.6875 L 9.96875 18.1875 L 4.75 14.75 Z M 13.9375 9 C 13.242188 9.007813 12.566406 9.378906 12.21875 10.125 L 12.03125 10.53125 L 11.625 10.59375 C 10.03125 10.855469 9.421875 12.863281 10.59375 14 L 10.90625 14.28125 L 10.84375 14.6875 C 10.59375 16.316406 12.269531 17.539063 13.6875 16.75 L 14.0625 16.5625 L 14.40625 16.75 C 15.84375 17.496094 17.515625 16.214844 17.21875 14.59375 L 17.125 14.1875 L 17.4375 13.90625 C 18.578125 12.738281 17.910156 10.746094 16.3125 10.53125 L 15.90625 10.46875 L 15.71875 10.09375 C 15.351563 9.359375 14.632813 8.992188 13.9375 9 Z M 14 12 C 14.550781 12 15 12.449219 15 13 C 14.996094 13.554688 14.550781 14 14 14 C 13.449219 14 13 13.554688 13 13 C 13 12.449219 13.445313 11.996094 14 12 Z M 22.1875 21.78125 C 22.039063 21.777344 21.925781 21.820313 21.84375 21.90625 C 21.515625 22.242188 21.9375 23.179688 22.78125 24 C 23.625 24.820313 24.546875 25.210938 24.875 24.875 C 25.203125 24.539063 24.8125 23.601563 23.96875 22.78125 C 23.335938 22.167969 22.632813 21.789063 22.1875 21.78125 Z M 27.25 22.9375 C 26.855469 23.078125 26.445313 23.859375 26.3125 24.84375 C 26.160156 25.96875 26.425781 26.9375 26.875 27 C 27.324219 27.0625 27.816406 26.1875 27.96875 25.0625 C 28.121094 23.9375 27.855469 23 27.40625 22.9375 C 27.351563 22.929688 27.304688 22.917969 27.25 22.9375 Z M 22.09375 26 C 21.703125 26.003906 21.402344 26.125 21.3125 26.34375 C 21.132813 26.777344 21.804688 27.457031 22.8125 27.875 C 23.820313 28.292969 24.789063 28.277344 24.96875 27.84375 C 25.148438 27.410156 24.476563 26.730469 23.46875 26.3125 C 22.964844 26.105469 22.484375 25.996094 22.09375 26 Z M 27.875 28.3125 C 26.699219 28.3125 25.75 28.6875 25.75 29.15625 C 25.75 29.625 26.699219 30 27.875 30 C 29.050781 30 30 29.625 30 29.15625 C 30 28.6875 29.050781 28.3125 27.875 28.3125 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 32 32" version="1.1" width="100" height="100" fill="000000">
<g id="surface1">
<path style=" " d="M 16 4 C 9.382813 4 4 9.382813 4 16 C 4 19.070313 5.15625 21.875 7.0625 24 L 5 24 L 5 26 L 11 26 L 11 20 L 9 20 L 9 23.125 C 7.15625 21.3125 6 18.792969 6 16 C 6 10.464844 10.464844 6 16 6 Z M 18.25 4.21875 L 17.6875 6.15625 C 18.347656 6.269531 19.003906 6.445313 19.625 6.6875 L 20.15625 4.75 C 19.53125 4.519531 18.90625 4.34375 18.25 4.21875 Z M 21 6 L 21 12 L 23 12 L 23 8.875 C 24.847656 10.683594 26 13.199219 26 16 C 26 21.535156 21.535156 26 16 26 L 16 28 C 22.617188 28 28 22.617188 28 16 C 28 12.921875 26.820313 10.121094 24.90625 8 L 27 8 L 27 6 Z M 12.375 25.3125 L 11.84375 27.25 C 12.46875 27.480469 13.09375 27.65625 13.75 27.78125 L 14.3125 25.84375 C 13.652344 25.730469 12.996094 25.554688 12.375 25.3125 Z "/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 936 B

View File

@@ -13,10 +13,12 @@
// = require leaflet
// = require leaflet.markercluster
// = require js-routes
// = require popper
// = require jquery
// = require jquery_ujs
// = require jquery-ui/widgets/autocomplete
// = require bootstrap-sprockets
// = require bootstrap-datepicker
// = require isotope
// = require bootstrap
// = require material
// = require_tree .

View File

@@ -31,7 +31,7 @@ jQuery ->
if el.data( 'uiAutocomplete' )
el.data( 'uiAutocomplete' )._renderItem = ( ul, item ) ->
$( '<li></li>' )
$( '<li class="list-group-item"></li>' )
.data( 'item.autocomplete', item )
.append( "<a>#{item.name}</a>" )
.appendTo( ul )

View File

@@ -0,0 +1 @@
$('.dropdown-toggle').dropdown();

View File

@@ -1,8 +0,0 @@
$('.planting-facts').isotope({
layoutMode: 'fitRows',
percentPosition: true,
itemSelector: '.fact',
fitRows: {
gutter: 10,
},
});

View File

@@ -0,0 +1,21 @@
.planting {
.crop-card {
height: 100%;
margin: .1em;
min-height: 300px;
width: 100px;
}
.img-thumbnail {
width: 100%;
}
}
.crop-photos {
margin-left: 3em;
}
.crops-search-form {
background-color: $white;
padding: 1em;
}

View File

View File

@@ -0,0 +1,76 @@
// signup widget on homepage
.jumbotron .signup {
background-color: lighten($green, 40%);
border: 1px solid lighten($green, 20%);
border-radius: 6px;
line-height: 200%;
padding: 15px;
text-align: center;
}
.homepage-cards {
display: flex;
flex: none;
flex-wrap: wrap;
margin: .5em;
// left: -.5em;
.card {
left: -.5em;
margin: .5em;
min-height: 100px;
padding: 0;
%h3.crop-name {
font-size: 2em;
}
}
.crop-card {
min-height: 80px;
width: 120px;
}
.thumbnail {
margin: .5em;
}
.img-card {
height: 150px;
}
}
.member-cards {
display: flex;
flex: none;
flex-wrap: wrap;
.card {
margin: 1em;
width: 150px;
}
}
@include media-breakpoint-down(sm) {
.homepage-cards {
.seed-card {
min-height: 80px;
width: 100%;
}
.member-card {
min-height: 80px;
width: 150px;
}
}
}
@include media-breakpoint-up(md) {
.homepage-cards {
.card {
width: 200px;
}
}
}

View File

@@ -0,0 +1,17 @@
.member-thumbnail {
border-radius: 12px;
height: 200px;
margin: 1em;
padding: .25em;
div {
display: inline-block;
vertical-align: top;
width: 5em;
}
}
.member-thumbnail div ~ div {
padding-left: 1em;
width: 15em;
}

View File

@@ -0,0 +1,56 @@
.photo-grid {
background: $beige;
}
// clear fix
.photo-grid:after {
clear: both;
content: "";
display: block;
}
.photo-grid-item {
float: left;
img {
display: block;
max-width: 100%;
}
}
.hero-photo {
max-height: 500px;
}
.photo-thumbnail {
margin-bottom: 1em;
margin-right: 1em;
max-width: 150px;
padding: 0;
position: relative;
img {
width: 100%;
}
.text {
bottom: 0;
color: $black;
display: none;
margin: 0;
position: absolute;
width: 100%;
}
p {
color: $white;
margin: 0;
padding: 5px;
}
&:hover {
.text {
display: block;
}
}
}

View File

@@ -0,0 +1,104 @@
.planting {
.planting-badges {
font-size: 1em;
position: absolute;
top: 3em;
.badge-super-late {
background-color: $red;
}
.badge-harvest {
background-color: $blue;
}
}
.planting-thumbnail {
padding: 0;
width: 150px;
.badge {
font-size: 100%;
}
}
.planting-full-badges {
.badge {
font-size: 200%;
}
}
.progress {
.progress-bar {
border-bottom-color: $green;
}
.progress-bar:after {
background-color: $beige;
}
}
.planting-name {
position: relative;
text-align: center;
top: 0;
}
.planting-quick-actions {
background-color: $white;
left: 0;
position: absolute;
top: 0;
}
.planting-thumbnail-photo {
height: 150px;
}
dl.planting-attributes {
dt {
text-align: left;
}
dd {
margin-left: auto;
}
}
}
.planting-facts {
display: flex;
flex-wrap: wrap;
flex: none;
.planting-fact-card {
background: $white;
background: $white;
border-radius: 5%;
border: 1px solid lighten($green, 20%);
margin: 1em;
padding: 1em;
text-align: center;
width: 120px;
strong {
font-align: center;
font-size: 4em;
}
span {
display: block;
}
h3 {
// padding-top: 1em;
}
span {
display: block;
}
img {
height: 50%;
}
}
}

View File

@@ -0,0 +1,19 @@
.predictions {
.predictions-card {
background: $white;
border-radius: 5%;
border: 1px solid lighten($green, 20%);
margin: 1em;
max-width: 250px;
text-align: center;
strong {
font-align: center;
font-size: 4em;
}
span {
display: block;
}
}
}

View File

View File

@@ -0,0 +1,55 @@
//$screen-md-min: 1028px
// Base colours
$beige: #f3f1ee;
$brown: #413f3b;
$green: #5f8e43;
$blue: #2f4365;
$red: #ff4d43;
$orange: #ffa500;
$yellow: #b2935c;
$white: #fff;
$body-bg: $beige;
$text-color: $brown;
$link-color: $green;
$graph-hover: $orange;
$primary: (
color: $green,
dark: darken($green, 20%),
light: lighten($green, 20%)
);
$secondary: (
color: $blue,
dark: darken($blue, 20%),
light: lighten($blue, 20%)
);
$success: (
color: $green,
dark: darken($green, 20%),
light: lighten($green, 20%)
);
$danger: (
color: $red,
dark: darken($red, 20%),
light: lighten($red, 20%)
);
$dark: (
color: $brown,
dark: darken($brown, 20%),
light: lighten($brown, 20%)
);
// Nav bar
$navbar-default-bg: $brown;
$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: darken($beige, 80%);
$navbar-default-brand-color: lighten($green, 20%);
$highest-level: 1070;

View File

@@ -1,10 +0,0 @@
@import 'jquery-ui/autocomplete'
@import 'bootstrap-datepicker'
@import 'leaflet'
@import 'leaflet.markercluster'
@import 'custom_bootstrap/custom_bootstrap'
@import 'overrides'
@import 'graphs'
@import 'predictions'
@import 'plantings'
@import 'photos'

View File

@@ -0,0 +1,27 @@
// Import original variables so they can be used in overrides
@import 'variables';
@import 'material';
@import 'jquery-ui/autocomplete';
@import 'bootstrap-datepicker';
@import 'leaflet';
@import 'leaflet.markercluster';
@import 'predictions';
@import 'plantings';
@import 'members';
@import 'harvests';
@import 'seeds';
@import 'crops';
@import 'homepage';
@import 'photos';
// Font Awesome
@import 'font-awesome-sprockets';
@import 'font-awesome';
@import 'material_icons';
@import 'rails_bootstrap_forms';
@import 'overrides';

View File

@@ -1,82 +0,0 @@
.btn:focus {
outline: dotted 2px #000;
}
div.active:focus {
outline: dotted 1px #000;
}
a:focus {
outline: dotted 1px #000;
}
.close:hover,
.close:focus {
outline: dotted 1px #000;
}
.nav > li > a:hover,
.nav > li > a:focus {
outline: dotted 1px #000;
}
.carousel-indicators li,
.carousel-indicators li.active {
height: 18px;
width: 18px;
border-width: 2px;
position: relative;
box-shadow: 0px 0px 0px 1px #808080;
}
.carousel-indicators.active li {
background-color: rgba(100, 149, 253, 0.6);
}
.carousel-indicators.active li.active {
background-color: white;
}
.carousel-tablist-highlight {
display: block;
position: absolute;
outline: 2px solid transparent;
background-color: transparent;
box-shadow: 0px 0px 0px 1px transparent;
}
.carousel-tablist-highlight.focus {
outline: 2px solid #6495ed;
background-color: rgba(0, 0, 0, 0.4);
}
a.carousel-control:focus {
outline: 2px solid #6495ed;
background-image: linear-gradient(
to right,
transparent 0px,
rgba(0, 0, 0, 0.5) 100%
);
box-shadow: 0px 0px 0px 1px #000000;
}
.carousel-pause-button {
position: absolute;
top: -30em;
left: -300em;
display: block;
}
.carousel-pause-button.focus {
top: 0.5em;
left: 0.5em;
}
.carousel:hover .carousel-caption,
.carousel.contrast .carousel-caption {
background-color: rgba(0, 0, 0, 0.5);
z-index: 10;
}
.alert-success {
color: #2d4821;
}
.alert-info {
color: #214c62;
}
.alert-warning {
color: #6c4a00;
background-color: #f9f1c6;
}
.alert-danger {
color: #d2322d;
}
.alert-danger:hover {
color: #a82824;
}

View File

@@ -1,59 +0,0 @@
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// !!! AUTOMATICALLY GENERATED FILE. DO NOT MODIFY !!!
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Core variables and mixins
@import "bootstrap-sprockets"
@import "bootstrap/variables"
// Modify this for custom colors, font-sizes, etc
@import "custom_bootstrap/variables"
@import "bootstrap/mixins"
// Modify this for custom mixins
@import "custom_bootstrap/mixins"
// Reset and dependencies
@import "bootstrap/normalize"
@import "bootstrap/print"
@import "bootstrap/glyphicons"
// Core CSS
@import "bootstrap/scaffolding"
@import "bootstrap/type"
@import "bootstrap/code"
@import "bootstrap/grid"
@import "bootstrap/tables"
@import "bootstrap/forms"
@import "bootstrap/buttons"
// Components
@import "bootstrap/component-animations"
@import "bootstrap/dropdowns"
@import "bootstrap/button-groups"
@import "bootstrap/input-groups"
@import "bootstrap/navs"
@import "bootstrap/navbar"
@import "bootstrap/breadcrumbs"
@import "bootstrap/pagination"
@import "bootstrap/pager"
@import "bootstrap/labels"
@import "bootstrap/badges"
@import "bootstrap/jumbotron"
@import "bootstrap/thumbnails"
@import "bootstrap/alerts"
@import "bootstrap/progress-bars"
@import "bootstrap/media"
@import "bootstrap/list-group"
@import "bootstrap/panels"
@import "bootstrap/responsive-embed"
@import "bootstrap/wells"
@import "bootstrap/close"
// Components w/ JavaScript
@import "bootstrap/modals"
@import "bootstrap/tooltip"
@import "bootstrap/popovers"
@import "bootstrap/carousel"
// Utility classes
@import "bootstrap/utilities"
@import "bootstrap/responsive-utilities"

View File

@@ -1 +0,0 @@
// Use this file to override Twitter Bootstrap mixins or define own mixins.

View File

@@ -1,56 +0,0 @@
// Use this file to override Twitter Bootstrap variables or define own variables.
// Import original variables so they can be used in overrides
@import 'bootstrap/variables.scss'
// Base colours
$beige: #f3f1ee
$brown: #413f3b
$green: #5f8e43
$blue: #2f4365
$red: #ff4d43
$orange: #ffa500
$yellow: #b2935c
$white: #ffffff
$body-bg: $beige
$text-color: $brown
$link-color: $green
$graph-hover: $orange
$brand-primary: $green
$font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif
$font-family-serif: Georgia, "Times New Roman", Times, serif
$font-family-mono: Monaco, Menlo, Consolas, "Courier New", monospace
$font-size-base: 14px
$font-family-base: $font-family-sans-serif
$line-height-base: 1.5
$alt-font-family: $font-family-serif
$headings-font-family: $font-family-sans-serif
$headings-font-weight: bold // instead of browser default, bold
$headings-color: inherit // empty to use BS default, $textColor
// Hero unit
$jumbotron-bg: darken($body-bg, 10%)
// Nav bar
$navbar-default-bg: $brown
$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: darken($beige,80%)
$navbar-default-brand-color: lighten($green, 20%)
// Top nav collapse threshold
$grid-float-breakpoint: $screen-md-min
$dropdown-bg: lighten($beige, 10%)
$dropdown-link-color: $brown
$dropdown-link-hover-color: $brown
$dropdown-link-hover-bg: lighten($green, 50%)

View File

@@ -1,2 +0,0 @@
.bar rect:hover
fill: $graph-hover

View File

@@ -1,10 +0,0 @@
.leaflet-popup-content-wrapper,
.leaflet-popup-tip
border: none
.thumbnail
background: #fff !important
border: solid 1px whitesmoke
.thumbnail .crop-thumbnail .cropinfo
padding-top: 14px

View File

@@ -0,0 +1,13 @@
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
border: none;
}
.thumbnail {
background: #fff !important;
border: solid 1px whitesmoke;
}
.thumbnail .crop-thumbnail .cropinfo {
padding-top: 14px;
}

View File

@@ -1,371 +0,0 @@
@import "bootstrap-sprockets"
@import "bootstrap"
@import "custom_bootstrap/variables"
// this padding needs to be done before the responsive stuff is imported
body
padding-top: $navbar-height
// Font Awesome
@import "font-awesome-sprockets"
@import "font-awesome"
.list-inline > li.first
padding-left: 0px
.activity-list
list-style-type: none
padding: 0
h2
font-size: 150%
h3
font-size: 120%
.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
.avatar
border-radius: 50%
z-index: 2
position: relative
.profile-sidebar
margin-top: -5rem
.profile-activity
background: white
padding: 2em
margin-top: 2em
.container
width: 100%
.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)
margin-left: 0px
.three-across:nth-child(3n+1)
margin-left: 0px
clear: both
// let's condense the hero unit a little
.jumbotron
padding-top: 30px
padding-bottom: 30px
// info under the main heading on homepage
.jumbotron .info
padding-top: 15px
// signup widget on homepage
.jumbotron .signup
background-color: lighten($green, 40%)
border: 1px solid lighten($green, 20%)
border-radius: 6px
line-height: 200%
padding: 15px
text-align: center
// stats shown on homepage. eg. "999 members..."
p.stats
font-weight: bold
.member-cards
display: flex
flex: none
flex-wrap: wrap
.card-row
display: grid
grid-template-columns: 50% 50%
grid-gap: 25px
grid-row-gap: 5px
.member-thumbnail
padding: .25em
margin: 1em
div
width: 5em
display: inline-block
vertical-align: top
.member-thumbnail div~div
padding-left: 1em
width: 15em
.progress
border-radius: 0
.progress-bar-text
text-align: center
.layout-actions
width: 100%
#placesmap, #cropmap
height: 500px
#membermap
height: 250px
z-index: 0
.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
color: $brown
.photo-thumbnail
padding: 0
position: relative
img
width: 100%
.text
display: none
color: #000
position: absolute
bottom: 0
background: rgba(0, 0, 0, 0.8)
width: 100%
margin: 0
p
padding: 5px
margin: 0
color: #fff
&:hover
.text
display: block
.thumbnail
border: none
text-align: center
margin-bottom: 1.5em
max-width: 160px
max-height: 200px
.member-thumbnail
text-align: left
img
height: 85px
width: 85px
max-width: 85px
.crop-thumbnail
height: 220px
.cropinfo
display: inline-block
max-width: 100%
white-space: nowrap
line-height: 1em
padding-bottom: 2px
.cropname
overflow: hidden
text-overflow: ellipsis
.scientificname
font-size: small
font-style: italic
overflow: hidden
text-overflow: ellipsis
.plantingcount
font-size: small
.crop-name a
padding-top: 2px
.scientific-name small
margin-bottom: -2px
li.crop-hierarchy
list-style-type: disc
.navbar-brand
margin: 0px
padding: 0px
.navbar-bottom
margin: 40px 0px 0px 0px !important
.post-actions
margin-bottom: 1rem
// footer
footer
#footer1, #footer2, #footer3
text-align: left
padding-top: 1em
padding-bottom: 2em
ul
list-style-type: none
list-style-position: outside
padding-left: 0px
margin-left: 0px
a
color: $navbar-default-link-color
text-decoration: none
a:hover
color: $navbar-default-link-hover-color
a:active
color: $navbar-default-link-active-color
.navbar-bottom.navbar
border-radius: 0
// ensure footer is pushed to bottom of browser window
#maincontainer
min-height: 80%
padding: 50px
html, body
height: 100%
.crop-image, .member-image
width: 100%
height: 100%
// Autosuggest
.ui-autocomplete
background: white
z-index: $zindex-tooltip
.alert
a
font-weight: 800
/* override "info" alert boxes to be green, not blue, on Growstuff */
$state-info-text: darken($green, 10%)
$state-info-bg: lighten($green, 50%)
/* and set "success" to be the same, as it was just very slightly
* different because the default bootstrap green is slightly different
* from ours */
$state-success-text: darken($green, 10%)
$state-success-bg: lighten($green, 50%)
.hide
display: none
#add-sci_name-row, #remove-sci_name-row, #add-alt_name-row, #remove-alt_name-row
display: none
.panel-footer
height: 6em
.panel
.dl-horizontal
text-overflow: ellipsis
overflow: hidden
.form-group.required .control-label:before
content: "* "
color: red
.margin-bottom
margin-bottom: 1em
.red
color: red
.truncate
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
ul.plantings
list-style-type: none
ul.thumbnail-buttons
list-style-type: none
text-align: right
.hover-wrapper .text
position: absolute
visibility: hidden
.hover-wrapper:hover .text
visibility: visible
.homepage-listing
padding-bottom: 6px
@media (min-width: $screen-md-min)
.planting-thumbnail
dl.planting-attributes
width: 100%
dt
text-align: left
width: 120px
dd
padding-left: 120px
margin-left: auto
.navbar .navbar-form
width: 250px
// Overrides applying only to mobile view. This must be at the end of the overrides file.
@media only screen and (max-width: 767px)
.sidebar
margin-left: 0
border-left: none
padding-left: 0
#map
height: 300px
.navbar .nav > li
display: block
.navbar .navbar-form
width: 185px
padding-left: 0
padding-right: 0
.homepage
.thumbnail
height: 180px
.seed-thumbnail
height: 220px
#maincontainer
padding: 10px

View File

@@ -0,0 +1,454 @@
body {
background-color: $beige;
font-family: $font-family-sans-serif;
}
section {
padding-top: 1em;
margin: 0;
}
.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
a {
color: $green;
}
a:hover {
color: $brown;
text-decoration: none;
}
.card a:hover {
background-color: $beige;
color: $blue;
}
span.badge {
background-color: $brown;
a {
color: $white;
}
}
.list-inline > li.first {
padding-left: 0;
}
.activity-list {
list-style-type: none;
padding: 0;
}
h2 {
font-size: 150%;
}
h3 {
font-size: 120%;
}
.main {
padding-right: 1em;
}
#navbar-search {
.input-group {
input {
background-color: $white;
color: $black;
}
input::placeholder {
color: $navbar-default-link-color;
}
}
}
.index-cards {
display: flex;
flex: none;
flex-wrap: wrap;
.card {
margin: 1em 1em 1em 0;
width: 200px;
}
}
img.img-icon {
width: 1.2em;
}
.img-square {
height: 150px;
object-fit: cover;
width: 150px;
}
.img-card {
height: 180px;
object-fit: cover;
width: 100%;
}
.img-responsive {
max-width: 100%;
}
.avatar {
border-radius: 50%;
padding: 1em;
position: relative;
z-index: 2;
}
.profile-sidebar {
margin-top: -5rem;
}
.profile-activity {
background: $white;
margin-top: 2em;
padding: 2em;
}
.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) {
margin-left: 0;
}
.three-across:nth-child(3n+1) {
clear: both;
margin-left: 0;
}
// let's condense the hero unit a little
.jumbotron {
background-color: darken($beige, 10%);
padding-top: 30px;
padding-bottom: 30px;
// signup widget on homepage
.signup {
background-color: lighten($green, 40%);
border-radius: 6px;
border: 1px solid lighten($green, 20%);
line-height: 200%;
padding: 15px;
text-align: center;
}
}
// info under the main heading on homepage
.jumbotron .info {
//padding-top: 15px
padding: 0.5em;
text-align: center;
}
// stats shown on homepage. eg. "999 members..."
p.stats {
font-weight: bold;
}
.card-row {
display: grid;
grid-gap: 25px;
grid-row-gap: 5px;
grid-template-columns: 50% 50%;
}
.card {
margin-bottom: 1em
}
.progress {
border-radius: 0;
.progress-bar-text {
text-align: center;
}
}
#placesmap,
#cropmap {
height: 500px;
}
#membermap {
height: 250px;
z-index: 0;
}
.location-not-set {
background-image: image-url('location-not-set.en.png');
background-position: center;
background-repeat: no-repeat;
height: 250px;
width: 100%;
}
.member-location {
font-size: small;
font-style: italic;
}
.member-location a {
color: $brown;
}
.associations {
list-style-type: none;
}
li.crop-hierarchy {
list-style-type: disc;
}
.navbar-brand {
margin: 0;
padding: 0;
}
.navbar-bottom {
margin: 40px 0 0 !important;
}
.post-actions {
margin-bottom: 1rem;
}
// footer
footer {
#footer1,
#footer2,
#footer3 {
padding-bottom: 2em;
padding-top: 1em;
text-align: left;
ul {
list-style-position: outside;
list-style-type: none;
margin-left: 0;
padding-left: 0;
}
a {
color: $navbar-default-link-color;
text-decoration: none;
}
a:hover {
color: $navbar-default-link-hover-color;
}
a:active {
color: $navbar-default-link-active-color;
}
}
}
// ensure footer is pushed to bottom of browser window
#maincontainer {
min-height: 80%;
}
#global-actions {
padding-top: 10px;
}
html,
body {
height: 100%;
}
.member-image {
border-radius: 50%;
}
// Autosuggest
.ui-autocomplete {
background: $white;
z-index: $highest-level;
}
.alert {
a {
font-weight: 800;
}
}
/* override "info" alert boxes to be green, not blue, on Growstuff */
$state-info-text: darken($green, 10%);
$state-info-bg: lighten($green, 50%);
/* and set "success" to be the same, as it was just very slightly
* different because the default bootstrap green is slightly different
* from ours */
$state-success-text: darken($green, 10%);
$state-success-bg: lighten($green, 50%);
.hide {
display: none;
}
#add-sci_name-row,
#remove-sci_name-row,
#add-alt_name-row,
#remove-alt_name-row {
display: none;
}
.panel-footer {
height: 6em;
}
.panel {
.dl-horizontal {
text-overflow: ellipsis;
overflow: hidden;
}
}
label.required:after {
color: red;
content:" *";
}
.margin-bottom {
margin-bottom: 1em;
}
.red {
color: red;
}
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
ul.plantings {
list-style-type: none;
}
ul.thumbnail-buttons {
list-style-type: none;
text-align: right;
}
.hover-wrapper .text {
position: absolute;
visibility: hidden;
}
.hover-wrapper:hover .text {
visibility: visible;
}
.homepage-listing {
padding-bottom: 6px;
}
.container {
max-width: 1500px;
}
// Small devices (landscape phones, less than 768px)
@include media-breakpoint-down(md) {
.planting-thumbnail {
dl.planting-attributes {
width: 100%;
dt {
text-align: left;
width: 120px;
}
dd {
margin-left: auto;
padding-left: 120px;
}
}
}
}
.form-page {
text-align: center;
.form-card {
display: inline-block;
margin-top: 0.5em;
max-width: 800px;
padding: 1em;
text-align: center;
}
.crop-card {
width: 100px;
}
}
// Overrides applying only to mobile view. This must be at the end of the overrides file.
// Extra small devices (portrait phones, less than 576px)
@include media-breakpoint-down(xs) {
#maincontainer {
width: 100%;
}
.sidebar {
margin-left: 0;
border-left: none;
padding-left: 0;
}
#map {
height: 300px;
}
.navbar .nav > li {
display: block;
}
.navbar .navbar-form {
padding-left: 0;
padding-right: 0;
.navbar-search {
width: auto;
}
}
#maincontainer {
padding: 10px;
}
.homepage-cards {
.crop-card {
width: 50px;
}
}
.index-cards {
.card {
width: 100%;
margin: 0.5em;
}
}
}

View File

@@ -1,27 +0,0 @@
.photo-grid
background: #DDD
.photo-grid-item
//background: #e6e5e4
//border: 2px solid #b6b5b4
//height: 100px
/* clear fix */
.photo-grid:after
content: ''
display: block
clear: both
/* ---- .photo-grid-item ---- */
.photo-grid-sizer,
.photo-grid-item
//width: 33.333%
.photo-grid-item
float: left
.photo-grid-item img
display: block
max-width: 100%

View File

@@ -1,61 +0,0 @@
.planting
.planting-badges
font-size: 100%
position: absolute
top: 3em
.badge-super-late
background-color: $red
.badge-harvest
background-color: $blue
.planting-super-late
.planting-late
background-color: $beige
.planting-thumbnail
width: 150px
padding: 0em
margin-bottom: 0.5em
margin-top: 0.5em
border: 1px solid darken($beige, 10%)
border-radius: 4px
.badge
font-size: 100%
.planting-full-badges
.badge
font-size: 200%
.planting-name
position: relative
text-align: center
font-size: 150%
top: -0.5em
.planting-quick-actions
position: absolute
left: 142px
top: 6px
.planting-thumbnail-photo
height: 150px
dl.planting-attributes
dt
text-align: left
dd
margin-left: auto
.fact
text-align: center
height: 180px
width: 160px
border: 1px solid lighten($green, 20%)
border-radius: 5%
background: $white
padding: 1em
margin: 0.3em
strong
font-size: 3em
font-align: center
h3
span
display: block
img
height: 50%

View File

@@ -1,14 +0,0 @@
.predictions
.prediction-metric
text-align: center
height: 180px
border: 1px solid lighten($green, 20%)
border-radius: 5%
background: $white
margin: 4px
strong
font-size: 4em
font-align: center
h3
span
display: block

View File

@@ -197,7 +197,8 @@ class CropsController < ApplicationController
def crops
q = Crop.approved.includes(:scientific_names, plantings: :photos)
q = q.popular unless @sort == 'alpha'
q.order("LOWER(crops.name)").includes(:photos).paginate(page: params[:page])
q.order(Arel.sql("LOWER(crops.name)"))
.includes(:photos).paginate(page: params[:page])
end
def requested_crops

View File

@@ -18,8 +18,17 @@ class MembersController < ApplicationController
@flickr_auth = @member.auth('flickr')
@facebook_auth = @member.auth('facebook')
@posts = @member.posts
@gardens = @member.gardens.active.order(:name)
@harvests = @member.harvests
# TODO: Consider shifting all of these onto a member activity model?
@activity = plantings_for_show
.union_all(harvests_for_show)
.union_all(posts_for_show)
.union_all(comments_for_show)
.union_all(photos_for_show)
.union_all(seeds_for_show)
.where(owner_id: @member.id)
.order(event_at: :desc)
.limit(30)
# The garden form partial is called from the "New Garden" tab;
# it requires a garden to be passed in @garden.
@@ -91,4 +100,71 @@ class MembersController < ApplicationController
Member.order(:login_name)
end.confirmed.paginate(page: params[:page])
end
# Queries for the show view/action
def plantings_for_show
Planting.select(
:id,
"'planting' as event_type",
'planted_at as event_at',
:owner_id,
:crop_id,
:slug
)
end
def harvests_for_show
Harvest.select(
:id,
"'harvest' as event_type",
'harvested_at as event_at',
:owner_id,
:crop_id,
:slug
)
end
def posts_for_show
Post.select(
:id,
"'post' as event_type",
'posts.created_at as event_at',
'author_id as owner_id',
'null as crop_id',
:slug
)
end
def comments_for_show
Comment.select(
:id,
"'comment' as event_type",
'comments.created_at as event_at',
'author_id as owner_id',
'null as crop_id',
'null as slug'
)
end
def photos_for_show
Photo.select(
:id,
"'photo' as event_type",
"photos.created_at as event_at",
'photos.owner_id',
'null as crop_id',
'null as slug'
)
end
def seeds_for_show
Seed.select(
:id,
"'seed' as event_type",
"seeds.created_at as event_at",
'seeds.owner_id',
'crop_id',
'slug'
)
end
end

View File

@@ -6,7 +6,7 @@ class NotificationsController < ApplicationController
# GET /notifications
def index
@notifications = Notification.by_recipient(current_member).order(:created_at).page(params[:page])
@notifications = Notification.by_recipient(current_member).order(:created_at).paginate(page: params[:page], per_page: 30)
end
# GET /notifications/1

View File

@@ -41,20 +41,27 @@ class PlantingsController < ApplicationController
end
def new
@planting = Planting.new(planted_at: Time.zone.today)
@planting = Planting.new(
planted_at: Time.zone.today,
owner: current_member,
garden: current_member.gardens.first
)
@seed = Seed.find_by(slug: params[:seed_id]) if params[:seed_id]
# using find_by_id here because it returns nil, unlike find
@crop = Crop.approved.find_by(id: params[:crop_id]) || Crop.new
@garden = Garden.find_by(owner: current_member, id: params[:garden_id]) || Garden.new
@crop = Crop.approved.find_by(id: params[:crop_id]) || Crop.new
if params[:garden_id]
@planting.garden = Garden.find_by(
owner: current_member,
id: params[:garden_id]
)
end
respond_with @planting
end
def edit
# the following are needed to display the form but aren't used
@crop = Crop.new
@garden = Garden.new
@crop = Crop.new
@gardens = @planting.owner.gardens.active.order_by_name
end
def create

View File

@@ -8,7 +8,7 @@ class PostsController < ApplicationController
# GET /posts.json
# GET /posts.rss
def index
@author = Member.find_by(slug: params[:author])
@author = Member.find_by(slug: params[:member_slug])
@posts = posts
respond_with(@posts)
end

View File

@@ -3,9 +3,7 @@ class SessionsController < Devise::SessionsController
def create
super do |_resource|
if Crop.pending_approval.present? && current_member.role?(:crop_wrangler)
flash[:alert] = "There are crops waiting to be wrangled."
end
flash[:alert] = "There are crops waiting to be wrangled." if Crop.pending_approval.present? && current_member.role?(:crop_wrangler)
end
end
end

View File

@@ -60,9 +60,7 @@ module ApplicationHelper
# 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}"
pluralize(collection.size, model.model_name.to_s.downcase)
end
def show_inactive_tickbox_path(type, owner, show_all)

View File

@@ -1,88 +1,126 @@
module ButtonsHelper
include IconsHelper
def garden_plant_something_button(garden)
link_to new_planting_path(garden_id: garden.id), class: "btn btn-default btn-xs btn-primary" do
def garden_plant_something_button(garden, classes: "btn btn-default")
return unless can? :edit, garden
link_to new_planting_path(garden_id: garden.id), class: classes do
planting_icon + ' ' + t('buttons.plant_something_here')
end
end
def garden_mark_active_button(garden)
link_to t('buttons.mark_as_active'),
garden_path(garden, garden: { active: 1 }),
method: :put, class: 'btn btn-default btn-xs'
def plant_something_button
return unless can? :create, Planting
link_to new_planting_path, class: "btn btn-default" do
planting_icon + ' ' + t('buttons.plant_something')
end
end
def garden_mark_inactive_button(garden)
def garden_mark_active_button(garden, classes: 'btn')
link_to t('buttons.mark_as_active'),
garden_path(garden, garden: { active: 1 }),
method: :put, class: classes
end
def garden_mark_inactive_button(garden, classes: 'btn')
link_to t('buttons.mark_as_inactive'),
garden_path(garden, garden: { active: 0 }),
method: :put, class: 'btn btn-default btn-xs',
data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' }
garden_path(garden, garden: { active: 0 }),
method: :put, class: classes,
data: { confirm: 'All plantings associated with this garden will be marked as finished. Are you sure?' }
end
def crop_plant_button(crop)
create_button(Planting,
new_planting_path(params: { crop_id: crop.id }),
planting_icon, t('buttons.plant'))
end
def crop_save_seeds_button(crop)
create_button(Seed,
new_seed_path(params: { crop_id: crop.id }),
seed_icon, t('buttons.save_seeds'))
end
def create_button(model_to_create, path, icon, label)
return unless can?(:create, model_to_create)
link_to path, class: "btn btn-sm" do
icon + ' ' + label
end
end
def crop_edit_button(crop)
edit_button(edit_crop_path(crop))
end
def seed_edit_button(seed)
edit_button(edit_seed_path(seed))
def seed_edit_button(seed, classes: "btn btn-raised btn-info")
edit_button(edit_seed_path(seed), classes: classes)
end
def harvest_edit_button(harvest)
edit_button(edit_harvest_path(harvest))
def harvest_edit_button(harvest, classes: "btn btn-raised btn-info")
edit_button(edit_harvest_path(harvest), classes: classes)
end
def garden_edit_button(garden)
edit_button(edit_garden_path(garden))
def garden_edit_button(garden, classes: "btn btn-raised btn-info")
edit_button(edit_garden_path(garden), classes: classes)
end
def planting_edit_button(planting)
edit_button(edit_planting_path(planting))
def planting_edit_button(planting, classes: "btn btn-raised btn-info")
edit_button(edit_planting_path(planting), classes: classes)
end
def planting_finish_button(planting)
def planting_finish_button(planting, classes: 'btn btn-default btn-secondary')
return unless can?(:edit, planting) || planting.finished
link_to planting_path(planting, planting: { finished: 1 }),
method: :put, class: 'btn btn-default btn-xs append-date' do
method: :put, class: "#{classes} append-date" do
finished_icon + ' ' + t('buttons.mark_as_finished')
end
end
def planting_harvest_button(planting)
return unless planting.active? && can?(:create, Harvest) && can?(:edit, planting)
def seed_finish_button(seed, classes: 'btn btn-default')
return unless can?(:create, Planting) && seed.active?
link_to new_planting_harvest_path(planting), class: "btn btn-default btn-xs" do
harvest_icon + ' ' + t('buttons.harvest')
link_to seed_path(seed, seed: { finished: 1 }), method: :put, class: "#{classes} append-date" do
finished_icon + ' ' + t('buttons.mark_as_finished')
end
end
def planting_save_seeds_button(planting)
def planting_harvest_button(planting, classes: 'btn btn-default')
return unless planting.active? && can?(:create, Harvest) && can?(:edit, planting)
link_to new_planting_harvest_path(planting), class: classes do
harvest_icon + ' ' + t('buttons.record_harvest')
end
end
def planting_save_seeds_button(planting, classes: 'btn btn-default')
return unless can?(:edit, planting)
link_to new_planting_seed_path(planting), class: "btn btn-default btn-xs" do
link_to new_planting_seed_path(planting), class: classes do
seed_icon + ' ' + t('buttons.save_seeds')
end
end
def add_photo_button(model)
def add_photo_button(model, classes: "btn btn-default")
return unless can?(:edit, model) && can?(:create, Photo)
link_to new_photo_path(id: model.id, type: model_type_for_photo(model)),
class: "btn btn-default btn-xs" do
class: classes do
photo_icon + ' ' + t('buttons.add_photo')
end
end
def edit_button(path)
link_to path, class: "btn btn-default btn-xs" do
def edit_button(path, classes: "btn btn-raised btn-info")
link_to path, class: classes do
edit_icon + ' ' + t('buttons.edit')
end
end
def delete_button(model, message: 'are_you_sure')
def delete_button(model, message: 'are_you_sure', classes: 'btn btn-danger')
return unless can? :destroy, model
link_to model, method: :delete, data: { confirm: t(message) }, class: 'btn btn-default btn-xs' do
link_to model, method: :delete, data: { confirm: t(message) }, class: classes do
delete_icon + ' ' + t('buttons.delete')
end
end

View File

@@ -2,19 +2,27 @@ module IconsHelper
include FontAwesome::Sass::Rails::ViewHelpers
def garden_icon
icon('fas', 'square')
image_icon 'home'
end
def planting_icon
icon('fas', 'seedling')
image_icon 'planting'
end
def member_icon
icon('fas', 'user')
end
def harvest_icon
icon('fas', 'carrot')
image_icon 'harvest'
end
def seed_icon
icon('fas', 'heart')
image_icon 'seeds'
end
def comment_icon
icon('fas', 'comment')
end
def finished_icon
@@ -38,7 +46,7 @@ module IconsHelper
end
def blog_icon
icon('fas', 'pen')
image_icon 'post'
end
def perennial_icon
@@ -49,6 +57,14 @@ module IconsHelper
planted_from
end
def delete_association_icon
icon('fas', 'backspace')
end
def like_icon
icon('fas', 'thumbs-up')
end
def sunniness_icon(sunniness)
if sunniness.present?
image_tag("sunniness_#{sunniness}.png", class: 'img', alt: sunniness, width: 55)
@@ -56,4 +72,8 @@ module IconsHelper
image_tag("sunniness_not_specified.png", class: 'img', alt: 'unknown', width: 55)
end
end
def image_icon(icon)
image_tag "icons/#{icon}.svg", class: 'img img-icon'
end
end

View File

@@ -1,50 +1,39 @@
module PhotosHelper
def crop_image_path(crop)
if crop.default_photo.present?
crop.default_photo.thumbnail_url
else
placeholder_image
end
def crop_image_path(crop, full_size: false)
photo_or_placeholder(crop, full_size: full_size)
end
def garden_image_path(garden)
if garden.default_photo.present?
garden.default_photo.thumbnail_url
else
placeholder_image
end
def garden_image_path(garden, full_size: false)
photo_or_placeholder(garden, full_size: full_size)
end
def planting_image_path(planting)
if planting.photos.present?
planting.photos.order(date_taken: :desc).first.thumbnail_url
else
placeholder_image
end
def planting_image_path(planting, full_size: false)
photo_or_placeholder(planting, full_size: full_size)
end
def harvest_image_path(harvest)
if harvest.photos.present?
harvest.photos.order(date_taken: :desc).first.thumbnail_url
elsif harvest.planting.present?
planting_image_path(harvest.planting)
else
placeholder_image
end
def harvest_image_path(harvest, full_size: false)
photo_or_placeholder(harvest, full_size: full_size)
end
def seed_image_path(seed)
if seed.default_photo.present?
seed.default_photo.thumbnail_url
elsif seed.crop.default_photo.present?
seed.crop.default_photo.thumbnail_url
else
placeholder_image
end
def seed_image_path(seed, full_size: false)
photo_or_placeholder(seed, full_size: full_size)
end
private
def photo_or_placeholder(item, full_size: false)
if item.default_photo.present?
item_photo(item, full_size: full_size)
else
placeholder_image
end
end
def item_photo(item, full_size:)
photo = item.default_photo
full_size ? photo.fullsize_url : photo.thumbnail_url
end
def placeholder_image
'placeholder_150.png'
end

View File

@@ -25,7 +25,7 @@ module PlantingsHelper
elsif planting.planted_from.present?
"#{planting.owner} planted #{planting.planted_from.pluralize}."
else
"#{planting.owner}."
"#{planting.owner} planted #{planting.crop}."
end
end

View File

@@ -0,0 +1,7 @@
module PostsHelper
def display_post_truncated(post)
length = 300
truncate(strip_tags(post.body), length: length,
separator: ' ', omission: '... ') { link_to "Read more", post_path(post) }
end
end

View File

@@ -1,3 +1,4 @@
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
self.per_page = 12
end

View File

@@ -18,4 +18,8 @@ class Comment < ApplicationRecord
)
end
end
def to_s
"#{author.login_name} commented on #{post.subject}"
end
end

View File

@@ -27,7 +27,7 @@ class Crop < ApplicationRecord
## Scopes
scope :recent, -> { approved.order(created_at: :desc) }
scope :toplevel, -> { approved.where(parent_id: nil) }
scope :popular, -> { approved.order("plantings_count desc, lower(name) asc") }
scope :popular, -> { approved.order(Arel.sql("plantings_count desc, lower(name) asc")) }
scope :pending_approval, -> { where(approval_status: "pending") }
scope :approved, -> { where(approval_status: "approved") }
scope :rejected, -> { where(approval_status: "rejected") }
@@ -47,17 +47,15 @@ class Crop < ApplicationRecord
validate :must_have_meaningful_reason_for_rejection
## Wikipedia urls are only necessary when approving a crop
validates :en_wikipedia_url,
format: {
with: %r{\Ahttps?:\/\/en\.wikipedia\.org\/wiki\/[[:alnum:]%_\.()-]+\z},
message: 'is not a valid English Wikipedia URL'
},
if: :approved?
format: {
with: %r{\Ahttps?:\/\/en\.wikipedia\.org\/wiki\/[[:alnum:]%_\.()-]+\z},
message: 'is not a valid English Wikipedia URL'
},
if: :approved?
####################################
# Elastic search configuration
if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
searchkick word_start: %i(name alternate_names scientific_names), case_sensitive: false
end
searchkick word_start: %i(name alternate_names scientific_names), case_sensitive: false if ENV["GROWSTUFF_ELASTICSEARCH"] == "true"
def planting_photos
Photo.joins(:plantings).where("plantings.crop_id": id)
@@ -117,7 +115,7 @@ class Crop < ApplicationRecord
end
def annual?
!perennial
perennial == false
end
def interesting?

View File

@@ -19,24 +19,24 @@ class Garden < ApplicationRecord
default_scope { joins(:owner) } # Ensures owner exists
scope :active, -> { where(active: true) }
scope :inactive, -> { where(active: false) }
scope :order_by_name, -> { order("lower(name) asc") }
scope :order_by_name, -> { order(Arel.sql("lower(name) asc")) }
validates :location, length: { maximum: 255 }
validates :slug, uniqueness: true
validates :name, uniqueness: { scope: :owner_id }
validates :name,
format: {
with: /\A\w+[\w ()]+\z/
},
length: { maximum: 255 }
format: {
with: /\A\w+[\w ()]+\z/
},
length: { maximum: 255 }
validates :area,
numericality: {
only_integer: false,
greater_than_or_equal_to: 0
},
allow_nil: true
numericality: {
only_integer: false,
greater_than_or_equal_to: 0
},
allow_nil: true
AREA_UNITS_VALUES = {
"square metres" => "square metre",

View File

@@ -54,8 +54,8 @@ class Member < ApplicationRecord
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable, :omniauthable
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable, :omniauthable
# set up geocoding
geocoded_by :location
@@ -69,18 +69,18 @@ class Member < ApplicationRecord
# Requires acceptance of the Terms of Service
validates :tos_agreement, acceptance: { allow_nil: true, accept: true }
validates :login_name,
length: {
minimum: 2, maximum: 25, message: "should be between 2 and 25 characters long"
},
exclusion: {
in: %w(growstuff admin moderator staff nearby), message: "name is reserved"
},
format: {
with: /\A\w+\z/, message: "may only include letters, numbers, or underscores"
},
uniqueness: {
case_sensitive: false
}
length: {
minimum: 2, maximum: 25, message: "should be between 2 and 25 characters long"
},
exclusion: {
in: %w(growstuff admin moderator staff nearby), message: "name is reserved"
},
format: {
with: /\A\w+\z/, message: "may only include letters, numbers, or underscores"
},
uniqueness: {
case_sensitive: false
}
#
# Triggers

View File

@@ -9,9 +9,9 @@ class Photo < ApplicationRecord
# creates a relationship for each assignee type
PHOTO_CAPABLE.each do |type|
has_many type.downcase.pluralize.to_s.to_sym,
through: :photographings,
source: :photographable,
source_type: type
through: :photographings,
source: :photographable,
source_type: type
end
default_scope { joins(:owner) } # Ensures the owner still exists

View File

@@ -33,7 +33,7 @@ class Planting < ApplicationRecord
##
## Scopes
default_scope { joins(:owner) } # Ensures the owner still exists
scope :active, -> { where(finished_at: nil) }
scope :active, -> { where('finished <> true').where('finished_at IS NULL OR finished_at < ?', Time.zone.now) }
scope :interesting, -> { has_photos.one_per_owner.order(planted_at: :desc) }
scope :recent, -> { order(created_at: :desc) }
scope :one_per_owner, lambda {
@@ -45,7 +45,7 @@ class Planting < ApplicationRecord
##
## Delegations
delegate :name, :en_wikipedia_url, :default_scientific_name, :plantings_count,
to: :crop, prefix: true
to: :crop, prefix: true
##
## Validations

View File

@@ -48,6 +48,10 @@ class Post < ApplicationRecord
end
end
def to_s
subject
end
private
def update_crops_posts_association

View File

@@ -52,6 +52,8 @@ class Seed < ApplicationRecord
scope :tradable, -> { where.not(tradable_to: 'nowhere') }
scope :interesting, -> { tradable.has_location }
scope :has_location, -> { joins(:owner).where.not("members.location": nil) }
scope :recent, -> { order(created_at: :desc) }
scope :active, -> { where('finished_at < ?', Time.zone.now) }
def default_photo
photos.order(created_at: :desc).first

View File

@@ -21,7 +21,6 @@ module Api
# Predictions
attribute :expected_lifespan
attribute :finish_predicted_at
attribute :percentage_grown
attribute :first_harvest_date
attribute :last_harvest_date

View File

@@ -1,5 +1,12 @@
- content_for :title, 'Admin'
- content_for :breadcrumbs do
%nav{"aria-label" => "breadcrumb"}
%ol.breadcrumb
%li.breadcrumb-item
= link_to 'Home', root_path
%li.breadcrumb-item.active= link_to 'Admin', admin_path
%h2 Manage
.row

View File

@@ -1,32 +1,37 @@
= form_for @alternate_name, html: { class: 'form-horizontal', role: "form" } do |f|
- if @alternate_name.errors.any?
#error_explanation
%h2
= pluralize(@alternate_name.errors.size, "error")
prohibited this alternate_name from being saved:
%ul
- @alternate_name.errors.full_messages.each do |msg|
%li= msg
.card.col-md-8.col-lg-7.mx-auto.float-none.white.z-depth-1.py-2.px-2
.card-body
- if content_for? :title
%h1.h2-responsive.text-center
%strong=yield :title
= form_for @alternate_name, html: { class: 'form-horizontal', role: "form" } do |f|
- if @alternate_name.errors.any?
#error_explanation
%h2
= pluralize(@alternate_name.errors.size, "error")
prohibited this alternate_name from being saved:
%ul
- @alternate_name.errors.full_messages.each do |msg|
%li= msg
%p
%span.help-block
For detailed crop wrangling guidelines, please consult the
= link_to "crop wrangling guide", "http://wiki.growstuff.org/index.php/Crop_wrangling"
on the Growstuff wiki.
%p
%span.help-block
For detailed crop wrangling guidelines, please consult the
= link_to "crop wrangling guide", "http://wiki.growstuff.org/index.php/Crop_wrangling"
on the Growstuff wiki.
.form-group
= f.label :crop_id, class: 'control-label col-md-2'
.col-md-8
= collection_select(:alternate_name, :crop_id,
Crop.all, :id, :name,
{ selected: @alternate_name.crop_id || @crop.id },
class: 'form-control')
.form-group
= f.label :crop_id, class: 'control-label col-md-2'
.col-md-8
= collection_select(:alternate_name, :crop_id,
Crop.all, :id, :name,
{ selected: @alternate_name.crop_id || @crop.id },
class: 'form-control')
.form-group
= f.label :name, class: 'control-label col-md-2'
.col-md-8
= f.text_field :name, class: 'form-control'
.form-group
= 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'
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit 'Save', class: 'btn btn-primary'

View File

@@ -1,20 +1,26 @@
= form_for(@comment, html: { class: "form-horizontal", role: "form" }) do |f|
- if @comment.errors.any?
#error_explanation
%h2
= pluralize(@comment.errors.size, "error")
prohibited this comment from being saved:
%ul
- @comment.errors.full_messages.each do |msg|
%li= msg
.card.col-md-8.col-lg-7.mx-auto.float-none.white.z-depth-1.py-2.px-2
.card-body
- if content_for? :title
%h1.h2-responsive.text-center
%strong=yield :title
= form_for(@comment, html: { class: "form-horizontal", role: "form" }) do |f|
- if @comment.errors.any?
#error_explanation
%h2
= pluralize(@comment.errors.size, "error")
prohibited this comment from being saved:
%ul
- @comment.errors.full_messages.each do |msg|
%li= msg
.form-group
= f.label :body, "Your comment:"
= f.text_area :body, rows: 6, class: 'form-control', autofocus: 'autofocus'
%span.help-block
= render partial: "shared/markdown_help"
.actions
= f.submit 'Post comment', class: 'btn btn-primary'
- if defined?(@post)
.field
= f.hidden_field :post_id, value: @post.id
.md-form
= f.text_area :body, rows: 6, class: 'form-control md-textarea', autofocus: 'autofocus'
= f.label :body, "Your comment:"
%span.help-block
= render partial: "shared/markdown_help"
.actions.text-right
= f.submit 'Post comment', class: 'btn btn-primary'
- if defined?(@post)
.field
= f.hidden_field :post_id, value: @post.id

View File

@@ -1,10 +1,22 @@
.well
.comment
.card.comment
.card-body
.row
.col-md-1
= render partial: "members/avatar", locals: { member: comment.author }
.col-md-11
.comment-meta
.col-md-1= render "members/tiny", member: comment.author
.col-md-11.border-left
- if can?(:edit, comment) || can?(:destroy, comment)
.dropdown.float-right
%button#comment-edit-button.btn.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", type: "button"} Actions
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "comment-edit-button"}
- if can? :edit, comment
= link_to edit_comment_path(comment), class: 'dropdown-item' do
= edit_icon
Edit
- if can? :destroy, comment
= link_to comment, method: :delete,
data: { confirm: 'Are you sure?' }, class: 'dropdown-item text-danger' do
= delete_icon
Delete
.comment-meta.text-muted
Posted by
- if comment.author.deleted?
Member Deleted
@@ -20,10 +32,3 @@
:growstuff_markdown
#{ strip_tags comment.body }
- if can?(:edit, comment) || can?(:destroy, comment)
.comment-actions
- if can? :edit, comment
= link_to 'Edit', edit_comment_path(comment), class: 'btn btn-default btn-xs'
- if can? :destroy, comment
= link_to 'Delete', comment, method: :delete,
data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs'

View File

@@ -1,20 +0,0 @@
= content_for :title, "Recent comments"
.pagination
= page_entries_info @comments
= will_paginate @comments
- @comments.each do |comment|
%h2
Comment on
= link_to comment.post.subject, comment.post
= render partial: "single", locals: { comment: comment }
.pagination
= page_entries_info @comments
= will_paginate @comments
%p
Subscribe to the #{ENV['GROWSTUFF_SITE_NAME']}
= succeed "." do
= link_to "comments RSS feed", comments_path(format: 'rss')

View File

@@ -1,6 +1,10 @@
= content_for :title, "New comment"
= render partial: "posts/single", locals: { post: @post || @comment.post, subject: true }
%section.blog-post
.card.post{ id: "post-#{@post.id}" }
.card-header
%h2.display-3= @post.subject
.card-body= render "posts/single", post: @post || @comment.post, subject: true
= render partial: "posts/comments", locals: { post: @post || @comment.post }

View File

@@ -1,17 +0,0 @@
= 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: og_description(@comment.post.body))
= 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 }
%h2 Showing 1 comment
= render partial: "single", locals: { comment: @comment }
= link_to "View all comments", post_path(@comment.post)

View File

@@ -1,16 +1,16 @@
.crop-actions
.btn-group
- if @crop.approved? && signed_in?
.crop-actions
- if can? :create, Planting
= link_to new_planting_path(crop_id: crop.id), class: 'btn btn-default' do
= link_to new_planting_path(crop_id: crop.id), class: 'btn btn-sm' do
= planting_icon
= t('buttons.plant_crop', crop_name: crop.name)
- if can? :create, Harvest
= link_to new_harvest_path(crop_id: crop.id), class: 'btn btn-default' do
= link_to new_harvest_path(crop_id: crop.id), class: 'btn btn-sm' do
= harvest_icon
= t('buttons.harvest_crop', crop_name: crop.name)
- if can? :create, Seed
= link_to new_seed_path(crop_id: crop.id), class: 'btn btn-default' do
= link_to new_seed_path(crop_id: crop.id), class: 'btn btn-sm' do
= seed_icon
= t('buttons.add_seed_to_stash', crop_name: crop.name)

View File

@@ -3,14 +3,25 @@
- if crop.alternate_names.empty?
%p None known.
- else
%ul
%ul.list-group.list-group-flush
- crop.alternate_names.each do |an|
%li
= an.name
%li.list-group-item.d-flex.justify-content-between.align-items-center
- if can? :edit, an
= link_to 'Edit', edit_alternate_name_path(an), class: 'btn btn-default btn-xs'
- if can? :destroy, an
= link_to 'Delete', an, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs'
%p
- if can? :edit, crop
= link_to 'Add', new_alternate_name_path(crop_id: crop.id), class: 'btn btn-default btn-xs'
.dropdown.planting-actions
%a#crop-actions-altnames.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", :type => "button", :href => '#'}
= an.name
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "crop-actions-altnames"}
- if can? :edit, an
= link_to edit_alternate_name_path(an), class: 'dropdown-item' do
= edit_icon
= t('.edit')
- if can? :destroy, an
= link_to an, method: :delete, data: { confirm: 'Are you sure?' }, class: 'dropdown-item' do
= delete_icon
= t('.delete')
- else
= an.name
%p.text-right
- if can? :edit, crop
= link_to 'Add', new_alternate_name_path(crop_id: crop.id), class: 'btn btn-default btn-xs'

View File

@@ -0,0 +1,30 @@
.card.card-crop
.crop-image
= link_to image_tag(crop_image_path(crop, full_size: true),
alt: '',
class: 'img img-card'),
crop
.card-body
%h3.card-title= link_to crop, crop
%p.crop-sci-name= crop.default_scientific_name
- if crop.annual? && crop.median_lifespan.present?
%p.card-text
Median Lifespan
%b= crop.median_lifespan
days
- unless crop.median_days_to_first_harvest.nil?
%p.card-text
First harvest expected
%b= crop.median_days_to_first_harvest
days after planting
- if crop.annual? && crop.median_days_to_last_harvest.present?
%p.card-text
Last harvest expected
%b= crop.median_days_to_last_harvest
days after planting
- if member_signed_in?
.card-footer
= crop_plant_button(crop)
= crop_save_seeds_button(crop)

View File

@@ -1,22 +1,36 @@
%h4 Find #{crop.name} seeds
- if crop.seeds.empty?
%p
There are no seeds available to trade on Growstuff right now.
- else
%ul
- crop.seeds.tradable.each do |seed|
%li
= link_to "#{seed.owner} will trade #{seed.tradable_to}.", seed_path(seed)
= render partial: 'members/location', locals: { member: seed.owner }
%p
= link_to "View all #{crop.name} seeds", crop_seeds_path(crop)
%p
= link_to "Purchase seeds via Ebay",
crop_ebay_seeds_url(crop),
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)
.card
.card-header
%h5.card-title Find #{crop.name} seeds
- if crop.seeds.empty?
.card-body
%p There are no seeds available to trade on Growstuff right now.
- else
= render partial: 'shared/signin_signup', locals: { to: 'list your seeds to trade' }
%ul.list-group
- crop.seeds.tradable.each do |seed|
%li.list-group-item
= link_to "#{seed.owner} will trade #{seed.tradable_to}.", seed_path(seed), class: 'card-link'
= render 'members/location', member: seed.owner
%li.list-group-item.d-flex.justify-content-between.align-items-center
= link_to crop_seeds_path(crop), class: 'card-link' do
= seed_icon
View all #{crop.name} seeds
%span.badge.badge-primary.badge-pill=crop.seeds.size
%ul.list-group
%li.list-group-item
= link_to crop_ebay_seeds_url(crop), class: 'card-link',
target: "_blank",
rel: "noopener noreferrer" do
= icon 'fas', 'money-check-alt'
Purchase seeds via Ebay
- if crop.approved?
- if current_member
%li.list-group-item
= link_to new_seed_path(crop_id: crop.id), class: 'card-link' do
= seed_icon
List #{crop.name} seeds to trade
- else
%li.list-group-item.active
= icon 'fas', 'user'
= render partial: 'shared/signin_signup', locals: { to: 'list your seeds to trade' }

View File

@@ -1,6 +1,6 @@
= form_for @crop, html: { class: 'form-horizontal', role: "form" } do |f|
= bootstrap_form_for(@crop) do |f|
- if @crop.errors.any?
#error_explanation
#error_explanation.alert.alert-warning{role: "alert"}
%h3
= pluralize(@crop.errors.size, "error")
prohibited this crop from being saved:
@@ -8,121 +8,99 @@
- @crop.errors.full_messages.each do |msg|
%li= msg
-# Handy link to crop wrangling policy/style guide, shown to wranglers only
- if can? :wrangle, @crop
%p
%span.help-block
For detailed crop wrangling guidelines, please consult the
= link_to "crop wrangling guide", "http://wiki.growstuff.org/index.php/Crop_wrangling"
on the Growstuff wiki.
.card.col-12.col-md-8.mx-auto.float-none.white
.card-header
- if content_for? :title
%h1.h2-responsive.text-center
%strong=yield :title
.card-body
-# Handy link to crop wrangling policy/style guide, shown to wranglers only
- if can? :wrangle, @crop
%p
%span.help-block
For detailed crop wrangling guidelines, please consult the
= link_to "crop wrangling guide", "http://wiki.growstuff.org/index.php/Crop_wrangling"
on the Growstuff wiki.
-# Everyone (wranglers and requesters) sees the basic info section
%h2 Basic information
-# Everyone (wranglers and requesters) sees the basic info section
%h2 Basic information
.form-group#new_crop
= f.label :name, class: 'control-label col-md-2'
.col-md-8
= f.text_field :name, class: 'form-control'
.form-group#new_crop
= f.text_field :name
%span.help-block
The common name for the crop, in English (required).
- if can? :wrangle, @crop
Wranglers: please ensure this is singular, and capitalize
proper nouns only.
.form-group
= f.label :perennial, 'Lifespan', class: 'control-label col-md-2'
.col-md-8
= f.radio_button(:perennial, false)
= f.label(:perennial_false, "Annual")
%span.help-block Living and reproducing in a single year or less
= f.radio_button(:perennial, true)
= f.label(:perennial_true, "Perennial")
%span.help-block Living more than two years
%h2 Lifespan
%p
= f.radio_button(:perennial, false, label: 'Annual')
%span.help-block Living and reproducing in a single year or less
%p
= f.radio_button(:perennial, true, label: "Perennial")
%span.help-block Living more than two years
.form-group
= f.label :en_wikipedia_url, 'Wikipedia URL', class: 'control-label col-md-2'
.col-md-8
= f.text_field :en_wikipedia_url, class: 'form-control', id: "en_wikipedia_url"
= f.text_field :en_wikipedia_url, id: "en_wikipedia_url", label: 'Wikipedia URL'
%span.help-block
Link to the crop's page on the English language Wikipedia (required).
-# Only crop wranglers see the crop hierarchy (for now)
- if can? :wrangle, @crop
.form-group
= f.label :parent_id, 'Parent crop', class: 'control-label col-md-2'
.col-md-8
= collection_select(:crop, :parent_id, Crop.all.order(:name), :id, :name,
{ include_blank: true }, class: 'form-control')
-# Only crop wranglers see the crop hierarchy (for now)
- if can? :wrangle, @crop
= f.collection_select(:parent_id, Crop.all.order(:name), :id, :name,
{ include_blank: true, label: 'Parent crop'})
%span.help-block Optional. For setting up crop hierarchies for varieties etc.
-# Everyone (wranglers and requesters) gets to add scientific names
%h2
Scientific names
= button_tag "+", id: "add-sci_name-row", type: "button"
= button_tag "-", id: "remove-sci_name-row", type: "button"
-# Everyone (wranglers and requesters) gets to add scientific names
%h2 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.name, id: "sci_name[#{index + 1}]", class: 'form-control'
%span.help-block Scientific name of crop.
.col-md-2
.form-group#scientific_names
- @crop.scientific_names.each.with_index do |sci, index|
.template.col-12{ id: "sci_template[#{index + 1}]" }
.col-2
= label_tag :scientific_names, "Scientific name #{index + 1}:", class: 'control-label'
.col-8
= text_field_tag "sci_name[#{index + 1}]", sci.name, id: "sci_name[#{index + 1}]", class: 'form-control'
%span.help-block Scientific name of crop.
%h2 Alternate names
= button_tag "+", id: "add-alt_name-row", type: "button"
= button_tag "-", id: "remove-alt_name-row", type: "button"
%h2
Alternate names
= button_tag "+", id: "add-alt_name-row", type: "button"
= button_tag "-", id: "remove-alt_name-row", type: "button"
.form-group#alternate_names
- @crop.alternate_names.each.with_index do |alt, index|
.template.col-12{ id: "alt_template[#{index + 1}]" }
.col-2
= label_tag :alternate_names, "Alternate name #{index + 1}:", class: 'control-label'
.col-8
= text_field_tag "alt_name[#{index + 1}]", alt.name, id: "alt_name[#{index + 1}]", class: 'form-control'
%span.help-block Alternate name of crop.
.col-2
.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
= label_tag :alternate_names, "Alternate name #{index + 1}:", class: 'control-label'
.col-md-8
= text_field_tag "alt_name[#{index + 1}]", alt.name, id: "alt_name[#{index + 1}]", class: 'form-control'
%span.help-block Alternate name of crop.
.col-md-2
-# This is used for comments from crop requesters. We need to show it
-# to everyone, but we don't include it on new crops from wranglers.
-# This is used for comments from crop requesters. We need to show it
-# to everyone, but we don't include it on new crops from wranglers.
- if (can?(:wrangle, @crop) && @crop.requester) || (cannot?(:wrangle, @crop) && @crop.new_record?)
%h2 Crop request notes
= f.text_area :request_notes, rows: 3, id: 'request_notes', label: 'Comments'
- if (can?(:wrangle, @crop) && @crop.requester) || (cannot?(:wrangle, @crop) && @crop.new_record?)
%h2 Crop request notes
.form-group
= f.label :request_notes, 'Comments', class: 'control-label col-md-2'
.col-md-8
= f.text_area :request_notes, rows: 3, class: 'form-control', id: 'request_notes'
-# A final explanation of what's going to happen next, for crop requesters
- unless can? :wrangle, @crop
%p
When you submit this form, your suggestion will be sent to our team of
volunteer crop wranglers for review. We'll let you know the outcome as soon as we can.
-# A final explanation of what's going to happen next, for crop requesters
- unless can? :wrangle, @crop
%p
When you submit this form, your suggestion will be sent to our team of
volunteer crop wranglers for review. We'll let you know the outcome as soon as we can.
-# Now, for crop wranglers, let's have approval/rejection at the bottom of the page
- if can?(:wrangle, @crop) && @crop.requester
%h2 Approve or reject pending crops
= f.select(:approval_status, @crop.approval_statuses, {})
= f.select(:reason_for_rejection, @crop.reasons_for_rejection, include_blank: true)
-# Now, for crop wranglers, let's have approval/rejection at the bottom of the page
- if can?(:wrangle, @crop) && @crop.requester
%h2 Approve or reject pending crops
.form-group
= f.label :approval_status, 'Approval status', class: 'control-label col-md-2'
.col-md-8
= f.select(:approval_status, @crop.approval_statuses, {}, class: 'form-control')
.form-group
= f.label :reason_for_rejection, 'Reason for rejection', class: 'control-label col-md-2'
.col-md-8
= f.select(:reason_for_rejection, @crop.reasons_for_rejection, include_blank: true, class: 'form-control')
.form-group
= f.label :rejection_notes, 'Rejection notes', class: 'control-label col-md-2'
.col-md-8
= f.text_area :rejection_notes, rows: 3, class: 'form-control'
= f.text_area :rejection_notes, rows: 3
%span.help-block
Please provide additional notes why this crop request was rejected if the above reasons do not apply.
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit 'Save', class: 'btn btn-primary'
.card-footer
.text-right= f.submit 'Save'

View File

@@ -1,20 +1,22 @@
%h4 #{crop.name.capitalize} harvests
- if crop.harvests.empty?
%p
Nobody has harvested this crop yet.
- else
%ul
- crop.harvests.order(harvested_at: :desc).limit(3).each do |harvest|
%li
= link_to "#{harvest.owner} harvested #{display_quantity(harvest)}.", harvest_path(harvest)
= render 'members/location', member: harvest.owner
%small
= distance_of_time_in_words(harvest.harvested_at, Time.zone.now)
ago.
%p
= link_to "View all #{crop.name} harvests", crop_harvests_path(crop)
- if crop.approved?
- if current_member
%p= link_to "Harvest #{crop.name}", new_harvest_path(crop_id: crop.id)
- else
= render partial: 'shared/signin_signup', locals: { to: "track your #{crop.name} harvests" }
.card
.card-body
%h3 #{crop.name.capitalize} harvests
- if crop.harvests.empty?
%p Nobody has harvested this crop yet.
- unless crop.harvests.empty?
%ul.list-group.list-group-flush
- crop.harvests.order(harvested_at: :desc).limit(3).each do |harvest|
%li.list-group-item
= link_to harvest_path(harvest), class: 'card-link' do
= harvest_icon
#{harvest.owner} harvested #{display_quantity(harvest)}.
.float-right= render 'members/location', member: harvest.owner
.harvest-timeago
%small #{distance_of_time_in_words(harvest.harvested_at, Time.zone.now)} ago.
.card-footer
%p= link_to "View all #{crop.name} harvests", crop_harvests_path(crop), class: 'card-link'
- if crop.approved?
- if current_member
%p= link_to "Harvest #{crop.name}", new_harvest_path(crop_id: crop.id), class: 'btn btn-block'
- else
= render partial: 'shared/signin_signup', locals: { to: "track your #{crop.name} harvests" }

View File

@@ -1,36 +0,0 @@
.well
.row
.col-md-4
= link_to image_tag(crop_image_path(crop),
alt: '',
class: 'img crop-image'),
crop
.col-md-8
%h3{ style: 'padding-top: 0px; margin-top: 0px' }
= link_to crop, crop
%p
%b Scientific name:
= crop.default_scientific_name
- if crop.annual? && crop.median_lifespan.present?
%p
Median Lifespan
%b= crop.median_lifespan
days
- unless crop.median_days_to_first_harvest.nil?
%p
First harvest expected
%b= crop.median_days_to_first_harvest
days after planting
- if crop.annual? && crop.median_days_to_last_harvest.present?
%p
Last harvest expected
%b= crop.median_days_to_last_harvest
days after planting
- if can? :create, Planting
= link_to "Plant #{crop.name}", new_planting_path(params: { crop_id: crop.id }), class: 'btn btn-primary'
- if can? :create, Seed
= link_to "Add #{crop.name} seeds to stash", new_seed_path(params: { crop_id: crop.id }), class: 'btn btn-primary'

View File

@@ -1,10 +1,9 @@
- [Planting, Harvest, Seed].each do |model_name|
.row
.col-md-12
%h3
= @crop.name
= t("activerecord.models.#{model_name.to_s.downcase}.other")
.row
- photos.by_model(model_name).limit(6).each do |photo|
.col-md-2.six-across
.thumbnail= link_to image_tag(photo.thumbnail_url, alt: photo.title, class: 'img'), photo
- if @crop.photos.size.positive?
%h2 #{photo_icon} Photos
- [Planting, Harvest, Seed].each do |model_name|
- if photos.by_model(model_name).size.positive?
%h3 #{@crop.name.capitalize} #{t("activerecord.models.#{model_name.to_s.downcase}.other")}
= render 'photos/gallery', photos: photos.by_model(model_name).limit(8)
= link_to 'more photos »', crop_photos_path(@crop), class: 'btn'
%hr/

View File

@@ -1,20 +1,17 @@
%h4 See who's planted #{crop.name.pluralize}
- if crop.plantings.empty?
%p
Nobody has planted this crop yet.
- else
%ul
- crop.plantings.order(planted_at: :desc).limit(3).each do |planting|
%li
= link_to planting, planting_path(planting)
= render partial: 'members/location', locals: { member: planting.owner }
%small
= distance_of_time_in_words(planting.created_at, Time.zone.now)
ago.
%p
= link_to "View all #{crop.name} plantings", crop_plantings_path(crop)
- if crop.approved?
- if current_member
%p= link_to "Plant #{crop.name}", new_planting_path(crop_id: crop.id)
- else
= render partial: 'shared/signin_signup', locals: { to: "track your #{crop.name} plantings" }
.card
.card-body
%h3 See who's planted #{crop.name.pluralize}
- unless crop.plantings.empty?
%ul.list-group.list-group-flush
- crop.plantings.order(planted_at: :desc).limit(5).each do |planting|
%li.list-group-item
= link_to planting, class: 'card-link' do
= planting_icon
= planting
.float-right= render 'members/location', member: planting.owner
.card-footer
- if crop.approved?
- if current_member
%p= link_to "Plant #{crop.name}", new_planting_path(crop_id: crop.id), class: 'btn btn-block'
- else
= render partial: 'shared/signin_signup', locals: { to: "track your #{crop.name} plantings" }

View File

@@ -13,10 +13,11 @@
- else
.pagination
= page_entries_info @posts
= will_paginate @posts, params: { anchor: "posts" }
= render 'layouts/pagination', collection: @posts
- @posts.each do |post|
= render partial: "posts/single", locals: { post: post, subject: true }
= render 'posts/preview', post: post
.pagination
= page_entries_info @posts
= will_paginate @posts, params: { anchor: "posts" }
= render 'layouts/pagination', collection: @posts

View File

@@ -1,32 +1,49 @@
.predictions
%h3
= icon 'fas', 'magic'
Predictions
.card-deck.mx-auto.predictions
- unless crop.perennial.nil?
.row
.col-md-12
%p
#{crop.name} is
.col
.card.predictions-card
.card-body.text-center
%h3
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
- if crop.perennial == true
Perennial
- elsif crop.perennial == false
Annual
%p.display-1
%i.far.fa-calendar
- if crop.perennial == true
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
a perennial crop
(living more than two years)
%small living more than two years
- elsif crop.perennial == false
= link_to 'https://en.wikipedia.org/wiki/Annual_vs._perennial_plant_evolution' do
an annual crop
(living and reproducing in a single year or less)
.row
- if crop.annual? && crop.median_lifespan.present?
.prediction-metric.col-md-3.col-xs-5
%h3 Median lifespan
%strong= crop.median_lifespan
%span days
%small living and reproducing in a single year or less
- if crop.median_days_to_first_harvest.present?
.prediction-metric.col-md-3.col-xs-5
%h3 First harvest expected
%strong= crop.median_days_to_first_harvest
%span days after planting
- if crop.annual? && crop.median_lifespan.present?
.col
.card.predictions-card
.card-body.text-center
%h3 Median lifespan
%p.display-1= crop.median_lifespan
%i.fas.fa-sun-o.fa-5x.pt-3.amber-text
%span days
- if crop.median_days_to_first_harvest.present?
.col
.card.predictions-card
.card-body.text-center
%h3 First harvest expected
%p.display-1= crop.median_days_to_first_harvest
%span days after planting
- if crop.annual? && crop.median_days_to_last_harvest.present?
.col
.card.predictions-card
.card-body.text-center
%h3 Last harvest expected
%p.display-1= crop.median_days_to_last_harvest
%span days after planting
- if crop.annual? && crop.median_days_to_last_harvest.present?
.prediction-metric.col-md-3.col-xs-5
%h3 Last harvest expected
%strong= crop.median_days_to_last_harvest
%span days after planting

View File

@@ -3,14 +3,23 @@
- if crop.scientific_names.empty?
%p None known.
- else
%ul
%ul.list-group.list-group-flush
- crop.scientific_names.each do |sn|
%li
= sn.name
%li.list-group-item.d-flex.justify-content-between.align-items-center
- if can? :edit, sn
= link_to 'Edit', edit_scientific_name_path(sn), class: 'btn btn-default btn-xs'
- if can? :destroy, sn
= link_to 'Delete', sn, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs'
%p
- if can? :edit, crop
= link_to 'Add', new_scientific_name_path(crop_id: crop.id), class: 'btn btn-default btn-xs'
.dropdown.planting-actions
%a#planting-actions-scinames.dropdown-toggle.card-link{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", :type => "button", :href => '#'}= sn.name
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "planting-actions-button"}
= link_to edit_scientific_name_path(sn), class: 'dropdown-item' do
= edit_icon
= t('.edit')
.dropdown-divider
= link_to sn, method: :delete, data: { confirm: 'Are you sure?' }, class: 'dropdown-item text-danger' do
= delete_icon
= t('.delete')
- else
= sn.name
%p.text-right
- if can? :edit, crop
= link_to 'Add', new_scientific_name_path(crop_id: crop.id), class: 'btn btn-default btn-xs'

View File

@@ -1,9 +1,6 @@
= form_tag search_crops_path, method: :get, id: 'navbar-search' do
= label_tag :term, "Search crop database:", class: 'sr-only'
.input
.input-group
= text_field_tag 'term', nil, class: 'search-query input-medium form-control', placeholder: 'Search crops'
.input-group-btn
%button.btn.btn-default{ style: "height: 34px;" }
= submit_tag "Search", class: 'btn sr-only'
%span.glyphicon.glyphicon-search
= form_tag search_crops_path, method: :get, class: 'form-inline', id: 'navbar-search' do
.input-group
%input.form-control{name: 'term', "aria-label" => "Search crops", placeholder: "Search crops", type: "search", id: 'term' }/
%button.btn.btn-default.text-white{type: "submit"}
= icon 'fas', 'search'
.sr-only Search

View File

@@ -1,18 +1,10 @@
- cache cache_key_for(Crop, crop.id) do
.thumbnail
.crop-thumbnail
- if crop
= link_to image_tag(crop_image_path(crop),
alt: crop.name, class: 'img'),
crop
.cropinfo
.cropname
= link_to crop.name, crop
- unless crop.scientific_names.empty?
.scientificname
= crop.scientific_names.first.name
- if crop.annual? && crop.median_lifespan.present?
.planting-lifespan
lifespan
%strong= crop.median_lifespan
days
.card.card-crop
.crop-image
= link_to image_tag(crop_image_path(crop, full_size: true),
alt: crop.name,
class: 'img img-card'),
crop
.card-body
%h3.text-center.crop-name= link_to crop, crop
%p.small.crop-sci-name.text-center= crop.default_scientific_name

View File

@@ -1,9 +1,17 @@
- if can?(:edit, crop) || can?(:destroy, crop)
%h4 Crop wrangling
%p
You are a
= succeed "." do
.alert.alert-success{role: "alert"}
%h4 Crop wrangling
%p
You are a
%strong CROP WRANGLER
.dropdown.crop-actions
%a#crop-actions-button.btn.btn-info.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", :type => "button", href: '#'} Actions
.dropdown-menu.dropdown-menu-xs{"aria-labelledby" => "crop-actions-button"}
= link_to edit_crop_path(crop), class: 'dropdown-item' do
= edit_icon
= t('.edit')
- if can? :destroy, crop
.dropdown-divider
= delete_button(crop, classes: 'dropdown-item text-danger')
%p= crop_edit_button(crop) if can? :edit, crop
%p= delete_button(crop) if can? :destroy, crop

View File

@@ -1,42 +1,38 @@
- content_for :title, t('.title')
- content_for :subtitle, t('.subtitle', crops_size: @crops.size)
- if can? :wrangle, Crop
= link_to 'Wrangle Crops', wrangle_crops_path, class: 'btn btn-primary'
- content_for :buttonbar do
- if can? :wrangle, Crop
= link_to 'Wrangle Crops', wrangle_crops_path, class: 'btn btn-secondary'
- if can? :create, Crop
= link_to 'Add New Crop', new_crop_path, class: 'btn btn-primary'
- if @num_requested_crops && @num_requested_crops.positive?
= link_to(I18n.t('crops.requested.link', number_crops: @num_requested_crops), requested_crops_path)
- content_for :breadcrumbs do
%li.breadcrumb-item.active= link_to 'Crops', crops_path
%h1=t('.title')
%p
#{ENV['GROWSTUFF_SITE_NAME']} tracks who's growing what, where.
View any crop page to see which of our members have planted it and find
information on how to grow it yourself.
= form_tag(crops_path, method: :get, class: 'form-inline', role: 'form') do
.form-group
= label_tag :sort, "Sort by:", class: 'sr-only'
= select_tag "sort",
options_for_select({ "Sort by popularity": 'popular',
"Sort alphabetically": 'alpha' },
@sort || 'popular'),
class: 'form-control'
= submit_tag "Show", class: 'btn btn-primary'
.pagination
= will_paginate @crops
= bootstrap_form_tag(url: crops_path, method: :get, layout: :inline) do |f|
= f.select "sort",
options_for_select({ "popularity": 'popular',
"alphabetically": 'alpha' },
@sort || 'popular'),
label: 'Sort by'
= f.submit "Show"
.row
- @crops.each do |crop|
.col-md-2.six-across
= render partial: "thumbnail", locals: { crop: crop }
.pagination= render 'layouts/pagination', collection: @crops
- if can? :create, Crop
%div
= link_to 'New Crop', new_crop_path, class: 'btn btn-primary'
.crops
.row
- @crops.each do |crop|
.col-6.col-md-3= render 'crops/thumbnail', crop: crop
.pagination
= will_paginate @crops
.pagination= render 'layouts/pagination', collection: @crops
%ul.list-inline
%li The data on this page is available in the following formats:

View File

@@ -1,19 +1,26 @@
- if @term
- content_for :title, "Crops matching \"#{@term}\""
- if @crops
- content_for :subtitle, "#{@crops.size} total"
- else
- content_for :title, "Crop search"
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to 'Crops', crops_path
%li.breadcrumb-item.active= link_to 'Search', search_crops_path(term: @term)
%div
= form_tag search_crops_path, method: :get, id: 'crop-search', class: 'form-inline' do
.form-group
= label_tag :term, "Search crops:", class: 'sr-only'
= text_field_tag 'term', nil,
class: 'search-query input-medium form-control',
placeholder: 'Search crops',
value: @term
= submit_tag "Search", class: 'btn btn-primary'
%section.crops-search-form
- if @term
- content_for :title, "Crops matching \"#{@term}\""
%h1 Crops matching "#{@term}"
- if @crops
%h2.text-muted Found #{@crops.size} total
- else
- content_for :title, "Crop search"
%h1 Crop search
= bootstrap_form_tag(url: search_crops_path, method: :get, html: { id: 'crop-search'}, layout: :inline) do |f|
= f.label :term, "Search crops:", class: 'sr-only'
= f.text_field 'term', class: 'search-query input-medium',
placeholder: 'Search crops',
label: 'crop',
value: @term
= f.submit "Search", class: 'btn btn-success'
- if @crops.empty?
%h2 No results found
@@ -25,13 +32,12 @@
instead.
- else
.pagination
= will_paginate @crops
.pagination= will_paginate @crops
#paginated_matches
.crops
.row
- @crops.each do |c|
.col-md-2.six-across= render partial: "thumbnail", locals: { crop: c }
- @crops.each do |crop|
.col-6.col-md-3= render 'crops/thumbnail', crop: crop
.pagination
= will_paginate @crops
.pagination= will_paginate @crops

View File

@@ -1,5 +1,4 @@
- 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)
@@ -11,114 +10,137 @@
- content_for :scripts do
= javascript_include_tag "charts"
= render partial: 'approval_status_message', locals: { crop: @crop }
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to 'Crops', crops_path
%li.breadcrumb-item.active= link_to @crop, @crop
- if @crop.approved?
- content_for :buttonbar do
= render 'crops/actions', crop: @crop
%h1
%strong= @crop.name.titleize
%small.text-muted= @crop.default_scientific_name
%p= render 'crops/actions', crop: @crop
= render 'approval_status_message', crop: @crop
.row
.col-md-9
%h2
%p
- if !@crop.plantings.empty?
= @crop.name.titleize
has been planted
#{@crop.name.titleize} has been planted
= pluralize(@crop.plantings.size, "time")
by #{ENV['GROWSTUFF_SITE_NAME']} members.
- else
Nobody is growing this yet. You could be the first!
- if @crop.perennial?
#{@crop.name.capitalize} is a perennial crop (living more than two years)
- elsif @crop.annual?
#{@crop.name.capitalize} is an annual crop (living and reproducing in a single year or less)
%hr/
%h3 Predictions
= render 'predictions', crop: @crop
%hr/
= render 'crops/photos', photos: @photos, crop: @crop
%h2 Photos
%p= render 'crops/photos', photos: @photos
%p= link_to 'more photos', crop_photos_path(@crop)
.row
.col-md-3
%h3 Sunniness
.card-deck.text-center
.col-md-4
%h3.section-heading.h3.pt-4 Sunniness
= pie_chart crop_sunniness_path(@crop, format: :json), legend: "bottom"
.col-md-3
%h3 Planted from
.col-md-4
%h3.section-heading.h3.pt-4 Planted from
= pie_chart crop_planted_from_path(@crop, format: :json), legend: "bottom"
.col-md-3
%h3 Harvested for
.col-md-4
%h3.section-heading.h3.pt-4 Harvested for
= pie_chart crop_harvested_for_path(@crop, format: :json), legend: "bottom"
.varieties= render 'varieties', crop: @crop
%h3 Crop Map
%h3
= icon 'fas', 'map'
Crop Map
%p
Only plantings by members who have set their locations are shown on this map.
- if current_member && current_member.location.blank?
= link_to "Set your location.", edit_member_registration_path
#cropmap
.row
.col-md-12
= render 'crops/posts', crop: @crop
= render 'crops/posts', crop: @crop
.col-md-3
= render 'wrangle', crop: @crop
.card
.crop-image
= image_tag crop_image_path(@crop, full_size: true),
class: 'img-card', alt: 'photo of crop'
.card-body
%h4 How to grow #{@crop.name.pluralize}
= render 'grown_for', crop: @crop
= render 'planting_advice', crop: @crop
- if @crop.parent
%hr/
%p.parent-crop
= @crop.name
is a variety of
= link_to @crop.parent, @crop.parent
.list-group.list-group-flush
.list-group-item.list-group-flush.d-flex.justify-content-between.align-items-center
= link_to crop_plantings_path(@crop), class: 'card-link' do
= planting_icon
#{@crop.name.capitalize} plantings
%span.badge.badge-primary.badge-pill=@crop.plantings.size
.list-group-item.d-flex.justify-content-between.align-items-center
= link_to crop_harvests_path(@crop), class: 'card-link' do
= harvest_icon
#{@crop.name.capitalize} harvests
%span.badge.badge-primary.badge-pill=@crop.harvests.size
= render partial: 'wrangle', locals: { crop: @crop }
.list-group-item.d-flex.justify-content-between.align-items-center
= link_to crop_seeds_path(@crop), class: 'card-link' do
= seed_icon
#{@crop.name.capitalize} seeds
%span.badge.badge-primary.badge-pill=@crop.seeds.size
%p
%li
= link_to crop_seeds_path(@crop) do
View all #{@crop.name} seeds
(#{@crop.seeds.size})
%li
= link_to crop_plantings_path(@crop) do
View all #{@crop.name} plantings
(#{@crop.plantings.size})
%li
= link_to crop_harvests_path(@crop) do
View all #{@crop.name} harvests
(#{@crop.harvests.size})
- if member_signed_in?
%p
= link_to member_seeds_path(current_member, crop_slug: @crop.slug) do
= display_seed_availability(@current_member, @crop)
- if member_signed_in?
.list-group-item.d-flex.justify-content-between.align-items-center
= link_to member_seeds_path(current_member, crop_slug: @crop.slug) do
= display_seed_availability(@current_member, @crop)
%h4 How to grow #{@crop.name.pluralize}
= render 'grown_for', crop: @crop
= render 'planting_advice', crop: @crop
= render 'scientific_names', crop: @crop
= render 'alternate_names', crop: @crop
- if @crop.parent
.parent-crop
= @crop.name
is a variety of
= succeed "." do
= link_to @crop.parent, @crop.parent
= render 'crops/thumbnail', crop: @crop.parent
.card-body
= render 'scientific_names', crop: @crop
= render 'alternate_names', crop: @crop
= render 'plantings', crop: @crop
= render 'harvests', crop: @crop
= render 'find_seeds', crop: @crop
.card
.card-body
%h5.card-title Learn more about #{@crop.name.pluralize}
%h6.card-subtitle.mb-2.text-muted resources outside #{ENV['GROWSTUFF_SITE_NAME']}
%h4 Learn more about #{@crop.name.pluralize}
%ul
%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/#{CGI.escape @crop.name}",
target: "_blank",
rel: "noopener noreferrer"
%li
= link_to "Gardenate - Planting reminders", "http://www.gardenate.com/plant/#{CGI.escape @crop.name}",
target: "_blank", rel: "noopener noreferrer"
- if current_member && current_member.location
%li
= link_to "Google",
'http://www.google.com/search?q=' + CGI.escape(['Growing',
@crop.name,
current_member.location].join(' ')),
%ul.list-group.list-group-flush
%li.list-group-item
= link_to @crop.en_wikipedia_url, target: "_blank", rel: "noopener noreferrer" do
= icon 'fas', 'external-link-alt'
Wikipedia (English)
%li.list-group-item
= link_to "https://openfarm.cc/en/crops/#{CGI.escape @crop.name}",
class: 'card-link',
target: "_blank",
rel: "noopener noreferrer"
rel: "noopener noreferrer" do
= icon 'fas', 'external-link-alt'
OpenFarm - Growing guide
%li.list-group-item
= link_to "http://www.gardenate.com/plant/#{CGI.escape @crop.name}",
target: "_blank",
class: 'card-link',
rel: "noopener noreferrer" do
= icon 'fas', 'external-link-alt'
Gardenate - Planting reminders
- if current_member && current_member.location
%li.list-group-item
= link_to 'http://www.google.com/search?q=' + CGI.escape(['Growing', @crop.name, current_member.location].join(' ')),
target: "_blank",
class: 'card-link',
rel: "noopener noreferrer" do
= icon 'fas', 'external-link-alt'
Google

View File

@@ -1,20 +1,16 @@
- content_for :title, "Resend confirmation instructions"
= form_for(resource, as: resource_name,
url: confirmation_path(resource_name),
html: { method: :post, class: 'form-horizontal', role: 'form' }) do |f|
= devise_error_messages!
.form-page
.card.form-card
%h2 Resend confirmation instructions
= form_for(resource, as: resource_name,
url: confirmation_path(resource_name),
html: { method: :post, class: 'form-horizontal', role: 'form' }) do |f|
= render 'devise/shared/error_messages', resource: resource
%p Enter either your login name or your email address to resend the confirmation email.
%p Enter either your login name or your email address to resend the confirmation email.
= f.text_field :login, class: 'form-control', placeholder: 'email or login name'
= f.submit "Resend confirmation instructions", class: 'btn btn-block my-4 btn-primary'
.form-group
= f.label :login, class: 'control-label col-md-2'
.col-md-8
= f.text_field :login, class: 'form-control'
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit "Resend confirmation instructions", class: 'btn btn-primary'
.form-group
.col-md-offset-2.col-md-8
= render "devise/shared/links"
.form-group
.col-md-offset-2.col-md-8
= render "devise/shared/links"

View File

@@ -3,7 +3,7 @@
= form_for(resource, as: resource_name,
url: password_path(resource_name),
html: { method: :put, class: 'form-horizontal', role: 'form' }) do |f|
= devise_error_messages!
= render 'devise/shared/error_messages', resource: resource
= f.hidden_field :reset_password_token
.form-group

View File

@@ -1,19 +1,14 @@
- content_for :title, "Forgot your password?"
= form_for(resource, as: resource_name,
url: password_path(resource_name),
html: { method: :post,
class: 'form-horizontal', role: 'form' }) do |f|
= devise_error_messages!
.form-page
%section.card.form-card
%h2 Forgot your password?
= form_for(resource, as: resource_name,
url: password_path(resource_name),
html: { method: :post,
class: 'text-center border border-light p-5', role: 'form' }) do |f|
= render 'devise/shared/error_messages', resource: resource
.form-group
= f.label :login, class: 'control-label col-md-2'
.col-md-8
= f.text_field :login, class: 'form-control'
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit "Send me reset password instructions", class: 'btn btn-primary'
= f.text_field :login, class: "form-control mb-4", placeholder: "E-mail", type: "email"
= f.submit "Send me reset password instructions", class: 'btn btn-block my-4 btn-primary'
.form-group
.col-md-offset-2.col-md-8
= render "devise/shared/links"
= render "devise/shared/links"

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