Compare commits

...

124 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
7a91336917 Merge pull request #3511 from Growstuff/dependabot/bundler/carrierwave-3.0.5
Bump carrierwave from 2.1.1 to 3.0.5
2023-12-21 09:16:50 +00:00
Cesy
62431c9a6e Merge pull request #3523 from Growstuff/dev
December Release
2023-12-21 09:14:06 +00:00
dependabot[bot]
d2a7ce2ca4 Bump carrierwave from 2.1.1 to 3.0.5
Bumps [carrierwave](https://github.com/carrierwaveuploader/carrierwave) from 2.1.1 to 3.0.5.
- [Release notes](https://github.com/carrierwaveuploader/carrierwave/releases)
- [Changelog](https://github.com/carrierwaveuploader/carrierwave/blob/master/CHANGELOG.md)
- [Commits](https://github.com/carrierwaveuploader/carrierwave/compare/v2.1.1...v3.0.5)

---
updated-dependencies:
- dependency-name: carrierwave
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-19 08:28:01 +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
176 changed files with 1851 additions and 711 deletions

View File

@@ -1,7 +1,7 @@
FROM mcr.microsoft.com/devcontainers/ruby:0-3.1-bullseye FROM mcr.microsoft.com/devcontainers/ruby:0-3.1-bullseye
# Install Rails # 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 # 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 # 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 #RUN bundle exec rake db:migrate
# [Optional] Uncomment this section to install additional OS packages. # [Optional] Uncomment this section to install additional OS packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here> && 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. # [Optional] Uncomment this line to install additional gems.
# RUN gem install <your-gem-names-here> # 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. // 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. // 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. // Use 'postCreateCommand' to run commands after the container is created.
// these don't actually work as postCreateCommands, you need to run them manually // 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 id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)" run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Setup yarn cache - 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'`) id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with: with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }} path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

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

View File

@@ -48,12 +48,6 @@ FactoryBot/CreateList:
- 'spec/views/places/show.html.haml_spec.rb' - 'spec/views/places/show.html.haml_spec.rb'
- 'spec/views/posts/index.html.haml_spec.rb' - 'spec/views/posts/index.html.haml_spec.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
FactoryBot/RedundantFactoryOption:
Exclude:
- 'spec/factories/scientific_name.rb'
# Offense count: 1135 # Offense count: 1135
# This cop supports unsafe autocorrection (--autocorrect-all). # This cop supports unsafe autocorrection (--autocorrect-all).
FactoryBot/SyntaxMethods: FactoryBot/SyntaxMethods:
@@ -101,15 +95,6 @@ Layout/LineEndStringConcatenationIndentation:
Layout/LineLength: Layout/LineLength:
Max: 304 Max: 304
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
# SupportedStyles: space, no_space
# SupportedStylesForEmptyBraces: space, no_space
Layout/SpaceBeforeBlockBraces:
Exclude:
- 'spec/models/photo_spec.rb'
# Offense count: 3 # Offense count: 3
# This cop supports safe autocorrection (--autocorrect). # This cop supports safe autocorrection (--autocorrect).
Lint/AmbiguousOperatorPrecedence: Lint/AmbiguousOperatorPrecedence:
@@ -242,15 +227,6 @@ RSpec/EmptyExampleGroup:
- 'spec/views/photos/edit.html.haml_spec.rb' - 'spec/views/photos/edit.html.haml_spec.rb'
- 'spec/views/posts/_single.html.haml_spec.rb' - 'spec/views/posts/_single.html.haml_spec.rb'
# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
RSpec/EmptyLineAfterExampleGroup:
Exclude:
- 'spec/features/crops/creating_a_crop_spec.rb'
- 'spec/features/likeable_spec.rb'
- 'spec/models/crop_spec.rb'
- 'spec/support/feature_helpers.rb'
# Offense count: 134 # Offense count: 134
# Configuration parameters: CountAsOne. # Configuration parameters: CountAsOne.
RSpec/ExampleLength: RSpec/ExampleLength:
@@ -323,13 +299,6 @@ RSpec/MessageChain:
RSpec/MessageSpies: RSpec/MessageSpies:
EnforcedStyle: receive EnforcedStyle: receive
# Offense count: 22
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: hash, symbol
RSpec/MetadataStyle:
Enabled: false
# Offense count: 1 # Offense count: 1
RSpec/MultipleDescribes: RSpec/MultipleDescribes:
Exclude: Exclude:

View File

@@ -97,5 +97,6 @@ submit the change with your pull request.
## Bots ## Bots
### Security and Dependency Updates ### Security and Dependency Updates
- `codefactor-io[bot]`
- DeppBot / [deppbot](https://github.com/deppbot) - DeppBot / [deppbot](https://github.com/deppbot)
- `dependabot[bot]` [dependabot](https://github.com/dependabot-bot) / [dependabot-preview](https://github.com/apps/dependabot-preview) - `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 # Match ruby version in .ruby-version
ruby File.read('.ruby-version') ruby File.read('.ruby-version')
gem 'rails', '~> 7.0.7' gem 'rails', '~> 7.1.0'
# Keeping old sprockets # Keeping old sprockets
# https://github.com/rails/sprockets-rails/issues/444#issuecomment-637817050 # https://github.com/rails/sprockets-rails/issues/444#issuecomment-637817050
@@ -33,18 +33,18 @@ gem 'material_icons'
# icons # icons
gem 'font-awesome-sass' gem 'font-awesome-sass'
gem 'uglifier' # JavaScript compressor gem 'terser'
gem 'oj' # Speeds up json gem 'oj' # Speeds up json
# planting and harvest predictions # planting and harvest predictions
# based on median values for the crop # based on median values for the crop
gem 'active_median', '0.2.0' gem 'active_median'
gem 'active_record_union' gem 'active_record_union'
gem 'flickraw' gem 'flickraw'
gem 'jquery-rails' 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 'cancancan' # for checking member privileges
gem 'csv_shaper' # CSV export gem 'csv_shaper' # CSV export
@@ -100,7 +100,7 @@ gem 'omniauth-twitter'
gem "chartkick" gem "chartkick"
# clever elastic search # clever elastic search
gem 'elasticsearch', '< 7.0.0' gem 'elasticsearch', '~> 7.0.0'
gem 'searchkick' gem 'searchkick'
gem "hashie", ">= 3.5.3" gem "hashie", ">= 3.5.3"
@@ -124,10 +124,19 @@ gem 'rack-protection', '>= 2.0.1'
gem 'mailboxer', '>= 0.15.1' gem 'mailboxer', '>= 0.15.1'
gem 'faraday' gem 'faraday'
gem 'faraday_middleware'
gem 'rack-cors' 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 group :production do
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
gem 'dalli' gem 'dalli'
@@ -153,6 +162,7 @@ group :development, :test do
gem 'factory_bot_rails' # for creating test data gem 'factory_bot_rails' # for creating test data
gem 'faker' gem 'faker'
gem 'haml-rails' # HTML templating language gem 'haml-rails' # HTML templating language
gem 'pry'
gem 'query_diet' gem 'query_diet'
gem 'rspec-activemodel-mocks' gem 'rspec-activemodel-mocks'
gem 'rspec-rails' # unit testing framework gem 'rspec-rails' # unit testing framework
@@ -172,11 +182,13 @@ group :development, :test do
end end
group :test do group :test do
gem 'axe-core-capybara'
gem 'axe-core-rspec'
gem 'codeclimate-test-reporter', require: false gem 'codeclimate-test-reporter', require: false
gem 'rails-controller-testing' gem 'rails-controller-testing'
gem 'selenium-webdriver' gem 'selenium-webdriver'
gem 'timecop' gem 'timecop'
gem 'webdrivers' gem 'vcr'
end end
group :travis do 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 GIT
remote: https://github.com/restarone/comfortable-mexican-sofa.git remote: https://github.com/restarone/comfortable-mexican-sofa.git
revision: ccf9415ae220453a199759b8ecbb8e9436c75c85 revision: ccf9415ae220453a199759b8ecbb8e9436c75c85
@@ -25,86 +33,110 @@ GEM
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (7.0.8) actioncable (7.1.3)
actionpack (= 7.0.8) actionpack (= 7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailbox (7.0.8) zeitwerk (~> 2.6)
actionpack (= 7.0.8) actionmailbox (7.1.3)
activejob (= 7.0.8) actionpack (= 7.1.3)
activerecord (= 7.0.8) activejob (= 7.1.3)
activestorage (= 7.0.8) activerecord (= 7.1.3)
activesupport (= 7.0.8) activestorage (= 7.1.3)
activesupport (= 7.1.3)
mail (>= 2.7.1) mail (>= 2.7.1)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
actionmailer (7.0.8) actionmailer (7.1.3)
actionpack (= 7.0.8) actionpack (= 7.1.3)
actionview (= 7.0.8) actionview (= 7.1.3)
activejob (= 7.0.8) activejob (= 7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
net-imap net-imap
net-pop net-pop
net-smtp net-smtp
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.2)
actionpack (7.0.8) actionpack (7.1.3)
actionview (= 7.0.8) actionview (= 7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
rack (~> 2.0, >= 2.2.4) nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.0, >= 1.2.0) rails-html-sanitizer (~> 1.6)
actiontext (7.0.8) actiontext (7.1.3)
actionpack (= 7.0.8) actionpack (= 7.1.3)
activerecord (= 7.0.8) activerecord (= 7.1.3)
activestorage (= 7.0.8) activestorage (= 7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
globalid (>= 0.6.0) globalid (>= 0.6.0)
nokogiri (>= 1.8.5) nokogiri (>= 1.8.5)
actionview (7.0.8) actionview (7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.11)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.1, >= 1.2.0) rails-html-sanitizer (~> 1.6)
active_link_to (1.0.5) active_link_to (1.0.5)
actionpack actionpack
addressable addressable
active_median (0.2.0) active_median (0.4.1)
activerecord (>= 4.2) activesupport (>= 6.1)
active_record_union (1.3.0) active_record_union (1.3.0)
activerecord (>= 4.0) activerecord (>= 4.0)
active_utils (3.4.1) active_utils (3.4.1)
activesupport (>= 4.2) activesupport (>= 4.2)
i18n i18n
activejob (7.0.8) activejob (7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (7.0.8) activemodel (7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
activerecord (7.0.8) activerecord (7.1.3)
activemodel (= 7.0.8) activemodel (= 7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
activestorage (7.0.8) timeout (>= 0.4.0)
actionpack (= 7.0.8) activestorage (7.1.3)
activejob (= 7.0.8) actionpack (= 7.1.3)
activerecord (= 7.0.8) activejob (= 7.1.3)
activesupport (= 7.0.8) activerecord (= 7.1.3)
activesupport (= 7.1.3)
marcel (~> 1.0) marcel (~> 1.0)
mini_mime (>= 1.1.0) activesupport (7.1.3)
activesupport (7.0.8) base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2) i18n (>= 1.6, < 2)
minitest (>= 5.1) minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0) tzinfo (~> 2.0)
addressable (2.8.5) addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0) public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2) ast (2.4.2)
autoprefixer-rails (10.4.7.0) autoprefixer-rails (10.4.7.0)
execjs (~> 2) 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) bcrypt (3.1.19)
better_errors (2.10.1) better_errors (2.10.1)
erubi (>= 1.0.0) erubi (>= 1.0.0)
@@ -117,7 +149,7 @@ GEM
erubi (~> 1.4) erubi (~> 1.4)
parser (>= 2.4) parser (>= 2.4)
smart_properties smart_properties
bigdecimal (3.1.4) bigdecimal (3.1.6)
bluecloth (2.2.0) bluecloth (2.2.0)
bonsai-elasticsearch-rails (7.0.1) bonsai-elasticsearch-rails (7.0.1)
elasticsearch-model (< 8) elasticsearch-model (< 8)
@@ -132,16 +164,16 @@ GEM
actionpack (>= 5.2) actionpack (>= 5.2)
activemodel (>= 5.2) activemodel (>= 5.2)
builder (3.2.4) builder (3.2.4)
bullet (7.1.4) bullet (7.1.6)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
uniform_notifier (~> 1.11) uniform_notifier (~> 1.11)
byebug (11.1.3) byebug (11.1.3)
cancancan (3.5.0) cancancan (3.5.0)
capybara (3.39.2) capybara (3.40.0)
addressable addressable
matrix matrix
mini_mime (>= 0.1.3) mini_mime (>= 0.1.3)
nokogiri (~> 1.8) nokogiri (~> 1.11)
rack (>= 1.6.0) rack (>= 1.6.0)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0) regexp_parser (>= 1.5, < 3.0)
@@ -152,17 +184,19 @@ GEM
capybara-screenshot (1.0.26) capybara-screenshot (1.0.26)
capybara (>= 1.0, < 4) capybara (>= 1.0, < 4)
launchy launchy
carrierwave (2.1.1) carrierwave (3.0.5)
activemodel (>= 5.0.0) activemodel (>= 6.0.0)
activesupport (>= 5.0.0) activesupport (>= 6.0.0)
addressable (~> 2.6) addressable (~> 2.6)
image_processing (~> 1.1) image_processing (~> 1.1)
mimemagic (>= 0.3.0) marcel (~> 1.0.0)
mini_mime (>= 0.1.3)
ssrf_filter (~> 1.0) ssrf_filter (~> 1.0)
chartkick (5.0.5) chartkick (5.0.5)
codeclimate-test-reporter (1.0.9) codeclimate-test-reporter (1.0.9)
simplecov (<= 0.13) simplecov (<= 0.13)
coderay (1.1.3)
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
coffee-rails (5.0.0) coffee-rails (5.0.0)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
railties (>= 5.2.0) railties (>= 5.2.0)
@@ -172,19 +206,22 @@ GEM
coffee-script-source (1.12.2) coffee-script-source (1.12.2)
comfy_bootstrap_form (4.0.9) comfy_bootstrap_form (4.0.9)
rails (>= 5.0.0) rails (>= 5.0.0)
concurrent-ruby (1.2.2) concurrent-ruby (1.2.3)
connection_pool (2.4.1) connection_pool (2.4.1)
crass (1.0.6) crass (1.0.6)
csv_shaper (1.3.2) csv_shaper (1.3.2)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
dalli (3.2.6) dalli (3.2.7)
base64
database_cleaner (2.0.2) database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3) database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.1.0) database_cleaner-active_record (2.1.0)
activerecord (>= 5.a) activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0) database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1) 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) devise (4.9.3)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
@@ -199,61 +236,44 @@ GEM
dotenv-rails (2.8.1) dotenv-rails (2.8.1)
dotenv (= 2.8.1) dotenv (= 2.8.1)
railties (>= 3.2) railties (>= 3.2)
elasticsearch (6.8.3) drb (2.2.0)
elasticsearch-api (= 6.8.3) ruby2_keywords
elasticsearch-transport (= 6.8.3) dumb_delegator (1.0.0)
elasticsearch-api (6.8.3) elasticsearch (7.0.0)
elasticsearch-api (= 7.0.0)
elasticsearch-transport (= 7.0.0)
elasticsearch-api (7.0.0)
multi_json multi_json
elasticsearch-model (7.1.1) elasticsearch-model (7.1.1)
activesupport (> 3) activesupport (> 3)
elasticsearch (> 1) elasticsearch (> 1)
hashie hashie
elasticsearch-rails (7.1.0) elasticsearch-rails (7.1.0)
elasticsearch-transport (6.8.3) elasticsearch-transport (7.0.0)
faraday (~> 1) faraday
multi_json multi_json
erubi (1.12.0) erubi (1.12.0)
erubis (2.7.0) erubis (2.7.0)
excon (0.93.1) excon (0.109.0)
execjs (2.8.1) execjs (2.8.1)
factory_bot (6.4.2) factory_bot (6.4.5)
activesupport (>= 5.0.0) activesupport (>= 5.0.0)
factory_bot_rails (6.4.2) factory_bot_rails (6.4.3)
factory_bot (~> 6.4) factory_bot (~> 6.4)
railties (>= 5.0.0) railties (>= 5.0.0)
faker (3.2.2) faker (3.2.3)
i18n (>= 1.8.11, < 2) i18n (>= 1.8.11, < 2)
faraday (1.10.3) faraday (2.9.0)
faraday-em_http (~> 1.0) faraday-net_http (>= 2.0, < 3.2)
faraday-em_synchrony (~> 1.0) faraday-net_http (3.1.0)
faraday-excon (~> 1.1) net-http
faraday-httpclient (~> 1.0) ffi (1.16.3)
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)
ffi (1.15.5)
flickraw (0.9.10) flickraw (0.9.10)
font-awesome-sass (5.15.1) font-awesome-sass (5.15.1)
sassc (>= 1.11) sassc (>= 1.11)
friendly_id (5.5.1) friendly_id (5.5.1)
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
gbifrb (0.2.0)
geocoder (1.8.2) geocoder (1.8.2)
gibbon (1.2.1) gibbon (1.2.1)
httparty httparty
@@ -263,8 +283,9 @@ GEM
gravatar-ultimate (2.0.0) gravatar-ultimate (2.0.0)
activesupport (>= 2.3.14) activesupport (>= 2.3.14)
rack rack
haml (5.2.2) haml (6.3.0)
temple (>= 0.8.0) temple (>= 0.8.2)
thor
tilt tilt
haml-i18n-extractor (0.5.9) haml-i18n-extractor (0.5.9)
activesupport activesupport
@@ -277,8 +298,8 @@ GEM
activesupport (>= 5.1) activesupport (>= 5.1)
haml (>= 4.0.6) haml (>= 4.0.6)
railties (>= 5.1) railties (>= 5.1)
haml_lint (0.52.0) haml_lint (0.55.0)
haml (>= 4.0) haml (>= 5.0)
parallel (~> 1.10) parallel (~> 1.10)
rainbow rainbow
rubocop (>= 1.0) rubocop (>= 1.0)
@@ -307,15 +328,21 @@ GEM
rails-i18n rails-i18n
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
terminal-table (>= 1.5.1) 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) image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5) mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3) 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) jquery-rails (4.6.0)
rails-dom-testing (>= 1, < 3) rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0) railties (>= 4.2.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
jquery-ui-rails (6.0.1)
railties (>= 3.2.16)
json (2.7.1) json (2.7.1)
json-schema (4.1.1) json-schema (4.1.1)
addressable (>= 2.8) addressable (>= 2.8)
@@ -364,25 +391,28 @@ GEM
mini_magick (4.12.0) mini_magick (4.12.0)
mini_mime (1.1.5) mini_mime (1.1.5)
mini_portile2 (2.8.5) mini_portile2 (2.8.5)
minitest (5.20.0) minitest (5.21.2)
moneta (1.0.0) moneta (1.0.0)
msgpack (1.7.2)
multi_json (1.15.0) multi_json (1.15.0)
multi_xml (0.6.0) multi_xml (0.6.0)
multipart-post (2.2.3) mutex_m (0.2.0)
net-imap (0.3.7) net-http (0.4.1)
uri
net-imap (0.4.9.1)
date date
net-protocol net-protocol
net-pop (0.1.2) net-pop (0.1.2)
net-protocol net-protocol
net-protocol (0.2.1) net-protocol (0.2.2)
timeout timeout
net-smtp (0.3.3) net-smtp (0.4.0.1)
net-protocol net-protocol
nio4r (2.5.9) nio4r (2.7.0)
nokogiri (1.15.5) nokogiri (1.16.0)
mini_portile2 (~> 2.8.2) mini_portile2 (~> 2.8.2)
racc (~> 1.4) racc (~> 1.4)
nokogiri (1.15.5-x86_64-linux) nokogiri (1.16.0-x86_64-linux)
racc (~> 1.4) racc (~> 1.4)
oauth (0.5.6) oauth (0.5.6)
oj (3.16.3) oj (3.16.3)
@@ -401,43 +431,54 @@ GEM
rack rack
orm_adapter (0.5.0) orm_adapter (0.5.0)
parallel (1.24.0) parallel (1.24.0)
parser (3.2.2.4) parser (3.3.0.5)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
percy-capybara (5.0.0) percy-capybara (5.0.0)
capybara (>= 3) capybara (>= 3)
pg (1.5.4) pg (1.5.4)
platform-api (3.5.0) platform-api (3.6.0)
heroics (~> 0.1.1) heroics (~> 0.1.1)
moneta (~> 1.0.0) moneta (~> 1.0.0)
rate_throttle_client (~> 0.1.0) rate_throttle_client (~> 0.1.0)
popper_js (1.16.1) 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) public_suffix (5.0.4)
puma (6.4.0) puma (6.4.2)
nio4r (~> 2.0) nio4r (~> 2.0)
query_diet (0.7.1) query_diet (0.7.1)
racc (1.7.3) racc (1.7.3)
rack (2.2.8) rack (2.2.8)
rack-cors (2.0.1) rack-cors (2.0.1)
rack (>= 2.0.0) 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 (~> 2.2, >= 2.2.4)
rack-session (1.0.2)
rack (< 3)
rack-test (2.1.0) rack-test (2.1.0)
rack (>= 1.3) rack (>= 1.3)
rails (7.0.8) rackup (1.0.0)
actioncable (= 7.0.8) rack (< 3)
actionmailbox (= 7.0.8) webrick
actionmailer (= 7.0.8) rails (7.1.3)
actionpack (= 7.0.8) actioncable (= 7.1.3)
actiontext (= 7.0.8) actionmailbox (= 7.1.3)
actionview (= 7.0.8) actionmailer (= 7.1.3)
activejob (= 7.0.8) actionpack (= 7.1.3)
activemodel (= 7.0.8) actiontext (= 7.1.3)
activerecord (= 7.0.8) actionview (= 7.1.3)
activestorage (= 7.0.8) activejob (= 7.1.3)
activesupport (= 7.0.8) activemodel (= 7.1.3)
activerecord (= 7.1.3)
activestorage (= 7.1.3)
activesupport (= 7.1.3)
bundler (>= 1.15.0) bundler (>= 1.15.0)
railties (= 7.0.8) railties (= 7.1.3)
rails-controller-testing (1.0.5) rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1) actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1)
@@ -457,13 +498,14 @@ GEM
rails_stdout_logging rails_stdout_logging
rails_serve_static_assets (0.0.5) rails_serve_static_assets (0.0.5)
rails_stdout_logging (0.0.5) rails_stdout_logging (0.0.5)
railties (7.0.8) railties (7.1.3)
actionpack (= 7.0.8) actionpack (= 7.1.3)
activesupport (= 7.0.8) activesupport (= 7.1.3)
method_source irb
rackup (>= 1.0.0)
rake (>= 12.2) rake (>= 12.2)
thor (~> 1.0) thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.5) zeitwerk (~> 2.6)
rainbow (3.1.1) rainbow (3.1.1)
raindrops (0.20.0) raindrops (0.20.0)
rake (13.1.0) rake (13.1.0)
@@ -471,9 +513,14 @@ GEM
rb-fsevent (0.11.2) rb-fsevent (0.11.2)
rb-inotify (0.10.1) rb-inotify (0.10.1)
ffi (~> 1.0) 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 connection_pool
regexp_parser (2.8.3) regexp_parser (2.9.0)
reline (0.4.2)
io-console (~> 0.5)
responders (3.1.1) responders (3.1.1)
actionpack (>= 5.2) actionpack (>= 5.2)
railties (>= 5.2) railties (>= 5.2)
@@ -495,7 +542,7 @@ GEM
rspec-mocks (3.12.6) rspec-mocks (3.12.6)
diff-lcs (>= 1.2.0, < 2.0) diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0) rspec-support (~> 3.12.0)
rspec-rails (6.1.0) rspec-rails (6.1.1)
actionpack (>= 6.1) actionpack (>= 6.1)
activesupport (>= 6.1) activesupport (>= 6.1)
railties (>= 6.1) railties (>= 6.1)
@@ -518,11 +565,11 @@ GEM
rswag-ui (2.13.0) rswag-ui (2.13.0)
actionpack (>= 3.1, < 7.2) actionpack (>= 3.1, < 7.2)
railties (>= 3.1, < 7.2) railties (>= 3.1, < 7.2)
rubocop (1.59.0) rubocop (1.60.2)
json (~> 2.3) json (~> 2.3)
language_server-protocol (>= 3.17.0) language_server-protocol (>= 3.17.0)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 3.2.2.4) parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0) regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0) rexml (>= 3.2.5, < 4.0)
@@ -531,22 +578,22 @@ GEM
unicode-display_width (>= 2.4.0, < 3.0) unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0) rubocop-ast (1.30.0)
parser (>= 3.2.1.0) parser (>= 3.2.1.0)
rubocop-capybara (2.19.0) rubocop-capybara (2.20.0)
rubocop (~> 1.41) rubocop (~> 1.41)
rubocop-factory_bot (2.24.0) rubocop-factory_bot (2.25.1)
rubocop (~> 1.33) rubocop (~> 1.41)
rubocop-rails (2.23.0) rubocop-rails (2.23.1)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.33.0, < 2.0) rubocop (>= 1.33.0, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0) rubocop-ast (>= 1.30.0, < 2.0)
rubocop-rspec (2.25.0) rubocop-rspec (2.26.1)
rubocop (~> 1.40) rubocop (~> 1.40)
rubocop-capybara (~> 2.17) rubocop-capybara (~> 2.17)
rubocop-factory_bot (~> 2.22) rubocop-factory_bot (~> 2.22)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-units (4.0.1) ruby-units (4.0.1)
ruby-vips (2.1.4) ruby-vips (2.2.0)
ffi (~> 1.12) ffi (~> 1.12)
ruby2_keywords (0.0.5) ruby2_keywords (0.0.5)
rubyzip (2.3.2) rubyzip (2.3.2)
@@ -565,19 +612,19 @@ GEM
tilt tilt
scout_apm (5.3.5) scout_apm (5.3.5)
parser parser
searchkick (4.6.3) searchkick (5.3.1)
activemodel (>= 5) activemodel (>= 6.1)
elasticsearch (>= 6, < 7.14)
hashie hashie
selenium-webdriver (4.10.0) selenium-webdriver (4.17.0)
base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5) rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0) rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0) websocket (~> 1.0)
sidekiq (7.2.0) sidekiq (7.2.1)
concurrent-ruby (< 2) concurrent-ruby (< 2)
connection_pool (>= 2.3.0) connection_pool (>= 2.3.0)
rack (>= 2.2.4) rack (>= 2.2.4)
redis-client (>= 0.14.0) redis-client (>= 0.19.0)
simplecov (0.13.0) simplecov (0.13.0)
docile (~> 1.1.0) docile (~> 1.1.0)
json (>= 1.8, < 3) json (>= 1.8, < 3)
@@ -591,40 +638,44 @@ GEM
actionpack (>= 5.2) actionpack (>= 5.2)
activesupport (>= 5.2) activesupport (>= 5.2)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
ssrf_filter (1.0.7) ssrf_filter (1.1.2)
stringio (3.1.0)
sysexits (1.2.0) sysexits (1.2.0)
temple (0.10.3) temple (0.10.3)
terminal-table (3.0.2) terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3) unicode-display_width (>= 1.1.1, < 3)
terser (1.2.0)
execjs (>= 0.3.0, < 3)
thor (1.3.0) thor (1.3.0)
thread_safe (0.3.6)
tilt (2.3.0) tilt (2.3.0)
timecop (0.9.8) timecop (0.9.8)
timeout (0.4.0) timeout (0.4.1)
trollop (1.16.2) trollop (1.16.2)
tzinfo (2.0.6) tzinfo (2.0.6)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.5.0) unicode-display_width (2.5.0)
unicorn (6.1.0) unicorn (6.1.0)
kgio (~> 2.6) kgio (~> 2.6)
raindrops (~> 0.7) raindrops (~> 0.7)
uniform_notifier (1.16.0) uniform_notifier (1.16.0)
uri (0.13.0)
validate_url (1.0.15) validate_url (1.0.15)
activemodel (>= 3.0.0) activemodel (>= 3.0.0)
public_suffix 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) warden (1.2.9)
rack (>= 2.0.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) webrat (0.7.3)
nokogiri (>= 1.2.0) nokogiri (>= 1.2.0)
rack (>= 1.0) rack (>= 1.0)
rack-test (>= 0.5.3) rack-test (>= 0.5.3)
webrick (1.8.1) webrick (1.8.1)
websocket (1.2.9) websocket (1.2.10)
websocket-driver (0.7.6) websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
@@ -642,9 +693,11 @@ PLATFORMS
x86_64-linux x86_64-linux
DEPENDENCIES DEPENDENCIES
active_median (= 0.2.0) active_median
active_record_union active_record_union
active_utils active_utils
axe-core-capybara
axe-core-rspec
better_errors better_errors
bluecloth bluecloth
bonsai-elasticsearch-rails bonsai-elasticsearch-rails
@@ -668,14 +721,14 @@ DEPENDENCIES
devise devise
discard (>= 1.2) discard (>= 1.2)
dotenv-rails dotenv-rails
elasticsearch (< 7.0.0) elasticsearch (~> 7.0.0)
factory_bot_rails factory_bot_rails
faker faker
faraday faraday
faraday_middleware
flickraw flickraw
font-awesome-sass font-awesome-sass
friendly_id friendly_id
gbifrb
geocoder geocoder
gibbon (~> 1.2.0) gibbon (~> 1.2.0)
gravatar-ultimate gravatar-ultimate
@@ -685,8 +738,9 @@ DEPENDENCIES
haml_lint (>= 0.25.1) haml_lint (>= 0.25.1)
hashie (>= 3.5.3) hashie (>= 3.5.3)
i18n-tasks i18n-tasks
icalendar
jquery-rails jquery-rails
jquery-ui-rails jquery-ui-rails!
jsonapi-resources jsonapi-resources
jsonapi-swagger jsonapi-swagger
leaflet-rails (>= 1.9.2) leaflet-rails (>= 1.9.2)
@@ -697,6 +751,7 @@ DEPENDENCIES
material-sass (= 4.1.1) material-sass (= 4.1.1)
material_icons material_icons
memcachier memcachier
msgpack
oj oj
omniauth (~> 1.3) omniauth (~> 1.3)
omniauth-flickr (>= 0.0.15) omniauth-flickr (>= 0.0.15)
@@ -704,15 +759,17 @@ DEPENDENCIES
percy-capybara (~> 5.0.0) percy-capybara (~> 5.0.0)
pg pg
platform-api platform-api
pry
puma puma
query_diet query_diet
rack-cors rack-cors
rack-protection (>= 2.0.1) rack-protection (>= 2.0.1)
rails (~> 7.0.7) rails (~> 7.1.0)
rails-assets-leaflet.markercluster! rails-assets-leaflet.markercluster!
rails-controller-testing rails-controller-testing
rails_12factor rails_12factor
rake (>= 10.0.0) rake (>= 10.0.0)
recaptcha
responders responders
rspec-activemodel-mocks rspec-activemodel-mocks
rspec-rails rspec-rails
@@ -730,18 +787,18 @@ DEPENDENCIES
selenium-webdriver selenium-webdriver
sidekiq sidekiq
sprockets (< 4) sprockets (< 4)
terser
timecop timecop
uglifier
unicorn unicorn
validate_url validate_url
webdrivers vcr
webrat webrat
will_paginate will_paginate
will_paginate-bootstrap-style will_paginate-bootstrap-style
xmlrpc xmlrpc
RUBY VERSION RUBY VERSION
ruby 3.1.4p223 ruby 3.1.4p223
BUNDLED WITH BUNDLED WITH
2.3.11 2.3.11

