Campaign settings (#6141) [deploy]

* feat: port over changes (+ suggestions) from https://github.com/thepracticaldev/dev.to/pull/5892/files

* chore: add query over multiple lines

* refactor: move the sql logic into the controller instead of in the template

* chore: appease code climate
This commit is contained in:
Ridhwana 2020-02-18 19:02:09 +02:00 committed by GitHub
parent b8955f19fe
commit 39007b4dab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 149 additions and 3 deletions

View file

@ -21,6 +21,8 @@ class Internal::ConfigsController < Internal::ApplicationController
def config_params
allowed_params = %i[
default_site_email social_networks_handle
campaign_hero_html_variant_name campaign_background_color
campaign_text_color campaign_sidebar_enabled campaign_featured_tags
main_social_image favicon_url logo_svg
rate_limit_follow_count_daily
ga_view_id ga_fetch_rate

View file

@ -38,6 +38,20 @@ class StoriesController < ApplicationController
private
def assign_hero_html
return if SiteConfig.campaign_hero_html_variant_name.blank?
@hero_html = HtmlVariant.relevant.select(:html).
find_by(group: "campaign", name: SiteConfig.campaign_hero_html_variant_name)&.html
end
def get_latest_campaign_articles
@latest_campaign_articles = Article.tagged_with(SiteConfig.campaign_featured_tags, any: true).
where("published_at > ?", 2.weeks.ago).where(approved: true).
order("hotness_score DESC").
pluck(:path, :title, :comments_count, :created_at)
end
def redirect_to_changed_username_profile
potential_username = params[:username].tr("@", "").downcase
user_or_org = User.find_by("old_username = ? OR old_old_username = ?", potential_username, potential_username) ||
@ -125,8 +139,10 @@ class StoriesController < ApplicationController
@default_home_feed = true
@featured_story, @stories = feed.default_home_feed(user_signed_in: user_signed_in?)
end
assign_hero_html
assign_podcasts
assign_classified_listings
get_latest_campaign_articles if SiteConfig.campaign_sidebar_enabled?
@article_index = true
@featured_story = (@featured_story || Article.new)&.decorate
@stories = ArticleDecorator.decorate_collection(@stories)

View file

@ -1,9 +1,11 @@
class HtmlVariant < ApplicationRecord
include CloudinaryHelper
GROUP_NAMES = %w[article_show_sidebar_cta article_show_below_article_cta badge_landing_page campaign].freeze
validates :html, presence: true
validates :name, uniqueness: true
validates :group, inclusion: { in: %w[article_show_sidebar_cta article_show_below_article_cta badge_landing_page] }
validates :group, inclusion: { in: GROUP_NAMES }
validates :success_rate, presence: true
validate :no_edits
@ -13,6 +15,8 @@ class HtmlVariant < ApplicationRecord
before_save :prefix_all_images
scope :relevant, -> { where(approved: true, published: true) }
def calculate_success_rate!
self.success_rate = html_variant_successes.size.to_f / (html_variant_trials.size * 10.0) # x10 because we only capture every 10th
save!

View file

@ -13,6 +13,13 @@ class SiteConfig < RailsSettings::Base
field :default_site_email, type: :string, default: "yo@dev.to"
field :social_networks_handle, type: :string, default: "thepracticaldev"
# campaign
field :campaign_hero_html_variant_name, type: :string, default: ""
field :campaign_background_color, type: :string, default: "FFFFFF"
field :campaign_text_color, type: :string, default: "000000"
field :campaign_featured_tags, type: :array, default: %w[]
field :campaign_sidebar_enabled, type: :boolean, default: 0
# images
field :main_social_image, type: :string, default: "https://thepracticaldev.s3.amazonaws.com/i/6hqmcjaxbgbon8ydw93z.png"
field :favicon_url, type: :string, default: "favicon.ico"

View file

@ -27,6 +27,7 @@
</div>
</div>
<% end %>
<%= render "articles/sidebar_campaign" if SiteConfig.campaign_sidebar_enabled? %>
<% if params[:timeframe].blank? && @classified_listings.any? %>
<div class="widget" id="sidebar-listings-widget">
<header class="widget-header-listings">

View file

@ -0,0 +1,16 @@
<div class="widget">
<header>
<h4>
<% SiteConfig.campaign_featured_tags.each do |t| %>
<%= link_to("##{t}", "/t/#{t}") %>
<% end %>
</h4>
</header>
<div class="widget-body">
<div class="widget-link-list">
<% @latest_campaign_articles.each do |plucked_article| %>
<%= render "articles/widget_list_item", plucked_article: plucked_article, show_comment_count: false %>
<% end %>
</div>
</div>
</div>

View file

@ -25,7 +25,7 @@
<%= f.label :published %>
<%= f.check_box :published %>
<%= f.label :group %>
<%= f.select(:group, options_for_select(["article_show_sidebar_cta", "article_show_below_article_cta", "badge_landing_page"], @html_variant.group || "article_show_sidebar_cta")) %>
<%= f.select(:group, options_for_select(HtmlVariant::GROUP_NAMES, @html_variant.group || "article_show_sidebar_cta")) %>
</div>
<%= f.submit %>
<% end %>

View file

@ -10,6 +10,7 @@
<a href="/html_variants?state=article_show_sidebar_cta" class="<%= "selected" if params[:state] == "article_show_sidebar_cta" %>">Show Page Sidebar</a>
<a href="/html_variants?state=article_show_below_article_cta" class="<%= "selected" if params[:state] == "article_show_below_article_cta" %>">Show Page Below Article</a>
<a href="/html_variants?state=badge_landing_page" class="<%= "selected" if params[:state] == "badge_landing_page" %>">Badge Landing Page</a>
<a href="/html_variants?state=campaign" class="<%= "selected" if params[:state] == "campaign" %>">Campaign</a>
</nav>
<% if params[:state] == "mine" %>
<h2>My Entries</h2>

View file

@ -45,6 +45,53 @@
</div>
</div>
<div class="card mt-3">
<div class="card-header">Campaign</div>
<div class="card-body">
<div class="form-group">
<%= f.label :campaign_hero_html_variant_name %>
<%= f.text_field :campaign_hero_html_variant_name,
class: "form-control",
value: SiteConfig.campaign_hero_html_variant_name,
placeholder: "" %>
<div class="alert alert-info">Hero HtmlVariant name</div>
</div>
<div class="form-group">
<%= f.label :campaign_background_color %>
<%= f.text_field :campaign_background_color,
class: "form-control",
value: SiteConfig.campaign_background_color,
placeholder: "FFFFFF" %>
<div class="alert alert-info">Campaign background color</div>
</div>
<div class="form-group">
<%= f.label :campaign_text_color %>
<%= f.text_field :campaign_text_color,
class: "form-control",
value: SiteConfig.campaign_text_color,
placeholder: "FFFFFF" %>
<div class="alert alert-info">Campaign text color</div>
</div>
<div class="form-group">
<%= f.label :campaign_sidebar_enabled %>
<%= f.check_box :campaign_sidebar_enabled, checked: SiteConfig.campaign_sidebar_enabled %>
<div class="alert alert-info">Campaign sidebar enabled or not</div>
</div>
<div class="form-group">
<%= f.label :campaign_featured_tags %>
<%= f.text_field :campaign_featured_tags,
class: "form-control",
value: SiteConfig.campaign_featured_tags.join(","),
placeholder: "List of campaign tags: comma separated, letters only e.g. shecoded,theycoded" %>
<div class="alert alert-info">Posts with which tags will be featured in the campaign sidebar (comma separated, letters only)</div>
</div>
</div>
</div>
<div class="card mt-3">
<div class="card-header">Images</div>
<div class="card-body">

View file

@ -7,7 +7,10 @@
</div>
<% end %>
<div id="page-content-inner">
<% if @hero_html %>
<%= @hero_html.html_safe %>
<% end %>
<%= yield %>
</div>
</div>
<%= render "shell/bottom" %>
<%= render "shell/bottom" %>

View file

@ -68,6 +68,55 @@ RSpec.describe "StoriesIndex", type: :request do
get "/"
expect(response.body).to include(CGI.escapeHTML(listing.title))
end
context "with campaign hero" do
let!(:hero_html) { create(:html_variant, group: "campaign", name: "hero", html: Faker::Book.title, published: true, approved: true) }
it "displays hero html when it exists and is set in config" do
SiteConfig.campaign_hero_html_variant_name = "hero"
get "/"
expect(response.body).to include(CGI.escapeHTML(hero_html.html))
end
it "doesn't display when campaign_hero_html_variant_name is not set" do
SiteConfig.campaign_hero_html_variant_name = ""
get "/"
expect(response.body).not_to include(CGI.escapeHTML(hero_html.html))
end
it "doesn't display when hero html is not approved" do
SiteConfig.campaign_hero_html_variant_name = "hero"
hero_html.update_column(:approved, false)
get "/"
expect(response.body).not_to include(CGI.escapeHTML(hero_html.html))
end
end
context "with campaign_sidebar" do
before do
SiteConfig.campaign_featured_tags = "shecoded,theycoded"
create(:article, approved: true, body_markdown: "---\ntitle: Super-sheep#{rand(1000)}\npublished: true\ntags: heyheyhey,shecoded\n---\n\nHello")
create(:article, approved: false, body_markdown: "---\ntitle: Unapproved-post#{rand(1000)}\npublished: true\ntags: heyheyhey,shecoded\n---\n\nHello")
end
it "doesn't display posts with the campaign tags when sidebar is disabled" do
SiteConfig.campaign_sidebar_enabled = false
get "/"
expect(response.body).not_to include(CGI.escapeHTML("Super-sheep"))
end
it "displays posts with the campaign tags when sidebar is enabled" do
SiteConfig.campaign_sidebar_enabled = true
get "/"
expect(response.body).not_to include(CGI.escapeHTML("Unapproved-post"))
end
it "displays only approved posts with the campaign tags" do
SiteConfig.campaign_sidebar_enabled = false
get "/"
expect(response.body).not_to include(CGI.escapeHTML("Super-puper"))
end
end
end
describe "GET query page" do