Compare commits

...

73 Commits

Author SHA1 Message Date
Daniel O'Connor
561aa6cd75 Mark tests skipped 2025-12-13 03:01:01 +00:00
Daniel O'Connor
49e24bb92b Trial playwright 2025-12-13 02:57:16 +00:00
Daniel O'Connor
3165d8b5c2 Trial playwright 2025-12-13 02:52:10 +00:00
Daniel O'Connor
a77b601327 Merge pull request #4381 from Growstuff/update-crop-page-titles
Update Crop Page Titles
2025-12-13 12:58:14 +10:30
Daniel O'Connor
b70168e3a1 Merge pull request #4395 from Growstuff/relax-interesting-criteria
Relax the criteria as photos are uploaded less often
2025-12-13 12:58:03 +10:30
Daniel O'Connor
d279f9bb64 Merge branch 'dev' into update-crop-page-titles 2025-12-13 12:48:34 +10:30
Daniel O'Connor
83f7ff7c3f Update app/views/crops/show.html.haml 2025-12-13 12:48:14 +10:30
Daniel O'Connor
ae639b6e74 Adjust expectation 2025-12-13 02:12:20 +00:00
Daniel O'Connor
d0ca944899 Relax the criteria as photos are uploaded less often 2025-12-13 01:15:02 +00:00
Daniel O'Connor
1edd4163e1 Merge pull request #4394 from Growstuff/dependabot/bundler/haml-7.1.0
Bump haml from 7.0.2 to 7.1.0
2025-12-13 11:28:58 +10:30
dependabot[bot]
9c03e85882 Bump haml from 7.0.2 to 7.1.0
Bumps [haml](https://github.com/haml/haml) from 7.0.2 to 7.1.0.
- [Release notes](https://github.com/haml/haml/releases)
- [Changelog](https://github.com/haml/haml/blob/main/CHANGELOG.md)
- [Commits](https://github.com/haml/haml/compare/v7.0.2...v7.1.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-12 07:02:42 +00:00
Daniel O'Connor
a303fd6b77 Merge pull request #4391 from Growstuff/pin-dep
Pin dep
2025-12-09 08:21:06 +10:30
Daniel O'Connor
21fea20c7e Bump 2025-12-08 21:50:37 +00:00
Daniel O'Connor
5049b6fd3b Pin 2025-12-08 21:49:38 +00:00
Daniel O'Connor
4bb8749948 Merge pull request #4390 from Growstuff/revert-4386-dependabot/bundler/friendly_id-5.6.0
Revert "Bump friendly_id from 5.5.1 to 5.6.0"
2025-12-09 08:15:22 +10:30
Daniel O'Connor
58548de1bd Revert "Bump friendly_id from 5.5.1 to 5.6.0" 2025-12-09 08:15:08 +10:30
Daniel O'Connor
673a96aaa0 Merge pull request #4389 from Growstuff/revert-4384-dependabot/bundler/dotenv-rails-3.2.0
Revert "Bump dotenv-rails from 3.1.8 to 3.2.0"
2025-12-09 08:11:55 +10:30
Daniel O'Connor
1bc3217be6 Revert "Bump dotenv-rails from 3.1.8 to 3.2.0" 2025-12-09 08:11:40 +10:30
Daniel O'Connor
c2a94c9068 Merge pull request #4382 from Growstuff/dependabot/bundler/faker-3.5.3
Bump faker from 3.5.2 to 3.5.3
2025-12-09 00:30:01 +10:30
Daniel O'Connor
70d3856914 Merge pull request #4388 from Growstuff/dependabot/bundler/oj-3.16.13
Bump oj from 3.16.12 to 3.16.13
2025-12-09 00:29:38 +10:30
dependabot[bot]
e6487e639c Bump oj from 3.16.12 to 3.16.13
Bumps [oj](https://github.com/ohler55/oj) from 3.16.12 to 3.16.13.
- [Release notes](https://github.com/ohler55/oj/releases)
- [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/ohler55/oj/compare/v3.16.12...v3.16.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 10:11:56 +00:00
dependabot[bot]
8d7cc71503 Bump faker from 3.5.2 to 3.5.3
Bumps [faker](https://github.com/faker-ruby/faker) from 3.5.2 to 3.5.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.5.2...v3.5.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 10:11:43 +00:00
Daniel O'Connor
773cbd06bf Merge pull request #4385 from Growstuff/dependabot/bundler/scout_apm-6.0.0
Bump scout_apm from 5.8.0 to 6.0.0
2025-12-08 20:41:16 +10:30
Daniel O'Connor
3d7d6d9e73 Merge pull request #4384 from Growstuff/dependabot/bundler/dotenv-rails-3.2.0
Bump dotenv-rails from 3.1.8 to 3.2.0
2025-12-08 20:41:05 +10:30
Daniel O'Connor
c7b98720e9 Merge pull request #4387 from Growstuff/dependabot/bundler/selenium-webdriver-4.39.0
Bump selenium-webdriver from 4.38.0 to 4.39.0
2025-12-08 20:40:49 +10:30
Daniel O'Connor
3ddef1b2e5 Bump friendly_id from 5.5.1 to 5.6.0 (#4386)
Bumps [friendly_id](https://github.com/norman/friendly_id) from 5.5.1 to 5.6.0.
- [Changelog](https://github.com/norman/friendly_id/blob/master/Changelog.md)
- [Commits](https://github.com/norman/friendly_id/compare/5.5.1...v5.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-08 20:40:25 +10:30
dependabot[bot]
78d665391e Bump selenium-webdriver from 4.38.0 to 4.39.0
Bumps [selenium-webdriver](https://github.com/SeleniumHQ/selenium) from 4.38.0 to 4.39.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.38.0...selenium-4.39.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 07:02:25 +00:00
dependabot[bot]
cf12b910d5 Bump friendly_id from 5.5.1 to 5.6.0
Bumps [friendly_id](https://github.com/norman/friendly_id) from 5.5.1 to 5.6.0.
- [Changelog](https://github.com/norman/friendly_id/blob/master/Changelog.md)
- [Commits](https://github.com/norman/friendly_id/compare/5.5.1...v5.6.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 07:01:36 +00:00
dependabot[bot]
400139bb6a Bump scout_apm from 5.8.0 to 6.0.0
Bumps [scout_apm](https://github.com/scoutapp/scout_apm_ruby) from 5.8.0 to 6.0.0.
- [Changelog](https://github.com/scoutapp/scout_apm_ruby/blob/master/CHANGELOG.markdown)
- [Commits](https://github.com/scoutapp/scout_apm_ruby/compare/v5.8.0...v6.0.0)

---
updated-dependencies:
- dependency-name: scout_apm
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-05 07:04:41 +00:00
dependabot[bot]
ceb4986542 Bump dotenv-rails from 3.1.8 to 3.2.0
Bumps [dotenv-rails](https://github.com/bkeepers/dotenv) from 3.1.8 to 3.2.0.
- [Release notes](https://github.com/bkeepers/dotenv/releases)
- [Changelog](https://github.com/bkeepers/dotenv/blob/main/Changelog.md)
- [Commits](https://github.com/bkeepers/dotenv/compare/v3.1.8...v3.2.0)

---
updated-dependencies:
- dependency-name: dotenv-rails
  dependency-version: 3.2.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-04 07:02:24 +00:00
google-labs-jules[bot]
7457edf559 Merge pull request #4380 from Growstuff/community-garden-landing-page
feat: Add community garden landing page
2025-12-03 18:20:40 +10:30
google-labs-jules[bot]
62951dc5d6 feat: Update crop page titles
- Include the correct English title case
- Include the scientific name if available
- Clearly indicate the crop page is a growing guide and open data repository.
2025-12-02 13:37:45 +00:00
Daniel O'Connor
f1c2a2a7fb Refactor author field to include type and name 2025-12-02 22:59:38 +10:30
Daniel O'Connor
48f96faba4 Include datePublished in social media posting
Added 'datePublished' field to social media posting data.
2025-12-02 22:58:05 +10:30
Daniel O'Connor
a0e8beb372 Update _head.html.haml 2025-12-02 22:51:08 +10:30
Daniel O'Connor
d91799cd51 Update _head.html.haml 2025-12-02 22:47:14 +10:30
Daniel O'Connor
840f57aa8f Delete public/google0bcc8a39985c1800.html 2025-12-02 22:46:06 +10:30
Daniel O'Connor
d28d2ebffd Add files via upload 2025-12-02 22:41:12 +10:30
Daniel O'Connor
fe51feb1b5 Merge pull request #4374 from Growstuff/CloCkWeRX-patch-2
Update sitemap URL in robots.txt
2025-12-02 22:36:42 +10:30
Daniel O'Connor
dad09384df Update sitemap URL in robots.txt 2025-12-02 22:36:29 +10:30
google-labs-jules[bot]
d7452280da Merge pull request #4372 from Growstuff/fix-sitemap-upload
Fix Sitemap Upload to S3
2025-12-02 22:21:26 +10:30
Daniel O'Connor
0d799f00f7 Merge pull request #4369 from Growstuff/sitemap-s3-upload
Upload Sitemap to S3
2025-12-02 02:08:11 +10:30
Daniel O'Connor
4ef1120ccb Merge pull request #4370 from Growstuff/CloCkWeRX-patch-2
Delete spec/tasks/sitemap_cached_spec.rb
2025-12-02 02:06:24 +10:30
Daniel O'Connor
4b9b85bdce bundle 2025-12-01 15:34:26 +00:00
google-labs-jules[bot]
e4c98487ba feat: Add more pages to sitemap
This commit adds static pages, harvests, posts, and photos to the sitemap.
2025-12-01 15:32:06 +00:00
Daniel O'Connor
be59bd9f27 Delete spec/tasks/sitemap_cached_spec.rb 2025-12-02 01:58:19 +10:30
google-labs-jules[bot]
62be64fd38 feat: Upload sitemap to S3 bucket
This commit configures the sitemap generation process to upload the sitemap to an S3 bucket instead of the local filesystem.

It introduces the `aws-sdk-s3` gem to handle the S3 communication. A new configuration file, `config/sitemap.rb`, has been added to define the S3 adapter and specify the models to be included in the sitemap. The S3 bucket, access keys, and region are configured via environment variables.
2025-12-01 15:27:59 +00:00
Daniel O'Connor
18df97acd6 Merge pull request #4368 from Growstuff/feature/add-sitemap-generator
Add Sitemap Generator
2025-12-02 01:32:39 +10:30
Daniel O'Connor
7ea74d8604 Delete config/sitemap.rb 2025-12-02 01:10:35 +10:30
Daniel O'Connor
0054e7d868 Delete lib/tasks/sitemap_cached.rake 2025-12-02 01:10:06 +10:30
Daniel O'Connor
b34442b16b bundle 2025-12-01 14:37:50 +00:00
Daniel O'Connor
0c6cb5b6fd Merge pull request #4367 from Growstuff/feature/dynamic-meta-descriptions
Add dynamic meta descriptions
2025-12-02 01:04:58 +10:30
google-labs-jules[bot]
7f75aed146 feat: Add sitemap generator
Adds the `sitemap_generator` gem to generate a sitemap.

- Includes static routes and dynamic routes for active crops, plantings, seeds, photos, posts, and members.
- Implements a caching mechanism to ensure the sitemap is generated no more frequently than every 72 hours.
- Updates `robots.txt` to point to the new sitemap.
- Includes a unit test for the caching Rake task.
2025-12-01 14:31:54 +00:00
google-labs-jules[bot]
91e1f1c004 feat: Add dynamic meta descriptions
This commit improves the meta descriptions for several pages by making them dynamic and object-specific.

- The default meta description in `app/views/layouts/_head.html.haml` has been updated to include a mention of open data.
- The `show.html.haml` views for crops, seeds, plantings, harvests, and members now have a `content_for :meta_description` block. This block uses the object's description or bio if available, and falls back to a generated string if not.
2025-12-01 14:21:43 +00:00
Daniel O'Connor
9e68fba87c Merge pull request #4366 from Growstuff/add-rack-deflater
Add and configure rack-deflater
2025-12-02 00:41:04 +10:30
Daniel O'Connor
ff658c0eb6 Merge pull request #4365 from Growstuff/add-meta-descriptions
Add meta descriptions to pages
2025-12-02 00:40:23 +10:30
Daniel O'Connor
88c63900c5 Update Gemfile 2025-12-02 00:33:28 +10:30
google-labs-jules[bot]
b029c65692 feat: Add and configure rack-deflater
This change adds the `rack-deflater` gem to the project and configures the application to use it. This will enable gzip compression for HTTP responses, improving performance by reducing the size of the data sent to the client.
2025-12-01 13:57:52 +00:00
Daniel O'Connor
d6a643fd88 Merge pull request #4364 from Growstuff/fix-nutrition-data-rendering
Fix nutrition data rendering
2025-12-02 00:25:34 +10:30
google-labs-jules[bot]
2742dba7fa feat: Add meta descriptions to pages
Adds a meta description tag to the landing, crops, plantings, harvests, seeds, and comments pages.

Also creates a new index page for comments.
2025-12-01 13:54:54 +00:00
Daniel O'Connor
e168070f08 Merge pull request #4363 from Growstuff/add-wikidata-pattern
Add pattern attribute to wikidata input on scientific names
2025-12-02 00:24:51 +10:30
google-labs-jules[bot]
65def47ead Fix: Correct nutrition data rendering and add AFCD name
This commit addresses two issues in the nutritional data view:

1.  **Fixes String Interpolation:** The HAML template incorrectly used an escaped hash (`\#{...}`) in string interpolations, which prevented the nutritional values from being rendered. This has been corrected by removing the backslash.
2.  **Adds AFCD Name:** The view now displays the `food_name` from the Australian Food Classification Data to provide more context to the user.
2025-12-01 13:41:31 +00:00
google-labs-jules[bot]
b5aaf2a124 feat: Add pattern attribute to wikidata input
Adds a pattern attribute to the wikidata input on scientific names to enforce the 'Q' followed by numbers format.
2025-12-01 13:30:24 +00:00
Daniel O'Connor
16956682a9 Merge pull request #4362 from Growstuff/feature/nutritional-data-partial
feat: Add nutritional data partial to crops and harvests
2025-12-01 23:58:17 +10:30
Daniel O'Connor
9ed06bebe6 Merge branch 'dev' into feature/nutritional-data-partial 2025-12-01 23:56:35 +10:30
Daniel O'Connor
e372ef3341 Merge pull request #4361 from Growstuff/improve-wikidata-rake-task
Improve Wikidata Rake Task
2025-12-01 23:56:10 +10:30
google-labs-jules[bot]
c45b75a967 feat: Add nutritional data partial to crops and harvests
This commit introduces a new partial to display nutritional data from the Australian Food Composition Database.

Key changes:
- Adds a database index to the `public_food_key` on the `crops` table.
- Establishes a `has_one` relationship between `Crop` and `AustralianFoodClassificationData`.
- Creates a `_nutritional_data.html.haml` partial to display a summary of key nutritional information.
- Renders the partial on the `show` pages for both crops and harvests.
2025-12-01 12:53:03 +00:00
google-labs-jules[bot]
72e7b7323f feat(rake): Prioritize scientific_names.wikidata_id in task
Improves the `wikidata:import_alternate_names` Rake task to first use the `wikidata_id` from the `scientific_names` table.

- Checks for a `wikidata_id` on a crop's `scientific_names`.
- Falls back to the existing `en_wikipedia_url` if no `wikidata_id` is found.
- Adds logging to indicate the source of the Wikidata ID.
- Improves error handling.
2025-12-01 12:52:49 +00:00
google-labs-jules[bot]
87f79fb071 feat(rake): Prioritize scientific names in Wikidata task
Improves the `wikidata:import_alternate_names` Rake task to first look up a crop's Wikidata ID using its scientific names.

- Iterates through a crop's scientific names to find a Wikidata ID.
- Falls back to the existing `en_wikipedia_url` if no ID is found via scientific names.
- Adds more detailed logging to the task.
- Improves error handling by checking for non-existent Wikipedia pages and using `.dig` for safer hash access.
2025-12-01 12:44:46 +00:00
Daniel O'Connor
c94cf21f72 Merge pull request #4359 from Growstuff/add-public-food-key-to-data-improvement
Add missing public food key id to data improvement page
2025-12-01 21:45:48 +10:30
google-labs-jules[bot]
31c72799ea feat: Add missing public food key id to data improvement page
This change adds a new tab to the data improvement page to show crops that are missing a public food key id.

I was unable to run tests or perform frontend verification due to a known issue with the Ruby environment.
2025-12-01 11:04:01 +00:00
Daniel O'Connor
9ae47afe04 Reduce to member login_name 2025-12-01 10:02:23 +00:00
Daniel O'Connor
e7d8ec6fd0 Fix styling 2025-12-01 09:29:42 +00:00
55 changed files with 1478 additions and 98 deletions

View File

@@ -68,10 +68,24 @@ jobs:
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -71,7 +71,22 @@ jobs:
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev google-chrome-stable
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Install NodeJS
uses: actions/setup-node@v6

View File

@@ -86,8 +86,24 @@ jobs:
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Prepare database for testing
run: bundle exec rails db:prepare

View File

@@ -86,8 +86,24 @@ jobs:
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Prepare database for testing
run: bundle exec rails db:prepare

View File

@@ -86,8 +86,24 @@ jobs:
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Prepare database for testing
run: bundle exec rails db:prepare

View File

@@ -86,8 +86,24 @@ jobs:
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Prepare database for testing
run: bundle exec rails db:prepare

View File

@@ -101,8 +101,24 @@ jobs:
- name: Install required JS packages
run: yarn install
- name: install chrome
run: sudo apt-get install google-chrome-stable
- name: Install required OS packages
run: |
sudo apt-get -y install libpq-dev
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- name: Prepare database for testing
run: bundle exec rails db:prepare

10
Gemfile
View File

@@ -136,6 +136,11 @@ gem "gbifrb"
gem "msgpack"
# Pinned due to RAILS_ENV=production bundle exec rake assets:precompile failing with ArgumentError: wrong number of arguments (given 1, expected 0) (ArgumentError)
# /tmp/build_8301a541/vendor/bundle/ruby/3.3.0/gems/connection_pool-3.0.2/lib/connection_pool.rb:48:in `initialize'
# /tmp/build_8301a541/vendor/bundle/ruby/3.3.0/gems/activesupport-7.2.3/lib/active_support/cache/mem_cache_store.rb:63:in `new'
gem "connection_pool", "< 3"
group :production do
gem 'bonsai-elasticsearch-rails' # Integration with Bonsa-Elasticsearch on heroku
gem 'dalli'
@@ -190,7 +195,7 @@ group :test do
gem "percy-capybara", "~> 5.0.0"
gem 'rails-controller-testing'
gem "rspec-rebound"
gem 'selenium-webdriver'
gem 'capybara-playwright-driver'
gem 'timecop'
gem 'vcr'
end
@@ -202,3 +207,6 @@ end
gem "i18n_data", "~> 1.1"
gem "paper_trail", "~> 17.0"
gem 'sitemap_generator'
gem 'aws-sdk-s3', '~> 1', '>= 1.114.0'

View File

@@ -121,6 +121,25 @@ GEM
ast (2.4.3)
autoprefixer-rails (10.4.16.0)
execjs (~> 2)
aws-eventstream (1.4.0)
aws-partitions (1.1189.0)
aws-sdk-core (3.239.2)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
bigdecimal
jmespath (~> 1, >= 1.6.1)
logger
aws-sdk-kms (1.118.0)
aws-sdk-core (~> 3, >= 3.239.1)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.205.0)
aws-sdk-core (~> 3, >= 3.234.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.12.1)
aws-eventstream (~> 1, >= 1.0.2)
axe-core-api (4.11.0)
dumb_delegator
ostruct
@@ -175,6 +194,10 @@ GEM
capybara-email (3.0.2)
capybara (>= 2.4, < 4.0)
mail
capybara-playwright-driver (0.5.7)
addressable
capybara
playwright-ruby-client (>= 1.16.0)
capybara-screenshot (1.0.26)
capybara (>= 1.0, < 4)
launchy
@@ -235,9 +258,9 @@ GEM
discard (1.4.0)
activerecord (>= 4.2, < 9.0)
domain_name (0.6.20240107)
dotenv (3.1.8)
dotenv-rails (3.1.8)
dotenv (= 3.1.8)
dotenv (3.2.0)
dotenv-rails (3.2.0)
dotenv (= 3.2.0)
railties (>= 6.1)
drb (2.2.3)
dumb_delegator (1.1.0)
@@ -265,7 +288,7 @@ GEM
factory_bot_rails (6.5.1)
factory_bot (~> 6.5)
railties (>= 6.1.0)
faker (3.5.2)
faker (3.5.3)
i18n (>= 1.8.11, < 2)
faraday (2.14.0)
faraday-net_http (>= 2.0, < 3.5)
@@ -277,7 +300,7 @@ GEM
flickraw (0.9.10)
font-awesome-sass (5.15.1)
sassc (>= 1.11)
friendly_id (5.5.1)
friendly_id (5.6.0)
activerecord (>= 4.0.0)
gbifrb (0.2.0)
geocoder (1.8.6)
@@ -293,7 +316,7 @@ GEM
gravatar-ultimate (2.0.0)
activesupport (>= 2.3.14)
rack
haml (7.0.2)
haml (7.1.0)
temple (>= 0.8.2)
thor
tilt
@@ -356,6 +379,7 @@ GEM
pp (>= 0.6.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jmespath (1.6.2)
jquery-rails (4.6.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
@@ -442,7 +466,7 @@ GEM
nokogiri (1.18.10-x86_64-linux-gnu)
racc (~> 1.4)
oauth (0.5.6)
oj (3.16.12)
oj (3.16.13)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (1.9.2)
@@ -472,6 +496,9 @@ GEM
heroics (~> 0.1.1)
moneta (~> 1.0.0)
rate_throttle_client (~> 0.1.0)
playwright-ruby-client (1.57.0)
concurrent-ruby (>= 1.1.6)
mime-types (>= 3.0)
popper_js (2.11.8)
pp (0.6.3)
prettyprint
@@ -551,7 +578,7 @@ GEM
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rdoc (6.16.1)
rdoc (6.17.0)
erb
psych (>= 4.0.0)
tsort
@@ -655,7 +682,7 @@ GEM
ruby-units (4.1.0)
ruby-vips (2.2.1)
ffi (~> 1.12)
rubyzip (3.2.1)
rubyzip (3.2.2)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@@ -669,13 +696,13 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
scout_apm (5.8.0)
scout_apm (6.0.0)
parser
searchkick (5.3.1)
activemodel (>= 6.1)
hashie
securerandom (0.4.1)
selenium-webdriver (4.38.0)
selenium-webdriver (4.39.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
@@ -688,6 +715,8 @@ GEM
rack (>= 2.2.4)
redis-client (>= 0.22.2)
simple_po_parser (1.1.6)
sitemap_generator (6.3.0)
builder (~> 3.0)
sprockets (3.7.5)
base64
concurrent-ruby (~> 1.0)
@@ -697,7 +726,7 @@ GEM
activesupport (>= 5.2)
sprockets (>= 3.0.0)
ssrf_filter (1.1.2)
stringio (3.1.8)
stringio (3.1.9)
sysexits (1.2.0)
temple (0.10.4)
terminal-table (4.0.0)
@@ -708,7 +737,7 @@ GEM
thread_safe (0.3.6)
tilt (2.6.1)
timecop (0.9.10)
timeout (0.4.4)
timeout (0.5.0)
tsort (0.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
@@ -759,6 +788,7 @@ DEPENDENCIES
active_median
active_record_union
active_utils
aws-sdk-s3 (~> 1, >= 1.114.0)
axe-core-capybara
axe-core-rspec
better_errors
@@ -773,10 +803,12 @@ DEPENDENCIES
cancancan
capybara
capybara-email
capybara-playwright-driver
capybara-screenshot
chartkick
coffee-rails
comfortable_mexican_sofa!
connection_pool (< 3)
crowdin-cli
csv_shaper
dalli
@@ -854,6 +886,7 @@ DEPENDENCIES
searchkick
selenium-webdriver
sidekiq
sitemap_generator
sprockets (< 4)
terser
timecop

View File

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 266 KiB

View File

@@ -33,4 +33,4 @@
@view-transition {
navigation: auto;
}
}

View File

@@ -170,6 +170,8 @@ class CropsController < ApplicationController
Crop.approved.where(sun_requirements: [nil, '']).order(plantings_count: :desc)
when 'height'
Crop.approved.where(height: nil).order(plantings_count: :desc)
when 'public_food_key'
Crop.approved.where(public_food_key: [nil, '']).order(plantings_count: :desc)
else
Crop.none
end

View File

@@ -10,4 +10,6 @@ class HomeController < ApplicationController
# the relevant class methods directly in the view, so that fragment
# caching will be effective.
end
def community_gardens; end
end

View File

@@ -58,7 +58,11 @@ module CropsHelper
subject_of_entities << {
'@type': "SocialMediaPosting",
url: post_url(post),
author: post.author
author: {
'@type': 'Person',
name: post.author.login_name
},
'datePublished': post.created_at
}
end

View File

@@ -1,2 +1,8 @@
# frozen_string_literal: true
class AustralianFoodClassificationData < ApplicationRecord
belongs_to :crop,
foreign_key: :public_food_key,
primary_key: :public_food_key,
inverse_of: :australian_food_classification_data
end

View File

@@ -53,7 +53,9 @@ module SearchHarvests
owners = []
1..limit.times do
where = {
photos_count: { gt: 0 },
# Disabled for now so that more relevant harvests are
# surfaced; even if we're falling back to crop photos.
# photos_count: { gt: 0 },
owner_id: { not: owners }
}
one_record = search('*',

View File

@@ -66,7 +66,9 @@ module SearchPlantings
owners = []
1..limit.times do
where = {
photos_count: { gt: 0 },
# Disabled for now so that more relevant plantings are
# surfaced; even if we're falling back to crop photos.
# photos_count: { gt: 0 },
owner_id: { not: owners }
}
one_record = search('*',

View File

@@ -28,6 +28,10 @@ class Crop < ApplicationRecord
has_many :companions, through: :crop_companions, source: :crop_b, class_name: 'Crop'
has_many :crop_posts, dependent: :delete_all
has_many :posts, through: :crop_posts, dependent: :delete_all
has_one :australian_food_classification_data,
foreign_key: :public_food_key,
primary_key: :public_food_key,
inverse_of: :crop
accepts_nested_attributes_for :scientific_names, allow_destroy: true, reject_if: :all_blank

View File

@@ -0,0 +1,13 @@
- content_for :title, "Comments"
- content_for :meta_description, "Browse and search for comments."
- content_for :breadcrumbs do
%li.breadcrumb-item.active= link_to "Comments", comments_path
%h1 Comments
= will_paginate @comments
- @comments.each do |comment|
= render 'single', comment: comment
= will_paginate @comments

View File

@@ -0,0 +1,38 @@
- data = crop.australian_food_classification_data
- if data
.card
.card-body
%h4.card-title Nutritional Data
%p.card-text A summary of nutritional data per 100g for #{data.food_name}.
%table.table.table-sm.table-borderless
%tbody
- if data.energy_with_dietary_fibre_equated_kj.to_f > 0
%tr
%th Energy
%td= "#{data.energy_with_dietary_fibre_equated_kj.to_f.round(1)} kJ"
- if data.protein_g.to_f > 0
%tr
%th Protein
%td= "#{data.protein_g.to_f.round(1)} g"
- if data.fat_total_g.to_f > 0
%tr
%th Fat, total
%td= "#{data.fat_total_g.to_f.round(1)} g"
- if data.available_carbohydrate_with_sugar_alcohols_g.to_f > 0
%tr
%th Carbohydrate
%td= "#{data.available_carbohydrate_with_sugar_alcohols_g.to_f.round(1)} g"
- if data.total_sugars_g.to_f > 0
%tr
%th - Sugars
%td= "#{data.total_sugars_g.to_f.round(1)} g"
- if data.total_dietary_fibre_g.to_f > 0
%tr
%th Fibre
%td= "#{data.total_dietary_fibre_g.to_f.round(1)} g"
- if data.sodium_na_mg.to_f > 0
%tr
%th Sodium
%td= "#{data.sodium_na_mg.to_f.round(1)} mg"
.card-footer
= link_to "See more", "https://afcd.foodstandards.gov.au/fooddetails.aspx?PFKID=#{data.public_food_key}", target: "_blank", rel: "noopener noreferrer"

View File

@@ -1,10 +1,10 @@
%h1 Data Improvement
- tabs = { photos: "Photos", descriptions: "Descriptions", youtube: "YouTube videos", alternate_names: "Alternate names", wikidata: "Wikidata ID", row_spacing: "Row spacing", sun_requirements: "Sun requirements", height: "Height" }
- tabs = { photos: "Photos", descriptions: "Descriptions", youtube: "YouTube videos", alternate_names: "Alternate names", wikidata: "Wikidata ID", public_food_key: "Public Food Key", row_spacing: "Row spacing", sun_requirements: "Sun requirements", height: "Height" }
%ul.nav.nav-tabs
- tabs.each do |key, value|
%li{class: ('active' if @active_tab == key.to_s)}
%li{class: "nav-item #{('active' if @active_tab == key.to_s)}"}
= link_to value, data_improvement_crops_path(tab: key)
.tab-content

View File

@@ -1,4 +1,5 @@
- content_for :title, t('.title')
- content_for :meta_description, "Browse and search for crops."
- content_for :buttonbar do
- if can? :wrangle, Crop

View File

@@ -1,5 +1,13 @@
= render 'schema_org', crop: @crop
- content_for :title, @crop.name
- content_for :title do
= @crop.name.titleize
- if @crop.default_scientific_name.present?
= " (#{@crop.default_scientific_name})"
- content_for :meta_description do
- if @crop.description.present?
= @crop.description
- else
= "Learn how to grow #{@crop.name}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: crop_image_path(@crop))
= tag("meta", property: "og:title", content: @crop.name)
@@ -128,6 +136,8 @@
= render 'openfarm_data', crop: @crop
= render 'nutritional_data', crop: @crop
= cute_icon
.card
.card-body

View File

@@ -1,5 +1,6 @@
- content_for(:title) do
= title('harvests', @owner, @crop, @planting)
- content_for :meta_description, "Browse and search for harvests."
- content_for :breadcrumbs do
- if @owner
%li.breadcrumb-item= link_to 'Harvests', harvests_path

View File

@@ -1,4 +1,9 @@
= content_for :title, "#{@harvest.crop} harvested by #{@harvest.owner}"
- content_for :meta_description do
- if @harvest.description.present?
= @harvest.description
- else
= "#{@harvest.crop} harvested by #{@harvest.owner}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: harvest_image_path(@harvest))
= tag("meta", property: "og:image:user_generated", content: "true")
@@ -71,3 +76,4 @@
.col-md-4.col-xs-12
= render @harvest.crop
= render 'crops/nutritional_data', crop: @harvest.crop

View File

@@ -0,0 +1,37 @@
- content_for :title do
= t('community_gardens.title')
- content_for :meta_description do
= t('community_gardens.meta_description')
.container.mt-5
.row
.col-lg-6.col-sm-12
.row
%h1.display-4= t('community_gardens.header')
%p.lead= t('community_gardens.lead')
.row
%h2= t('community_gardens.features_title')
%ul
%li Track all your plantings and harvests
%li Keep notes your community's progress
%li Add collaborators to your garden plots
%li See what other community gardens are growing
%li Get advice and support from our community of gardeners
.row
%h2= t('community_gardens.get_started')
%p= t('community_gardens.get_started_text')
%p
= link_to t('.sign_up'), new_member_registration_path, class: 'btn btn-success btn-lg'
.row
%h2= t('community_gardens.collaborate')
%p= t('community_gardens.collaborate_text')
%p
= link_to t('community_gardens.learn_more'), gardens_path, class: 'btn btn-info btn-lg'
.col-lg-6.d-lg-block.d-xs-none
.container
=image_tag("girlwithvegetables-0038331hotifw.svg", width: "100%")

View File

@@ -1,5 +1,7 @@
- content_for :title do
= ENV['GROWSTUFF_SITE_NAME']
- content_for :meta_description do
Growstuff is a community of food gardeners. Let's learn to grow food together.
- if member_signed_in?
.row

View File

@@ -27,9 +27,14 @@
%title
= content_for?(:title) ? yield(:title) + " - #{ENV['GROWSTUFF_SITE_NAME']} " : ENV['GROWSTUFF_SITE_NAME']
- if content_for?(:meta_description)
%meta{name: "description", content: yield(:meta_description)}
- else
%meta{name: "description", content: "Growstuff is a community of food gardeners. Let's learn to grow food together. All our data is open data."}
= csrf_meta_tags
= stylesheet_link_tag "application", media: "all"
%link{ href: path_to_image("growstuff-apple-touch-icon-precomposed.png"), rel: "apple-touch-icon-precomposed" }
%link{ href: "https://fonts.googleapis.com/css?family=Modak|Raleway&display=swap", rel: "stylesheet" }
= favicon_link_tag 'favicon.ico'
= tag("meta", name: "google-site-verification", content: "j249rPGdBqZ7gcShcdsSXCnGN5lqCuTISJnlQXxOfu4")

View File

@@ -52,6 +52,7 @@
.dropdown-menu{"aria-labelledby" => "navbarDropdown"}
= link_to t('.community_map'), places_path, class: 'dropdown-item'
= link_to t('.browse_members'), members_path, class: 'dropdown-item'
= link_to t('.community_gardens'), community_gardens_path, class: 'dropdown-item'
= link_to t('.posts'), posts_path, class: 'dropdown-item'
= link_to t('.forums'), forums_path, class: 'dropdown-item'

View File

@@ -1,4 +1,9 @@
- content_for :title, @member.login_name
- content_for :meta_description do
- if @member.bio.present?
= @member.bio
- else
= "Gardening profile for #{@member.login_name}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: avatar_uri(@member, 200))
= tag("meta", property: "og:image:user_generated", content: "true")

View File

@@ -1,4 +1,5 @@
- content_for :title, title('plantings', @owner, @crop, @planting)
- content_for :meta_description, "Browse and search for plantings."
- content_for :breadcrumbs do
- if @owner

View File

@@ -1,4 +1,9 @@
= content_for :title, "#{@planting.crop} in #{@planting.location}"
- content_for :meta_description do
- if @planting.description.present?
= @planting.description
- else
= "#{@planting.crop} planted in #{@planting.location} by #{@planting.owner}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: planting_image_path(@planting))
= tag("meta", property: "og:title", content: "#{@planting.crop} in #{@planting.location}")

View File

@@ -27,7 +27,7 @@
.form-group
= f.label :wikidata_id, "Wikidata ID", class: 'control-label col-md-2'
.col-md-8
= f.text_field :wikidata_id, class: 'form-control'
= f.text_field :wikidata_id, class: 'form-control', pattern: 'Q[1-9][0-9]*'
.form-group
.form-actions.col-md-offset-2.col-md-8
= f.submit 'Save', class: 'btn btn-primary'

View File

@@ -6,6 +6,7 @@
%li.breadcrumb-item.active= link_to 'Seeds', seeds_path
- content_for :title, title('seeds', @owner, @crop, @planting)
- content_for :meta_description, "Browse and search for seeds."
.row
.col-md-2

View File

@@ -1,4 +1,9 @@
- content_for :title, "#{@seed.owner}'s #{@seed.crop} seeds"
- content_for :meta_description do
- if @seed.description.present?
= @seed.description
- else
= "Seeds for #{@seed.crop.name}, shared by #{@seed.owner}."
- content_for :opengraph do
= tag("meta", property: "og:image", content: seed_image_path(@seed))
- if @seed.description

View File

@@ -3,4 +3,6 @@
# This file is used by Rack-based servers to start the application.
require File.expand_path('config/environment', __dir__)
use Rack::Deflater
run Rails.application

View File

@@ -219,6 +219,18 @@ en:
pwa_ios_steps_html: 1. Tap the <strong>Share</strong> button in Safari.<br>2. Scroll down and tap <strong>Add to Home Screen</strong>'.
pwa_ios_title: For iOS (iPhone/iPad)
pwa_title: Want to install Growstuff on your phone?
community_gardens:
title: Community Gardens on Growstuff
meta_description: Manage your community garden, track your plantings, and collaborate with other gardeners.
header: Community Gardens
lead: Growstuff is open source and the perfect place to manage your community garden. Track your plantings, celebrate your harvests, and collaborate with your fellow gardeners, all in one place.
get_started: Get Started Today
get_started_text: Signing up for Growstuff is free and easy. Create an account to start tracking your garden today.
sign_up: Sign up for free
collaborate: Collaborate with Your Team
collaborate_text: Invite other gardeners to collaborate on your garden plots. Share the work, share the harvest, and grow together as a community.
learn_more: Learn more about gardens
features_title: Features for Community Gardens
label:
days_until_harvest: "%{number} days"
weeks_until_harvest: "%{number} weeks until harvest"
@@ -235,6 +247,7 @@ en:
browse_members: Browse Members
community: Community
community_map: Community Map
community_gardens: Community Gardens
garden_type: Garden Type
garden_types: Garden Types
crop_wrangling: Crop Wrangling

View File

@@ -23,6 +23,7 @@ Rails.application.routes.draw do
resources :authentications, only: %i(create destroy)
get "home/index"
get '/community-gardens', to: 'home#community_gardens'
root to: 'home#index'
concern :has_photos do

55
config/sitemap.rb Normal file
View File

@@ -0,0 +1,55 @@
# frozen_string_literal: true
require 'aws-sdk-s3'
# Set the host name for URL creation
SitemapGenerator::Sitemap.default_host = 'https://growstuff.org'
SitemapGenerator::Sitemap.adapter = SitemapGenerator::AwsSdkAdapter.new(
ENV['S3_SITEMAP_BUCKET'],
access_key_id: ENV['S3_ACCESS_KEY'],
secret_access_key: ENV['S3_SECRET_KEY'],
region: ENV.fetch('S3_AWS_REGION', 'us-east-1')
)
SitemapGenerator::Sitemap.create do
# Add static pages
add '/about', changefreq: 'monthly'
add '/community', changefreq: 'monthly'
add '/contact', changefreq: 'monthly'
# Add crops
Crop.approved.find_each do |crop|
add crop_path(crop), lastmod: crop.updated_at
end
# Add members
Member.kept.find_each do |member|
add member_path(member), lastmod: member.updated_at
end
# Add plantings
Planting.active.find_each do |planting|
add planting_path(planting), lastmod: planting.updated_at
end
# Add seeds
Seed.active.find_each do |seed|
add seed_path(seed), lastmod: seed.updated_at
end
# Add harvests
Harvest.find_each do |harvest|
add harvest_path(harvest), lastmod: harvest.updated_at
end
# Add posts
Post.find_each do |post|
add post_path(post), lastmod: post.updated_at
end
# Add photos
Photo.find_each do |photo|
add photo_path(photo), lastmod: photo.updated_at
end
end

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddIndexToCropsPublicFoodKey < ActiveRecord::Migration[7.2]
def change
add_index :crops, :public_food_key
end
end

View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2025_11_30_053104) do
ActiveRecord::Schema[7.2].define(version: 2025_12_01_045000) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -564,6 +564,7 @@ ActiveRecord::Schema[7.2].define(version: 2025_11_30_053104) do
t.index ["creator_id"], name: "index_crops_on_creator_id"
t.index ["name"], name: "index_crops_on_name"
t.index ["parent_id"], name: "index_crops_on_parent_id"
t.index ["public_food_key"], name: "index_crops_on_public_food_key"
t.index ["requester_id"], name: "index_crops_on_requester_id"
t.index ["slug"], name: "index_crops_on_slug", unique: true
end

View File

@@ -13,45 +13,65 @@ namespace :wikidata do
end
Crop.all.each do |crop|
next unless crop.en_wikipedia_url.present?
puts "Processing crop: #{crop.name}"
wikidata_id = nil
begin
title = crop.en_wikipedia_url.split('/').last
puts "Processing crop: #{crop.name} (Wikipedia title: #{title})"
# Try to find Wikidata ID from the scientific_names table first
if (sci_name_with_id = crop.scientific_names.find { |sn| sn.wikidata_id.present? })
wikidata_id = sci_name_with_id.wikidata_id
puts " Found Wikidata ID in scientific_names table: #{wikidata_id}"
# If not found, try the existing en_wikipedia_url method
elsif crop.en_wikipedia_url.present?
begin
title = crop.en_wikipedia_url.split('/').last
puts " Searching for Wikidata ID using Wikipedia URL: #{crop.en_wikipedia_url}"
# Get Wikidata ID from Wikipedia API
wiki_uri = URI("https://en.wikipedia.org/w/api.php?action=query&prop=pageprops&titles=#{title}&format=json")
wiki_response = Net::HTTP.get(wiki_uri)
wiki_data = JSON.parse(wiki_response)
page_id = wiki_data['query']['pages'].keys.first
wikidata_id = wiki_data['query']['pages'][page_id]['pageprops']['wikibase_item']
# Get Wikidata ID from Wikipedia API
wiki_uri = URI("https://en.wikipedia.org/w/api.php?action=query&prop=pageprops&titles=#{title}&format=json")
wiki_response = Net::HTTP.get(wiki_uri)
wiki_data = JSON.parse(wiki_response)
pages = wiki_data['query']['pages']
page_id = pages.keys.first
if wikidata_id
puts " Found Wikidata ID: #{wikidata_id}"
if page_id != "-1" && pages[page_id]['pageprops'] && pages[page_id]['pageprops']['wikibase_item']
wikidata_id = pages[page_id]['pageprops']['wikibase_item']
puts " Found Wikidata ID via Wikipedia URL: #{wikidata_id}"
end
rescue StandardError => e
puts " Error querying Wikipedia for URL #{crop.en_wikipedia_url}: #{e.message}"
end
end
if wikidata_id
begin
# Get aliases from Wikidata API
wikidata_uri = URI("https://www.wikidata.org/w/api.php?action=wbgetentities&ids=#{wikidata_id}&props=aliases&format=json")
wikidata_response = Net::HTTP.get(wikidata_uri)
wikidata_data = JSON.parse(wikidata_response)
aliases = wikidata_data['entities'][wikidata_id]['aliases']
aliases.each do |lang, values|
values.each do |value|
next if AlternateName.exists?(name: value['value'], language: lang, crop: crop)
aliases = wikidata_data.dig('entities', wikidata_id, 'aliases')
if aliases
aliases.each do |lang, values|
values.each do |value|
next if AlternateName.exists?(name: value['value'], language: lang, crop: crop)
AlternateName.create!(
name: value['value'],
language: lang,
crop: crop,
creator: creator
)
puts " Added alternate name: #{value['value']} (#{lang})"
AlternateName.create!(
name: value['value'],
language: lang,
crop: crop,
creator: creator
)
puts " Added alternate name: #{value['value']} (#{lang})"
end
end
else
puts " No aliases found for Wikidata ID: #{wikidata_id}"
end
else
puts " Could not find Wikidata ID for #{crop.name}"
rescue StandardError => e
puts " Error processing Wikidata aliases for #{crop.name}: #{e.message}"
end
rescue StandardError => e
puts " Error processing crop #{crop.name}: #{e.message}"
else
puts " Could not find Wikidata ID for #{crop.name}"
end
end
end

View File

@@ -16,7 +16,8 @@
"csslint": "^1.0.5",
"eslint": "^5.0.0",
"eslint-config-google": "^0.9.1",
"jshint": "^2.9.4"
"jshint": "^2.9.4",
"playwright": "1.57.0"
},
"repository": {
"type": "git",

View File

@@ -140,3 +140,5 @@ Crawl-delay: 5
#
User-agent: *
Disallow: /api/
Sitemap: https://growstuff-prod.s3.us-west-2.amazonaws.com/sitemap.xml.gz

View File

@@ -605,7 +605,7 @@ describe Planting do
before { described_class.reindex }
it { expect(subject.count).to eq 2 }
it { expect(subject.map(&:id)).to eq([interesting_planting.id.to_s, finished_interesting_planting.id.to_s]) }
it { expect(subject.count).to eq 3 }
it { expect(subject.map(&:id)).to eq([interesting_planting.id.to_s, finished_interesting_planting.id.to_s, planting.id.to_s]) }
end
end

View File

@@ -10,35 +10,36 @@ Rails.application.eager_load!
require 'capybara'
require 'capybara/rspec'
require 'selenium/webdriver'
require 'capybara-screenshot/rspec'
require 'axe-capybara'
require 'axe-rspec'
# require 'capybara-screenshot/rspec'
# require 'axe-capybara'
# require 'axe-rspec'
# Required for running in the dev container
Capybara.register_driver :selenium_chrome_customised_headless do |app|
options = Selenium::WebDriver::Options.chrome
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--window-size=1920,1080")
options.add_argument("--disable-dev-shm-usage")
Capybara.register_driver :playwright_chrome_customised do |app|
# options = Capybara::Playwright::Options.chrome
# # options.add_argument("--headless")
# options.add_argument("--no-sandbox")
# options.add_argument("--window-size=1920,1080")
# options.add_argument("--disable-dev-shm-usage")
# driver = Selenium::WebDriver.for :chrome, options: options
Capybara::Selenium::Driver.new(app, browser: :chrome, options:)
Capybara::Playwright::Driver.new(app,
browser_type: ENV["PLAYWRIGHT_BROWSER"]&.to_sym || :chromium,
headless: true)
end
# Ability to pass in flags to
if ENV["CAPYBARA_DRIVER"]
Capybara.default_driver = ENV["CAPYBARA_DRIVER"].to_sym
Capybara.javascript_driver = ENV["CAPYBARA_DRIVER"].to_sym
else
Capybara.default_driver = :selenium_chrome_customised_headless
Capybara.javascript_driver = :selenium_chrome_customised_headless
Capybara.default_driver = :playwright_chrome_customised
Capybara.javascript_driver = :playwright_chrome_customised
end
Capybara.enable_aria_label = true
Capybara::Screenshot.register_driver(:selenium_chrome_customised_headless) do |driver, path|
Capybara::Screenshot.register_driver(:playwright_chrome_customised) do |driver, path|
driver.browser.save_screenshot(path)
end
Capybara::Screenshot.register_filename_prefix_formatter(:rspec) do |example|
@@ -50,7 +51,7 @@ Capybara.server_port = 8081
# TODO: Find a better home.
shared_examples 'is accessible' do
it "is accessible" do
it "is accessible", pending: 'not compatible with playwright' do
expect(page).to be_axe_clean.skipping('color-contrast', 'heading-order', 'aria-required-children').according_to :wcag2a
end
end
@@ -122,15 +123,15 @@ RSpec.configure do |config|
# TODO: Why are we setting this page size then straight afterwards, maximising?
width = 1920
height = 1080
Capybara.current_session.driver.browser.manage.window.resize_to(width, height)
# Capybara.current_session.driver.browser.manage.window.resize_to(width, height)
if page.driver.browser.respond_to?(:url_blacklist)
page.driver.browser.url_blacklist = [
'gravatar.com',
'okfn.org',
'googlecode.com'
]
end
# if page.driver.browser.respond_to?(:url_blacklist)
# page.driver.browser.url_blacklist = [
# 'gravatar.com',
# 'okfn.org',
# 'googlecode.com'
# ]
# end
# Historically, we wanted to .maximize; but this actually undoes the resize_to step above
# with chrome headless

View File

@@ -801,6 +801,11 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
fsevents@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -1298,6 +1303,20 @@ picomatch@^2.3.0, picomatch@^2.3.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
playwright-core@1.57.0:
version "1.57.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.57.0.tgz#3dcc9a865af256fa9f0af0d67fc8dd54eecaebf5"
integrity sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==
playwright@1.57.0:
version "1.57.0"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.57.0.tgz#74d1dacff5048dc40bf4676940b1901e18ad0f46"
integrity sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==
dependencies:
playwright-core "1.57.0"
optionalDependencies:
fsevents "2.3.2"
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"