View File

@@ -5,7 +5,7 @@ jQuery ->
$(".remove-altname-row").css("display", "inline-block") $(".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 sci_index = $('#scientific_names .template').length + 1
@@ -21,7 +21,7 @@ jQuery ->
element = document.getElementById(tmp) element = document.getElementById(tmp)
element.remove() 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 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; padding-bottom: 0;
} }
h5.crop-sci-name { .crop-sci-name {
background-color: $beige; background-color: $beige;
color: $black; color: $black;
font-size: 0.7em; font-size: 0.7em;

View File

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

View File

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

View File

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

View File

@@ -8,7 +8,7 @@ class AdminController < ApplicationController
def newsletter def newsletter
authorize! :manage, :all 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 respond_with @members
end end
end end

View File

@@ -9,7 +9,7 @@ class AlternateNamesController < ApplicationController
# GET /alternate_names # GET /alternate_names
# GET /alternate_names.json # GET /alternate_names.json
def index 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) respond_with(@alternate_names)
end end

View File

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

View File

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

View File

@@ -63,7 +63,7 @@ class PhotosController < ApplicationController
def photo_params def photo_params
params.require(:photo).permit(:source_id, :source, :title, :license_name, 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 end
# Item with photos attached # Item with photos attached

View File

@@ -6,7 +6,7 @@ class PlantPartsController < ApplicationController
responders :flash responders :flash
def index 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) respond_with(@plant_parts)
end end

View File

@@ -3,6 +3,7 @@
class PlantingsController < DataController class PlantingsController < DataController
after_action :update_crop_medians, only: %i(create update destroy) after_action :update_crop_medians, only: %i(create update destroy)
after_action :update_planting_medians, only: :update 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 def index
@show_all = params[:all] == '1' @show_all = params[:all] == '1'
@@ -29,7 +30,6 @@ class PlantingsController < DataController
) )
@filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_fs(:number)}.csv" @filename = "Growstuff-#{specifics}Plantings-#{Time.zone.now.to_fs(:number)}.csv"
respond_with(@plantings) respond_with(@plantings)
end end

