diff --git a/.env.local.example b/.env.local.example index 969d2865..990cc833 100644 --- a/.env.local.example +++ b/.env.local.example @@ -7,8 +7,8 @@ MAPBOX_KEY=placeholder WEB_CONCURRENCY=0 # run in solo mode instead of clustering for development AWS_SECRET_ACCESS_KEY=placeholder AWS_ACCESS_KEY_ID=placeholder -AWS_PICTURE_PATH=https://s3.amazonaws.com//location_picture_xref/photo/:id/medium/:filename AWS_REGION= +AWS_BUCKET_NAME= GOOGLE_MAPS_API_KEY= HERE_MAPS_API_KEY= MAPBOX_DEV_API_KEY= diff --git a/Gemfile b/Gemfile index 9df1cbb5..cbbe8322 100644 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,7 @@ gem "exception_notification" gem "geocoder" gem "haml-rails" gem "has_scope" +gem "image_processing" gem "inherited_resources" gem "kaminari" gem "kt-paperclip" diff --git a/Gemfile.lock b/Gemfile.lock index b118f16d..27741204 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -216,6 +216,9 @@ GEM htmlentities (4.3.4) i18n (1.14.6) concurrent-ruby (~> 1.0) + image_processing (1.13.0) + mini_magick (>= 4.9.5, < 5) + ruby-vips (>= 2.0.17, < 3) inherited_resources (2.0.1) actionpack (>= 6.0) has_scope (>= 0.6) @@ -269,6 +272,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2024.0305) mini_histogram (0.3.1) + mini_magick (4.13.2) mini_mime (1.1.5) mini_portile2 (2.8.8) minitest (5.25.4) @@ -439,6 +443,9 @@ GEM rubocop (~> 1.61) ruby-progressbar (1.13.0) ruby-statistics (3.0.1) + ruby-vips (2.2.2) + ffi (~> 1.12) + logger rubyzip (2.3.2) sanitize (6.1.3) crass (~> 1.0.2) @@ -553,6 +560,7 @@ DEPENDENCIES geocoder haml-rails has_scope + image_processing inherited_resources kaminari kt-paperclip diff --git a/app/assets/stylesheets/actiontext.css b/app/assets/stylesheets/actiontext.css new file mode 100644 index 00000000..3cfcb2b7 --- /dev/null +++ b/app/assets/stylesheets/actiontext.css @@ -0,0 +1,31 @@ +/* + * Provides a drop-in pointer for the default Trix stylesheet that will format the toolbar and + * the trix-editor content (whether displayed or under editing). Feel free to incorporate this + * inclusion directly in any other asset bundle and remove this file. + * + *= require trix +*/ + +/* + * We need to override trix.css’s image gallery styles to accommodate the + * element we wrap around attachments. Otherwise, + * images in galleries will be squished by the max-width: 33%; rule. +*/ +.trix-content .attachment-gallery > action-text-attachment, +.trix-content .attachment-gallery > .attachment { + flex: 1 0 33%; + padding: 0 0.5em; + max-width: 33%; +} + +.trix-content .attachment-gallery.attachment-gallery--2 > action-text-attachment, +.trix-content .attachment-gallery.attachment-gallery--2 > .attachment, .trix-content .attachment-gallery.attachment-gallery--4 > action-text-attachment, +.trix-content .attachment-gallery.attachment-gallery--4 > .attachment { + flex-basis: 50%; + max-width: 50%; +} + +.trix-content action-text-attachment .attachment { + padding: 0 !important; + max-width: 100% !important; +} diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index d2d93f82..542ccc43 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -1,7 +1,6 @@ class PagesController < ApplicationController respond_to :xml, :json, :html, :js, :rss - def contact_sent user = current_user.nil? ? nil : current_user return if params["contact_msg"].blank? || (!user && params["contact_email"].blank?) || params["contact_msg"].match?(/vape/) || params["contact_msg"].match?(/seo/) || params["contact_msg"].match?(/Ezoic/) diff --git a/app/mailboxes/application_mailbox.rb b/app/mailboxes/application_mailbox.rb new file mode 100644 index 00000000..ac22d03c --- /dev/null +++ b/app/mailboxes/application_mailbox.rb @@ -0,0 +1,3 @@ +class ApplicationMailbox < ActionMailbox::Base + # routing /something/i => :somewhere +end diff --git a/app/models/location_picture_xref.rb b/app/models/location_picture_xref.rb index e0882a48..b56e93a1 100644 --- a/app/models/location_picture_xref.rb +++ b/app/models/location_picture_xref.rb @@ -2,21 +2,7 @@ class LocationPictureXref < ApplicationRecord belongs_to :location, optional: true belongs_to :user, optional: true - has_attached_file :photo, - storage: :s3, - bucket: "pbm-images", - path: "location_picture_xref/photo/:id/:style/:filename", - url: ENV.fetch("AWS_PICTURE_PATH", "https://s3.amazonaws.com/pbm-images/location_picture_xref/photo/:id/medium/:filename"), - styles: { - thumb: "36x25>", - medium: "300x300>", - large: "800x800>" - }, - s3_credentials: { - access_key_id: ENV["AWS_ACCESS_KEY_ID"], - secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"] - }, - s3_region: ENV["AWS_REGION"] + has_one_attached :photo do_not_validate_attachment_file_type :photo @@ -24,7 +10,7 @@ def rails_admin_default_object_label_method; end def create_user_submission user_info = user ? user.username : "UNKNOWN USER" - submission = "#{user_info} added a picture of #{location.name} in #{location.city}#{photo.nil? ? '' : ': https:' + photo.url(:large)}" + submission = "#{user_info} added a picture of #{location.name} in #{location.city}" UserSubmission.create(user_name: user.username, location_name: location.name, city_name: location.city, lat: location.lat, lon: location.lon, region_id: location.region_id, location: location, submission_type: UserSubmission::NEW_PICTURE_TYPE, submission: submission, user: user) Rails.logger.info "USER SUBMISSION USER ID #{user&.id} #{submission}" diff --git a/app/views/active_storage/blobs/_blob.html.erb b/app/views/active_storage/blobs/_blob.html.erb new file mode 100644 index 00000000..49ba357d --- /dev/null +++ b/app/views/active_storage/blobs/_blob.html.erb @@ -0,0 +1,14 @@ +
attachment--<%= blob.filename.extension %>"> + <% if blob.representable? %> + <%= image_tag blob.representation(resize_to_limit: local_assigns[:in_gallery] ? [ 800, 600 ] : [ 1024, 768 ]) %> + <% end %> + +
+ <% if caption = blob.try(:caption) %> + <%= caption %> + <% else %> + <%= blob.filename %> + <%= number_to_human_size blob.byte_size %> + <% end %> +
+
diff --git a/app/views/layouts/action_text/contents/_content.html.erb b/app/views/layouts/action_text/contents/_content.html.erb new file mode 100644 index 00000000..9e3c0d0d --- /dev/null +++ b/app/views/layouts/action_text/contents/_content.html.erb @@ -0,0 +1,3 @@ +
+ <%= yield -%> +
diff --git a/app/views/location_picture_xrefs/_form.html.haml b/app/views/location_picture_xrefs/_form.html.haml index 8e61e24b..be57955d 100644 --- a/app/views/location_picture_xrefs/_form.html.haml +++ b/app/views/location_picture_xrefs/_form.html.haml @@ -2,7 +2,7 @@ %span.red.font14.p_10.block Choose a picture that gives a feel for the place. No need to include a picture of every single machine. = form_for LocationPictureXref.new, :id => "new_location_picture_xref_#{l.id}", :html => {:id => "new_location_picture_xref_#{l.id}", :multipart => true}, :remote => true do |f| = f.hidden_field :location_id, { :value => l.id } - = f.file_field :photo, :id => 'file_chooser_button' + = f.file_field :photo, :id => 'file_chooser_button', :direct_upload => true %br/ = f.submit "Upload", :class => 'submit_picture' diff --git a/app/views/location_picture_xrefs/_show_thumbs.html.haml b/app/views/location_picture_xrefs/_show_thumbs.html.haml index 9277fd7e..1e78beb5 100644 --- a/app/views/location_picture_xrefs/_show_thumbs.html.haml +++ b/app/views/location_picture_xrefs/_show_thumbs.html.haml @@ -1,4 +1,4 @@ - location_picture_xrefs.each do |lpx| - - if lpx.photo? - = link_to image_tag(lpx.photo.url(:medium)), lpx.photo.url(:large), :class => "location_thumb location_picture_xref_#{lpx.id}", :"data-lightbox" => "location_thumb" + - if lpx.photo.attached? + = link_to image_tag(lpx.photo.variant(resize_to_limit: [100,100])), lpx.photo.variant(resize_to_limit: [800,800]), :class => "location_thumb location_picture_xref_#{lpx.id}", :"data-lightbox" => "location_thumb" = render :partial => 'location_picture_xrefs/remove_picture', :locals => {:lpx => lpx} diff --git a/config/environments/development.rb b/config/environments/development.rb index 11e718ca..c238a3a2 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -32,7 +32,8 @@ end # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = :local + config.active_storage.service = :amazon + config.active_storage.variant_processor = :vips # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false diff --git a/config/environments/production.rb b/config/environments/production.rb index 7d524daa..501200a4 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -37,7 +37,8 @@ # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = :local + config.active_storage.service = :amazon + config.active_storage.variant_processor = :vips # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 24a8f016..b315f66c 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -37,7 +37,8 @@ # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = :local + config.active_storage.service = :amazon + config.active_storage.variant_processor = :vips # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil diff --git a/config/storage.yml b/config/storage.yml index d32f76e8..43138203 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -6,13 +6,13 @@ local: service: Disk root: <%= Rails.root.join("storage") %> -# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) -# amazon: -# service: S3 -# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> -# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> -# region: us-east-1 -# bucket: your_own_bucket +#Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +amazon: + service: S3 + access_key_id: <%= ENV["AWS_ACCESS_KEY_ID"] %> + secret_access_key: <%= ENV["AWS_SECRET_ACCESS_KEY"] %> + region: us-west-1 + bucket: <%= ENV["AWS_BUCKET_NAME"] %> # Remember not to checkin your GCS keyfile to a repository # google: diff --git a/db/migrate/20250129200229_create_action_text_tables.action_text.rb b/db/migrate/20250129200229_create_action_text_tables.action_text.rb new file mode 100644 index 00000000..c1c0a9d8 --- /dev/null +++ b/db/migrate/20250129200229_create_action_text_tables.action_text.rb @@ -0,0 +1,26 @@ +# This migration comes from action_text (originally 20180528164100) +class CreateActionTextTables < ActiveRecord::Migration[6.0] + def change + # Use Active Record's configured type for primary and foreign keys + primary_key_type, foreign_key_type = primary_and_foreign_key_types + + create_table :action_text_rich_texts, id: primary_key_type do |t| + t.string :name, null: false + t.text :body, size: :long + t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type + + t.timestamps + + t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true + end + end + + private + def primary_and_foreign_key_types + config = Rails.configuration.generators + setting = config.options[config.orm][:primary_key_type] + primary_key_type = setting || :primary_key + foreign_key_type = setting || :bigint + [ primary_key_type, foreign_key_type ] + end +end diff --git a/db/migrate/20250129200703_create_action_mailbox_tables.action_mailbox.rb b/db/migrate/20250129200703_create_action_mailbox_tables.action_mailbox.rb new file mode 100644 index 00000000..7b2b8079 --- /dev/null +++ b/db/migrate/20250129200703_create_action_mailbox_tables.action_mailbox.rb @@ -0,0 +1,20 @@ +# This migration comes from action_mailbox (originally 20180917164000) +class CreateActionMailboxTables < ActiveRecord::Migration[6.0] + def change + create_table :action_mailbox_inbound_emails, id: primary_key_type do |t| + t.integer :status, default: 0, null: false + t.string :message_id, null: false + t.string :message_checksum, null: false + + t.timestamps + + t.index [ :message_id, :message_checksum ], name: "index_action_mailbox_inbound_emails_uniqueness", unique: true + end + end + + private + def primary_key_type + config = Rails.configuration.generators + config.options[config.orm][:primary_key_type] || :primary_key + end +end diff --git a/lib/tasks/migrate_paperclip.rake b/lib/tasks/migrate_paperclip.rake new file mode 100644 index 00000000..b118634d --- /dev/null +++ b/lib/tasks/migrate_paperclip.rake @@ -0,0 +1,19 @@ +namespace :location_picture_xrefs do + task migrate_to_active_storage: :environment do + LocationPictureXref.where.not(photo_file_name: nil).find_each do |lpx| + # This step helps us catch any attachments we might have uploaded that + # don't have an explicit file extension in the filename + image_original = lpx.photo_file_name + # ext = File.extname(image) + # image_original = CGI.unescape(image.gsub(ext, "_original#{ext}")) + + # this url pattern can be changed to reflect whatever service you use + lpx_url = "https://s3.amazonaws.com/pbm-images/location_picture_xref/photo/#{lpx.id}/original/#{image_original}" + lpx.photo.attach(io: OpenURI.open_uri(lpx_url), + filename: lpx.photo_file_name, + content_type: lpx.photo_content_type) + rescue OpenURI::HTTPError, URI::InvalidURIError => e + puts "bad image path #{lpx_url}" + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4fcf3a93..6803f890 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,7 @@ # rubocop:disable Style/MixinUsage # This file is copied to spec/ when you run 'rails generate rspec:install' ENV['RAILS_ENV'] = 'test' -ENV['AWS_REGION'] = 'us-east-1' +ENV['AWS_REGION'] = 'us-west-1' require File.expand_path('../../config/environment', __FILE__) require 'factory_bot_rails' require 'rspec/rails' diff --git a/test/fixtures/action_text/rich_texts.yml b/test/fixtures/action_text/rich_texts.yml new file mode 100644 index 00000000..8b371ea6 --- /dev/null +++ b/test/fixtures/action_text/rich_texts.yml @@ -0,0 +1,4 @@ +# one: +# record: name_of_fixture (ClassOfFixture) +# name: content +# body:

In a million stars!