diff --git a/.env.example b/.env.example index e8f8e79a..4249163f 100644 --- a/.env.example +++ b/.env.example @@ -4,4 +4,5 @@ CONVERTKIT_FORM_ID= CONVERTKIT_TAG_ID= ADMIN_USERNAME= ADMIN_PASSWORD= -SYNTH_API_KEY= \ No newline at end of file +SYNTH_API_KEY= +BANNERBEAR_API_KEY= \ No newline at end of file diff --git a/Gemfile b/Gemfile index 5f9c99f9..c3e43f03 100644 --- a/Gemfile +++ b/Gemfile @@ -28,6 +28,7 @@ gem "tzinfo-data", platforms: %i[ windows jruby ] gem "redcarpet" gem "avo", ">= 3.2" gem "revise_auth" +gem "bannerbear" group :development, :test do diff --git a/Gemfile.lock b/Gemfile.lock index dce43493..970c43a1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -127,6 +127,8 @@ GEM turbo_power (>= 0.6.0) view_component (>= 3.7.0) zeitwerk (>= 2.6.12) + bannerbear (0.1.4) + httparty base64 (0.2.0) bcrypt (3.1.20) better_html (2.1.1) @@ -413,6 +415,7 @@ PLATFORMS DEPENDENCIES avo (>= 3.2) + bannerbear bootsnap brakeman capybara diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index b451bf4c..c7f4bd9d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -7,6 +7,10 @@ def description(page_description) content_for(:description) { page_description } end + def meta_image(meta_image) + content_for(:meta_image) { meta_image } + end + def markdown(text) options = { filter_html: true, diff --git a/app/models/article.rb b/app/models/article.rb index 9e8046a2..fb0a0128 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -1,4 +1,6 @@ class Article < ApplicationRecord + include MetaImage + def self.random_sample(count, exclude:) where.not(id: exclude.id).order(Arel.sql("RANDOM()")).limit(count) end @@ -6,4 +8,10 @@ def self.random_sample(count, exclude:) def to_param slug end + + private + + def create_meta_image + super(title) + end end diff --git a/app/models/concerns/meta_image.rb b/app/models/concerns/meta_image.rb new file mode 100644 index 00000000..fa599cdb --- /dev/null +++ b/app/models/concerns/meta_image.rb @@ -0,0 +1,28 @@ +module MetaImage + extend ActiveSupport::Concern + + included do + after_commit :create_meta_image, on: [ :create, :update ] + end + + private + + def create_meta_image(custom_text) + bb = Bannerbear::Client.new + begin + response = bb.create_image("RnxGpW5lvKw0bEXrJ1", + synchronous: true, + modifications: [ + { + name: "text", + text: custom_text + } + ] + ) + + self.update_columns(meta_image_url: response["image_url"]) + rescue => e + Rails.logger.error "Failed to create image: #{e.message}" + end + end +end diff --git a/app/models/term.rb b/app/models/term.rb index 96ef5d18..a22cceda 100644 --- a/app/models/term.rb +++ b/app/models/term.rb @@ -1,4 +1,6 @@ class Term < ApplicationRecord + include MetaImage + def self.random_sample(count, exclude:) where.not(id: exclude.id).order(Arel.sql("RANDOM()")).limit(count) end @@ -6,4 +8,10 @@ def self.random_sample(count, exclude:) def to_param slug end + + private + + def create_meta_image + super(title) + end end diff --git a/app/models/tool.rb b/app/models/tool.rb index 89ad8fc9..1403ad67 100644 --- a/app/models/tool.rb +++ b/app/models/tool.rb @@ -1,4 +1,6 @@ class Tool < ApplicationRecord + include MetaImage + CATEGORIES = { retirement: { name: "Retirement", @@ -39,4 +41,10 @@ def to_param def category CATEGORIES[category_slug&.to_sym] end + + private + + def create_meta_image + super(name) + end end diff --git a/app/views/articles/show.html.erb b/app/views/articles/show.html.erb index d03646c6..9432b014 100644 --- a/app/views/articles/show.html.erb +++ b/app/views/articles/show.html.erb @@ -1,6 +1,7 @@ <% title @article.title description "#{markdown(@article.content).gsub(%r{]+?>}, '')[0...300]}..." + meta_image @article.meta_image_url if @article.meta_image_url.present? %> <%= link_to articles_path, class: "w-9 h-9 rounded-full grid place-items-center mx-auto text-gray-500 hover:bg-gray-200/50 bg-transparent border border-gray-300 hover:border-gray-300 " do %> diff --git a/app/views/terms/show.html.erb b/app/views/terms/show.html.erb index 43b6200e..49239220 100644 --- a/app/views/terms/show.html.erb +++ b/app/views/terms/show.html.erb @@ -1,6 +1,7 @@ <% title "#{@term.title} - Financial Terms" description "#{markdown(@term.content).gsub(%r{]+?>}, '')[0...300]}..." + meta_image @term.meta_image_url if @term.meta_image_url.present? %> <%= link_to terms_path, class: "w-9 h-9 rounded-full grid place-items-center mx-auto text-gray-500 hover:bg-gray-200/50 bg-transparent border border-gray-300 hover:border-gray-300 " do %> diff --git a/app/views/tools/_compound_interest_calculator.html.erb b/app/views/tools/_compound_interest_calculator.html.erb index d39c7d9a..c1f1eb3a 100644 --- a/app/views/tools/_compound_interest_calculator.html.erb +++ b/app/views/tools/_compound_interest_calculator.html.erb @@ -1,8 +1,3 @@ -<% - title "Compound Interest Calculator" - description "See how your investments grow over time by earning interest on interest and letting your money work for you." -%> -
<%= form_with html: { class: "bg-gray-25 p-4 rounded-lg flex flex-col gap-4 col-span-1", data: { action: "submit->compound-interest-calculator#calculate" }} do |form| %>
diff --git a/app/views/tools/_financial_freedom_calculator.html.erb b/app/views/tools/_financial_freedom_calculator.html.erb index 84f1d5ea..1fa5cbd5 100644 --- a/app/views/tools/_financial_freedom_calculator.html.erb +++ b/app/views/tools/_financial_freedom_calculator.html.erb @@ -1,8 +1,3 @@ -<% - title "Financial Freedom Calculator" - description "Want to know how many years of financial freedom you have ahead of you based on your savings and expenses? Take a look at Maybe's Financial Freedom Calculator and see how long your savings will last!" -%> -
<%= form_with html: { class: "bg-gray-25 p-4 rounded-lg flex flex-col gap-4 col-span-1", data: { action: "submit->financial-freedom-calculator#calculate" }} do |form| %>
diff --git a/app/views/tools/_inflation_calculator.html.erb b/app/views/tools/_inflation_calculator.html.erb index d29fd595..b006866e 100644 --- a/app/views/tools/_inflation_calculator.html.erb +++ b/app/views/tools/_inflation_calculator.html.erb @@ -1,82 +1,77 @@ -<% - title "Inflation Calculator" - description "Calculate how inflation is impacting an asset’s future price and your future buying power." -%> - -
- <%= form_with html: { class: "bg-gray-25 p-4 rounded-lg flex flex-col gap-4 col-span-1" , data: { action: "submit->inflation-calculator#calculate" }} do |form| %> -
- <%= form.unit_field :initial_amount, label: "Initial Amount" , value: 0, unit_symbol: "$" %> -
+
+ <%= form_with html: { class: "bg-gray-25 p-4 rounded-lg flex flex-col gap-4 col-span-1" , data: { action: "submit->inflation-calculator#calculate" }} do |form| %> +
+ <%= form.unit_field :initial_amount, label: "Initial Amount" , value: 0, unit_symbol: "$" %> +
-
- <%= form.unit_field :inflation_percentage, label: "Inflation in %" , label_right: "%", value: 3 %> -
+
+ <%= form.unit_field :inflation_percentage, label: "Inflation in %" , label_right: "%", value: 3 %> +
-
- <%= form.unit_field :years, label: "Years" , label_right: "years", value: 0 %> -
+
+ <%= form.unit_field :years, label: "Years" , label_right: "years", value: 0 %> +
-
- <%= form.submit "Calculate" %> -
- <% end %> -
-
-
-
- <%= lucide_icon "keyboard" , class: "h-6 w-6 mx-auto" %> -

Fill in the fields to calculate your investment's ROI.

-
+
+ <%= form.submit "Calculate" %> +
+ <% end %> +
+
+
+
+ <%= lucide_icon "keyboard" , class: "h-6 w-6 mx-auto" %> +

Fill in the fields to calculate your investment's ROI.

+
- +
+
\ No newline at end of file diff --git a/app/views/tools/_loan_calculator.html.erb b/app/views/tools/_loan_calculator.html.erb index 883d2eca..90f55cad 100644 --- a/app/views/tools/_loan_calculator.html.erb +++ b/app/views/tools/_loan_calculator.html.erb @@ -1,73 +1,70 @@ -<% title "Loan Calculator" - description "The Loan Calculator allows you to easily plan your loans and understand your repayment schedule." %> +
-
- - <%= form_with html: { class: "bg-gray-25 p-4 rounded-lg flex flex-col gap-4 col-span-1" , data: { action: "submit->loan-calculator#calculate" }} do |form| %> -
- <%= form.unit_field :loan_amount, label: "Loan amount", value: 0, unit_symbol: "$", data: { controller: "autonumeric" } %> -
+ <%= form_with html: { class: "bg-gray-25 p-4 rounded-lg flex flex-col gap-4 col-span-1" , data: { action: "submit->loan-calculator#calculate" }} do |form| %> +
+ <%= form.unit_field :loan_amount, label: "Loan amount", value: 0, unit_symbol: "$", data: { controller: "autonumeric" } %> +
-
- <%= form.unit_field :loan_term, label: "Loan term" , value: 0, outer_div_class: "border-0 shadow-none focus-within:border-transparent focus-within:ring-0 focus-within:ring-transparent" %> - <%= render partial: "shared/period_select_loan" , locals: { value: "years" } %> -
+
+ <%= form.unit_field :loan_term, label: "Loan term" , value: 0, outer_div_class: "border-0 shadow-none focus-within:border-transparent focus-within:ring-0 focus-within:ring-transparent" %> + <%= render partial: "shared/period_select_loan" , locals: { value: "years" } %> +
-
- <%= form.unit_field :interest_rate, label: "Interest rate", value: 0, unit_symbol: "%", step: "any" %> -
+
+ <%= form.unit_field :interest_rate, label: "Interest rate", value: 0, unit_symbol: "%", step: "any" %> +
-
- <%= form.date_field :date, as: :date,label: "Start date" , value: form.object.try(:strftime,"%m/%d/%Y"), required: true, max: Date.today %> -
+
+ <%= form.date_field :date, as: :date,label: "Start date" , value: form.object.try(:strftime,"%m/%d/%Y"), required: true, max: Date.today %> +
-
- <%= form.submit "Calculate" %> -
- <% end %> +
+ <%= form.submit "Calculate" %> +
+ <% end %> -
-
-
-
- <%= lucide_icon "keyboard" , class: "h-6 w-6 mx-auto" %> -

Fill in the fields to calculate inflation.

-
+
+
+
+
+ <%= lucide_icon "keyboard" , class: "h-6 w-6 mx-auto" %> +

Fill in the fields to calculate inflation.

+
-
+
diff --git a/app/views/tools/_roi_calculator.html.erb b/app/views/tools/_roi_calculator.html.erb index 952fd886..e3cbde88 100644 --- a/app/views/tools/_roi_calculator.html.erb +++ b/app/views/tools/_roi_calculator.html.erb @@ -1,8 +1,3 @@ -<% - title "ROI Calculator" - description "See how to calculate the return on your investments and evaluate the gain or loss." -%> -
<%= form_with html: { class: "bg-gray-25 p-4 rounded-lg flex flex-col gap-4 col-span-1", data: { action: "submit->roi-calculator#calculate" }} do |form| %>
diff --git a/app/views/tools/show.html.erb b/app/views/tools/show.html.erb index 80c0cf15..2424e4aa 100644 --- a/app/views/tools/show.html.erb +++ b/app/views/tools/show.html.erb @@ -1,10 +1,15 @@ +<% + title @tool.name + description @tool.intro + meta_image @tool.meta_image_url if @tool.meta_image_url.present? +%>
-

+

<%= link_to "Tools", tools_path %> / <%= @tool.name %>

<%= @tool.name %>

-
+
<%= markdown @tool.intro %>
diff --git a/db/migrate/20240610173601_add_meta_images.rb b/db/migrate/20240610173601_add_meta_images.rb new file mode 100644 index 00000000..dcc6b529 --- /dev/null +++ b/db/migrate/20240610173601_add_meta_images.rb @@ -0,0 +1,8 @@ +class AddMetaImages < ActiveRecord::Migration[8.0] + def change + add_column :articles, :meta_image_url, :string + add_column :stocks, :meta_image_url, :string + add_column :terms, :meta_image_url, :string + add_column :tools, :meta_image_url, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index ed5254a7..19b04bf5 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_06_06_084019) do +ActiveRecord::Schema[8.0].define(version: 2024_06_10_173601) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -22,6 +22,7 @@ t.string "author_name" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "meta_image_url" end create_table "stocks", force: :cascade do |t| @@ -32,6 +33,7 @@ t.text "description" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "meta_image_url" end create_table "terms", force: :cascade do |t| @@ -47,6 +49,7 @@ t.string "video_thumbnail_url" t.date "video_upload_date" t.string "video_duration" + t.string "meta_image_url" end create_table "tools", force: :cascade do |t| @@ -59,6 +62,7 @@ t.datetime "updated_at", null: false t.string "category_slug" t.string "icon" + t.string "meta_image_url" end create_table "users", force: :cascade do |t| diff --git a/lib/tasks/maintenance.rake b/lib/tasks/maintenance.rake new file mode 100644 index 00000000..4cac0d1f --- /dev/null +++ b/lib/tasks/maintenance.rake @@ -0,0 +1,14 @@ +namespace :maintenance do + desc "Create meta images for all content" + task create_meta_images: :environment do + Article.all.each do |article| + article.touch + end + Term.all.each do |term| + term.touch + end + Tool.all.each do |tool| + tool.touch + end + end +end