View File

@@ -3,6 +3,8 @@
class RegistrationsController < Devise::RegistrationsController class RegistrationsController < Devise::RegistrationsController
respond_to :json respond_to :json
prepend_before_action :check_captcha, only: [:create] # Change this to be any actions you want to protect with recaptcha.
def edit def edit
@twitter_auth = current_member.auth('twitter') @twitter_auth = current_member.auth('twitter')
@flickr_auth = current_member.auth('flickr') @flickr_auth = current_member.auth('flickr')
@@ -46,6 +48,25 @@ class RegistrationsController < Devise::RegistrationsController
render "edit" render "edit"
end end
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 end
# check if we need the current password to update fields # check if we need the current password to update fields

View File

@@ -1,15 +1,15 @@
# frozen_string_literal: true # frozen_string_literal: true
class ScientificNamesController < ApplicationController class ScientificNamesController < ApplicationController
before_action :authenticate_member!, except: %i(index show) before_action :authenticate_member!, except: %i(index show gbif_suggest)
load_and_authorize_resource load_and_authorize_resource except: [:gbif_suggest]
respond_to :html, :json respond_to :html, :json
responders :flash responders :flash
# GET /scientific_names # GET /scientific_names
# GET /scientific_names.json # GET /scientific_names.json
def index 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) respond_with(@scientific_names)
end end
@@ -35,7 +35,7 @@ class ScientificNamesController < ApplicationController
def create def create
@scientific_name = ScientificName.new(scientific_name_params) @scientific_name = ScientificName.new(scientific_name_params)
@scientific_name.creator = current_member @scientific_name.creator = current_member
gbif_sync!(@scientific_name)
@scientific_name.save @scientific_name.save
respond_with(@scientific_name.crop) respond_with(@scientific_name.crop)
end end
@@ -43,7 +43,9 @@ class ScientificNamesController < ApplicationController
# PUT /scientific_names/1 # PUT /scientific_names/1
# PUT /scientific_names/1.json # PUT /scientific_names/1.json
def update 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) respond_with(@scientific_name.crop)
end end
@@ -56,9 +58,26 @@ class ScientificNamesController < ApplicationController
respond_with(@crop) respond_with(@crop)
end end
def gbif_suggest
render json: gbif_service.suggest(params[:term])
end
private 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 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
end end

