Compare commits

..

122 Commits

Author SHA1 Message Date
Daniel O'Connor
7e1432c8c4 Merge branch 'mainline' into dev 2024-02-04 10:32:34 +10:30
Daniel O'Connor
6102f0629b Revert 140fe7a (#3612)
* Revert 140fe7a

* Split rendering behaviour
2024-02-04 10:25:41 +10:30
Daniel O'Connor
bc47ea4e23 Merge pull request #3546 from Growstuff/dev
January 2024 Release
2024-02-03 18:24:57 +10:30
Daniel O'Connor
fb86448061 HAML 6 (#3607)
* HAML

* rewrite

* Fix specs - but likely still wrong

* Return temple

* Trailing line

* Fix specs

* This was rearranged, apparently.

* Fix tests

* Retain escaping

* Fix specs

* Rubocop

* Apparently the escaped filter doesn't work with interpolation. Swap to our implementation
2024-02-03 17:33:39 +10:30
dependabot[bot]
e450a0613f Merge pull request #3608 from Growstuff/dependabot/bundler/dalli-3.2.7 2024-01-30 11:43:24 +00:00
dependabot[bot]
4b4d246237 Bump dalli from 3.2.6 to 3.2.7
Bumps [dalli](https://github.com/petergoldstein/dalli) from 3.2.6 to 3.2.7.
- [Changelog](https://github.com/petergoldstein/dalli/blob/main/CHANGELOG.md)
- [Commits](https://github.com/petergoldstein/dalli/compare/v3.2.6...v3.2.7)

---
updated-dependencies:
- dependency-name: dalli
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 09:34:52 +00:00
dependabot[bot]
823e73575c Merge pull request #3609 from Growstuff/dependabot/bundler/capybara-3.40.0 2024-01-29 09:33:47 +00:00
dependabot[bot]
a4b4348f0b Bump capybara from 3.39.2 to 3.40.0
Bumps [capybara](https://github.com/teamcapybara/capybara) from 3.39.2 to 3.40.0.
- [Changelog](https://github.com/teamcapybara/capybara/blob/master/History.md)
- [Commits](https://github.com/teamcapybara/capybara/compare/3.39.2...3.40.0)

---
updated-dependencies:
- dependency-name: capybara
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 07:16:18 +00:00
Daniel O'Connor
008667515e Swap from ugifier to terser 2024-01-27 01:28:55 +00:00
Daniel O'Connor
8249edd966 Add msgpack due to rails requesting it 2024-01-27 00:14:21 +00:00
Daniel O'Connor
f338274611 Rails 7.1 (#3590)
* Rails 7.1

* Update application.rb

* Bump searchkick

* Bump to 7.0.0

* Fix

* Fix crop search

* Sync translation

* Drop required from form group

* Loosen specs further

* Fix Gemfile

* Update seeds_request_spec.rb

* Update test.rb

* Rename
2024-01-27 10:06:47 +10:30
Daniel O'Connor
ad4a6e17e2 iCalendar feed of plantings (#3588)
* Register mime type

* Add rough first pass

* Index predictions, and add links

* Trailing space

* Fix implementation

* Fix names, make public

* Fix names, make public

* Fix

* Fix tyyos

* Add date

* If there are no predictions, keep growing

* Add a todo

* Fix factories

* Specs
2024-01-27 00:38:33 +10:30
Daniel O'Connor
254fd156f0 Remove faraday_middleware (#3604)
* Remove faraday_middleware

* Remove outdated migration

* Remove outdated migration
2024-01-27 00:10:17 +10:30
Daniel O'Connor
b711618027 Unpin active_median (#3603)
* Unpin active_median

* Remove outdated migration

* Remove outdated migration
2024-01-26 23:47:59 +10:30
Brenda Wallace
30626859c3 Auto corrected by following Format Css Code (#3594)
Co-authored-by: Awesome Code <team@xinminlabs.com>
Co-authored-by: Daniel O'Connor <daniel.oconnor@gmail.com>
2024-01-26 23:01:55 +10:30
Daniel O'Connor
140fe7a087 Bump searchkick, elasticsearch (#3602)
* Bump searchkick

* Bump to 7.0.0

* Fix

* Fix crop search
2024-01-26 23:01:39 +10:30
dependabot[bot]
49cd657916 Merge pull request #3601 from Growstuff/dependabot/bundler/rspec-rails-6.1.1 2024-01-26 10:34:17 +00:00
dependabot[bot]
4ad4379991 Bump rspec-rails from 6.1.0 to 6.1.1
Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 6.1.0 to 6.1.1.
- [Changelog](https://github.com/rspec/rspec-rails/blob/main/Changelog.md)
- [Commits](https://github.com/rspec/rspec-rails/compare/v6.1.0...v6.1.1)

---
updated-dependencies:
- dependency-name: rspec-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-26 07:54:49 +00:00
dependabot[bot]
b55f9654ea Merge pull request #3600 from Growstuff/dependabot/bundler/rubocop-1.60.2 2024-01-26 06:42:09 +00:00
dependabot[bot]
6ad47f7203 Bump rubocop from 1.60.1 to 1.60.2
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.60.1 to 1.60.2.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.60.1...v1.60.2)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-25 07:58:32 +00:00
dependabot[bot]
e879541257 Merge pull request #3599 from Growstuff/dependabot/bundler/haml_lint-0.55.0 2024-01-24 10:23:22 +00:00
dependabot[bot]
cc2eec4fe8 Bump haml_lint from 0.54.0 to 0.55.0
Bumps [haml_lint](https://github.com/sds/haml-lint) from 0.54.0 to 0.55.0.
- [Release notes](https://github.com/sds/haml-lint/releases)
- [Changelog](https://github.com/sds/haml-lint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sds/haml-lint/compare/v0.54.0...v0.55.0)

---
updated-dependencies:
- dependency-name: haml_lint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-24 07:24:09 +00:00
Daniel O'Connor
f87c5db40e Merge pull request #3597 from Growstuff/dependabot/bundler/selenium-webdriver-4.17.0
Bump selenium-webdriver from 4.16.0 to 4.17.0
2024-01-23 23:05:43 +10:30
Daniel O'Connor
581b85a300 Merge pull request #3598 from Growstuff/dependabot/bundler/haml_lint-0.54.0
Bump haml_lint from 0.53.0 to 0.54.0
2024-01-23 23:05:21 +10:30
Daniel O'Connor
32f39b47e2 Merge pull request #3596 from Growstuff/dependabot/bundler/axe-core-rspec-4.8.1
Bump axe-core-rspec from 4.8.0 to 4.8.1
2024-01-23 23:05:08 +10:30
Daniel O'Connor
29c614d31e Merge pull request #3595 from Growstuff/dependabot/bundler/axe-core-capybara-4.8.1
Bump axe-core-capybara from 4.8.0 to 4.8.1
2024-01-23 23:04:50 +10:30
dependabot[bot]
52012ea238 Bump haml_lint from 0.53.0 to 0.54.0
Bumps [haml_lint](https://github.com/sds/haml-lint) from 0.53.0 to 0.54.0.
- [Release notes](https://github.com/sds/haml-lint/releases)
- [Changelog](https://github.com/sds/haml-lint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sds/haml-lint/compare/v0.53.0...v0.54.0)

---
updated-dependencies:
- dependency-name: haml_lint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-23 07:53:28 +00:00
dependabot[bot]
9aed6af772 Bump selenium-webdriver from 4.16.0 to 4.17.0
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.16.0 to 4.17.0.
- [Release notes](https://github.com/SeleniumHQ/selenium/releases)
- [Changelog](https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES)
- [Commits](https://github.com/SeleniumHQ/selenium/compare/selenium-4.16.0...selenium-4.17.0)

---
updated-dependencies:
- dependency-name: selenium-webdriver
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-23 07:37:55 +00:00
dependabot[bot]
53abbaddd7 Bump axe-core-rspec from 4.8.0 to 4.8.1
Bumps [axe-core-rspec](https://github.com/dequelabs/axe-core-gems) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/dequelabs/axe-core-gems/releases)
- [Changelog](https://github.com/dequelabs/axe-core-gems/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/dequelabs/axe-core-gems/compare/v4.8.0...v4.8.1)

---
updated-dependencies:
- dependency-name: axe-core-rspec
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-23 07:36:40 +00:00
dependabot[bot]
b443afc965 Bump axe-core-capybara from 4.8.0 to 4.8.1
Bumps [axe-core-capybara](https://github.com/dequelabs/axe-core-gems) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/dequelabs/axe-core-gems/releases)
- [Changelog](https://github.com/dequelabs/axe-core-gems/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/dequelabs/axe-core-gems/compare/v4.8.0...v4.8.1)

---
updated-dependencies:
- dependency-name: axe-core-capybara
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-23 07:33:10 +00:00
Daniel O'Connor
12ff09ad51 Add Accessibility assertions to rspec, replacing accessbility-lint + fixes (#3573)
* Add dep

* Add tests around accessibility

* Add examples in a few places

* Try to fix screenshots

* Remove redundant role

* Adjust rules, colors, etc so tests pass

* Update app/assets/stylesheets/overrides.scss

* Wrap in label

* Omit rule, which is failing with a false positive

* Update index.haml

* Update _blurb.html.haml
2024-01-22 22:09:27 +10:30
Daniel O'Connor
75aba7158f Merge pull request #3593 from Growstuff/rename
Rename spec/models/garden_type.rb
2024-01-22 22:08:49 +10:30
dependabot[bot]
093fa645fd Merge pull request #3591 from Growstuff/dependabot/bundler/recaptcha-5.16.0 2024-01-22 08:38:58 +00:00
Daniel O'Connor
1d52f8fcad Rename 2024-01-22 08:31:33 +00:00
dependabot[bot]
a134b1e3ab Bump recaptcha from 5.15.0 to 5.16.0
Bumps [recaptcha](https://github.com/ambethia/recaptcha) from 5.15.0 to 5.16.0.
- [Changelog](https://github.com/ambethia/recaptcha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ambethia/recaptcha/compare/v5.15.0...v5.16.0)

---
updated-dependencies:
- dependency-name: recaptcha
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 08:22:25 +00:00
dependabot[bot]
c5694ad1ab Merge pull request #3592 from Growstuff/dependabot/bundler/sidekiq-7.2.1 2024-01-22 08:21:35 +00:00
dependabot[bot]
28bdf9adde Bump sidekiq from 7.2.0 to 7.2.1
Bumps [sidekiq](https://github.com/sidekiq/sidekiq) from 7.2.0 to 7.2.1.
- [Changelog](https://github.com/sidekiq/sidekiq/blob/main/Changes.md)
- [Commits](https://github.com/sidekiq/sidekiq/compare/v7.2.0...v7.2.1)

---
updated-dependencies:
- dependency-name: sidekiq
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 07:51:40 +00:00
Daniel O'Connor
ae3747ce83 Merge pull request #3589 from Growstuff/jquery-ui-rails
Update jquery-ui-rails
2024-01-22 00:33:38 +10:30
Daniel O'Connor
50b6708c7f Update jquery-ui-rails 2024-01-21 13:42:48 +00:00
Daniel O'Connor
196b8078e6 Posts - Ensure responsive (#3584)
* Fix model validations and responsiveness

* Fix model validations and responsiveness

* Update app/models/post.rb
2024-01-21 16:05:14 +10:30
Daniel O'Connor
86cc678fc7 Add feature 2024-01-21 05:20:57 +00:00
Daniel O'Connor
91f8c2e0b3 Harvests - Compare dates to dates when determing how long ago something was (#3585)
* Compare dates to dates

* Adjust timeline display to check if Date or Time
2024-01-21 15:20:32 +10:30
Daniel O'Connor
8546794311 Recaptcha (#3586)
* add recaptcha on register view

Update new.html.haml to add it

* Update Gemfile to add recaptcha

* Update env-example to show recaptcha

* More view corrections for recaptcha

* Update registrations_controller.rb to add recaptcha

* Update env-example with test config

* Recaptcha help text

* Fix trailing spaces

* Fix trailing space

* Add Recaptcha to gemfile.lock

* Fixing Gemfile.lock space

* Typo on comments in view

* Update app/views/devise/registrations/new.html.haml

* Fix signup

---------

Co-authored-by: Cesy <cesy.avon@gmail.com>
2024-01-21 15:20:03 +10:30
Daniel O'Connor
b77df88df9 Issues/1475: Ensure we have pagination (#3193)
* Paginate, 100 at a time

* Limited i18n

* Paginate roles

* Pagination

* Pagination

* i18n and pagination

* Paginate alternate names

* Silence code climate

* Rewrite coverage as a feature

* Remove coverage in favour of crops/scientific_name_spec

* Add missing admin link

* Rewrite coverage as feature

* Rewrite coverage

---------

Co-authored-by: Brenda Wallace <brenda@wallace.net.nz>
2024-01-21 14:19:36 +10:30
Daniel O'Connor
1f0cfa9b6c Add GBIF to our scientific names, so that our crops can associate creative commons photos (#3559)
* Add GBIF cient

* Add lookup

* Add autocomplete for GBIF lookup

* Add extra detail to scientific names

* Autocomplete

* Add routes

* Rmeove mapping

* Add autocomplete

* Update GBIF data on save

* db/schema

* Style

* Extract service

* Add concern

* Add concern

* Save photos

* Initial coverage

* Coverage

* Add coverage

* Shut up, codeclimate

* Shut up, codeclimate

* Unused

* Shut up, codeclimate

* Apply suggestions from code review

* Remove localhost

* Fix rubocop

* Fix rubocop

* Add UI links

* Add rake

* Indent

* Update Gemfile.lock

* Update lib/tasks/gbif.rake

* Update app/views/crops/_scientific_names.html.haml

* Rubocop

* Expand edit photo form

* Fix error

* Add model validations

* Skip photos without backlinks

* Fix tests

* Add photo words

* Allow blank

* Rubocop and handle invalid legacy data

* Apply suggestions from code review

* Update lib/tasks/gbif.rake
2024-01-21 13:22:25 +10:30
Daniel O'Connor
1840e36d77 Merge pull request #3583 from Growstuff/active-plantings
Crops > Plantings - Show count of active only as the following page is active
2024-01-21 13:22:08 +10:30
Daniel O'Connor
c114f080a9 Active only as the following page is active 2024-01-21 01:58:53 +00:00
Daniel O'Connor
4aae30309b Merge pull request #3582 from Growstuff/add-label
Accessibility: Wrap checkbox in label
2024-01-21 12:10:11 +10:30
Daniel O'Connor
09a7ce6483 Wrap in label 2024-01-21 01:21:09 +00:00
Daniel O'Connor
adb0ed041b Merge pull request #3580 from Growstuff/headings
Drop use of h5
2024-01-20 21:22:05 +10:30
Daniel O'Connor
d663d0ffa3 Drop use of h5 2024-01-20 04:28:10 +00:00
Daniel O'Connor
756d35f29b Merge pull request #3579 from Growstuff/CloCkWeRX-patch-1
Update gardens_spec.rb
2024-01-20 14:40:41 +10:30
Daniel O'Connor
b5ad9b51db Update gardens_spec.rb 2024-01-20 13:01:08 +10:30
Daniel O'Connor
8ee4b5f1aa Update _menu.haml
Fix accessibility issue
2024-01-19 19:22:37 +10:30
Daniel O'Connor
edc52774f4 Merge pull request #3576 from Growstuff/dependabot/bundler/rubocop-1.60.1
Bump rubocop from 1.60.0 to 1.60.1
2024-01-18 22:59:36 +10:30
Daniel O'Connor
f4f32301fc Merge pull request #3577 from Growstuff/dependabot/github_actions/actions/cache-4
Bump actions/cache from 3 to 4
2024-01-18 22:59:20 +10:30
dependabot[bot]
af354f2f67 Bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 07:53:35 +00:00
dependabot[bot]
d64e1ea06f Bump rubocop from 1.60.0 to 1.60.1
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.60.0 to 1.60.1.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.60.0...v1.60.1)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 07:41:29 +00:00
Daniel O'Connor
58a5b6ce5c Merge pull request #3568 from Growstuff/CloCkWeRX-patch-1
Darken green buttons, headings etc for Accessbility contrast ratios
2024-01-18 13:05:06 +10:30
Daniel O'Connor
1174846b72 Merge pull request #3575 from Growstuff/CloCkWeRX-patch-2
Accessibility Update _avatar.html.haml
2024-01-18 13:02:17 +10:30
Daniel O'Connor
4a45acf79b Update _avatar.html.haml
Fix naming
2024-01-18 08:32:49 +10:30
Daniel O'Connor
59d800bd93 Merge pull request #3574 from Growstuff/landmark
Accessibility: Landmarks
2024-01-18 08:29:48 +10:30
Daniel O'Connor
c771713b0b Merge branch 'dev' into CloCkWeRX-patch-1 2024-01-18 07:55:05 +10:30
Daniel O'Connor
5cc6135b2d Mark breadcrumbs as a nav 2024-01-17 21:13:41 +00:00
Daniel O'Connor
6e23aff347 Add main landmark to document 2024-01-17 21:11:43 +00:00
Daniel O'Connor
e4e1d3e674 Merge pull request #3569 from Growstuff/upgrade-webdrivers
Update webdrivers in devcontainer
2024-01-18 00:36:13 +10:30
Daniel O'Connor
ea3349fc85 Merge branch 'dev' of https://github.com/Growstuff/growstuff into upgrade-webdrivers 2024-01-17 13:39:21 +00:00
Daniel O'Connor
2f027f4f0d Make capybara work in the devcontainer 2024-01-17 13:38:19 +00:00
Daniel O'Connor
a1637c4259 Merge pull request #3570 from Growstuff/upgrade-rails
Bump installed rails in dev container
2024-01-17 23:39:14 +10:30
Daniel O'Connor
cc3961ed26 Merge pull request #3572 from Growstuff/fix-capybara-initialisation
Avoid trying to connect to selenium for non selenium tests
2024-01-17 23:38:55 +10:30
Daniel O'Connor
006e7553e5 Merge branch 'fix-capybara-initialisation' into upgrade-webdrivers 2024-01-17 12:50:17 +00:00
Daniel O'Connor
12fdb95c6a Avoid trying to connect to selenium for non selenium tests 2024-01-17 12:48:24 +00:00
Daniel O'Connor
cab4c2dfca Drop webdrivers for selenium 4.11+ 2024-01-17 12:35:08 +00:00
Daniel O'Connor
bb0cb16b80 Merge branch 'dev' into upgrade-webdrivers 2024-01-17 22:58:07 +10:30
Daniel O'Connor
e659560623 Merge pull request #3571 from Growstuff/add-bash-complete
Add bash complete to dev container
2024-01-17 22:57:33 +10:30
Daniel O'Connor
3197c61f3a Add bash complete 2024-01-17 12:23:50 +00:00
Daniel O'Connor
2a5db86f89 Bump installed rails 2024-01-17 12:21:41 +00:00
Daniel O'Connor
891315e3ef Update webdrivers 2024-01-17 12:19:50 +00:00
Daniel O'Connor
9171892d0b Darken green buttons, headings etc for Accessbility contrast ratios
#2067
2024-01-17 22:17:40 +10:30
Daniel O'Connor
78eaf0b4c9 Address minor accessibility issues: Image elements do not have [alt] attributes (#3561)
* Add alt tags

* Update app/views/members/_tiny.haml

* Update app/views/home/_plantings.html.haml

* Use crop_name as this is a searchkick record
2024-01-17 22:02:09 +10:30
Daniel O'Connor
562e5a8b76 Merge pull request #3567 from Growstuff/CloCkWeRX-patch-1
Update _menu.haml
2024-01-17 20:59:34 +10:30
Daniel O'Connor
fa6aa1a9fb Update app/views/layouts/_menu.haml 2024-01-17 20:16:49 +10:30
Daniel O'Connor
9276ade62f Update _menu.haml 2024-01-17 19:58:40 +10:30
Daniel O'Connor
64d06c67ad Merge pull request #3565 from Growstuff/CloCkWeRX-patch-1
Update icons_helper.rb to render alt tag
2024-01-17 19:40:48 +10:30
Daniel O'Connor
2d524d8489 Merge pull request #3566 from Growstuff/CloCkWeRX-patch-2
Remove counts from Photos#index
2024-01-17 19:40:29 +10:30
Daniel O'Connor
afb07d2cb5 Remove counts from Photos#index
Fix #3560
2024-01-17 18:19:29 +10:30
Daniel O'Connor
a118a95b54 Update icons_helper.rb 2024-01-17 18:12:58 +10:30
Daniel O'Connor
33af3bae65 Update icons_helper.rb to render alt tag 2024-01-17 18:10:48 +10:30
dependabot[bot]
bc8080c759 Merge pull request #3563 from Growstuff/dependabot/bundler/bullet-7.1.6 2024-01-16 10:58:52 +00:00
dependabot[bot]
3455d27840 Bump bullet from 7.1.5 to 7.1.6
Bumps [bullet](https://github.com/flyerhzm/bullet) from 7.1.5 to 7.1.6.
- [Changelog](https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flyerhzm/bullet/compare/7.1.5...7.1.6)

---
updated-dependencies:
- dependency-name: bullet
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-16 10:44:18 +00:00
dependabot[bot]
533d166bd7 Merge pull request #3564 from Growstuff/dependabot/bundler/rubocop-1.60.0 2024-01-16 10:42:36 +00:00
dependabot[bot]
4885bfd9cf Bump rubocop from 1.59.0 to 1.60.0
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.59.0 to 1.60.0.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.59.0...v1.60.0)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-16 07:18:55 +00:00
dependabot[bot]
471d8decec Merge pull request #3562 from Growstuff/dependabot/bundler/faker-3.2.3 2024-01-15 09:26:37 +00:00
dependabot[bot]
9935d20c97 Bump faker from 3.2.2 to 3.2.3
Bumps [faker](https://github.com/faker-ruby/faker) from 3.2.2 to 3.2.3.
- [Release notes](https://github.com/faker-ruby/faker/releases)
- [Changelog](https://github.com/faker-ruby/faker/blob/main/CHANGELOG.md)
- [Commits](https://github.com/faker-ruby/faker/compare/v3.2.2...v3.2.3)

---
updated-dependencies:
- dependency-name: faker
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 07:44:47 +00:00
Daniel O'Connor
cddfecbd67 Update .rubocop.yml (#3550) 2024-01-14 23:44:54 +10:30
dependabot[bot]
4941d84e8f Merge pull request #3556 from Growstuff/dependabot/bundler/platform-api-3.6.0 2024-01-14 10:41:21 +00:00
dependabot[bot]
a117f71b1f Bump platform-api from 3.5.0 to 3.6.0
Bumps [platform-api](https://github.com/heroku/platform-api) from 3.5.0 to 3.6.0.
- [Changelog](https://github.com/heroku/platform-api/blob/master/CHANGELOG.md)
- [Commits](https://github.com/heroku/platform-api/compare/v3.5.0...v3.6.0)

---
updated-dependencies:
- dependency-name: platform-api
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-12 07:58:56 +00:00
Cesy
0450ec3883 Merge pull request #3551 from Growstuff/dependabot/bundler/rubocop-rspec-2.26.1
Bump rubocop-rspec from 2.26.0 to 2.26.1
2024-01-11 13:58:47 +00:00
dependabot[bot]
c11c289237 Bump rubocop-rspec from 2.26.0 to 2.26.1
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 2.26.0 to 2.26.1.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v2.26.0...v2.26.1)

---
updated-dependencies:
- dependency-name: rubocop-rspec
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-09 08:34:45 +00:00
dependabot[bot]
8a9bf37a3f Merge pull request #3555 from Growstuff/dependabot/bundler/haml_lint-0.53.0 2024-01-09 08:33:46 +00:00
dependabot[bot]
fad0e579d4 Bump haml_lint from 0.52.0 to 0.53.0
Bumps [haml_lint](https://github.com/sds/haml-lint) from 0.52.0 to 0.53.0.
- [Release notes](https://github.com/sds/haml-lint/releases)
- [Changelog](https://github.com/sds/haml-lint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sds/haml-lint/compare/v0.52.0...v0.53.0)

---
updated-dependencies:
- dependency-name: haml_lint
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-09 08:02:51 +00:00
dependabot[bot]
af00477e5b Merge pull request #3552 from Growstuff/dependabot/bundler/bullet-7.1.5 2024-01-09 08:00:04 +00:00
dependabot[bot]
ade829eab8 Bump bullet from 7.1.4 to 7.1.5
Bumps [bullet](https://github.com/flyerhzm/bullet) from 7.1.4 to 7.1.5.
- [Changelog](https://github.com/flyerhzm/bullet/blob/main/CHANGELOG.md)
- [Commits](https://github.com/flyerhzm/bullet/compare/7.1.4...7.1.5)

---
updated-dependencies:
- dependency-name: bullet
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-09 07:45:46 +00:00
dependabot[bot]
69a02f942b Merge pull request #3553 from Growstuff/dependabot/bundler/puma-6.4.2 2024-01-09 07:43:48 +00:00
dependabot[bot]
d876017094 Bump puma from 6.4.1 to 6.4.2
Bumps [puma](https://github.com/puma/puma) from 6.4.1 to 6.4.2.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/master/History.md)
- [Commits](https://github.com/puma/puma/compare/v6.4.1...v6.4.2)

---
updated-dependencies:
- dependency-name: puma
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 07:35:31 +00:00
Daniel O'Connor
ee45b518ce Rubocop fixes (Stacked PR) (#3454)
* Fix todo

* Rubcop

* Rubocop

* Rubocop

* Rename harvests_routing_spec.rb to harvests_controller_routing_spec.rb

Making codeclimate happier

* Rename for CodeFactor: updates_routing_spec.rb to posts_controller_updates_routing_spec.rb

For codefactor

* Rename for CodeFactor: follows_routing_spec.rb to follows_controller_routing_spec.rb

* Rename for CodeFactor: forums_routing_spec.rb to forums_controller_routing_spec.rb

* Rename spec/routing/roles_routing_spec.rb to spec/routing/admin/roles_controller_routing_spec.rb

* Rename authentications_routing_spec.rb to authentications_controller_routing_spec.rb

* Rename for CodeFactor: plantings_routing_spec.rb to plantings_controller_routing_spec.rb

* Rename for CodeFactor: scientific_names_routing_spec.rb to scientific_names_controller_routing_spec.rb

* Rename for CodeFactor: seeds_routing_spec.rb to seeds_controller_routing_spec.rb

* Rename for CodeFactor: comments_routing_spec.rb to comments_controller_routing_spec.rb

* Rename for CodeFactor: garden_types_routing_spec.rb to garden_types_controller_routing_spec.rb

* Rename for CodeFactor: admin_routing_spec.rb to admin_controller_routing_spec.rb

* Rename for CodeFactor: gardens_routing_spec.rb to gardens_controller_routing_spec.rb

* Rename for CodeFactor: photos_routing_spec.rb to photos_controller_routing_spec.rb

* Rename for CodeFactor: plant_parts_routing_spec.rb to plant_parts_controller_routing_spec.rb

* Rename for CodeFactor: crops_routing_spec.rb to crops_controller_routing_spec.rb

* [CodeFactor] Apply fixes

* Rename

* Code factor bot

---------

Co-authored-by: Cesy <cesy.avon@gmail.com>
Co-authored-by: codefactor-io <support@codefactor.io>
2024-01-07 21:05:59 +10:30
Daniel O'Connor
4435407b95 Suppress Time.to_s warning until next rails (#3548)
* Fix warning

* Update config/application.rb
2024-01-07 13:27:57 +10:30
Daniel O'Connor
5eaee19ccf Merge branch 'mainline' into dev 2024-01-07 13:27:34 +10:30
Daniel O'Connor
6b9a29e2ca Merge pull request #3547 from Growstuff/swagger_root
Fix rswag deprecations
2024-01-07 13:22:13 +10:30
Daniel O'Connor
235109ccee Fix deprecation 2024-01-07 01:57:19 +00:00
dependabot[bot]
a9577b70bb Merge pull request #3545 from Growstuff/dependabot/bundler/rubocop-rspec-2.26.0 2024-01-07 01:13:46 +00:00
dependabot[bot]
80b3269359 Bump rubocop-rspec from 2.25.0 to 2.26.0
Bumps [rubocop-rspec](https://github.com/rubocop/rubocop-rspec) from 2.25.0 to 2.26.0.
- [Release notes](https://github.com/rubocop/rubocop-rspec/releases)
- [Changelog](https://github.com/rubocop/rubocop-rspec/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rspec/compare/v2.25.0...v2.26.0)

---
updated-dependencies:
- dependency-name: rubocop-rspec
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-05 07:13:34 +00:00
dependabot[bot]
13057f52fb Merge pull request #3544 from Growstuff/dependabot/bundler/puma-6.4.1 2024-01-03 10:28:41 +00:00
dependabot[bot]
f135756911 Bump puma from 6.4.0 to 6.4.1
Bumps [puma](https://github.com/puma/puma) from 6.4.0 to 6.4.1.
- [Release notes](https://github.com/puma/puma/releases)
- [Changelog](https://github.com/puma/puma/blob/master/History.md)
- [Commits](https://github.com/puma/puma/compare/v6.4.0...v6.4.1)

---
updated-dependencies:
- dependency-name: puma
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 07:38:47 +00:00
dependabot[bot]
9d64e967c5 Merge pull request #3541 from Growstuff/dependabot/bundler/rack-protection-3.2.0 2024-01-02 07:56:22 +00:00
dependabot[bot]
9b8e154035 Bump rack-protection from 3.1.0 to 3.2.0
Bumps [rack-protection](https://github.com/sinatra/sinatra) from 3.1.0 to 3.2.0.
- [Changelog](https://github.com/sinatra/sinatra/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sinatra/sinatra/compare/v3.1.0...v3.2.0)

---
updated-dependencies:
- dependency-name: rack-protection
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-02 07:41:55 +00:00
dependabot[bot]
76eefdc104 Merge pull request #3542 from Growstuff/dependabot/bundler/factory_bot_rails-6.4.3 2024-01-02 07:40:58 +00:00
dependabot[bot]
43d0603995 Bump factory_bot_rails from 6.4.2 to 6.4.3
Bumps [factory_bot_rails](https://github.com/thoughtbot/factory_bot_rails) from 6.4.2 to 6.4.3.
- [Release notes](https://github.com/thoughtbot/factory_bot_rails/releases)
- [Changelog](https://github.com/thoughtbot/factory_bot_rails/blob/main/NEWS.md)
- [Commits](https://github.com/thoughtbot/factory_bot_rails/compare/v6.4.2...v6.4.3)

---
updated-dependencies:
- dependency-name: factory_bot_rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 07:32:42 +00:00
Daniel O'Connor
7a06bfcbf8 Merge pull request #3539 from Growstuff/dependabot/bundler/rubocop-rails-2.23.1
Bump rubocop-rails from 2.23.0 to 2.23.1
2023-12-25 18:22:00 +10:30
dependabot[bot]
ebed7900c8 Bump rubocop-rails from 2.23.0 to 2.23.1
Bumps [rubocop-rails](https://github.com/rubocop/rubocop-rails) from 2.23.0 to 2.23.1.
- [Release notes](https://github.com/rubocop/rubocop-rails/releases)
- [Changelog](https://github.com/rubocop/rubocop-rails/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop-rails/compare/v2.23.0...v2.23.1)

---
updated-dependencies:
- dependency-name: rubocop-rails
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 07:23:10 +00:00
Cesy
62431c9a6e Merge pull request #3523 from Growstuff/dev
December Release
2023-12-21 09:14:06 +00:00
Daniel O'Connor
9559c2ef57 Merge pull request #3402 from Growstuff/dev
Production release August 2023
2023-08-11 13:06:30 +09:30
150 changed files with 1813 additions and 647 deletions

View File

@@ -1,7 +1,7 @@
FROM mcr.microsoft.com/devcontainers/ruby:0-3.1-bullseye
# Install Rails
RUN gem install rails:7.0.7 webdrivers:5.2.0
RUN gem install rails:7.0.8
# Default value to allow debug server to serve content over GitHub Codespace's port forwarding service
# The value is a comma-separated list of allowed domains
@@ -12,8 +12,12 @@ ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev,.preview.app.github.dev,.app.git
#RUN bundle exec rake db:migrate
# [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends bash-completion
# Chrome for testing packages. https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-doesnt-launch-on-linux
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get -y install --no-install-recommends ca-certificates fonts-liberation libasound2 libatk-bridge2.0-0 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 libgcc1 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils
# [Optional] Uncomment this line to install additional gems.
# RUN gem install <your-gem-names-here>

View File

@@ -14,7 +14,7 @@
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// This can be used to network with other containers or the host.
"forwardPorts": [3000, 5432, 9200],
"forwardPorts": [3000, 5432, 9200, 8081],
// Use 'postCreateCommand' to run commands after the container is created.
// these don't actually work as postCreateCommands, you need to run them manually

View File

@@ -76,7 +76,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache
uses: actions/cache@v3
uses: actions/cache@v4
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@@ -7,7 +7,7 @@ AllCops:
Exclude:
- 'db/schema.rb'
- 'vendor/**/*'
TargetRailsVersion: 6.0
TargetRailsVersion: 7.0
Rails:
Enabled: true

View File

@@ -97,5 +97,6 @@ submit the change with your pull request.
## Bots
### Security and Dependency Updates
- `codefactor-io[bot]`
- DeppBot / [deppbot](https://github.com/deppbot)
- `dependabot[bot]` [dependabot](https://github.com/dependabot-bot) / [dependabot-preview](https://github.com/apps/dependabot-preview)

26
Gemfile
View File

@@ -5,7 +5,7 @@ source 'https://rubygems.org'
# Match ruby version in .ruby-version
ruby File.read('.ruby-version')
gem 'rails', '~> 7.0.7'
gem 'rails', '~> 7.1.0'
# Keeping old sprockets
# https://github.com/rails/sprockets-rails/issues/444#issuecomment-637817050
@@ -33,18 +33,18 @@ gem 'material_icons'
# icons
gem 'font-awesome-sass'
gem 'uglifier' # JavaScript compressor
gem 'terser'
gem 'oj' # Speeds up json
# planting and harvest predictions
# based on median values for the crop
gem 'active_median', '0.2.0'
gem 'active_median'
gem 'active_record_union'
gem 'flickraw'
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'jquery-ui-rails', github: 'jquery-ui-rails/jquery-ui-rails', tag: 'v7.0.0' # See https://github.com/jquery-ui-rails/jquery-ui-rails/issues/146
gem 'cancancan' # for checking member privileges
gem 'csv_shaper' # CSV export
@@ -100,7 +100,7 @@ gem 'omniauth-twitter'
gem "chartkick"
# clever elastic search
gem 'elasticsearch', '< 7.0.0'
gem 'elasticsearch', '~> 7.0.0'
gem 'searchkick'
gem "hashie", ">= 3.5.3"
@@ -124,10 +124,19 @@ gem 'rack-protection', '>= 2.0.1'
gem 'mailboxer', '>= 0.15.1'
gem 'faraday'
gem 'faraday_middleware'
gem 'rack-cors'
gem 'icalendar'
# for signups as requested by email service
gem 'recaptcha'
# External APIs for data
gem "gbifrb"
gem "msgpack"
group :production do
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
gem 'dalli'
@@ -153,6 +162,7 @@ group :development, :test do
gem 'factory_bot_rails' # for creating test data
gem 'faker'
gem 'haml-rails' # HTML templating language
gem 'pry'
gem 'query_diet'
gem 'rspec-activemodel-mocks'
gem 'rspec-rails' # unit testing framework
@@ -172,11 +182,13 @@ group :development, :test do
end
group :test do
gem 'axe-core-capybara'
gem 'axe-core-rspec'
gem 'codeclimate-test-reporter', require: false
gem 'rails-controller-testing'
gem 'selenium-webdriver'
gem 'timecop'
gem 'webdrivers'
gem 'vcr'
end
group :travis do

View File

@@ -1,3 +1,11 @@
GIT
remote: https://github.com/jquery-ui-rails/jquery-ui-rails.git
revision: 413265e81f790f795239e07e7e25e01429b2f18d
tag: v7.0.0
specs:
jquery-ui-rails (7.0.0)
railties (>= 3.2.16)
GIT
remote: https://github.com/restarone/comfortable-mexican-sofa.git
revision: ccf9415ae220453a199759b8ecbb8e9436c75c85
@@ -25,86 +33,110 @@ GEM
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
actioncable (7.1.3)
actionpack (= 7.1.3)
activesupport (= 7.1.3)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
zeitwerk (~> 2.6)
actionmailbox (7.1.3)
actionpack (= 7.1.3)
activejob (= 7.1.3)
activerecord (= 7.1.3)
activestorage (= 7.1.3)
activesupport (= 7.1.3)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.8)
actionpack (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activesupport (= 7.0.8)
actionmailer (7.1.3)
actionpack (= 7.1.3)
actionview (= 7.1.3)
activejob (= 7.1.3)
activesupport (= 7.1.3)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.8)
actionview (= 7.0.8)
activesupport (= 7.0.8)
rack (~> 2.0, >= 2.2.4)
rails-dom-testing (~> 2.2)
actionpack (7.1.3)
actionview (= 7.1.3)
activesupport (= 7.1.3)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.8)
actionpack (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
actiontext (7.1.3)
actionpack (= 7.1.3)
activerecord (= 7.1.3)
activestorage (= 7.1.3)
activesupport (= 7.1.3)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.8)
activesupport (= 7.0.8)
actionview (7.1.3)
activesupport (= 7.1.3)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
active_link_to (1.0.5)
actionpack
addressable
active_median (0.2.0)
activerecord (>= 4.2)
active_median (0.4.1)
activesupport (>= 6.1)
active_record_union (1.3.0)
activerecord (>= 4.0)
active_utils (3.4.1)
activesupport (>= 4.2)
i18n
activejob (7.0.8)
activesupport (= 7.0.8)
activejob (7.1.3)
activesupport (= 7.1.3)
globalid (>= 0.3.6)
activemodel (7.0.8)
activesupport (= 7.0.8)
activerecord (7.0.8)
activemodel (= 7.0.8)
activesupport (= 7.0.8)
activestorage (7.0.8)
actionpack (= 7.0.8)
activejob (= 7.0.8)
activerecord (= 7.0.8)
activesupport (= 7.0.8)
activemodel (7.1.3)
activesupport (= 7.1.3)
activerecord (7.1.3)
activemodel (= 7.1.3)
activesupport (= 7.1.3)
timeout (>= 0.4.0)
activestorage (7.1.3)
actionpack (= 7.1.3)
activejob (= 7.1.3)
activerecord (= 7.1.3)
activesupport (= 7.1.3)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.8)
activesupport (7.1.3)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
autoprefixer-rails (10.4.7.0)
execjs (~> 2)
axe-core-api (4.8.1)
dumb_delegator
virtus
axe-core-capybara (4.8.1)
axe-core-api
dumb_delegator
axe-core-rspec (4.8.1)
axe-core-api
dumb_delegator
virtus
axiom-types (0.1.1)
descendants_tracker (~> 0.0.4)
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
base64 (0.2.0)
bcrypt (3.1.19)
better_errors (2.10.1)
erubi (>= 1.0.0)
@@ -117,7 +149,7 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (3.1.4)
bigdecimal (3.1.6)
bluecloth (2.2.0)
bonsai-elasticsearch-rails (7.0.1)
elasticsearch-model (< 8)
@@ -132,16 +164,16 @@ GEM
actionpack (>= 5.2)
activemodel (>= 5.2)
builder (3.2.4)
bullet (7.1.4)
bullet (7.1.6)
activesupport (>= 3.0.0)
uniform_notifier (~> 1.11)
byebug (11.1.3)
cancancan (3.5.0)
capybara (3.39.2)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
@@ -162,6 +194,9 @@ GEM
chartkick (5.0.5)
codeclimate-test-reporter (1.0.9)
simplecov (<= 0.13)
coderay (1.1.3)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
coffee-rails (5.0.0)
coffee-script (>= 2.2.0)
railties (>= 5.2.0)
@@ -171,19 +206,22 @@ GEM
coffee-script-source (1.12.2)
comfy_bootstrap_form (4.0.9)
rails (>= 5.0.0)
concurrent-ruby (1.2.2)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
crass (1.0.6)
csv_shaper (1.3.2)
activesupport (>= 3.0.0)
dalli (3.2.6)
dalli (3.2.7)
base64
database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.1.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.3.3)
date (3.3.4)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (4.9.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
@@ -198,61 +236,44 @@ GEM
dotenv-rails (2.8.1)
dotenv (= 2.8.1)
railties (>= 3.2)
elasticsearch (6.8.3)
elasticsearch-api (= 6.8.3)
elasticsearch-transport (= 6.8.3)
elasticsearch-api (6.8.3)
drb (2.2.0)
ruby2_keywords
dumb_delegator (1.0.0)
elasticsearch (7.0.0)
elasticsearch-api (= 7.0.0)
elasticsearch-transport (= 7.0.0)
elasticsearch-api (7.0.0)
multi_json
elasticsearch-model (7.1.1)
activesupport (> 3)
elasticsearch (> 1)
hashie
elasticsearch-rails (7.1.0)
elasticsearch-transport (6.8.3)
faraday (~> 1)
elasticsearch-transport (7.0.0)
faraday
multi_json
erubi (1.12.0)
erubis (2.7.0)
excon (0.93.1)
excon (0.109.0)
execjs (2.8.1)
factory_bot (6.4.2)
factory_bot (6.4.5)
activesupport (>= 5.0.0)
factory_bot_rails (6.4.2)
factory_bot_rails (6.4.3)
factory_bot (~> 6.4)
railties (>= 5.0.0)
faker (3.2.2)
faker (3.2.3)
i18n (>= 1.8.11, < 2)
faraday (1.10.3)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
faraday_middleware (1.2.0)
faraday (~> 1.0)
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (3.1.0)
net-http
ffi (1.16.3)
flickraw (0.9.10)
font-awesome-sass (5.15.1)
sassc (>= 1.11)
friendly_id (5.5.1)
activerecord (>= 4.0.0)
gbifrb (0.2.0)
geocoder (1.8.2)
gibbon (1.2.1)
httparty
@@ -262,8 +283,9 @@ GEM
gravatar-ultimate (2.0.0)
activesupport (>= 2.3.14)
rack
haml (5.2.2)
temple (>= 0.8.0)
haml (6.3.0)
temple (>= 0.8.2)
thor
tilt
haml-i18n-extractor (0.5.9)
activesupport
@@ -276,8 +298,8 @@ GEM
activesupport (>= 5.1)
haml (>= 4.0.6)
railties (>= 5.1)
haml_lint (0.52.0)
haml (>= 4.0)
haml_lint (0.55.0)
haml (>= 5.0)
parallel (~> 1.10)
rainbow
rubocop (>= 1.0)
@@ -306,15 +328,21 @@ GEM
rails-i18n
rainbow (>= 2.2.2, < 4.0)
terminal-table (>= 1.5.1)
icalendar (2.10.1)
ice_cube (~> 0.16)
ice_cube (0.16.4)
ice_nine (0.11.2)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
io-console (0.7.2)
irb (1.11.1)
rdoc
reline (>= 0.4.2)
jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jquery-ui-rails (6.0.1)
railties (>= 3.2.16)
json (2.7.1)
json-schema (4.1.1)
addressable (>= 2.8)
@@ -363,25 +391,28 @@ GEM
mini_magick (4.12.0)
mini_mime (1.1.5)
mini_portile2 (2.8.5)
minitest (5.20.0)
minitest (5.21.2)
moneta (1.0.0)
msgpack (1.7.2)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.2.3)
net-imap (0.3.7)
mutex_m (0.2.0)
net-http (0.4.1)
uri
net-imap (0.4.9.1)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.1)
net-protocol (0.2.2)
timeout
net-smtp (0.3.3)
net-smtp (0.4.0.1)
net-protocol
nio4r (2.5.9)
nokogiri (1.15.5)
nio4r (2.7.0)
nokogiri (1.16.0)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.15.5-x86_64-linux)
nokogiri (1.16.0-x86_64-linux)
racc (~> 1.4)
oauth (0.5.6)
oj (3.16.3)
@@ -400,43 +431,54 @@ GEM
rack
orm_adapter (0.5.0)
parallel (1.24.0)
parser (3.2.2.4)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
percy-capybara (5.0.0)
capybara (>= 3)
pg (1.5.4)
platform-api (3.5.0)
platform-api (3.6.0)
heroics (~> 0.1.1)
moneta (~> 1.0.0)
rate_throttle_client (~> 0.1.0)
popper_js (1.16.1)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
psych (5.1.2)
stringio
public_suffix (5.0.4)
puma (6.4.0)
puma (6.4.2)
nio4r (~> 2.0)
query_diet (0.7.1)
racc (1.7.3)
rack (2.2.8)
rack-cors (2.0.1)
rack (>= 2.0.0)
rack-protection (3.1.0)
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
rack-session (1.0.2)
rack (< 3)
rack-test (2.1.0)
rack (>= 1.3)
rails (7.0.8)
actioncable (= 7.0.8)
actionmailbox (= 7.0.8)
actionmailer (= 7.0.8)
actionpack (= 7.0.8)
actiontext (= 7.0.8)
actionview (= 7.0.8)
activejob (= 7.0.8)
activemodel (= 7.0.8)
activerecord (= 7.0.8)
activestorage (= 7.0.8)
activesupport (= 7.0.8)
rackup (1.0.0)
rack (< 3)
webrick
rails (7.1.3)
actioncable (= 7.1.3)
actionmailbox (= 7.1.3)
actionmailer (= 7.1.3)
actionpack (= 7.1.3)
actiontext (= 7.1.3)
actionview (= 7.1.3)
activejob (= 7.1.3)
activemodel (= 7.1.3)
activerecord (= 7.1.3)
activestorage (= 7.1.3)
activesupport (= 7.1.3)
bundler (>= 1.15.0)
railties (= 7.0.8)
railties (= 7.1.3)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
@@ -456,13 +498,14 @@ GEM
rails_stdout_logging
rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5)
railties (7.0.8)
actionpack (= 7.0.8)
activesupport (= 7.0.8)
method_source
railties (7.1.3)
actionpack (= 7.1.3)
activesupport (= 7.1.3)
irb
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
raindrops (0.20.0)
rake (13.1.0)
@@ -470,9 +513,14 @@ GEM
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
redis-client (0.18.0)
rdoc (6.6.2)
psych (>= 4.0.0)
recaptcha (5.16.0)
redis-client (0.19.1)
connection_pool
regexp_parser (2.8.3)
regexp_parser (2.9.0)
reline (0.4.2)
io-console (~> 0.5)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
@@ -494,7 +542,7 @@ GEM
rspec-mocks (3.12.6)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-rails (6.1.0)
rspec-rails (6.1.1)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
@@ -517,11 +565,11 @@ GEM
rswag-ui (2.13.0)
actionpack (>= 3.1, < 7.2)
railties (>= 3.1, < 7.2)
rubocop (1.59.0)
rubocop (1.60.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.2.2.4)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
@@ -530,16 +578,16 @@ GEM
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-capybara (2.19.0)
rubocop-capybara (2.20.0)
rubocop (~> 1.41)
rubocop-factory_bot (2.24.0)
rubocop (~> 1.33)
rubocop-rails (2.23.0)
rubocop-factory_bot (2.25.1)
rubocop (~> 1.41)
rubocop-rails (2.23.1)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.25.0)
rubocop-rspec (2.26.1)
rubocop (~> 1.40)
rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22)
@@ -564,19 +612,19 @@ GEM
tilt
scout_apm (5.3.5)
parser
searchkick (4.6.3)
activemodel (>= 5)
elasticsearch (>= 6, < 7.14)
searchkick (5.3.1)
activemodel (>= 6.1)
hashie
selenium-webdriver (4.10.0)
selenium-webdriver (4.17.0)
base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
sidekiq (7.2.0)
sidekiq (7.2.1)
concurrent-ruby (< 2)
connection_pool (>= 2.3.0)
rack (>= 2.2.4)
redis-client (>= 0.14.0)
redis-client (>= 0.19.0)
simplecov (0.13.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
@@ -591,39 +639,43 @@ GEM
activesupport (>= 5.2)
sprockets (>= 3.0.0)
ssrf_filter (1.1.2)
stringio (3.1.0)
sysexits (1.2.0)
temple (0.10.3)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
terser (1.2.0)
execjs (>= 0.3.0, < 3)
thor (1.3.0)
thread_safe (0.3.6)
tilt (2.3.0)
timecop (0.9.8)
timeout (0.4.0)
timeout (0.4.1)
trollop (1.16.2)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.5.0)
unicorn (6.1.0)
kgio (~> 2.6)
raindrops (~> 0.7)
uniform_notifier (1.16.0)
uri (0.13.0)
validate_url (1.0.15)
activemodel (>= 3.0.0)
public_suffix
vcr (6.2.0)
virtus (2.0.0)
axiom-types (~> 0.1)
coercible (~> 1.0)
descendants_tracker (~> 0.0, >= 0.0.3)
warden (1.2.9)
rack (>= 2.0.9)
webdrivers (5.3.1)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (~> 4.0, < 4.11)
webrat (0.7.3)
nokogiri (>= 1.2.0)
rack (>= 1.0)
rack-test (>= 0.5.3)
webrick (1.8.1)
websocket (1.2.9)
websocket (1.2.10)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
@@ -641,9 +693,11 @@ PLATFORMS
x86_64-linux
DEPENDENCIES
active_median (= 0.2.0)
active_median
active_record_union
active_utils
axe-core-capybara
axe-core-rspec
better_errors
bluecloth
bonsai-elasticsearch-rails
@@ -667,14 +721,14 @@ DEPENDENCIES
devise
discard (>= 1.2)
dotenv-rails
elasticsearch (< 7.0.0)
elasticsearch (~> 7.0.0)
factory_bot_rails
faker
faraday
faraday_middleware
flickraw
font-awesome-sass
friendly_id
gbifrb
geocoder
gibbon (~> 1.2.0)
gravatar-ultimate
@@ -684,8 +738,9 @@ DEPENDENCIES
haml_lint (>= 0.25.1)
hashie (>= 3.5.3)
i18n-tasks
icalendar
jquery-rails
jquery-ui-rails
jquery-ui-rails!
jsonapi-resources
jsonapi-swagger
leaflet-rails (>= 1.9.2)
@@ -696,6 +751,7 @@ DEPENDENCIES
material-sass (= 4.1.1)
material_icons
memcachier
msgpack
oj
omniauth (~> 1.3)
omniauth-flickr (>= 0.0.15)
@@ -703,15 +759,17 @@ DEPENDENCIES
percy-capybara (~> 5.0.0)
pg
platform-api
pry
puma
query_diet
rack-cors
rack-protection (>= 2.0.1)
rails (~> 7.0.7)
rails (~> 7.1.0)
rails-assets-leaflet.markercluster!
rails-controller-testing
rails_12factor
rake (>= 10.0.0)
recaptcha
responders
rspec-activemodel-mocks
rspec-rails
@@ -729,18 +787,18 @@ DEPENDENCIES
selenium-webdriver
sidekiq
sprockets (< 4)
terser
timecop
uglifier
unicorn
validate_url
webdrivers
vcr
webrat
will_paginate
will_paginate-bootstrap-style
xmlrpc
RUBY VERSION
ruby 3.1.4p223
ruby 3.1.4p223
BUNDLED WITH
2.3.11

View File

@@ -5,7 +5,7 @@ jQuery ->
$(".remove-altname-row").css("display", "inline-block")
-$ ->
sci_template = "<div id='sci_template[INDEX]' class='template col-md-12'><div class='col-md-2'><label>Scientific name INDEX:</label></div><div class='col-md-8'><input name='sci_name[INDEX]' class='form-control', id='sci_name[INDEX]')'></input><span class='help-block'>Scientific name of crop.</span></div><div class='col-md-2'></div></div>"
sci_template = "<div id='sci_template[INDEX]' class='template col-md-12'><div class='col-md-2'><label>Scientific name INDEX:</label></div><div class='col-md-8'><input name='sci_name[INDEX]' class='scientific-name-auto-suggest form-control' id='sci_name[INDEX]' data-source-url='/scientific_names/gbif_suggest')'></input><span class='help-block'>Scientific name of crop</span><input type='text' id='sci_gbif_key[INDEX]' class=''></div><div class='col-md-2'></div></div>"
sci_index = $('#scientific_names .template').length + 1
@@ -21,7 +21,7 @@ jQuery ->
element = document.getElementById(tmp)
element.remove()
alt_template = "<div id='alt_template[INDEX]' class='template col-md-12'><div class='col-md-2'><label>Alternate name INDEX:</label></div><div class='col-md-8'><input name='alt_name[INDEX]' class='form-control', id='alt_name[INDEX]')'></input><span class='help-block'>Alternate name of crop.</span></div><div class='col-md-2'></div></div>"
alt_template = "<div id='alt_template[INDEX]' class='template col-md-12'><div class='col-md-2'><label>Alternate name INDEX:</label></div><div class='col-md-8'><input name='alt_name[INDEX]' class='form-control' id='alt_name[INDEX]')'></input><span class='help-block'>Alternate name of crop.</span></div><div class='col-md-2'></div></div>"
alt_index = $('#alternate_names .template').length + 1

View File

@@ -0,0 +1,31 @@
# TODO: This assumes one autocomplete per page.
# Needs to be a function so that when we append one of these, it gets uniquely associated with the hidden controls.
jQuery ->
if el = $( '.scientific-name-auto-suggest' )
id = $( '.scientific-name-auto-suggest-id' )
el.autocomplete
minLength: 3,
source: el.attr( 'data-source-url' ),
focus: ( event, ui ) ->
el.val( ui.item.canonicalName )
id.val( ui.item.nameKey )
false
select: ( event, ui ) ->
el.val( ui.item.canonicalName )
id.val( ui.item.nameKey )
false
response: ( event, ui ) ->
id.val( "" )
for item in ui.content
if item.name == el.val()
id.val( item.nameKey )
if el.data( 'uiAutocomplete' )
el.data( 'uiAutocomplete' )._renderItem = ( ul, item ) ->
$( '<li class="list-group-item"></li>' )
.data( 'item.autocomplete', item )
.append( "<a>#{item.canonicalName} (#{item.scientificName}) - #{item.rank}</a>" )
.appendTo( ul )

View File

@@ -19,7 +19,7 @@
padding-bottom: 0;
}
h5.crop-sci-name {
.crop-sci-name {
background-color: $beige;
color: $black;
font-size: 0.7em;

View File

@@ -1,10 +1,10 @@
//$screen-md-min: 1028px
// Base colours
$beige: #f3f1ee;
$beige: #f4f2ef;
$brown: #413f3b;
$green: #5f8e43;
$green: #57803c;
$blue: #2f4365;
$red: #ff4d43;
$orange: #ffa500;

View File

@@ -101,12 +101,16 @@ section {
background: $white;
box-shadow: 1px 3px 3px 1px darken($beige, 20%);
cursor: pointer;
transition: 0.3s transform cubic-bezier(0.155, 1.105, 0.295, 1.12), 0.3s box-shadow,
transition:
0.3s transform cubic-bezier(0.155, 1.105, 0.295, 1.12),
0.3s box-shadow,
0.3s -webkit-transform cubic-bezier(0.155, 1.105, 0.295, 1.12);
}
.card:hover {
box-shadow: 0 10px 20px darken($beige, 30%), 0 4px 8px darken($beige, 40%);
box-shadow:
0 10px 20px darken($beige, 30%),
0 4px 8px darken($beige, 40%);
transform: scale(1.1);
}
}
@@ -354,7 +358,9 @@ ul.thumbnail-buttons {
text-align: center;
}
}
.text-muted {
color: $blue;
}
.jumbotron {
background-color: $beige;
margin-bottom: 1em;
@@ -364,15 +370,23 @@ ul.thumbnail-buttons {
h1 {
font-size: 400%;
}
.stats a {
color: $black;
}
// signup widget on homepage
.signup {
background-color: lighten($green, 40%);
border: 1px solid lighten($green, 20%);
background-color: darken($green, 20%);
border: 1px solid darken($green, 20%);
color: $white;
border-radius: 6px;
line-height: 200%;
padding: 15px;
text-align: center;
.btn-info {
background-color: $blue;
}
}
.info {

View File

@@ -8,7 +8,7 @@ module Admin
responders :flash
def index
@roles = Role.all.order(:name)
@roles = Role.all.order(:name).paginate(page: params[:page])
respond_with @roles
end
@@ -33,7 +33,7 @@ module Admin
def destroy
@role.destroy
respond_with @role, location: admin_roles_path
respond_with @role, location: admin_roles_path, notice: "Role was successfully deleted"
end
private

View File

@@ -8,7 +8,7 @@ class AdminController < ApplicationController
def newsletter
authorize! :manage, :all
@members = Member.confirmed.wants_newsletter.all
@members = Member.confirmed.wants_newsletter.all.paginate(page: params[:page], per_page: 100)
respond_with @members
end
end

View File

@@ -9,7 +9,7 @@ class AlternateNamesController < ApplicationController
# GET /alternate_names
# GET /alternate_names.json
def index
@alternate_names = AlternateName.all.order(:name)
@alternate_names = AlternateName.all.order(:name).paginate(page: params[:page], per_page: 100)
respond_with(@alternate_names)
end

View File

@@ -46,6 +46,12 @@ class CropsController < ApplicationController
respond_with @crop, location: @crop
end
def gbif
@crop = Crop.find(params[:crop_slug])
@crop.update_gbif_data!
respond_with @crop, location: @crop
end
def hierarchy
@crops = Crop.toplevel.order(:name)
respond_with @crops
@@ -58,7 +64,15 @@ class CropsController < ApplicationController
page: params[:page],
per_page: Crop.per_page,
current_member:)
respond_with @crops
respond_to do |format|
format.html do
render
end
format.json do
render json: @crops.to_a
end
end
end
def show
@@ -120,6 +134,7 @@ class CropsController < ApplicationController
if @crop.approval_status_changed?(from: "pending", to: "approved")
notifier.deliver_now!
@crop.update_openfarm_data!
@crop.update_gbif_data!
end
else
@crop.approval_status = @crop.approval_status_was
@@ -163,7 +178,7 @@ class CropsController < ApplicationController
return if params[param_name].blank?
destroy_names(name_type)
params[param_name].each do |_i, value|
params[param_name].each_value do |value|
create_name!(name_type, value) unless value.empty?
end
end

View File

@@ -41,7 +41,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def after_sign_in_path_for(resource)
if resource.tos_agreement
super resource
super(resource)
else
finish_signup_path(resource)
end

View File

@@ -63,7 +63,7 @@ class PhotosController < ApplicationController
def photo_params
params.require(:photo).permit(:source_id, :source, :title, :license_name,
:license_url, :thumbnail_url, :fullsize_url, :link_url)
:license_url, :thumbnail_url, :fullsize_url, :link_url, :date_taken)
end
# Item with photos attached

View File

@@ -6,7 +6,7 @@ class PlantPartsController < ApplicationController
responders :flash
def index
@plant_parts = PlantPart.all.order(:name)
@plant_parts = PlantPart.all.order(:name).paginate(page: params[:page], per_page: 100)
respond_with(@plant_parts)
end

View File

@@ -3,6 +3,7 @@
class PlantingsController < DataController
after_action :update_crop_medians, only: %i(create update destroy)
after_action :update_planting_medians, only: :update
respond_to :ics, only: [:index] # TODO: This can be shifted up when all relevant controllers respond to ical
def index
@show_all = params[:all] == '1'
@@ -29,7 +30,6 @@ class PlantingsController < DataController
)
@filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_fs(:number)}.csv"
respond_with(@plantings)
end

View File

@@ -3,6 +3,8 @@
class RegistrationsController < Devise::RegistrationsController
respond_to :json
prepend_before_action :check_captcha, only: [:create] # Change this to be any actions you want to protect with recaptcha.
def edit
@twitter_auth = current_member.auth('twitter')
@flickr_auth = current_member.auth('flickr')
@@ -46,6 +48,25 @@ class RegistrationsController < Devise::RegistrationsController
render "edit"
end
end
private
def sign_up_params
params.require(:member).permit(:login_name, :email, :tos_agreement, :newsletter, :password, :password_confirmation)
end
def check_captcha
return if verify_recaptcha # verify_recaptcha(action: 'signup') for v3
self.resource = resource_class.new sign_up_params
resource.validate # Look for any other validation errors besides reCAPTCHA
set_minimum_password_length
respond_with_navigational(resource) do
flash.discard(:recaptcha_error) # We need to discard flash to avoid showing it on the next page reload
render :new
end
end
end
# check if we need the current password to update fields

View File

@@ -1,15 +1,15 @@
# frozen_string_literal: true
class ScientificNamesController < ApplicationController
before_action :authenticate_member!, except: %i(index show)
load_and_authorize_resource
before_action :authenticate_member!, except: %i(index show gbif_suggest)
load_and_authorize_resource except: [:gbif_suggest]
respond_to :html, :json
responders :flash
# GET /scientific_names
# GET /scientific_names.json
def index
@scientific_names = ScientificName.all.order(:name)
@scientific_names = ScientificName.all.order(:name).paginate(page: params[:page], per_page: 100)
respond_with(@scientific_names)
end
@@ -35,7 +35,7 @@ class ScientificNamesController < ApplicationController
def create
@scientific_name = ScientificName.new(scientific_name_params)
@scientific_name.creator = current_member
gbif_sync!(@scientific_name)
@scientific_name.save
respond_with(@scientific_name.crop)
end
@@ -43,7 +43,9 @@ class ScientificNamesController < ApplicationController
# PUT /scientific_names/1
# PUT /scientific_names/1.json
def update
@scientific_name.update(scientific_name_params)
@scientific_name.assign_attributes(scientific_name_params)
gbif_sync!(@scientific_name)
@scientific_name.save
respond_with(@scientific_name.crop)
end
@@ -56,9 +58,26 @@ class ScientificNamesController < ApplicationController
respond_with(@crop)
end
def gbif_suggest
render json: gbif_service.suggest(params[:term])
end
private
def gbif_sync!(model)
return unless model.gbif_key
result = gbif_service.fetch(model.gbif_key)
model.gbif_rank = result["rank"]
model.gbif_status = result["status"]
end
def scientific_name_params
params.require(:scientific_name).permit(:crop_id, :name)
params.require(:scientific_name).permit(:crop_id, :name, :gbif_key)
end
def gbif_service
GbifService.new
end
end

View File

@@ -93,7 +93,7 @@ module IconsHelper
def plant_part_icon(name)
if File.exist? Rails.root.join('app', 'assets', 'images', 'icons', 'plant_parts', "#{name}.svg")
image_tag "icons/plant_parts/#{name}.svg", class: 'img img-icon', 'aria-hidden' => "true"
image_tag "icons/plant_parts/#{name}.svg", class: 'img img-icon', 'aria-hidden' => "true", alt: name
else
planting_icon
end
@@ -101,7 +101,7 @@ module IconsHelper
def crop_icon(crop)
if crop.svg_icon.present?
image_tag(crop_path(crop, format: 'svg'), class: 'crop-icon')
image_tag(crop_path(crop, format: 'svg'), class: 'crop-icon', alt: crop)
elsif crop.parent.present?
crop_icon(crop.parent)
else
@@ -123,6 +123,6 @@ module IconsHelper
end
def image_icon(icon)
image_tag "icons/#{icon}.svg", class: 'img img-icon', 'aria-hidden' => "true"
image_tag "icons/#{icon}.svg", class: 'img img-icon', 'aria-hidden' => "true", alt: icon
end
end

View File

@@ -79,6 +79,7 @@ class Ability
can :manage, ScientificName
can :manage, AlternateName
can :openfarm, Crop
can :gbif, Crop
end
# any member can create a crop provisionally

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
module GbifData
extend ActiveSupport::Concern
included do
def update_gbif_data!
GbifService.new.update_crop(self)
end
end
end

View File

@@ -4,6 +4,7 @@ class Crop < ApplicationRecord
extend FriendlyId
include PhotoCapable
include OpenFarmData
include GbifData
include SearchCrops
friendly_id :name, use: %i(slugged finders)

View File

@@ -16,8 +16,13 @@ class Photo < ApplicationRecord
Crop.distinct.joins(:photo_associations).where(photo_associations: { photo: self })
end
validates :fullsize_url, url: true
validates :thumbnail_url, url: true
validates :fullsize_url, url: true, presence: true
validates :thumbnail_url, url: true, presence: true
validates :link_url, url: true, presence: true
validates :owner, presence: true
validates :title, presence: true
validates :license_name, presence: true # Should assert this is one of CC-BY, CC-BY-NC, etc
validates :license_url, url: true, allow_blank: true
# creates a relationship for each assignee type
PHOTO_CAPABLE.each do |type|

View File

@@ -24,8 +24,11 @@ class Post < ApplicationRecord
#
# Validations
validates :subject, presence: true, length: { maximum: 255 }
validates :body, presence: true
def author_date_subject
return unless author
# slugs are created before created_at is set
time = created_at || Time.zone.now
"#{author.login_name} #{time.strftime('%Y%m%d')} #{subject}"

View File

@@ -0,0 +1,193 @@
# frozen_string_literal: true
require 'English'
class GbifService
def initialize
@cropbot = Member.find_by(login_name: 'cropbot')
@species = Gbif::Species
end
def suggest(term)
# Query the GBIF name autocomplete and discover the scientific name.
# [
# {
# "key": 2932942,
# "nameKey": 1970347,
# "kingdom": "Plantae",
# "phylum": "Tracheophyta",
# "order": "Solanales",
# "family": "Solanaceae",
# "genus": "Capsicum",
# "species": "Capsicum chinense",
# "kingdomKey": 6,
# "phylumKey": 7707728,
# "classKey": 220,
# "orderKey": 1176,
# "familyKey": 7717,
# "genusKey": 2932937,
# "speciesKey": 2932942,
# "parent": "Capsicum",
# "parentKey": 2932937,
# "nubKey": 2932942,
# "scientificName": "Capsicum chinense Jacq.",
# "canonicalName": "Capsicum chinense",
# "rank": "SPECIES",
# "status": "ACCEPTED",
# "synonym": false,
# "higherClassificationMap": {
# "6": "Plantae",
# "220": "Magnoliopsida",
# "1176": "Solanales",
# "7717": "Solanaceae",
# "2932937": "Capsicum",
# "7707728": "Tracheophyta"
# },
# "class": "Magnoliopsida"
# },
# {
# "key": 12079498,
# "nameKey": 81778754,
# "kingdom": "Plantae",
# "phylum": "Tracheophyta",
# "order": "Solanales",
# "family": "Solanaceae",
# "genus": "Capsicum",
# "species": "Capsicum chinense",
# "kingdomKey": 6,
# "phylumKey": 7707728,
# "classKey": 220,
# "orderKey": 1176,
# "familyKey": 7717,
# "genusKey": 2932937,
# "speciesKey": 2932942,
# "parent": "Capsicum",
# "parentKey": 2932937,
# "nubKey": 12079498,
# "scientificName": "Capsicum annuum var. chinense (Jacq.) Alef.",
# "canonicalName": "Capsicum annuum chinense",
# "rank": "VARIETY",
# "status": "SYNONYM",
# "synonym": true,
# "higherClassificationMap": {
# "6": "Plantae",
# "220": "Magnoliopsida",
# "1176": "Solanales",
# "7717": "Solanaceae",
# "2932937": "Capsicum",
# "2932942": "Capsicum chinense",
# "7707728": "Tracheophyta"
# },
# "class": "Magnoliopsida"
# }
# ]
@species.name_suggest(q: term)
end
def import!
Crop.order(updated_at: :desc).each do |crop|
Rails.logger.debug { "#{crop.id}, #{crop.name}" }
update_crop(crop) if crop.valid?
rescue ActiveRecord::RecordInvalid
Rails.logger.error($ERROR_INFO.message)
end
end
def update_crop(crop)
# Attempt to resolve the scientific names via /species/match.
gbif_usage_key = crop.scientific_names.detect { |sn| sn.gbif_key.present? }&.gbif_key
unless gbif_usage_key
crop.scientific_names.each do |sn|
result = @species.name_backbone(name: sn.name) # , higherTaxonKey: 6, nameType: 'SCIENTIFIC')
next unless result["confidence"] > 95 && result["matchType"] == "EXACT"
sn.gbif_key = result["usageKey"]
sn.gbif_rank = result["rank"]
sn.gbif_status = result["status"]
sn.save!
end
gbif_usage_key = crop.scientific_names.detect { |sn| sn.gbif_key.present? }&.gbif_key
end
# No match? Fall back to common names
unless gbif_usage_key
query_results = @species.name_lookup(q: crop.name, higherTaxonKey: 6)
# We only want one result, otherwise it needs human.
return unless query_results["results"].length == 1
query_result = query_results["results"].first
gbif_usage_key = query_result["key"]
crop.scientific_names.create!(gbif_key: gbif_usage_key, name: query_result["canonicalName"], creator: @cropbot)
end
gbif_record = fetch(gbif_usage_key)
if gbif_record.present?
# crop.update! openfarm_data: gbif_record.fetch('data', false)
# save_companions(crop, gbif_record)
save_photos(crop, gbif_usage_key)
else
Rails.logger.debug "\tcrop not found on GBIF"
# crop.update!(openfarm_data: false)
end
end
def save_photos(crop, key)
# https://api.gbif.org/v1/occurrence/search?taxon_key=3084850
occurrences = Gbif::Occurrences.search(taxonKey: key, mediatype: 'StillImage', limit: 3, hasCoordinate: true)
occurrences["results"].each do |result|
next unless result["media"]
media = result["media"].first
next unless media["identifier"]
# Example: "https://inaturalist-open-data.s3.amazonaws.com/photos/250226497/original.jpg"
url = media["identifier"]
md5 = Digest::MD5.hexdigest(url)
width = 200
thumbnail = "https://api.gbif.org/v1/image/cache/#{width}x/occurrence/#{result['key']}/media/#{md5}"
next unless url.start_with? 'http'
next if Photo.find_by(source_id: result["key"], source: 'gbif')
next if media["references"].blank?
photo = Photo.new(
# This is for the overall observation which may technically have multiple media. However, we're only taking the first.
source_id: result["key"],
source: 'gbif',
owner: @cropbot,
thumbnail_url: thumbnail,
fullsize_url: url,
title: "Photo by #{media['creator']} via #{media['publisher']} (Copyright #{media['rightsHolder']})",
license_name: case media["license"]
when "http://creativecommons.org/licenses/by/4.0/"
"CC BY 4.0"
when "http://creativecommons.org/licenses/by-nc/4.0/"
"CC BY-NC 4.0"
else
media["license"]
end,
license_url: media["license"],
link_url: media["references"]
)
photo.date_taken = DateTime.parse(media["created"]) if media["created"]
if photo.valid?
Photo.transaction do
photo.save
PhotoAssociation.find_or_create_by! photo:, photographable: crop
end
Rails.logger.debug { "\t saved photo #{photo.id} #{photo.source_id}" }
else
Rails.logger.warn "Photo not valid"
end
end
end
def fetch(key)
Gbif::Request.new("species/#{key}", nil, nil, nil).perform
end
end

View File

@@ -30,6 +30,7 @@
%li= link_to "Crop Wrangling", wrangle_crops_path, class: 'nav-link'
%li= link_to "Alternate names", alternate_names_path, class: 'nav-link'
%li= link_to "Scientific names", scientific_names_path, class: 'nav-link'
%li= link_to "Plant parts", plant_parts_path, class: 'nav-link'
.col-md-4
.card

View File

@@ -4,3 +4,4 @@
- @members.each do |m|
= m.email
%br/
= will_paginate @members

View File

@@ -5,7 +5,7 @@
%li.breadcrumb-item.active= link_to 'Roles', admin_roles_path
- if can? :create, Role
%p= link_to 'New Role', new_admin_role_path, class: 'btn btn-primary'
%p= link_to 'New role', new_admin_role_path, class: 'btn btn-primary'
%table.table.table-striped
%thead
@@ -25,6 +25,8 @@
= edit_icon
= t('.edit')
- if can?(:destroy, role) && ! role.members.any?
= link_to admin_role_path(role), method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs text-danger' do
= link_to admin_role_path(role), method: :delete, data: { confirm: t(:are_you_sure?) }, class: 'btn btn-default btn-xs text-danger' do
= delete_icon
= t('.delete')
= will_paginate(@roles)

View File

@@ -3,7 +3,7 @@
- if content_for? :title
%h1.h2-responsive.text-center
%strong=yield :title
= form_for @alternate_name, html: { class: 'form-horizontal', role: "form" } do |f|
= form_for @alternate_name, html: { class: 'form-horizontal' } do |f|
- if @alternate_name.errors.any?
#error_explanation
%h2

View File

@@ -17,10 +17,11 @@
%td= link_to 'Show', alternate_name
%td
- if can? :edit, alternate_name
= link_to 'Edit', edit_alternate_name_path(alternate_name), class: 'btn btn-default btn-xs'
= link_to t('buttons.edit'), edit_alternate_name_path(alternate_name), class: 'btn btn-default btn-xs'
%td
- if can? :destroy, alternate_name
= link_to 'Delete', alternate_name,
method: :delete,
data: { confirm: 'Are you sure?' },
class: 'btn btn-default btn-xs'
= link_to t('buttons.delete'), alternate_name,
method: :delete,
data: { confirm: t(:are_you_sure?) },
class: 'btn btn-default btn-xs'
= will_paginate(@alternate_names)

View File

@@ -3,7 +3,7 @@
- if content_for? :title
%h1.h2-responsive.text-center
%strong=yield :title
= form_for(@comment, html: { class: "form-horizontal", role: "form" }) do |f|
= form_for(@comment, html: { class: "form-horizontal" }) do |f|
- if @comment.errors.any?
#error_explanation
%h2

View File

@@ -7,7 +7,7 @@
%item
%title Comment by #{comment.author.login_name} on #{comment.post.subject}
%description
:escaped
:escaped_markdown
<p>
Comment on
#{ link_to comment.post.subject, post_url(comment.post) }

View File

@@ -52,9 +52,9 @@
= truncate(strip_tags(conversation.messages.last.body), length: 150, separator: ' ', omission: '... ')
.col-md-1
- if @box == 'trash'
= link_to conversation_path(conversation, box: @box), method: :put, class: 'restore' do
= link_to conversation_path(conversation, box: @box), method: :put, class: 'restore', title: "Restore" do
= icon 'fas', 'trash-restore'
- else
= check_box_tag 'conversation_ids[]', conversation.id, false, class: 'selectable'
= check_box_tag 'conversation_ids[]', conversation.id, false, class: 'selectable', "aria-label": "Select for deletion"
- unless @conversations.empty?
= will_paginate @conversations

View File

@@ -1,7 +1,7 @@
.card.card-crop
.crop-image
= link_to image_tag(crop_image_path(crop),
alt: '',
alt: "Image of #{crop.name}",
class: 'img img-card'),
crop
.card-body

View File

@@ -65,8 +65,12 @@
.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.
= text_field_tag "sci_name[#{index + 1}]", sci.name, id: "sci_name[#{index + 1}]",
class: 'scientific-name-auto-suggest form-control',
data: { source_url: gbif_suggest_scientific_names_path }
%span.help-block Searches GBIF to determine scientific name of crop.
= hidden_field_tag "sci_gbif_key[#{index + 1}]", sci.gbif_key, id: "sci_gbif_key[#{index + 1}]",
class: 'scientific-name-auto-suggest-id'
%h2 Alternate names
= button_tag "+", class: "add-altname-row", type: "button"
= button_tag "-", class: "remove-altname-row", type: "button"

View File

@@ -1,6 +1,6 @@
- cache crop do
= link_to image_tag(crop_image_path(crop),
alt: crop.name, class: 'image-responsive crop-image'),
alt: "Image of #{crop.name}", class: 'image-responsive crop-image'),
crop.name,
rel: "popover",
'data-trigger': 'hover',

View File

@@ -25,4 +25,4 @@
%p= simple_format @crop.description
.col-md-3
= image_tag crop_image_path(@crop),
class: 'img-responsive shadow rounded crop-hero-photo', alt: 'photo of crop'
class: 'img-responsive shadow rounded crop-hero-photo', alt: "Image of #{@crop.name}"

View File

@@ -16,7 +16,13 @@
= delete_icon
= t('.delete')
- else
.badge= sn.name
- if sn.gbif_key
= link_to sn.name, "https://www.gbif.org/species/#{sn.gbif_key}",
class: 'card-link',
target: "_blank",
rel: "noopener noreferrer"
- else
.badge= sn.name
%p.text-right
- if can? :edit, crop

View File

@@ -2,11 +2,12 @@
.card.crop-thumbnail
= link_to crop_path(slug: crop.slug) do
= image_tag(crop.thumbnail_url.presence || placeholder_image,
alt: crop.name,
alt: "Image of #{crop.name}",
class: 'img img-card')
.text
%h3.crop-name= link_to crop.name, crop_path(slug: crop.slug)
%h5.crop-sci-name
= crop.scientific_names.first
- if crop.scientific_names.any?
%div.crop-sci-name
= crop.scientific_names.first

View File

@@ -14,6 +14,10 @@
= icon 'far', 'update'
Fetch data from OpenFarm
= link_to crop_gbif_path(crop), method: :post, class: 'dropdown-item' do
= icon 'far', 'update'
Fetch data from GBIF
- if can? :destroy, crop
.dropdown-divider
= delete_button(crop, classes: 'dropdown-item text-danger')

View File

@@ -86,7 +86,7 @@
= 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
%span.badge.badge-primary.badge-pill=@crop.plantings.active.size
.list-group-item.d-flex.justify-content-between.align-items-center
= link_to crop_harvests_path(@crop), class: 'card-link' do
= harvest_icon

View File

@@ -3,9 +3,10 @@
%h1 Join #{ENV['GROWSTUFF_SITE_NAME']}
.card-body
%p Sign up for a #{ENV['GROWSTUFF_SITE_NAME']} account to track your vegetable garden and connect with other local growers.
%p If you have accessibility issues with the captcha, please contact us via the links in the footer and we will help.
= bootstrap_form_for(resource, as: resource_name, url: registration_path(resource_name),
html: { class: "text-center border border-light p-5" }) do |f|
html: { class: "text-center border border-light p-5", data: { turbo: false } }) do |f|
= render 'devise/shared/error_messages', resource: resource
= f.text_field :login_name
@@ -28,4 +29,9 @@
= f.submit "Sign up", class: 'btn btn-block btn-success'
-# START add reCAPTCHA
= flash[:recaptcha_error]
= recaptcha_tags
-# END add reCAPTCHA
.card-footer= render "devise/shared/links"

View File

@@ -1,4 +1,4 @@
= form_for @garden_type, html: { class: 'form-horizontal', role: "form" } do |f|
= form_for @garden_type, html: { class: 'form-horizontal' } do |f|
- if @garden_type.errors.any?
#error_explanation
%h2= "#{pluralize(@garden_type.errors.count, "error")} prohibited this garden_type from being saved:"

View File

@@ -1,5 +1,5 @@
.card
= link_to garden do
= image_tag garden_image_path(garden), class: 'img-card', alt: garden
= image_tag garden_image_path(garden), class: 'img-card', alt: "Image of #{garden.name}"
.card-body.text-center
%h4.card-title= garden.name

View File

@@ -1,3 +1,3 @@
= link_to image_tag(garden_image_path(garden),
alt: garden.name, class: 'img-responsive'),
alt: "Image of #{garden.name}", class: 'img-responsive'),
garden_path(garden)

View File

@@ -12,9 +12,10 @@
.row
.col-md-2
= render 'layouts/nav', model: Garden
= link_to show_inactive_tickbox_path('gardens', owner: @owner, show_all: @show_all) do
= check_box_tag 'active', 'all', @show_all
include in-active
%label
= link_to show_inactive_tickbox_path('gardens', owner: @owner, show_all: @show_all) do
= check_box_tag 'active', 'all', @show_all
include in-active
- if @owner.present?
%hr/
= render @owner

View File

@@ -33,7 +33,7 @@
%h3
Harvested
= editable :date, @harvest, :harvested_at, display_field: '.harvested_at'
%strong.harvested_at #{time_ago_in_words @harvest.harvested_at} ago
%strong.harvested_at #{distance_of_time_in_words @harvest.harvested_at, Time.zone.now.to_date} ago
%span.harvested_at= I18n.l @harvest.harvested_at
.card{class: @harvest.quantity.present? ? '' : 'text-muted'}

View File

@@ -1,9 +1,10 @@
.row.homepage-blurb
.col-md-8.info
%h1 Growstuff - An open gardening platform
%p= t('.intro', site_name: ENV['GROWSTUFF_SITE_NAME'])
= render 'stats'
.col-md-4
.signup
%p= t('.perks')
%p= link_to(t('.sign_up'), new_member_registration_path, class: 'btn btn-info btn-block')
%p= link_to(t('.sign_up'), new_member_registration_path, class: 'btn btn-primary btn-block')
%p= t('.already_html', sign_in: link_to(t('.sign_in_linktext'), new_member_session_path, class: 'btn btn-primary'))

View File

@@ -4,9 +4,9 @@
= link_to harvest_path(slug: harvest.slug), class: 'list-group-item list-group-item-action flex-column align-items-start' do
.d-flex.w-100.justify-content-between.homepage--list-item
%div
%h5= harvest.crop_name
%h4= harvest.crop_name
%span.badge.badge-success=harvest.plant_part
%small.text-muted
harvested by #{harvest.owner_login_name}
%p.mb-2
= image_tag harvest.thumbnail_url, width: 75, class: 'rounded shadow'
= image_tag harvest.thumbnail_url, width: 75, class: 'rounded shadow', alt: "Image of #{harvest.crop_name} by #{harvest.owner}"

View File

@@ -3,9 +3,9 @@
= link_to planting_path(slug: planting['slug']), class: 'list-group-item list-group-item-action flex-column align-items-start' do
.d-flex.w-100.justify-content-between.homepage--list-item
%p.mb-2
= image_tag planting['thumbnail_url'], width: 75, class: 'rounded shadow'
= image_tag planting['thumbnail_url'], width: 75, class: 'rounded shadow', alt: "Image of #{planting['crop_name']} by #{planting['owner_login_name']}"
.text-right
%h5= planting['crop_name']
%h4= planting['crop_name']
- if planting['planted_from'].present?
%span.badge.badge-success= planting['planted_from'].pluralize
%small.text-muted planted by #{planting['owner_login_name']}

View File

@@ -22,10 +22,10 @@
= render 'crops'
= link_to "#{t('home.crops.view_all')} »", crops_path, class: 'btn btn-block'
.col-xl-3.col-12
%section.recent-crops
%section.recent-crops.card
- cache cache_key_for(Crop, 'recent') do
%h2= t('.recently_added')
%p
%p.card-body
!= CropSearchService.recent(30).map { |c| link_to(c['name'], crop_path(slug: c['slug'])) }.join(", ")
.col-xl-3.col
%section.plantings

View File

@@ -3,13 +3,13 @@
- if signed_in?
%li.nav-item
= link_to timeline_index_path, method: :get, class: 'nav-link text-white' do
= image_tag 'icons/notification.svg', class: 'img img-icon'
= image_tag 'icons/notification.svg', class: 'img img-icon', alt: "Notifications"
%li.nav-item
= link_to member_gardens_path(current_member), class: 'nav-link text-white' do
= link_to member_gardens_path(current_member), class: 'nav-link text-white', title: "My gardens" do
= image_icon 'gardens'
%li.nav-item.dropdown
%a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#", role: "button"}
= image_tag "icons/gardener.svg", class: 'img img-icon'
= image_tag "icons/gardener.svg", class: 'img img-icon', alt: t('.record'), aria: { hidden: "true" }
= t('.record')
.dropdown-menu
= link_to new_planting_path, class: 'dropdown-item' do
@@ -60,7 +60,7 @@
%li.nav-item.dropdown
%a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#", role: "button"}
= image_tag(avatar_uri(current_member, 50), alt: '', height: 25, width: 25)
= image_tag(avatar_uri(current_member, 50), alt: 'Avatar of current member', height: 25, width: 25, aria: { hidden: "true" })
= current_member.login_name
- if current_member.unread_count.positive?
%span.badge.badge-info= current_member.unread_count

View File

@@ -1,9 +1,9 @@
- if current_member.present?
.flex-column.nav-pills.layout-nav
.flex-column.nav-pills.layout-nav{"role" => "tablist", "aria-orientation"=>"vertical"}
/ %h2.card-title #{model} links
= link_to url_for([current_member, model]), class: 'nav-link' do
= link_to url_for([current_member, model]), class: 'nav-link tab' do
My #{model.model_name.human.pluralize}
= link_to model, class: 'nav-link' do
= link_to model, class: 'nav-link tab' do
Everyone's #{model.model_name.human.pluralize}
- if can?(:create, model)
= link_to url_for([model, action: :new]), class: 'btn' do

View File

@@ -12,9 +12,10 @@
.container
#maincontainer
- if content_for?(:breadcrumbs)
%ol.breadcrumb{ "aria-label" => "breadcrumb" }
%li.breadcrumb-item= link_to 'Home', root_path
= yield(:breadcrumbs)
%nav{ "aria-label" => "breadcrumb" }
%ol.breadcrumb
%li.breadcrumb-item= link_to 'Home', root_path
= yield(:breadcrumbs)
- if content_for?(:buttonbar)
= yield(:buttonbar)
@@ -22,7 +23,7 @@
%small= yield(:subtitle)
= render "shared/flash_messages", flash: flash
= yield
%main= yield
%footer.page-footer.font-small.bg-dark.pt-4= render "layouts/footer"
/

View File

@@ -1 +1 @@
= link_to image_tag(avatar_uri(member, 150), alt: member, class: 'avatar img img-fluid'), member_path(member)
= link_to image_tag(avatar_uri(member, 150), alt: "Avatar of #{member}", class: 'avatar img img-fluid'), member_path(member)

View File

@@ -4,7 +4,7 @@
= member
- else
= link_to member do
= image_tag(avatar_uri(member, 100), alt: '', height: 50, width: 50)
= image_tag(avatar_uri(member, 100), alt: member.login_name, height: 50, width: 50)
= member

View File

@@ -74,6 +74,9 @@
= render 'timeline/photos', photo: resolve_model(event) if event.event_type == 'photo'
%small
- if event.event_at.present?
#{time_ago_in_words(event.event_at)} ago
- if event.event_at.kind_of?(Date)
#{distance_of_time_in_words(event.event_at, Time.zone.now.to_date)} ago
- else
#{time_ago_in_words(event.event_at)} ago
- else
unknown date

View File

@@ -5,7 +5,8 @@
%h5.ellipsis
= photo_icon
= link_to photo.title, photo_path(id: photo.id)
%i by #{link_to photo.owner_login_name, member_path(slug: photo.owner_slug)}
- if photo.owner_slug
%i by #{link_to photo.owner_login_name, member_path(slug: photo.owner_slug)}
- if photo.date_taken.present?
%small.text-muted
%time{datetime: photo.date_taken}= I18n.l(photo.date_taken.to_date)

View File

@@ -5,6 +5,31 @@
= form_for(@photo) do |f|
.form-group
= f.label :title
= f.text_field :title, placeholder: "title"
= f.text_field :title, placeholder: "title", required: true
.form-group
= f.label :thumbnail_url
= f.url_field :thumbnail_url
.form-group
= f.label :fullsize_url
= f.url_field :fullsize_url
.form-group
= f.label :link_url
= f.url_field :link_url
.form-group
= f.label :license_name
= f.text_field :license_name
.form-group
= f.label :license_url
= f.text_field :license_url
.form-group
= f.label :date_taken
= f.datetime_field :date_taken
.form-group
.form-actions= f.submit 'Save', class: 'btn'

View File

@@ -9,7 +9,6 @@
- content_for :breadcrumbs do
%li.breadcrumb-item= link_to 'Photos', photos_path
= page_entries_info @photos
= will_paginate @photos
.index-cards

View File

@@ -1,7 +1,7 @@
- content_for :title, "New Photo"
%h1 New Photo
%h2 Choose photo for #{link_to @item, @item}
%h2 Choose photo for #{link_to @item, @item} from Flickr, or contribute to unique crops to <a href="https://inaturalist.org/" target="_blank">iNaturalist</a> or <a href="https://identify.plantnet.org/" target="_blank">Pl@ntNet</a> via the app.
- if @please_reconnect_flickr
%h2.alert Please reconnect your flickr account

View File

@@ -3,7 +3,7 @@
%h1 Plant Parts
- if can? :create, PlantPart
= link_to 'New Plant part', new_plant_part_path, class: 'btn btn-info'
= link_to 'New plant part', new_plant_part_path, class: 'btn btn-info'
.index-cards
- @plant_parts.each do |plant_part|
@@ -20,6 +20,8 @@
.card-footer
%p
- if can? :edit, plant_part
= link_to 'Edit', edit_plant_part_path(plant_part), class: 'btn btn-default btn-xs'
= link_to t('buttons.edit'), edit_plant_part_path(plant_part), class: 'btn btn-default btn-xs'
- if can? :destroy, plant_part
= link_to 'Delete', plant_part, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default btn-xs'
= link_to t('buttons.delete'), plant_part, method: :delete, data: { confirm: t(:are_you_sure?) }, class: 'btn btn-default btn-xs'
= will_paginate(@plant_parts)

View File

@@ -5,6 +5,7 @@
= tag("meta", property: "og:url", content: request.original_url)
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
%h1 #{@plant_part.name.titlecase}
- if @plant_part.crops.empty?
%p No crops are harvested for this plant part (yet).
- else

View File

@@ -14,7 +14,7 @@
= link_to plantings_path(planting: {crop_id: planting.crop_id, garden_id: garden.id}), method: :post do
.md-v-line
.d-flex.justify-content-between
= image_tag garden_image_path(garden), class: 'img', height: 50
= image_tag garden_image_path(garden), class: 'img', height: 50, alt: garden.name
%span
%h4= garden.name
%p= garden.description

View File

@@ -10,5 +10,5 @@
- else
%p No photos.
- if can?(:edit, planting) && can?(:create, Photo)
%p Add a photo to visually track growth of this planting
%p Add a photo to visually track growth of this planting, to Flickr, iNaturalist or Pl@ntNet
= add_photo_button(planting)

View File

@@ -30,6 +30,8 @@
= link_to (@owner ? member_plantings_path(@owner, format: format) : plantings_path(format: format)) do
= icon 'fas', format.to_s
= format.upcase
- if @owner
.badge.badge-info= link_to "iCal", member_plantings_path(@owner, format: 'ics', protocol: 'webcal', only_path: false)
.badge.badge-success= link_to 'API Methods', '/api-docs'
.col-md-10

View File

@@ -0,0 +1,42 @@
<%
# TODO Refactor to a Planting <-> Ical view class?
cal = Icalendar::Calendar.new
cal.description = "Plantings by #{@owner.login_name}"
@plantings.each do |planting|
event = Icalendar::Event.new
lines = []
lines << "Quantity: #{planting['quantity'] ? planting['quantity'] : 'unknown' }"
lines << "Planted on: #{planting['planted_at'] ? planting['planted_at'] : 'unknown' }"
lines << "Sunniness: #{planting['sunniness'] ? planting['sunniness'] : 'unknown' }"
lines << "Planted from: #{planting['planted_from'] ? planting['planted_from'] : 'unknown' }"
lines << "First harvest from: #{planting['first_harvest_predicted_at'] ? planting['first_harvest_predicted_at'] : 'unknown' }"
lines << "Last harvest from: #{planting['last_harvest_predicted_at'] ? planting['last_harvest_predicted_at'] : 'unknown' }"
lines << "Finish predicted at: #{planting['finish_predicted_at'] ? planting['finish_predicted_at'] : 'unknown'}"
lines << "Finished at: #{planting['finished_at'] ? planting['finished_at'] : 'unknown' }"
lines << planting.description
finish_date = Date.parse(planting['finished_at'] || planting['finish_predicted_at'] || planting['last_harvest_predicted_at']) rescue nil
event.dtstart = Time.at(planting['created_at'])
event.dtend = finish_date || 1.day.from_now
event.summary = planting['crop_name']
event.description = lines.join("\n")
event.ip_class = "PUBLIC"
event.url = planting_url(slug: planting['slug'])
cal.add_event(event)
if finish_date && finish_date > Date.today
todo = Icalendar::Todo.new
todo.dtstart = planting['first_harvest_predicted_at'] || finish_date || Date.today
todo.due = finish_date
todo.summary = "Harvest #{planting['crop_name']}"
cal.add_todo(todo)
end
end
cal.publish
%>
<%= cal.to_ical %>

View File

@@ -76,7 +76,7 @@
= link_to planting, class: 'list-group-item list-group-item-action flex-column align-items-start' do
.d-flex.w-100.justify-content-between
%p.mb-2
= image_tag planting_image_path(planting), width: 75, class: 'rounded shadow'
= image_tag planting_image_path(planting), width: 75, class: 'rounded shadow', alt: "Image of #{planting.crop.name} by #{planting.owner}"
.text-right
%h5= planting.crop.name
- if planting.planted_from.present?

View File

@@ -1,7 +1,7 @@
.view
= link_to post do
= image_tag post_image_path(post), class: 'img img-cover'
= image_tag post_image_path(post), class: 'img img-cover', alt: "A photo related to this post"
%h4.font-weight-bold.mb-3
%strong
= link_to post do
@@ -16,5 +16,5 @@
= link_to crop do
= crop_icon(crop)
= crop.name.pluralize
/ = image_tag avatar_uri(post.author, 50), class: 'avatar'
/ = image_tag avatar_uri(post.author, 50), class: 'avatar', alt: post.author
= link_to 'Read more', post, class: 'btn btn-rounded btn-md'

View File

@@ -9,10 +9,10 @@
%h1= @author ? t('.title.author_posts', author: @author) : t('.title.default')
.row
.col-2
.col-8= will_paginate @posts
.col-md-2
.col-md-8= will_paginate @posts
.row
.col-2
.col-md-2
= render 'layouts/nav', model: Post
%hr/
%p
@@ -28,7 +28,7 @@
or
= succeed "." do
= link_to "comments RSS feed", comments_path(format: 'rss')
.col-10
.col-md-10
.row.posts
- @posts.each do |post|
.col-lg-3.col-md-6.mb-3.post

View File

@@ -8,7 +8,7 @@
%title Comment by #{comment.author.login_name} on #{comment.created_at}
%description
:escaped
:escaped_markdown
<p>
Comment on
#{ link_to @post.subject, post_url(@post) }

View File

@@ -1,4 +1,4 @@
= form_for @scientific_name, html: { class: 'form-horizontal', role: "form" } do |f|
= form_for @scientific_name, html: { class: 'form-horizontal' } do |f|
- if @scientific_name.errors.any?
#error_explanation
%h2

View File

@@ -17,8 +17,10 @@
%td= link_to 'Show', scientific_name
%td
- if can? :edit, scientific_name
= link_to 'Edit', edit_scientific_name_path(scientific_name), class: 'btn btn-default btn-xs'
= link_to t('buttons.edit'), edit_scientific_name_path(scientific_name), class: 'btn btn-default btn-xs'
%td
- if can? :destroy, scientific_name
= link_to 'Delete', scientific_name, method: :delete, data: { confirm: 'Are you sure?' },
= link_to t('buttons.delete'), scientific_name, method: :delete, data: { confirm: t(:are_you_sure?) },
class: 'btn btn-default btn-xs'
= will_paginate @scientific_names

View File

@@ -1,5 +1,5 @@
.media
= link_to(image_tag(photo.thumbnail_url, width: 150, class: 'rounded'), photo)
= link_to(image_tag(photo.thumbnail_url, width: 150, class: 'rounded', alt: photo.title), photo)
.media-body
%p
%ul.associations

View File

@@ -16,7 +16,10 @@
= render 'timeline/photos', photo: resolve_model(event) if event.event_type == 'photo'
%small
- if event.event_at.present?
#{time_ago_in_words(event.event_at)} ago
- if event.event_at.kind_of?(Date)
#{distance_of_time_in_words(event.event_at, Time.zone.now.to_date)} ago
- else
#{time_ago_in_words(event.event_at)} ago
- else
unknown date

View File

@@ -3,6 +3,8 @@
require_relative 'boot'
require 'rails/all'
ENV['RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION'] = "true"
require 'openssl'
# Require the gems listed in Gemfile, including any gems
@@ -16,8 +18,6 @@ module Growstuff
I18n.config.enforce_available_locales = true
config.active_record.legacy_connection_handling = false
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = 'UTC'

View File

@@ -26,8 +26,8 @@ Rails.application.configure do
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress JavaScripts and CSS.
config.assets.js_compressor = Uglifier.new(harmony: true)
# config.assets.css_compressor = :sass
config.assets.js_compressor = :terser
# config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false

View File

@@ -25,7 +25,7 @@ Rails.application.configure do
config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false
config.action_dispatch.show_exceptions = :none
# Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false

View File

@@ -3,3 +3,4 @@
# Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf
Mime::Type.register "text/calendar", :ics

View File

@@ -5,7 +5,7 @@ Rswag::Api.configure do |c|
# This is used by the Swagger middleware to serve requests for API descriptions
# NOTE: If you're using rswag-specs to generate Swagger, you'll need to ensure
# that it's configured to generate files in the same folder
c.swagger_root = Rails.root.to_s + '/swagger'
c.openapi_root = Rails.root.to_s + '/swagger'
# Inject a lamda function to alter the returned Swagger prior to serialization
# The function will have access to the rack env for the current request

View File

@@ -7,5 +7,5 @@ Rswag::Ui.configure do |c|
# NOTE: If you're using rspec-api to expose Swagger files (under swagger_root) as JSON or YAML endpoints,
# then the list below should correspond to the relative paths for those endpoints
c.swagger_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
c.openapi_endpoint '/api-docs/v1/swagger.json', 'API V1 Docs'
end

View File

@@ -25,7 +25,7 @@ en:
invalid: 'Invalid email or password.'
invalid_token: 'Invalid authentication token.'
timeout: 'Your session expired, please sign in again to continue.'
inactive: 'Your account was not activated yet.'
inactive: 'Your account is not activated.'
sessions:
signed_in: 'Signed in successfully.'
signed_out: 'Signed out successfully.'

View File

@@ -53,7 +53,11 @@ Rails.application.routes.draw do
get 'author/:author' => 'posts#index', as: 'by_author', on: :collection
end
resources :scientific_names
resources :scientific_names do
collection do
get :gbif_suggest
end
end
resources :alternate_names
resources :plant_parts
resources :photos
@@ -73,6 +77,7 @@ Rails.application.routes.draw do
get 'planted_from' => 'charts/crops#planted_from', constraints: { format: 'json' }
get 'harvested_for' => 'charts/crops#harvested_for', constraints: { format: 'json' }
post :openfarm
post :gbif
collection do
get 'requested'

View File

@@ -1,12 +0,0 @@
# frozen_string_literal: true
class CreateMedianFunction < ActiveRecord::Migration[4.2]
def up
# commented out, because we upgraded the gem later and this function was removed
# ActiveMedian.create_function
end
def down
# ActiveMedian.drop_function
end
end

View File

@@ -1,6 +0,0 @@
class RemoveMedianFunction < ActiveRecord::Migration[6.0]
def change
# No longer needed, after upgrading to activemedian 0.2.0
ActiveMedian.drop_function
end
end

View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
class AddGbif < ActiveRecord::Migration[7.0]
def change
add_column :scientific_names, :gbif_key, :int
add_column :scientific_names, :gbif_rank, :string
add_column :scientific_names, :gbif_status, :string
add_column :scientific_names, :wikidata_id, :string
end
end

View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2023_03_13_015323) do
ActiveRecord::Schema[7.0].define(version: 2024_01_14_045751) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -543,6 +543,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_03_13_015323) do
t.datetime "created_at", precision: nil
t.datetime "updated_at", precision: nil
t.integer "creator_id"
t.integer "gbif_key"
t.string "gbif_rank"
t.string "gbif_status"
t.string "wikidata_id"
end
create_table "seeds", id: :serial, force: :cascade do |t|

View File

@@ -10,7 +10,7 @@
# include:
# mapbox_map_id
# To use it, copy application.yml.example to application.yml (which is
# To use it, copy env-example.yml or application.yml.example to application.yml (which is
# .gitignored) and fill in the appropriate values.
# Settings in this file will be available to you as ENV['WHATEVER']
@@ -59,3 +59,14 @@ GROWSTUFF_ELASTICSEARCH="true"
GROWSTUFF_EMAIL='noreply@dev.growstuff.org'
ELASTIC_SEARCH_VERSION="7.5.1-amd64"
# We also now use SMTP2GO in prod and Mailgun in staging
# and recaptcha to solve our email issues after SendGrid stopped working
MAILGUN_SMTP_LOGIN=""
MAILGUN_SMTP_PASSWORD=""
MAILGUN_SMTP_PORT=""
MAILGUN_SMTP_SERVER=""
# These recaptcha values are the official Google test ones from
# https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha.-what-should-i-do
# In production, replace them with real ones
RECAPTCHA_SITE_KEY="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
RECAPTCHA_SECRET_KEY="6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"

View File

@@ -3,15 +3,14 @@
require 'bluecloth'
require 'haml/filters/growstuff_markdown'
module Haml::Filters
module EscapedMarkdown
include Haml::Filters::Base
def render(text)
Haml::Helpers.html_escape Haml::Filters::GrowstuffMarkdown.render(text)
class Haml::Filters
class EscapedMarkdown < Haml::Filters::GrowstuffMarkdown
def compile(node)
[:escape, true, super(node)]
end
end
# Register it as the handler for the :escaped_markdown HAML command.
# The automatic system gives us :escapedmarkdown, which is ugly.
defined['escaped_markdown'] = EscapedMarkdown
Haml::Filters.registered[:escaped_markdown] ||= EscapedMarkdown
end

View File

@@ -2,15 +2,15 @@
require 'bluecloth'
module Haml::Filters
module GrowstuffMarkdown
include Haml::Filters::Base
class Haml::Filters
class GrowstuffMarkdown < Haml::Filters::Markdown
def render(text)
@expanded = text
def compile(node)
@expanded = node.value[:text]
expand_crops!
expand_members!
BlueCloth.new(@expanded).to_html
node.value[:text] = @expanded
compile_with_tilt(node, 'markdown')
end
private
@@ -72,5 +72,5 @@ module Haml::Filters
# Register it as the handler for the :growstuff_markdown HAML command.
# The automatic system gives us :growstuffmarkdown, which is ugly.
defined['growstuff_markdown'] = GrowstuffMarkdown
Haml::Filters.registered[:growstuff_markdown] = GrowstuffMarkdown
end

10
lib/tasks/gbif.rake Normal file
View File

@@ -0,0 +1,10 @@
# frozen_string_literal: true
namespace :gbif do
desc "Retrieve crop info from GBIF"
task import: :environment do
Rails.logger = Logger.new(STDOUT)
GbifService.new.import!
end
end

View File

@@ -0,0 +1,57 @@
---
http_interactions:
- request:
method: get
uri: https://api.gbif.org/v1/species/2930137
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- Faraday/v1.10.3 Gbif/v0.2.0
X-USER-AGENT:
- Faraday/v1.10.3 Gbif/v0.2.0
response:
status:
code: 200
message: OK
headers:
vary:
- Origin, Access-Control-Request-Method, Access-Control-Request-Headers
x-content-type-options:
- nosniff
x-xss-protection:
- 1; mode=block
pragma:
- no-cache
expires:
- '0'
x-frame-options:
- DENY
content-type:
- application/json
date:
- Sun, 14 Jan 2024 10:03:58 GMT
cache-control:
- public, max-age=3601
x-varnish:
- 952863014 979042621
age:
- '126'
via:
- 1.1 varnish (Varnish/6.0)
accept-ranges:
- bytes
content-length:
- '938'
connection:
- keep-alive
body:
encoding: UTF-8
string: '{"key":2930137,"nubKey":2930137,"nameKey":10463714,"taxonID":"gbif:2930137","kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"datasetKey":"d7dddbf4-2cf0-4f39-9b2a-bb099caae36c","constituentKey":"7ddf754f-d193-4cc9-b351-99906754a03b","parentKey":2928997,"parent":"Solanum","scientificName":"Solanum
lycopersicum L.","canonicalName":"Solanum lycopersicum","vernacularName":"Garden
tomato","authorship":"L.","nameType":"SCIENTIFIC","rank":"SPECIES","origin":"SOURCE","taxonomicStatus":"ACCEPTED","nomenclaturalStatus":[],"remarks":"","publishedIn":"L.
(1753). In: Sp. Pl. 185.","numDescendants":23,"lastCrawled":"2023-08-22T23:20:59.545+00:00","lastInterpreted":"2023-08-22T23:12:05.487+00:00","issues":[],"class":"Magnoliopsida"}'
recorded_at: Sun, 14 Jan 2024 10:06:05 GMT
recorded_with: VCR 6.2.0

View File

@@ -0,0 +1,103 @@
---
http_interactions:
- request:
method: get
uri: https://api.gbif.org/v1/species/suggest?limit=100&q=Solanum+lycopersicum
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- Faraday/v1.10.3 Gbif/v0.2.0
X-USER-AGENT:
- Faraday/v1.10.3 Gbif/v0.2.0
response:
status:
code: 200
message: OK
headers:
vary:
- Origin, Access-Control-Request-Method, Access-Control-Request-Headers
x-content-type-options:
- nosniff
x-xss-protection:
- 1; mode=block
pragma:
- no-cache
expires:
- '0'
x-frame-options:
- DENY
content-type:
- application/json
date:
- Sun, 14 Jan 2024 10:06:04 GMT
cache-control:
- public, max-age=3601
x-varnish:
- '993984559'
age:
- '0'
via:
- 1.1 varnish (Varnish/6.0)
accept-ranges:
- bytes
content-length:
- '10730'
connection:
- keep-alive
body:
encoding: UTF-8
string: '[{"key":2930137,"nameKey":10463714,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":2930137,"scientificName":"Solanum
lycopersicum L.","canonicalName":"Solanum lycopersicum","rank":"SPECIES","status":"ACCEPTED","synonym":false,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum"},"class":"Magnoliopsida"},{"key":7815295,"nameKey":31973001,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":7815295,"parent":"Solanum","parentKey":2928997,"nubKey":7815295,"scientificName":"Solanum
lycopersicum Blanco, 1837","canonicalName":"Solanum lycopersicum","rank":"SPECIES","status":"DOUBTFUL","synonym":false,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum"},"class":"Magnoliopsida"},{"key":8586238,"nameKey":6531517,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Lycopersicum
solanum-lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":8586238,"parent":"Solanum","parentKey":2928997,"nubKey":8586238,"scientificName":"Lycopersicum
solanum-lycopersicum Hill","canonicalName":"Lycopersicum solanum-lycopersicum","rank":"SPECIES","status":"DOUBTFUL","synonym":false,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum"},"class":"Magnoliopsida"},{"key":8640337,"nameKey":6531515,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Lycopersicum
solanum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":8640337,"parent":"Solanum","parentKey":2928997,"nubKey":8640337,"scientificName":"Lycopersicum
solanum Medik.","canonicalName":"Lycopersicum solanum","rank":"SPECIES","status":"DOUBTFUL","synonym":false,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum"},"class":"Magnoliopsida"},{"key":7608359,"nameKey":6531353,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":7608359,"scientificName":"Lycopersicon
solanum-lycopersicum Hill","canonicalName":"Lycopersicon solanum-lycopersicum","rank":"SPECIES","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":11519041,"nameKey":97469846,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum
lycopersicum","parentKey":2930137,"nubKey":11519041,"scientificName":"Solanum
lycopersicum subsp. lycopersicum","canonicalName":"Solanum lycopersicum lycopersicum","rank":"SUBSPECIES","status":"ACCEPTED","synonym":false,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":11760453,"nameKey":97469847,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum
lycopersicum","parentKey":2930137,"nubKey":11760453,"scientificName":"Solanum
lycopersicum subsp. cerasiforme (Alef.) Voss","canonicalName":"Solanum lycopersicum
cerasiforme","rank":"SUBSPECIES","status":"ACCEPTED","synonym":false,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":7904703,"nameKey":10463761,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum
lycopersicum","parentKey":2930137,"nubKey":7904703,"scientificName":"Solanum
lycopersicum var. cerasiforme (Alef.) Voss","canonicalName":"Solanum lycopersicum
cerasiforme","rank":"VARIETY","status":"ACCEPTED","synonym":false,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":11014233,"nameKey":36721070,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":11014233,"scientificName":"Solanum
lycopersicum var. piriforme (Alef.) Voss","canonicalName":"Solanum lycopersicum
piriforme","rank":"VARIETY","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":10798260,"nameKey":36720428,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":10798260,"scientificName":"Solanum
lycopersicum var. ribisiodes Voss","canonicalName":"Solanum lycopersicum ribisiodes","rank":"VARIETY","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":2930169,"nameKey":10463787,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":2930169,"scientificName":"Solanum
lycopersicum var. esculentum (Mill.) Voss","canonicalName":"Solanum lycopersicum
esculentum","rank":"VARIETY","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":4274699,"nameKey":10463795,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":4274699,"scientificName":"Solanum
lycopersicum var. lycopersicum","canonicalName":"Solanum lycopersicum lycopersicum","rank":"VARIETY","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":8118741,"nameKey":10463759,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":8118741,"scientificName":"Solanum
lycopersicum var. cerasiforme (Alef.) Fosberg","canonicalName":"Solanum lycopersicum
cerasiforme","rank":"VARIETY","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":2930179,"nameKey":10463798,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":2930179,"scientificName":"Solanum
lycopersicum var. oviforme Voss","canonicalName":"Solanum lycopersicum oviforme","rank":"VARIETY","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"},{"key":2930165,"nameKey":10463770,"kingdom":"Plantae","phylum":"Tracheophyta","order":"Solanales","family":"Solanaceae","genus":"Solanum","species":"Solanum
lycopersicum","kingdomKey":6,"phylumKey":7707728,"classKey":220,"orderKey":1176,"familyKey":7717,"genusKey":2928997,"speciesKey":2930137,"parent":"Solanum","parentKey":2928997,"nubKey":2930165,"scientificName":"Solanum
lycopersicum var. cerasiforme (Dunal) D.M.Spooner, G.J.Anderson & R.K.Jansen","canonicalName":"Solanum
lycopersicum cerasiforme","rank":"VARIETY","status":"SYNONYM","synonym":true,"higherClassificationMap":{"6":"Plantae","7707728":"Tracheophyta","220":"Magnoliopsida","1176":"Solanales","7717":"Solanaceae","2928997":"Solanum","2930137":"Solanum
lycopersicum"},"class":"Magnoliopsida"}]'
recorded_at: Sun, 14 Jan 2024 10:06:04 GMT
recorded_with: VCR 6.2.0

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long

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