diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 56fd89ff67b..524bb644dae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,16 +12,16 @@ jobs: strategy: matrix: - ruby-version: [3.1] + ruby-version: ['4.0'] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby-version }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: vendor/bundle key: gems-${{ runner.os }}-${{ matrix.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6a032b44969..266f8558468 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,16 +11,16 @@ jobs: runs-on: ubuntu-latest env: - ruby-version: 2.6 + ruby-version: '4.0' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ env.ruby-version }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: vendor/bundle key: gems-${{ runner.os }}-${{ env.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} diff --git a/.github/workflows/dev_deploy.yml b/.github/workflows/dev_deploy.yml index d9edd290178..f47441fcd3d 100644 --- a/.github/workflows/dev_deploy.yml +++ b/.github/workflows/dev_deploy.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v1 @@ -53,16 +53,16 @@ jobs: runs-on: ubuntu-latest env: - ruby-version: 2.6 + ruby-version: '4.0' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ env.ruby-version }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: vendor/bundle key: gems-${{ runner.os }}-${{ env.ruby-version }}-${{ hashFiles('**/Gemfile.lock') }} diff --git a/.ruby-version b/.ruby-version index 6cb9d3dd0d6..1454f6ed4b7 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.3 +4.0.1 diff --git a/Gemfile b/Gemfile index 28ad6f4375f..6ec509acae2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,18 +1,23 @@ ruby '>= 3.1' source 'https://rubygems.org' +gem 'benchmark' gem 'bigdecimal' -gem 'mutex_m' gem 'base64' +gem 'csv' +gem 'logger' +gem 'mutex_m' +gem 'ostruct' +gem 'rdoc' # Middleman -gem 'middleman', '~> 4.4' +gem 'middleman', '~> 4.6.3' gem 'middleman-syntax', '~> 3.2' gem 'middleman-autoprefixer', '~> 3.0' gem 'middleman-sprockets', '~> 4.1' gem 'middleman-data_source' gem 'rouge', '~> 3.21' gem 'redcarpet', '~> 3.6.0' -gem 'nokogiri', '~> 1.18.1' +gem 'nokogiri', '~> 1.19' gem 'sass' gem 'webrick' diff --git a/Gemfile.lock b/Gemfile.lock index 3d66c0fc216..ec8f64dc858 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,81 +1,99 @@ GEM remote: https://rubygems.org/ specs: - activesupport (7.0.8) - concurrent-ruby (~> 1.0, >= 1.0.2) + activesupport (8.1.2) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) + json + logger (>= 1.4.2) minitest (>= 5.1) - tzinfo (~> 2.0) - addressable (2.8.6) - public_suffix (>= 2.0.2, < 6.0) - autoprefixer-rails (10.3.1.0) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + uri (>= 0.13.1) + addressable (2.8.8) + public_suffix (>= 2.0.2, < 8.0) + autoprefixer-rails (10.4.21.0) execjs (~> 2) - backports (3.24.1) base64 (0.3.0) + benchmark (0.5.0) bigdecimal (4.0.1) borrower (0.10.0) coffee-script (2.4.1) coffee-script-source execjs coffee-script-source (1.12.2) - concurrent-ruby (1.2.3) - contracts (0.16.1) - dotenv (2.8.1) - erubis (2.7.0) - execjs (2.9.1) + concurrent-ruby (1.3.6) + connection_pool (3.0.2) + contracts (0.17.3) + csv (3.3.5) + date (3.5.1) + dotenv (3.2.0) + drb (2.2.3) + erb (6.0.2) + erubi (1.13.1) + execjs (2.10.0) fast_blank (1.0.1) - fastimage (2.3.0) - ffi (1.16.3) - haml (6.3.0) + fastimage (2.4.0) + ffi (1.17.3) + ffi (1.17.3-x86_64-linux-gnu) + haml (6.4.0) temple (>= 0.8.2) thor tilt hamster (3.0.0) concurrent-ruby (~> 1.0) - hashie (3.6.0) - i18n (1.6.0) + hashie (5.1.0) + logger + i18n (1.14.8) concurrent-ruby (~> 1.0) - kramdown (2.4.0) - rexml - listen (3.8.0) + json (2.18.1) + kramdown (2.5.2) + rexml (>= 3.4.4) + listen (3.10.0) + logger rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) + logger (1.7.0) memoist (0.16.2) - middleman (4.5.1) - coffee-script (~> 2.2) - haml (>= 4.0.5) - kramdown (>= 2.3.0) - middleman-cli (= 4.5.1) - middleman-core (= 4.5.1) + middleman (4.6.3) + middleman-cli (= 4.6.3) + middleman-core (= 4.6.3) middleman-autoprefixer (3.0.0) autoprefixer-rails (~> 10.0) middleman-core (>= 4.0.0) - middleman-cli (4.5.1) - thor (>= 0.17.0, < 1.3.0) - middleman-core (4.5.1) - activesupport (>= 6.1, < 7.1) + middleman-cli (4.6.3) + thor (>= 0.17.0, < 2) + middleman-core (4.6.3) + activesupport (>= 6.1) addressable (~> 2.4) - backports (~> 3.6) - bundler (~> 2.0) - contracts (~> 0.13, < 0.17) + bundler (> 2.0) + coffee-script (~> 2.2) + contracts dotenv - erubis + erubi execjs (~> 2.0) fast_blank fastimage (~> 2.0) + haml (>= 4.0.5, < 7) hamster (~> 3.0) - hashie (~> 3.4) - i18n (~> 1.6.0) + hashie (>= 3.4, < 6.0) + i18n (>= 1.6, < 1.15) + kramdown (~> 2.4) listen (~> 3.0) memoist (~> 0.14) - padrino-helpers (~> 0.15.0) + padrino-helpers (>= 0.15, < 0.17) parallel - rack (>= 1.4.5, < 3) + rack (>= 3) + rackup sassc (~> 2.0) servolux - tilt (~> 2.0.9) + tilt (~> 2.2) toml - uglifier (~> 3.0) + uglifier (>= 3, < 5) webrick middleman-data_source (0.8.1) borrower (~> 0.9) @@ -84,34 +102,47 @@ GEM middleman-sprockets (4.1.1) middleman-core (~> 4.0) sprockets (>= 3.0) - middleman-syntax (3.4.0) + middleman-syntax (3.6.1) middleman-core (>= 3.2) rouge (~> 3.2) mini_portile2 (2.8.9) - minitest (5.21.2) + minitest (6.0.2) + drb (~> 2.0) + prism (~> 1.5) mutex_m (0.3.0) - nokogiri (1.18.10) + nokogiri (1.19.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.18.10-x86_64-linux-gnu) + nokogiri (1.19.1-x86_64-linux-gnu) racc (~> 1.4) - padrino-helpers (0.15.3) + ostruct (0.6.3) + padrino-helpers (0.16.0) i18n (>= 0.6.7, < 2) - padrino-support (= 0.15.3) - tilt (>= 1.4.1, < 3) - padrino-support (0.15.3) - parallel (1.24.0) + padrino-support (= 0.16.0) + tilt (>= 2.1, < 3) + padrino-support (0.16.0) + parallel (1.27.0) parslet (2.0.0) - public_suffix (5.0.4) + prism (1.9.0) + psych (5.3.1) + date + stringio + public_suffix (7.0.2) racc (1.8.1) - rack (2.2.8) + rack (3.2.5) rack-test (0.6.3) rack (>= 1.0) + rackup (2.3.1) + rack (>= 3) rb-fsevent (0.11.2) - rb-inotify (0.10.1) + rb-inotify (0.11.1) ffi (~> 1.0) + rdoc (7.2.0) + erb + psych (>= 4.0.0) + tsort redcarpet (3.6.1) - rexml (3.2.6) + rexml (3.4.4) rouge (3.30.0) sass (3.7.4) sass-listen (~> 4.0.0) @@ -120,19 +151,24 @@ GEM rb-inotify (~> 0.9, >= 0.9.7) sassc (2.4.0) ffi (~> 1.9) + securerandom (0.4.1) servolux (0.13.0) - sprockets (3.7.2) + sprockets (4.2.2) concurrent-ruby (~> 1.0) - rack (> 1, < 3) - temple (0.10.3) - thor (1.2.2) - tilt (2.0.11) + logger + rack (>= 2.2.4, < 4) + stringio (3.2.0) + temple (0.10.4) + thor (1.5.0) + tilt (2.7.0) toml (0.3.0) parslet (>= 1.8.0, < 3.0.0) + tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - uglifier (3.2.0) + uglifier (4.2.1) execjs (>= 0.3.0, < 3) + uri (1.1.1) webrick (1.9.2) PLATFORMS @@ -141,21 +177,26 @@ PLATFORMS DEPENDENCIES base64 + benchmark bigdecimal - middleman (~> 4.4) + csv + logger + middleman (~> 4.6.3) middleman-autoprefixer (~> 3.0) middleman-data_source middleman-sprockets (~> 4.1) middleman-syntax (~> 3.2) mutex_m - nokogiri (~> 1.18.1) + nokogiri (~> 1.19) + ostruct + rdoc redcarpet (~> 3.6.0) rouge (~> 3.21) sass webrick RUBY VERSION - ruby 3.1.2p20 + ruby 4.0.1p0 BUNDLED WITH 2.6.8 diff --git a/config.rb b/config.rb index 3074398dd49..a50b869bfd7 100644 --- a/config.rb +++ b/config.rb @@ -3,6 +3,7 @@ # from: https://github.com/slatedocs/slate/issues/738#issuecomment-406353752 require './lib/nesting_unique_head.rb' require './lib/bulk_data_schema.rb' +require './config/borrower_patch.rb' # Markdown set :markdown_engine, :redcarpet diff --git a/config/borrower_patch.rb b/config/borrower_patch.rb new file mode 100644 index 00000000000..276bb8d887c --- /dev/null +++ b/config/borrower_patch.rb @@ -0,0 +1,9 @@ +# This is a monkey patch to fix the File.exists? method that was removed in newer Ruby versions +# The borrower gem (v0.10.0) uses this deprecated method, but in Ruby 3.4+ it's been removed +# This patch adds back the method by redirecting to the new File.exist? method + +class File + def self.exists?(path) + exist?(path) + end +end diff --git a/source/data/tables.sql b/source/data/tables.sql index 89c59ddcf10..7e60a929dbe 100644 --- a/source/data/tables.sql +++ b/source/data/tables.sql @@ -51,7 +51,7 @@ CREATE TABLE event_imports ("id" integer, "event_import_batch_id" integer, "impo DROP TABLE IF EXISTS event_types; CREATE TABLE event_types ("id" bigint, "organisation_id" bigint, "name" CHARACTER VARYING(max), "localized_names" CHARACTER VARYING(max), "created_at" timestamp without time zone, "updated_at" timestamp without time zone, "external_ids" CHARACTER VARYING(max), "crm_settings" CHARACTER VARYING(max)); DROP TABLE IF EXISTS events; -CREATE TABLE events ("id" integer, "title" CHARACTER VARYING(max), "slug" CHARACTER VARYING(max), "start_at" timestamp without time zone, "end_at" timestamp without time zone, "location_id" integer, "created_at" timestamp without time zone, "updated_at" timestamp without time zone, "user_id" integer, "organisation_id" integer, "calendar_id" integer, "admin_status" CHARACTER VARYING(max), "admin_reason" CHARACTER VARYING(max), "administered_at" timestamp without time zone, "max_attendees_count" integer, "locale" CHARACTER VARYING(max), "target_id" integer, "thank_attendee_email_content" CHARACTER VARYING(max), "approaching_event_attendee_email_content" CHARACTER VARYING(max), "notify_changes_to_attendees" boolean, "sharing_disabled" boolean, "host_address" CHARACTER VARYING(max), "cancel_reason" CHARACTER VARYING(max), "cancelled_at" timestamp without time zone, "local_chapter_id" integer, "launched_at" timestamp without time zone, "hidden_address" boolean, "promoted_from_waitlist_email_content" CHARACTER VARYING(max), "petition_id" integer, "extra_location_info" CHARACTER VARYING(max), "external_action_id" CHARACTER VARYING(max), "request_referer" CHARACTER VARYING(max), "time_zone" CHARACTER VARYING(max), "hidden_at" timestamp without time zone, "daisy_chain_id" bigint, "new_member_daisy_chain_id" bigint, "forum_enabled" boolean, "reviewer_id" integer, "event_type_id" integer, "region_id" bigint, "settings" CHARACTER VARYING(max), "campaigner_contactable" boolean, "crm_settings" CHARACTER VARYING(max), "created_by_id" bigint, "reviewer_type" CHARACTER VARYING(max), "mentor_id" bigint, "redirect_to" CHARACTER VARYING(max), "web_conference_url" CHARACTER VARYING(max), "virtual" boolean, "content_updated_at" timestamp without time zone, "external_ids" CHARACTER VARYING(max), "featured" boolean, "theme_id" bigint, "utm_params" CHARACTER VARYING(max), "location_venue" CHARACTER VARYING(max), "unconfirmed_location" boolean, "staff_led_organiser_type" CHARACTER VARYING(max), "staff_led_organiser_id" bigint, "unlisted_at" timestamp(6) without time zone, "user_ip" CHARACTER VARYING(max), "user_agent" CHARACTER VARYING(max)); +CREATE TABLE events ("id" integer, "title" CHARACTER VARYING(max), "slug" CHARACTER VARYING(max), "start_at" timestamp without time zone, "end_at" timestamp without time zone, "location_id" integer, "created_at" timestamp without time zone, "updated_at" timestamp without time zone, "user_id" integer, "organisation_id" integer, "calendar_id" integer, "admin_status" CHARACTER VARYING(max), "admin_reason" CHARACTER VARYING(max), "administered_at" timestamp without time zone, "max_attendees_count" integer, "locale" CHARACTER VARYING(max), "target_id" integer, "thank_attendee_email_content" CHARACTER VARYING(max), "approaching_event_attendee_email_content" CHARACTER VARYING(max), "notify_changes_to_attendees" boolean, "sharing_disabled" boolean, "host_address" CHARACTER VARYING(max), "cancel_reason" CHARACTER VARYING(max), "cancelled_at" timestamp without time zone, "local_chapter_id" integer, "launched_at" timestamp without time zone, "hidden_address" boolean, "promoted_from_waitlist_email_content" CHARACTER VARYING(max), "petition_id" integer, "extra_location_info" CHARACTER VARYING(max), "external_action_id" CHARACTER VARYING(max), "request_referer" CHARACTER VARYING(max), "time_zone" CHARACTER VARYING(max), "hidden_at" timestamp without time zone, "daisy_chain_id" bigint, "new_member_daisy_chain_id" bigint, "forum_enabled" boolean, "reviewer_id" integer, "event_type_id" integer, "region_id" bigint, "settings" CHARACTER VARYING(max), "campaigner_contactable" boolean, "crm_settings" CHARACTER VARYING(max), "created_by_id" bigint, "reviewer_type" CHARACTER VARYING(max), "mentor_id" bigint, "redirect_to" CHARACTER VARYING(max), "web_conference_url" CHARACTER VARYING(max), "virtual" boolean, "content_updated_at" timestamp without time zone, "external_ids" CHARACTER VARYING(max), "featured" boolean, "theme_id" bigint, "utm_params" CHARACTER VARYING(max), "location_venue" CHARACTER VARYING(max), "unconfirmed_location" boolean, "staff_led_organiser_type" CHARACTER VARYING(max), "staff_led_organiser_id" bigint, "unlisted_at" timestamp(6) without time zone, "send_prompt_to_repeat" boolean, "prompt_to_repeat_sent_at" timestamp(6) without time zone, "predecessor_event_id" bigint, "user_ip" CHARACTER VARYING(max), "user_agent" CHARACTER VARYING(max)); DROP TABLE IF EXISTS export_download_logs; CREATE TABLE export_download_logs ("id" bigint, "user_id" bigint, "data_export_id" bigint, "created_at" timestamp without time zone); DROP TABLE IF EXISTS external_events; diff --git a/source/includes/authenticated_api/_events.md.erb b/source/includes/authenticated_api/_events.md.erb index cb0b36fe403..1c2e1e0ce11 100644 --- a/source/includes/authenticated_api/_events.md.erb +++ b/source/includes/authenticated_api/_events.md.erb @@ -160,7 +160,8 @@ The response includes all the same data as the single-event endpoint for each ev "twitter_share_message": "Attending this event to deliver our petition", "twitter_share_title": "Deliver the Petition to the Wizard", "web_share_api_share_message": "Check out this event in the Emerald City", - "whatsapp_share_message": "I'm attending this event to deliver the petition. Join me!" + "whatsapp_share_message": "I'm attending this event to deliver the petition. Join me!", + "share_by_email_body": "I'm attending this event and thought you might be interested. Will you join me?" } } ``` @@ -290,7 +291,8 @@ the event `slug` is `chapter-meeting-1`. "twitter_share_message": null, "twitter_share_title": null, "web_share_api_share_message": null, - "whatsapp_share_message": null + "whatsapp_share_message": null, + "share_by_email_body": null } } ``` @@ -346,6 +348,7 @@ max_attendees_count | Integer | Limit on how many people, besides the host, may meta_description | String | Custom meta description for the event page (used for SEO and social media previews) meta_title | String | Custom meta title for the event page (used for SEO and social media previews) redirect_to | String | If set, visitors to the event page will be redirected to this URL +share_by_email_body | String | Custom message pre-filled in the email body when supporters click the "Share by Email" button. Supports Liquid templating. Set to `null` to use the organisation's default. sharing_disabled | Boolean | Turns off the social sharing prompts for the event title | String | Event title twitter_share_description | String | Custom description used when sharing the event on Twitter/X diff --git a/source/includes/authenticated_api/_petitions.md.erb b/source/includes/authenticated_api/_petitions.md.erb index b2c6bba9df1..84ca622ab2b 100644 --- a/source/includes/authenticated_api/_petitions.md.erb +++ b/source/includes/authenticated_api/_petitions.md.erb @@ -164,7 +164,8 @@ Petition are pieces of content that can be signed by members. "twitter_share_message": "Sign this petition to end tea taxes", "twitter_share_title": "No Taxes on Tea", "web_share_api_share_message": "Check out this petition about tea taxes", - "whatsapp_share_message": "I just signed a petition about tea taxes. Join me!" + "whatsapp_share_message": "I just signed a petition about tea taxes. Join me!", + "share_by_email_body": "I just signed this petition and thought you might be interested. Will you join me?" } } ``` @@ -345,7 +346,8 @@ Get a paginated list of all petitions, including ones that are unlaunched or oth "twitter_share_message": null, "twitter_share_title": null, "web_share_api_share_message": null, - "whatsapp_share_message": null + "whatsapp_share_message": null, + "share_by_email_body": null } } ``` @@ -439,6 +441,7 @@ meta_title | String | Custom meta title for the petition page (used for SEO and partnerships | Array | List of partnerships this petition should be associated with, formatted like `[{"slug": "foo"}, {"slug": "bar"}]`. If the petition was associated with any partnerships that are not included in the list, it will be removed from those partnerships. petition_creator_name_override | String | Name to display for the petition creator on the petition page. Set to `null` to use the name from the petition creator's user account. redirect_to | String | If set, visitors to the petition page will be redirected to this URL +share_by_email_body | String | Custom message pre-filled in the email body when supporters click the "Share by Email" button. Supports Liquid templating. Set to `null` to use the organisation's default. show_progress_bar | Boolean | Whether to show the signature progress bar on the petition page signature_count_add_amount | Integer | If set, the displayed signature total on the petition page will be this much higher than the actual number of signatures recorded by the platform. This is usually used to reflect signatures that were gathered elsewhere and cannot be added to the platform, or signers whose data has been anonymized. A negative number can be specified to subtract from the total. title | String | Petition title