View File

@@ -93,7 +93,7 @@ module IconsHelper
def plant_part_icon(name) def plant_part_icon(name)
if File.exist? Rails.root.join('app', 'assets', 'images', 'icons', 'plant_parts', "#{name}.svg") 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 else
planting_icon planting_icon
end end
@@ -101,7 +101,7 @@ module IconsHelper
def crop_icon(crop) def crop_icon(crop)
if crop.svg_icon.present? 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? elsif crop.parent.present?
crop_icon(crop.parent) crop_icon(crop.parent)
else else
@@ -123,6 +123,6 @@ module IconsHelper
end end
def image_icon(icon) 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
end end

View File

@@ -79,6 +79,7 @@ class Ability
can :manage, ScientificName can :manage, ScientificName
can :manage, AlternateName can :manage, AlternateName
can :openfarm, Crop can :openfarm, Crop
can :gbif, Crop
end end
# any member can create a crop provisionally # 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 extend FriendlyId
include PhotoCapable include PhotoCapable
include OpenFarmData include OpenFarmData
include GbifData
include SearchCrops include SearchCrops
friendly_id :name, use: %i(slugged finders) 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 }) Crop.distinct.joins(:photo_associations).where(photo_associations: { photo: self })
end end
validates :fullsize_url, url: true validates :fullsize_url, url: true, presence: true
validates :thumbnail_url, url: 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 # creates a relationship for each assignee type
PHOTO_CAPABLE.each do |type| PHOTO_CAPABLE.each do |type|

