Refactor classified listing social previews (#7679)

* Refactor classified listing social previews

* Rename decorator method

* Fix overeager renaming
This commit is contained in:
Michael Kohl 2020-05-07 01:00:09 +07:00 committed by GitHub
parent caccdba9ac
commit 7e6c2b3977
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 138 additions and 33 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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) %>
</div>
<div class="preview-category">
<%= @category %>
<%= @listing.social_preview_category %>
</div>
<div class="preview-dev-logo">
<%= inline_svg_tag("devlistings-horizontal.svg", class: "logo", size: "30vw*10vw", aria: false, title: "DEV logo") %>

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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