From efeac696e41231a0643a1b27e8fbe7b13cdf73e5 Mon Sep 17 00:00:00 2001 From: Jason Zimdars Date: Wed, 28 Aug 2024 17:11:40 -0500 Subject: [PATCH] Wire up image attachments for bubbles --- app/assets/images/default-picture.webp | Bin 0 -> 53382 bytes app/controllers/splats_controller.rb | 2 +- .../controllers/upload_preview_controller.js | 20 ++++++ app/models/splat.rb | 2 + app/views/splats/_form.html.erb | 14 ++++- ...te_active_storage_tables.active_storage.rb | 57 ++++++++++++++++++ db/schema.rb | 32 +++++++++- 7 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 app/assets/images/default-picture.webp create mode 100644 app/javascript/controllers/upload_preview_controller.js create mode 100644 db/migrate/20240828215240_create_active_storage_tables.active_storage.rb diff --git a/app/assets/images/default-picture.webp b/app/assets/images/default-picture.webp new file mode 100644 index 0000000000000000000000000000000000000000..9696faeb3daa7054e4369424360a42539afc88d6 GIT binary patch literal 53382 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 literal 0 HcmV?d00001 diff --git a/app/controllers/splats_controller.rb b/app/controllers/splats_controller.rb index cfe056b28..471006d19 100644 --- a/app/controllers/splats_controller.rb +++ b/app/controllers/splats_controller.rb @@ -38,6 +38,6 @@ class SplatsController < ApplicationController end def splat_params - params.require(:splat).permit(:title, :body, :color, category_ids: []) + params.require(:splat).permit(:title, :body, :color, :image, category_ids: []) end end diff --git a/app/javascript/controllers/upload_preview_controller.js b/app/javascript/controllers/upload_preview_controller.js new file mode 100644 index 000000000..4ce38ae9a --- /dev/null +++ b/app/javascript/controllers/upload_preview_controller.js @@ -0,0 +1,20 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static values = { defaultImage: String } + static targets = [ "image", "input", "button" ] + + previewImage() { + const file = this.inputTarget.files[0] + + if (file) { + this.imageTarget.src = URL.createObjectURL(this.inputTarget.files[0]); + this.imageTarget.onload = () => { URL.revokeObjectURL(this.imageTarget.src) } + } + } + + clear() { + this.imageTarget.src = this.defaultImageValue + this.buttonTarget.style.visibility = "hidden" + } +} diff --git a/app/models/splat.rb b/app/models/splat.rb index 342f392d3..c721475f8 100644 --- a/app/models/splat.rb +++ b/app/models/splat.rb @@ -4,6 +4,8 @@ class Splat < ApplicationRecord has_many :categories, through: :categorizations, dependent: :destroy has_many :comments, dependent: :destroy + has_one_attached :image, dependent: :purge_later + belongs_to :creator, class_name: "User", default: -> { Current.user } enum :color, %w[ diff --git a/app/views/splats/_form.html.erb b/app/views/splats/_form.html.erb index a4bc3df66..4c695df63 100644 --- a/app/views/splats/_form.html.erb +++ b/app/views/splats/_form.html.erb @@ -26,12 +26,22 @@ <% end %> +
+ Attachment + +
+ <%= form.label :body, class: "flex flex-column justify-start align-start" do %> <%= form.text_area :body, class: "input full-width", rows: 10, placeholder: "Details…" %> <% end %> diff --git a/db/migrate/20240828215240_create_active_storage_tables.active_storage.rb b/db/migrate/20240828215240_create_active_storage_tables.active_storage.rb new file mode 100644 index 000000000..6bd8bd082 --- /dev/null +++ b/db/migrate/20240828215240_create_active_storage_tables.active_storage.rb @@ -0,0 +1,57 @@ +# This migration comes from active_storage (originally 20170806125915) +class CreateActiveStorageTables < ActiveRecord::Migration[7.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 :active_storage_blobs, id: primary_key_type do |t| + t.string :key, null: false + t.string :filename, null: false + t.string :content_type + t.text :metadata + t.string :service_name, null: false + t.bigint :byte_size, null: false + t.string :checksum + + if connection.supports_datetime_with_precision? + t.datetime :created_at, precision: 6, null: false + else + t.datetime :created_at, null: false + end + + t.index [ :key ], unique: true + end + + create_table :active_storage_attachments, id: primary_key_type do |t| + t.string :name, null: false + t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type + t.references :blob, null: false, type: foreign_key_type + + if connection.supports_datetime_with_precision? + t.datetime :created_at, precision: 6, null: false + else + t.datetime :created_at, null: false + end + + t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true + t.foreign_key :active_storage_blobs, column: :blob_id + end + + create_table :active_storage_variant_records, id: primary_key_type do |t| + t.belongs_to :blob, null: false, index: false, type: foreign_key_type + t.string :variation_digest, null: false + + t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true + t.foreign_key :active_storage_blobs, column: :blob_id + 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/schema.rb b/db/schema.rb index 2a337ad4b..72426805f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2024_08_26_201811) do +ActiveRecord::Schema[8.0].define(version: 2024_08_28_215240) do create_table "accounts", force: :cascade do |t| t.string "name", null: false t.datetime "created_at", null: false @@ -18,6 +18,34 @@ ActiveRecord::Schema[8.0].define(version: 2024_08_26_201811) do t.index ["name"], name: "index_accounts_on_name", unique: true end + create_table "active_storage_attachments", force: :cascade do |t| + t.string "name", null: false + t.string "record_type", null: false + t.bigint "record_id", null: false + t.bigint "blob_id", null: false + t.datetime "created_at", null: false + t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" + t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true + end + + create_table "active_storage_blobs", force: :cascade do |t| + t.string "key", null: false + t.string "filename", null: false + t.string "content_type" + t.text "metadata" + t.string "service_name", null: false + t.bigint "byte_size", null: false + t.string "checksum" + t.datetime "created_at", null: false + t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true + end + + create_table "active_storage_variant_records", force: :cascade do |t| + t.bigint "blob_id", null: false + t.string "variation_digest", null: false + t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true + end + create_table "boosts", force: :cascade do |t| t.string "body" t.integer "creator_id", null: false @@ -80,6 +108,8 @@ ActiveRecord::Schema[8.0].define(version: 2024_08_26_201811) do t.index ["email_address"], name: "index_users_on_email_address", unique: true end + add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" + add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" add_foreign_key "categorizations", "categories" add_foreign_key "categorizations", "splats" add_foreign_key "sessions", "users"