View File

@@ -24,8 +24,11 @@ class Post < ApplicationRecord
# #
# Validations # Validations
validates :subject, presence: true, length: { maximum: 255 } validates :subject, presence: true, length: { maximum: 255 }
validates :body, presence: true
def author_date_subject def author_date_subject
return unless author
# slugs are created before created_at is set # slugs are created before created_at is set
time = created_at || Time.zone.now time = created_at || Time.zone.now
"#{author.login_name} #{time.strftime('%Y%m%d')} #{subject}" "#{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 "Crop Wrangling", wrangle_crops_path, class: 'nav-link'
%li= link_to "Alternate names", alternate_names_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 "Scientific names", scientific_names_path, class: 'nav-link'
%li= link_to "Plant parts", plant_parts_path, class: 'nav-link'
.col-md-4 .col-md-4
.card .card

View File

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

View File

@@ -5,7 +5,7 @@
%li.breadcrumb-item.active= link_to 'Roles', admin_roles_path %li.breadcrumb-item.active= link_to 'Roles', admin_roles_path
- if can? :create, Role - 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 %table.table.table-striped
%thead %thead
@@ -25,6 +25,8 @@
= edit_icon = edit_icon
= t('.edit') = t('.edit')
- if can?(:destroy, role) && ! role.members.any? - 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 = delete_icon
= t('.delete') = t('.delete')
= will_paginate(@roles)

