diff --git a/app/controllers/social_previews_controller.rb b/app/controllers/social_previews_controller.rb
index 15751d8bb..fc25d074e 100644
--- a/app/controllers/social_previews_controller.rb
+++ b/app/controllers/social_previews_controller.rb
@@ -9,7 +9,8 @@ class SocialPreviewsController < ApplicationController
not_found unless @article.published
template = @article.tags.
- where("tags.social_preview_template IS NOT NULL AND tags.social_preview_template != ?", "article").
+ where.not(social_preview_template: nil).
+ where.not(social_preview_template: "article").
select(:social_preview_template).first&.social_preview_template
# make sure that the template exists
@@ -25,8 +26,7 @@ class SocialPreviewsController < ApplicationController
end
def listing
- @listing = ClassifiedListing.find(params[:id])
- define_categories
+ @listing = ClassifiedListing.find(params[:id]).decorate
set_respond
end
@@ -51,25 +51,6 @@ class SocialPreviewsController < ApplicationController
private
- # TODO: [thepracticaldev/oss] don't hardcode this
- def define_categories
- cat_info = {
- "collabs": ["Collaborators Wanted", "#5AE8D9"],
- "cfp": ["Call For Proposal", "#f58f8d"],
- "forhire": ["Available For Hire", "#b78cf4"],
- "education": ["Education", "#5AABE8"],
- "jobs": ["Now Hiring", "#53c3ad"],
- "mentors": ["Offering Mentorship", "#A69EE8"],
- "mentees": ["Looking For Mentorship", "#88aedb"],
- "forsale": ["Stuff For Sale", "#d0adfb"],
- "events": ["Upcoming Event", "#f8b3d0"],
- "misc": ["Miscellaneous", "#6393FF"],
- "products": ["Products & Tools", "#5AE8D9"]
- }
- @category = cat_info[@listing.category.to_sym][0]
- @cat_color = cat_info[@listing.category.to_sym][1]
- end
-
def set_respond(template = nil)
respond_to do |format|
format.html do
diff --git a/app/dashboards/classified_listing_category_dashboard.rb b/app/dashboards/classified_listing_category_dashboard.rb
index ec436426c..901b3d287 100644
--- a/app/dashboards/classified_listing_category_dashboard.rb
+++ b/app/dashboards/classified_listing_category_dashboard.rb
@@ -15,6 +15,8 @@ class ClassifiedListingCategoryDashboard < Administrate::BaseDashboard
name: Field::String,
rules: Field::String,
slug: Field::String,
+ social_preview_description: Field::String,
+ social_preview_color: Field::String,
updated_at: Field::DateTime
}.freeze
diff --git a/app/decorators/classified_listing_decorator.rb b/app/decorators/classified_listing_decorator.rb
new file mode 100644
index 000000000..983c84f77
--- /dev/null
+++ b/app/decorators/classified_listing_decorator.rb
@@ -0,0 +1,14 @@
+class ClassifiedListingDecorator < ApplicationDecorator
+ DEFAULT_COLOR = "#000000".freeze
+
+ def social_preview_category
+ category = object.classified_listing_category
+ category.social_preview_description.presence || category.name
+ end
+
+ def social_preview_color(brightness: 1.0)
+ category = object.classified_listing_category
+ color = category.social_preview_color.presence || DEFAULT_COLOR
+ HexComparer.new([color]).brightness(brightness)
+ end
+end
diff --git a/app/models/classified_listing_category.rb b/app/models/classified_listing_category.rb
index 417246e82..1554b5e34 100644
--- a/app/models/classified_listing_category.rb
+++ b/app/models/classified_listing_category.rb
@@ -1,6 +1,21 @@
class ClassifiedListingCategory < ApplicationRecord
has_many :classified_listings
+ before_validation :normalize_social_preview_color
+
validates :name, :cost, :rules, :slug, presence: true
validates :name, :slug, uniqueness: true
+
+ # This needs to be a hex color of format "#CCC" or "#A1B2C3"
+ validates :social_preview_color,
+ format: /\A#(?:[a-f0-9]{3}){1,2}\z/,
+ allow_blank: true
+
+ private
+
+ def normalize_social_preview_color
+ return unless social_preview_color
+
+ self.social_preview_color = social_preview_color.downcase
+ end
end
diff --git a/app/views/social_previews/listing.html.erb b/app/views/social_previews/listing.html.erb
index 6f485d788..4233aa43f 100644
--- a/app/views/social_previews/listing.html.erb
+++ b/app/views/social_previews/listing.html.erb
@@ -35,7 +35,7 @@
}
h1 {
- color: <%= HexComparer.new([@cat_color]).brightness(0.70) %>;
+ color: <%= @listing.social_preview_color(brightness: 0.70) %>;
width: 92%;
margin: 0;
padding: 1vw;
@@ -46,7 +46,7 @@
font-size: 3.1vw;
padding: 0 4vw;
font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", "Roboto", sans-serif;
- color: <%= HexComparer.new([@cat_color]).brightness(0.77) %>;
+ color: <%= @listing.social_preview_color(brightness: 0.77) %>;
}
.preview-category {
@@ -78,7 +78,7 @@
<%= sanitize_rendered_markdown(@listing.processed_html) %>
- <%= @category %>
+ <%= @listing.social_preview_category %>
<%= inline_svg_tag("devlistings-horizontal.svg", class: "logo", size: "30vw*10vw", aria: false, title: "DEV logo") %>
diff --git a/db/migrate/20200504075409_add_social_preview_columns_to_classified_listing_categories.rb b/db/migrate/20200504075409_add_social_preview_columns_to_classified_listing_categories.rb
new file mode 100644
index 000000000..02e6dfd36
--- /dev/null
+++ b/db/migrate/20200504075409_add_social_preview_columns_to_classified_listing_categories.rb
@@ -0,0 +1,6 @@
+class AddSocialPreviewColumnsToClassifiedListingCategories < ActiveRecord::Migration[5.2]
+ def change
+ add_column :classified_listing_categories, :social_preview_description, :string
+ add_column :classified_listing_categories, :social_preview_color, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index b6efc3919..39299d161 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.define(version: 2020_05_01_032629) do
+ActiveRecord::Schema.define(version: 2020_05_04_075409) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -316,6 +316,8 @@ ActiveRecord::Schema.define(version: 2020_05_01_032629) do
t.string "name", null: false
t.string "rules", null: false
t.string "slug", null: false
+ t.string "social_preview_color"
+ t.string "social_preview_description"
t.datetime "updated_at", null: false
t.index ["name"], name: "index_classified_listing_categories_on_name", unique: true
t.index ["slug"], name: "index_classified_listing_categories_on_slug", unique: true
diff --git a/lib/tasks/temporary/classified_listings.rake b/lib/tasks/temporary/classified_listings.rake
index ae6084957..a3a0eb130 100644
--- a/lib/tasks/temporary/classified_listings.rake
+++ b/lib/tasks/temporary/classified_listings.rake
@@ -1,12 +1,24 @@
namespace :temporary do
namespace :classified_listings do
- desc "Backfill classified listings categories"
- task backfill_categories: :environment do
- ClassifiedListing::CATEGORIES_AVAILABLE.each do |key, attributes|
- category = ClassifiedListingCategory.find_or_create_by!(attributes.merge(slug: key))
- ClassifiedListing.
- where(category: key.to_s).
- update_all(classified_listing_category_id: category.id)
+ desc "Backfill social preview info for classified listings categories"
+ task backfill_social_preview_info: :environment do
+ info = {
+ "collabs": ["Collaborators Wanted", "#5ae8d9"],
+ "cfp": ["Call For Proposal", "#f58f8d"],
+ "forhire": ["Available For Hire", "#b78cf4"],
+ "education": ["Education", "#5aabe8"],
+ "jobs": ["Now Hiring", "#53c3ad"],
+ "mentors": ["Offering Mentorship", "#a69ee8"],
+ "mentees": ["Looking For Mentorship", "#88aedb"],
+ "forsale": ["Stuff For Sale", "#d0adfb"],
+ "events": ["Upcoming Event", "#f8b3d0"],
+ "misc": ["Miscellaneous", "#6393ff"],
+ "products": ["Products & Tools", "#5ae8d9"]
+ }
+ info.each do |slug, (description, color)|
+ ClassifiedListingCategory.
+ where(slug:slug).
+ update(social_preview_description: description, social_preview_color: color)
end
end
end
diff --git a/spec/decorators/classified_listing_decorator_spec.rb b/spec/decorators/classified_listing_decorator_spec.rb
new file mode 100644
index 000000000..071ba5bbd
--- /dev/null
+++ b/spec/decorators/classified_listing_decorator_spec.rb
@@ -0,0 +1,42 @@
+require "rails_helper"
+
+RSpec.describe ClassifiedListingDecorator, type: :decorator do
+ let_it_be_readonly(:category) { create(:classified_listing_category) }
+ let(:decorated_listing) do
+ build(:classified_listing, classified_listing_category: category).decorate
+ end
+
+ describe "#social_preview_category" do
+ it "returns the category name if the social preview category is blank" do
+ allow(category).to receive(:social_preview_description).and_return(nil)
+
+ expect(decorated_listing.social_preview_category).to eq(category.name)
+ end
+
+ it "returns the category's social preview descripton if available" do
+ expect(decorated_listing.social_preview_category).
+ to eq(category.social_preview_description)
+ end
+ end
+
+ describe "#social_preview_color" do
+ it "returns the default color if social preview color is blank" do
+ allow(category).to receive(:social_preview_color).and_return(nil)
+
+ expect(decorated_listing.social_preview_color).
+ to eq(ClassifiedListingDecorator::DEFAULT_COLOR)
+ end
+
+ it "returns the category's social preview color if available" do
+ expect(decorated_listing.social_preview_color).
+ to eq(category.social_preview_color)
+ end
+
+ it "can modify the brightness" do
+ color = category.social_preview_color
+
+ expect(decorated_listing.social_preview_color(brightness: 0.8)).
+ to eq(HexComparer.new([color]).brightness(0.8))
+ end
+ end
+end
diff --git a/spec/factories/classified_listing_categories.rb b/spec/factories/classified_listing_categories.rb
index 0176c4a69..a1e6cbac1 100644
--- a/spec/factories/classified_listing_categories.rb
+++ b/spec/factories/classified_listing_categories.rb
@@ -4,17 +4,23 @@ FactoryBot.define do
cost { [1, 5, 25].sample }
rules { Faker::Hipster.paragraph(sentence_count: 1) }
slug { "education" }
+ social_preview_description { "Education" }
+ social_preview_color { "#5aabe8" }
trait :cfp do
name { "Conference CFP" }
slug { "cfp" }
cost { 5 }
+ social_preview_description { "Call For Proposal" }
+ social_preview_color { "#f58f8d" }
end
trait :jobs do
name { "Job Listings" }
slug { "jobs" }
cost { 1 }
+ social_preview_description { "Now Hiring" }
+ social_preview_color { "#53c3ad" }
end
end
end
diff --git a/spec/models/classified_listing_category_spec.rb b/spec/models/classified_listing_category_spec.rb
index 560f22033..4df93fa07 100644
--- a/spec/models/classified_listing_category_spec.rb
+++ b/spec/models/classified_listing_category_spec.rb
@@ -12,5 +12,30 @@ RSpec.describe ClassifiedListingCategory, type: :model do
it { is_expected.to validate_presence_of(:slug) }
it { is_expected.to validate_uniqueness_of(:name) }
it { is_expected.to validate_uniqueness_of(:slug) }
+
+ context "when validating social preview colors" do
+ let(:category) { build(:classified_listing_category) }
+
+ it "rejects invalid formats" do
+ category.social_preview_color = "#DEV.TO"
+ category.validate
+
+ expect(category.errors[:social_preview_color]).to eq(["is invalid"])
+ end
+
+ it "normalizes the input to lowercase before validation" do
+ category.social_preview_color = "#CCCCCC"
+ category.validate
+
+ expect(category.social_preview_color).to eq("#cccccc")
+ end
+
+ it "accepts missing social preview colors" do
+ category.social_preview_color = nil
+ category.validate
+
+ expect(category).to be_valid
+ end
+ end
end
end