diff --git a/app/controllers/api/v0/articles_controller.rb b/app/controllers/api/v0/articles_controller.rb index c62c9e13b..f99d55ee5 100644 --- a/app/controllers/api/v0/articles_controller.rb +++ b/app/controllers/api/v0/articles_controller.rb @@ -24,7 +24,7 @@ module Api tag_list = if params[:tag_list].present? params[:tag_list].split(",") else - ["career","discuss","productivity"] + ["career", "discuss", "productivity"] end @articles = [] 4.times do diff --git a/app/controllers/internal/articles_controller.rb b/app/controllers/internal/articles_controller.rb index 70ae205fe..3c5625d1d 100644 --- a/app/controllers/internal/articles_controller.rb +++ b/app/controllers/internal/articles_controller.rb @@ -69,6 +69,22 @@ class Internal::ArticlesController < Internal::ApplicationController page(params[:page]). per(100). limited_columns_internal_select + when "boosted-additional-articles" + @articles = Article. + includes(:user). + order("published_at DESC"). + boosted_via_additional_articles. + page(params[:page]). + per(100). + limited_columns_internal_select + when "boosted-dev-digest" + @articles = Article. + includes(:user). + order("published_at DESC"). + boosted_via_dev_digest_email. + page(params[:page]). + per(100). + limited_columns_internal_select else #MIX @articles = Article. where(published: true). @@ -97,6 +113,9 @@ class Internal::ArticlesController < Internal::ApplicationController article.featured = article_params[:featured].to_s == "true" article.approved = article_params[:approved].to_s == "true" article.live_now = article_params[:live_now].to_s == "true" + article.email_digest_eligible = article_params[:email_digest_eligible].to_s == "true" + article.boosted_additional_articles = article_params[:boosted_additional_articles].to_s == "true" + article.boosted_dev_digest_email = article_params[:boosted_dev_digest_email].to_s == "true" article.update!(article_params) if article.live_now Article.where.not(id: article.id).where(live_now: true).update_all(live_now: false) @@ -115,6 +134,9 @@ class Internal::ArticlesController < Internal::ApplicationController :body_markdown, :approved, :live_now, + :email_digest_eligible, + :boosted_additional_articles, + :boosted_dev_digest_email, :main_image_background_hex_color, :featured_number) end diff --git a/app/decorators/article_decorator.rb b/app/decorators/article_decorator.rb index d21d26c40..035332367 100644 --- a/app/decorators/article_decorator.rb +++ b/app/decorators/article_decorator.rb @@ -42,4 +42,13 @@ class ArticleDecorator < ApplicationDecorator "short" end end + + def internal_utm_params(place="additional_box") + campaign = if boosted + "#{organization&.slug}_boosted" + else + "regular" + end + "?utm_source=#{place}&utm_medium=internal&utm_campaign=#{ campaign }&booster_org=#{organization&.slug}" + end end diff --git a/app/javascript/packs/pack.js b/app/javascript/packs/pack.js index 7c1fb7b73..362048a2d 100644 --- a/app/javascript/packs/pack.js +++ b/app/javascript/packs/pack.js @@ -2,16 +2,20 @@ import { h, render } from 'preact'; import Onboarding from '../src/Onboarding'; import { getUserData } from '../src/utils/getUserData'; -HTMLDocument.prototype.ready = new Promise((resolve) => { - if (document.readyState !== 'loading') { return resolve(); } +HTMLDocument.prototype.ready = new Promise(resolve => { + if (document.readyState !== 'loading') { + return resolve(); + } document.addEventListener('DOMContentLoaded', () => resolve()); }); function shouldShowOnboarding() { - return document.head.getElementsByTagName('meta')[2].content === 'true' && + return ( + document.head.getElementsByTagName('meta')[2].content === 'true' && document.body.getAttribute('data-user') && document.body.getAttribute('data-user') !== 'undefined' && JSON.parse(document.body.getAttribute('data-user')).saw_onboarding === false + ); } function renderPage() { @@ -22,8 +26,8 @@ function renderPage() { } } -document.ready - .then(getUserData() - .then(() => { - renderPage(); - })); +document.ready.then( + getUserData().then(() => { + renderPage(); + }), +); diff --git a/app/labor/boosted_article.rb b/app/labor/boosted_article.rb index 798314ec2..7c9b5ba9a 100644 --- a/app/labor/boosted_article.rb +++ b/app/labor/boosted_article.rb @@ -7,11 +7,19 @@ class BoostedArticle @not_ids = options[:not_ids] end - def get - Article.where(boosted: true). - includes(:user). - includes(:organization). - where.not(id: not_ids, organization_id: nil). - tagged_with(tags, any: true).sample + def get(area = "additional_articles") + if area == "additional_articles" + Article.boosted_via_additional_articles. + includes(:user). + includes(:organization). + where.not(id: not_ids, organization_id: nil). + tagged_with(tags, any: true).sample + else + Article.boosted_via_dev_digest_email. + includes(:user). + includes(:organization). + where.not(id: not_ids, organization_id: nil). + tagged_with(tags, any: true).sample + end end end diff --git a/app/labor/email_logic.rb b/app/labor/email_logic.rb index a6b4ea917..635d0f41e 100644 --- a/app/labor/email_logic.rb +++ b/app/labor/email_logic.rb @@ -33,7 +33,7 @@ class EmailLogic articles = if user_has_followings? @user.followed_articles. where("published_at > ?", fresh_date). - where(published: true). + where(published: true, email_digest_eligible: true). where.not(user_id: @user.id). where("positive_reactions_count > ?", 15). order("positive_reactions_count DESC"). diff --git a/app/mailers/digest_mailer.rb b/app/mailers/digest_mailer.rb index 9a86f9510..e81d47784 100644 --- a/app/mailers/digest_mailer.rb +++ b/app/mailers/digest_mailer.rb @@ -5,6 +5,9 @@ class DigestMailer < ApplicationMailer @user = user @articles = articles.first(6) @unsubscribe = generate_unsubscribe_token(@user.id, :email_digest_periodic) + @boosted_article = BoostedArticle.new(@user, + @articles.first, + {not_ids: @articles.pluck(:id)}).get("dev_digest_email") subject = generate_title(@articles) mail(to: @user.email, subject: subject) end diff --git a/app/models/article.rb b/app/models/article.rb index 7180042af..b0451023d 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -4,6 +4,7 @@ class Article < ApplicationRecord include CloudinaryHelper include ActionView::Helpers include AlgoliaSearch + include Storext.model acts_as_taggable_on :tags @@ -63,14 +64,23 @@ class Article < ApplicationRecord scope :limited_columns_internal_select, -> { select(:path, :title, :id, :featured, :approved, :published, :comments_count, :positive_reactions_count, :cached_tag_list, - :main_image, :main_image_background_hex_color, :updated_at, + :main_image, :main_image_background_hex_color, :updated_at, :boost_states, :video, :user_id, :organization_id, :video_source_url, :video_code, :video_thumbnail_url, :video_closed_caption_track_url, :social_image, :published_from_feed, :crossposted_at, :published_at, :featured_number, - :live_now, :last_buffered, :facebook_last_buffered, :created_at, :body_markdown + :live_now, :last_buffered, :facebook_last_buffered, :created_at, :body_markdown, + :email_digest_eligible ) } + scope :boosted_via_additional_articles, -> { + where("boost_states ->> 'boosted_additional_articles' = 'true'") + } + + scope :boosted_via_dev_digest_email, -> { + where("boost_states ->> 'boosted_dev_digest_email' = 'true'") + } + algoliasearch per_environment: true, enqueue: :trigger_delayed_index do add_index "searchables", id: :index_id, @@ -142,6 +152,12 @@ class Article < ApplicationRecord end end + store_attributes :boost_states do + boosted_additional_articles Boolean, default: false + boosted_dev_digest_email Boolean, default: false + end + + def self.filter_excluded_tags(tag = nil) if tag == "hiring" tagged_with("hiring") diff --git a/app/views/additional_content_boxes/_article_box.html.erb b/app/views/additional_content_boxes/_article_box.html.erb index 5d71f4d3a..33fb4d9f0 100644 --- a/app/views/additional_content_boxes/_article_box.html.erb +++ b/app/views/additional_content_boxes/_article_box.html.erb @@ -12,6 +12,7 @@
- " data-details="<%= organization&.slug %>__<%= article.slug %>"> + " data-details="<%= organization&.slug %>__<%= article.slug %>"> <%= article.description %>