View File

@@ -3,7 +3,7 @@
- if content_for? :title - if content_for? :title
%h1.h2-responsive.text-center %h1.h2-responsive.text-center
%strong=yield :title %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? - if @alternate_name.errors.any?
#error_explanation #error_explanation
%h2 %h2

View File

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

View File

@@ -3,7 +3,7 @@
- if content_for? :title - if content_for? :title
%h1.h2-responsive.text-center %h1.h2-responsive.text-center
%strong=yield :title %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? - if @comment.errors.any?
#error_explanation #error_explanation
%h2 %h2

View File

@@ -7,7 +7,7 @@
%item %item
%title Comment by #{comment.author.login_name} on #{comment.post.subject} %title Comment by #{comment.author.login_name} on #{comment.post.subject}
%description %description
:escaped :escaped_markdown
<p> <p>
Comment on Comment on
#{ link_to comment.post.subject, post_url(comment.post) } #{ 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: '... ') = truncate(strip_tags(conversation.messages.last.body), length: 150, separator: ' ', omission: '... ')
.col-md-1 .col-md-1
- if @box == 'trash' - 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' = icon 'fas', 'trash-restore'
- else - 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? - unless @conversations.empty?
= will_paginate @conversations = will_paginate @conversations

View File

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

View File

@@ -65,8 +65,12 @@
.col-2 .col-2
= label_tag :scientific_names, "Scientific name #{index + 1}:", class: 'control-label' = label_tag :scientific_names, "Scientific name #{index + 1}:", class: 'control-label'
.col-8 .col-8
= text_field_tag "sci_name[#{index + 1}]", sci.name, id: "sci_name[#{index + 1}]", class: 'form-control' = text_field_tag "sci_name[#{index + 1}]", sci.name, id: "sci_name[#{index + 1}]",
%span.help-block Scientific name of crop. 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 %h2 Alternate names
= button_tag "+", class: "add-altname-row", type: "button" = button_tag "+", class: "add-altname-row", type: "button"
= button_tag "-", class: "remove-altname-row", type: "button" = button_tag "-", class: "remove-altname-row", type: "button"

View File

@@ -1,6 +1,6 @@
- cache crop do - cache crop do
= link_to image_tag(crop_image_path(crop), = 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, crop.name,
rel: "popover", rel: "popover",
'data-trigger': 'hover', 'data-trigger': 'hover',

View File

@@ -25,4 +25,4 @@
%p= simple_format @crop.description %p= simple_format @crop.description
.col-md-3 .col-md-3
= image_tag crop_image_path(@crop), = 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 = delete_icon
= t('.delete') = t('.delete')
- else - 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 %p.text-right
- if can? :edit, crop - if can? :edit, crop

View File

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

View File

@@ -14,6 +14,10 @@
= icon 'far', 'update' = icon 'far', 'update'
Fetch data from OpenFarm 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 - if can? :destroy, crop
.dropdown-divider .dropdown-divider
= delete_button(crop, classes: 'dropdown-item text-danger') = delete_button(crop, classes: 'dropdown-item text-danger')

View File

@@ -86,7 +86,7 @@
= link_to crop_plantings_path(@crop), class: 'card-link' do = link_to crop_plantings_path(@crop), class: 'card-link' do
= planting_icon = planting_icon
#{@crop.name.capitalize} plantings #{@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 .list-group-item.d-flex.justify-content-between.align-items-center
= link_to crop_harvests_path(@crop), class: 'card-link' do = link_to crop_harvests_path(@crop), class: 'card-link' do
= harvest_icon = harvest_icon

View File

@@ -3,9 +3,10 @@
%h1 Join #{ENV['GROWSTUFF_SITE_NAME']} %h1 Join #{ENV['GROWSTUFF_SITE_NAME']}
.card-body .card-body
%p Sign up for a #{ENV['GROWSTUFF_SITE_NAME']} account to track your vegetable garden and connect with other local growers. %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), = 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 = render 'devise/shared/error_messages', resource: resource
= f.text_field :login_name = f.text_field :login_name
@@ -28,4 +29,9 @@
= f.submit "Sign up", class: 'btn btn-block btn-success' = 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" .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? - if @garden_type.errors.any?
#error_explanation #error_explanation
%h2= "#{pluralize(@garden_type.errors.count, "error")} prohibited this garden_type from being saved:" %h2= "#{pluralize(@garden_type.errors.count, "error")} prohibited this garden_type from being saved:"

View File

@@ -1,5 +1,5 @@
.card .card
= link_to garden do = 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 .card-body.text-center
%h4.card-title= garden.name %h4.card-title= garden.name

View File

@@ -1,3 +1,3 @@
= link_to image_tag(garden_image_path(garden), = 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) garden_path(garden)

View File

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

View File

@@ -33,7 +33,7 @@
%h3 %h3
Harvested Harvested
= editable :date, @harvest, :harvested_at, display_field: '.harvested_at' = 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 %span.harvested_at= I18n.l @harvest.harvested_at
.card{class: @harvest.quantity.present? ? '' : 'text-muted'} .card{class: @harvest.quantity.present? ? '' : 'text-muted'}

View File

@@ -1,9 +1,10 @@
.row.homepage-blurb .row.homepage-blurb
.col-md-8.info .col-md-8.info
%h1 Growstuff - An open gardening platform
%p= t('.intro', site_name: ENV['GROWSTUFF_SITE_NAME']) %p= t('.intro', site_name: ENV['GROWSTUFF_SITE_NAME'])
= render 'stats' = render 'stats'
.col-md-4 .col-md-4
.signup .signup
%p= t('.perks') %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')) %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 = 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 .d-flex.w-100.justify-content-between.homepage--list-item
%div %div
%h5= harvest.crop_name %h4= harvest.crop_name
%span.badge.badge-success=harvest.plant_part %span.badge.badge-success=harvest.plant_part
%small.text-muted %small.text-muted
harvested by #{harvest.owner_login_name} harvested by #{harvest.owner_login_name}
%p.mb-2 %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 = 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 .d-flex.w-100.justify-content-between.homepage--list-item
%p.mb-2 %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 .text-right
%h5= planting['crop_name'] %h4= planting['crop_name']
- if planting['planted_from'].present? - if planting['planted_from'].present?
%span.badge.badge-success= planting['planted_from'].pluralize %span.badge.badge-success= planting['planted_from'].pluralize
%small.text-muted planted by #{planting['owner_login_name']} %small.text-muted planted by #{planting['owner_login_name']}

View File

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

View File

@@ -3,13 +3,13 @@
- if signed_in? - if signed_in?
%li.nav-item %li.nav-item
= link_to timeline_index_path, method: :get, class: 'nav-link text-white' do = 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 %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' = image_icon 'gardens'
%li.nav-item.dropdown %li.nav-item.dropdown
%a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#", role: "button"} %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') = t('.record')
.dropdown-menu .dropdown-menu
= link_to new_planting_path, class: 'dropdown-item' do = link_to new_planting_path, class: 'dropdown-item' do
@@ -60,7 +60,7 @@
%li.nav-item.dropdown %li.nav-item.dropdown
%a.nav-link.dropdown-toggle{"aria-expanded" => "false", "aria-haspopup" => "true", "data-toggle" => "dropdown", href: "#", role: "button"} %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 = current_member.login_name
- if current_member.unread_count.positive? - if current_member.unread_count.positive?
%span.badge.badge-info= current_member.unread_count %span.badge.badge-info= current_member.unread_count

View File

@@ -1,9 +1,9 @@
- if current_member.present? - 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 / %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} 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} Everyone's #{model.model_name.human.pluralize}
- if can?(:create, model) - if can?(:create, model)
= link_to url_for([model, action: :new]), class: 'btn' do = link_to url_for([model, action: :new]), class: 'btn' do

View File

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

View File

@@ -74,6 +74,9 @@
= render 'timeline/photos', photo: resolve_model(event) if event.event_type == 'photo' = render 'timeline/photos', photo: resolve_model(event) if event.event_type == 'photo'
%small %small
- if event.event_at.present? - 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 - else
unknown date unknown date

View File

@@ -5,7 +5,8 @@
%h5.ellipsis %h5.ellipsis
= photo_icon = photo_icon
= link_to photo.title, photo_path(id: photo.id) = 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? - if photo.date_taken.present?
%small.text-muted %small.text-muted
%time{datetime: photo.date_taken}= I18n.l(photo.date_taken.to_date) %time{datetime: photo.date_taken}= I18n.l(photo.date_taken.to_date)

View File

@@ -5,6 +5,31 @@
= form_for(@photo) do |f| = form_for(@photo) do |f|
.form-group .form-group
= f.label :title = 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-group
.form-actions= f.submit 'Save', class: 'btn' .form-actions= f.submit 'Save', class: 'btn'

View File

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

View File

@@ -1,7 +1,7 @@
- content_for :title, "New Photo" - content_for :title, "New Photo"
%h1 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 - if @please_reconnect_flickr
%h2.alert Please reconnect your flickr account %h2.alert Please reconnect your flickr account

View File

@@ -3,7 +3,7 @@
%h1 Plant Parts %h1 Plant Parts
- if can? :create, PlantPart - 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 .index-cards
- @plant_parts.each do |plant_part| - @plant_parts.each do |plant_part|
@@ -20,6 +20,8 @@
.card-footer .card-footer
%p %p
- if can? :edit, plant_part - 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 - 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:url", content: request.original_url)
= tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME']) = tag("meta", property: "og:site_name", content: ENV['GROWSTUFF_SITE_NAME'])
%h1 #{@plant_part.name.titlecase}
- if @plant_part.crops.empty? - if @plant_part.crops.empty?
%p No crops are harvested for this plant part (yet). %p No crops are harvested for this plant part (yet).
- else - else

View File

@@ -14,7 +14,7 @@
= link_to plantings_path(planting: {crop_id: planting.crop_id, garden_id: garden.id}), method: :post do = link_to plantings_path(planting: {crop_id: planting.crop_id, garden_id: garden.id}), method: :post do
.md-v-line .md-v-line
.d-flex.justify-content-between .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 %span
%h4= garden.name %h4= garden.name
%p= garden.description %p= garden.description

View File

@@ -10,5 +10,5 @@
- else - else
%p No photos. %p No photos.
- if can?(:edit, planting) && can?(:create, Photo) - 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) = add_photo_button(planting)

View File

@@ -30,6 +30,8 @@
= link_to (@owner ? member_plantings_path(@owner, format: format) : plantings_path(format: format)) do = link_to (@owner ? member_plantings_path(@owner, format: format) : plantings_path(format: format)) do
= icon 'fas', format.to_s = icon 'fas', format.to_s
= format.upcase = 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' .badge.badge-success= link_to 'API Methods', '/api-docs'
.col-md-10 .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 = link_to planting, class: 'list-group-item list-group-item-action flex-column align-items-start' do
.d-flex.w-100.justify-content-between .d-flex.w-100.justify-content-between
%p.mb-2 %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 .text-right
%h5= planting.crop.name %h5= planting.crop.name
- if planting.planted_from.present? - if planting.planted_from.present?

View File

@@ -1,7 +1,7 @@
.view .view
= link_to post do = 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 %h4.font-weight-bold.mb-3
%strong %strong
= link_to post do = link_to post do
@@ -16,5 +16,5 @@
= link_to crop do = link_to crop do
= crop_icon(crop) = crop_icon(crop)
= crop.name.pluralize = 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' = 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') %h1= @author ? t('.title.author_posts', author: @author) : t('.title.default')
.row .row
.col-2 .col-md-2
.col-8= will_paginate @posts .col-md-8= will_paginate @posts
.row .row
.col-2 .col-md-2
= render 'layouts/nav', model: Post = render 'layouts/nav', model: Post
%hr/ %hr/
%p %p
@@ -28,7 +28,7 @@
or or
= succeed "." do = succeed "." do
= link_to "comments RSS feed", comments_path(format: 'rss') = link_to "comments RSS feed", comments_path(format: 'rss')
.col-10 .col-md-10
.row.posts .row.posts
- @posts.each do |post| - @posts.each do |post|
.col-lg-3.col-md-6.mb-3.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} %title Comment by #{comment.author.login_name} on #{comment.created_at}
%description %description
:escaped :escaped_markdown
<p> <p>
Comment on Comment on
#{ link_to @post.subject, post_url(@post) } #{ 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? - if @scientific_name.errors.any?
#error_explanation #error_explanation
%h2 %h2

View File

@@ -17,8 +17,10 @@
%td= link_to 'Show', scientific_name %td= link_to 'Show', scientific_name
%td %td
- if can? :edit, scientific_name - 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 %td
- if can? :destroy, scientific_name - 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' class: 'btn btn-default btn-xs'
= will_paginate @scientific_names

View File

@@ -1,5 +1,5 @@
.media .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 .media-body
%p %p
%ul.associations %ul.associations

View File

@@ -16,7 +16,10 @@
= render 'timeline/photos', photo: resolve_model(event) if event.event_type == 'photo' = render 'timeline/photos', photo: resolve_model(event) if event.event_type == 'photo'
%small %small
- if event.event_at.present? - 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 - else
unknown date unknown date

View File

@@ -3,6 +3,8 @@
require_relative 'boot' require_relative 'boot'
require 'rails/all' require 'rails/all'
ENV['RAILS_DISABLE_DEPRECATED_TO_S_CONVERSION'] = "true"
require 'openssl' require 'openssl'
# Require the gems listed in Gemfile, including any gems # Require the gems listed in Gemfile, including any gems
@@ -16,8 +18,6 @@ module Growstuff
I18n.config.enforce_available_locales = true 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. # 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. # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
config.time_zone = '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? config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress JavaScripts and CSS. # Compress JavaScripts and CSS.
config.assets.js_compressor = Uglifier.new(harmony: true) config.assets.js_compressor = :terser
# config.assets.css_compressor = :sass # config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed. # Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false config.assets.compile = false

View File

@@ -25,7 +25,7 @@ Rails.application.configure do
config.action_controller.perform_caching = false config.action_controller.perform_caching = false
# Raise exceptions instead of rendering exception templates. # 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. # Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false config.action_controller.allow_forgery_protection = false

View File

@@ -3,3 +3,4 @@
# Add new mime types for use in respond_to blocks: # Add new mime types for use in respond_to blocks:
# Mime::Type.register "text/richtext", :rtf # 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 # 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 # 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 # 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 # 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 # 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, # 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 # 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 end

View File

@@ -25,7 +25,7 @@ en:
invalid: 'Invalid email or password.' invalid: 'Invalid email or password.'
invalid_token: 'Invalid authentication token.' invalid_token: 'Invalid authentication token.'
timeout: 'Your session expired, please sign in again to continue.' timeout: 'Your session expired, please sign in again to continue.'
inactive: 'Your account was not activated yet.' inactive: 'Your account is not activated.'
sessions: sessions:
signed_in: 'Signed in successfully.' signed_in: 'Signed in successfully.'
signed_out: 'Signed out 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 get 'author/:author' => 'posts#index', as: 'by_author', on: :collection
end end
resources :scientific_names resources :scientific_names do
collection do
get :gbif_suggest
end
end
resources :alternate_names resources :alternate_names
resources :plant_parts resources :plant_parts
resources :photos resources :photos
@@ -73,6 +77,7 @@ Rails.application.routes.draw do
get 'planted_from' => 'charts/crops#planted_from', constraints: { format: 'json' } get 'planted_from' => 'charts/crops#planted_from', constraints: { format: 'json' }
get 'harvested_for' => 'charts/crops#harvested_for', constraints: { format: 'json' } get 'harvested_for' => 'charts/crops#harvested_for', constraints: { format: 'json' }
post :openfarm post :openfarm
post :gbif
collection do collection do
get 'requested' 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. # 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 # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" 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 "created_at", precision: nil
t.datetime "updated_at", precision: nil t.datetime "updated_at", precision: nil
t.integer "creator_id" t.integer "creator_id"
t.integer "gbif_key"
t.string "gbif_rank"
t.string "gbif_status"
t.string "wikidata_id"
end end
create_table "seeds", id: :serial, force: :cascade do |t| create_table "seeds", id: :serial, force: :cascade do |t|

View File

@@ -10,7 +10,7 @@
# include: # include:
# mapbox_map_id # 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. # .gitignored) and fill in the appropriate values.
# Settings in this file will be available to you as ENV['WHATEVER'] # 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' GROWSTUFF_EMAIL='noreply@dev.growstuff.org'
ELASTIC_SEARCH_VERSION="7.5.1-amd64" 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 'bluecloth'
require 'haml/filters/growstuff_markdown' require 'haml/filters/growstuff_markdown'
module Haml::Filters class Haml::Filters
module EscapedMarkdown class EscapedMarkdown < Haml::Filters::GrowstuffMarkdown
include Haml::Filters::Base def compile(node)
def render(text) [:escape, true, super(node)]
Haml::Helpers.html_escape Haml::Filters::GrowstuffMarkdown.render(text)
end end
end end
# Register it as the handler for the :escaped_markdown HAML command. # Register it as the handler for the :escaped_markdown HAML command.
# The automatic system gives us :escapedmarkdown, which is ugly. # The automatic system gives us :escapedmarkdown, which is ugly.
defined['escaped_markdown'] = EscapedMarkdown Haml::Filters.registered[:escaped_markdown] ||= EscapedMarkdown
end end

View File

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

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