Add organization to feed and adjust page styling (#1089)

* Add organization to feed and adjust page styling

* Add conditional indexing to article agolia

* Early return in algolia org logic

* Make org optional in algolia

* Modify org cta styling
This commit is contained in:
Ben Halpern 2018-11-12 12:28:51 -05:00 committed by GitHub
parent 52d434b065
commit 8b1755a2b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 94 additions and 55 deletions

View file

@ -29,11 +29,15 @@ function insertNewArticles(user){
if (insertPlace) {
articlesJSON.forEach(function(article){
var articlePoints = 0
var containsUserID = findOne([article.user_id], user.followed_user_ids)
var containsUserID = findOne([article.user_id], user.followed_user_ids || [])
var containsOrganizationID = findOne([article.organization_id], user.followed_organization_ids || [])
articlePoints = articlePoints + (intersect_arrays(user.followed_tag_names, article.cached_tag_list_array).length*2) + article.positive_reactions_count
if (containsUserID || article.user_id === user.id) {
articlePoints = articlePoints + 16
}
if (containsOrganizationID) {
articlePoints = articlePoints + 16
}
article['points'] = articlePoints
});
var sortedArticles = articlesJSON.sort(function(a, b) {
@ -55,11 +59,15 @@ function insertTopArticles(user){
if (insertPlace) {
articlesJSON.forEach(function(article){
var articlePoints = 0
var containsUserID = findOne([article.user_id], user.followed_user_ids)
var containsUserID = findOne([article.user_id], user.followed_user_ids || [])
var containsOrganizationID = findOne([article.organization_id], user.followed_organization_ids || [])
articlePoints = articlePoints + intersect_arrays(user.followed_tag_names, article.cached_tag_list_array).length
if (containsUserID) {
articlePoints = articlePoints + 1
}
if (containsOrganizationID) {
articlePoints = articlePoints + 1
}
article['points'] = articlePoints
});
var sortedArticles = articlesJSON.sort(function(a, b) {

View file

@ -45,16 +45,11 @@ function buildArticleHTML(article) {
if ((rc || '0') > 0 && article.class_name != "User") {
var reactionsCountHTML = '<div class="article-engagement-count reactions-count"><a href="'+article.path+'"><img src="<%= asset_path("reactions-stack.png") %>" alt="heart" /><span id="engagement-count-number-'+article.id+'" class="engagement-count-number">'+(rc || '0')+'</span></a></div>'
}
if ( article.organization && article.tag_list.indexOf("hiring") > -1 && !document.getElementById("organization-index-page") ){
var picUrl = article.organization.profile_image_90
var profileUsername = article.organization.slug
} else {
var picUrl = article.user.profile_image_90
var profileUsername = article.user.username
}
var classicHeadline = "";
if (article.is_classic) {
classicHeadline = '<a href="'+article.path+'" class="article-classic-headline" id="article-classic-headline"><div class="article-classic-headline-inner">Classic from '+article.published_at_month_day+'</div></a>'
var picUrl = article.user.profile_image_90
var profileUsername = article.user.username
var orgHeadline = "";
if (article.organization && !document.getElementById("organization-article-index")) {
orgHeadline = '<div class="article-organization-headline"><a href="/'+article.organization.slug+'" class="article-organization-headline-inner"><img src="'+article.organization.profile_image_90+'" />'+article.organization.name+'</a><a class="org-headline-filler" href="'+article.path+'">&nbsp;</a></div>'
}
var bodyTextSnippet = "";
var commentsBlobSnippet = "";
@ -98,7 +93,7 @@ function buildArticleHTML(article) {
publishDate = '・'+article.readable_publish_date
}
return '<div class="single-article single-article-small-pic">\
'+classicHeadline+'\
'+orgHeadline+'\
<div class="small-pic">\
<a href="/'+profileUsername+'" class="small-pic-link-wrapper">\
<img src="'+picUrl+'" alt="'+profileUsername+' profile">\

View file

@ -194,19 +194,30 @@
margin-top:12px;
}
}
.article-classic-headline{
.article-organization-headline {
display:block;
margin-bottom:calc(-1px - 0.6vw);
.article-classic-headline-inner{
background: lighten($yellow,8%);
display: flex;
.article-organization-headline-inner {
background: darken($light-gray, 7%);
color: $black;
padding: 4px 8px;
border-radius: 3px;
font-weight:500;
padding: 6px 12px;
border-radius: 100px;
font-weight:600;
display:inline-block;
margin-top:10px;
margin-left: 10px;
font-size:calc(0.8em + 0.1vw);
font-size:calc(0.9em);
img {
height: calc(1.3em);
width: calc(1.3em);
vertical-align: - 0.27em;
margin-right: 6px;
border-radius: 100px;
}
}
a.org-headline-filler {
flex: 1;
}
}
.small-pic{

View file

@ -155,33 +155,30 @@
color:#333842;
font-family: $monospace;
}
.primary-sticky-nav-org-cta-link-wrapper {
text-align: center;
}
a.primary-sticky-nav-org-cta-link{
width:100%;
display: block;
display: inline-block;
font-size:1.25em;
border:0px;
border-radius:3px;
padding: 11px 0px 5px;
border-radius:100px;
padding: 6px 38px;
margin-top: 20px;
background: white;
color: $black;
font-family: $helvetica-condensed;
font-weight: bold;
border: 1px solid darken($light-medium-gray, 10%);
text-align: center;
font-stretch: condensed;
.primary-sticky-nav-org-cta-link-domain-small{
display: block;
font-weight: 400;
padding-top: 2px;
font-size:0.75em;
color: darken($light-medium-gray, 9%);
font-family: $monospace;
}
box-shadow: $light-shadow;
margin-bottom: 5px;
&:hover {
border: 1px solid darken($light-medium-gray, 14%);
box-shadow: $shadow;
transition: all 0.1s;
box-shadow: $dark-shadow;
padding: 7px 39px;
margin-bottom: 4px;
margin-top: 19px;
transition: all 0.3s;
}
}
}

View file

@ -28,4 +28,6 @@ $helvetica-condensed: "HelveticaNeue-CondensedBold", "HelveticaNeueBoldCondensed
$outline-color: darken($light-medium-gray, 2%);
$shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.18);
$light-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.1);
$dark-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.25);
$bold-shadow: 3px 3px 0px darken($light-medium-gray, 13%);

View file

@ -38,6 +38,7 @@ class AsyncInfoController < ApplicationController
followed_tag_names: @user.cached_followed_tag_names,
followed_tags: @user.cached_followed_tags.to_json(only: %i[id name bg_color_hex text_color_hex]),
followed_user_ids: @user.cached_following_users_ids,
followed_organization_ids: @user.cached_following_organizations_ids,
reading_list_ids: ReadingList.new(@user).cached_ids_of_articles,
saw_onboarding: @user.saw_onboarding,
checked_code_of_conduct: @user.checked_code_of_conduct,

View file

@ -133,7 +133,7 @@ class Article < ApplicationRecord
enqueue: :trigger_delayed_index do
attributes :title, :path, :class_name, :comments_count,
:tag_list, :positive_reactions_count, :id, :hotness_score,
:readable_publish_date, :flare_tag
:readable_publish_date, :flare_tag, :user_id, :organization_id
attribute :published_at_int do
published_at.to_i
end
@ -142,6 +142,13 @@ class Article < ApplicationRecord
name: user.name,
profile_image_90: ProfileImage.new(user).get(90) }
end
attribute :organization do
if organization
{ slug: organization.slug,
name: organization.name,
profile_image_90: ProfileImage.new(organization).get(90) }
end
end
tags do
[tag_list,
"user_#{user_id}",

View file

@ -222,14 +222,19 @@ class User < ApplicationRecord
"user-#{id}-#{updated_at}-#{following_users_count}/following_users_ids",
expires_in: 120.hours,
) do
# More efficient query. May not cover future edge cases.
# Should probably only return users who have published lately
# But this should be okay for most for now.
Follow.where(follower_id: id, followable_type: "User").limit(150).pluck(:followable_id)
end
end
def cached_following_organizations_ids
Rails.cache.fetch(
"user-#{id}-#{updated_at}-#{following_orgs_count}/following_organizations_ids",
expires_in: 120.hours,
) do
Follow.where(follower_id: id, followable_type: "Organization").limit(150).pluck(:followable_id)
end
end
def cached_preferred_langs
Rails.cache.fetch("user-#{id}-#{updated_at}/cached_preferred_langs", expires_in: 24.hours) do
langs = []

View file

@ -1,3 +1,6 @@
<% if @organization_article_index %>
<div id="organization-article-index"></div>
<% end %>
<% if !user_signed_in? || !@default_home_feed %>
<% @stories.each_with_index do |story,i| %>
<% next if story.id == @featured_story.id %>
@ -31,17 +34,19 @@
<% cache("fetched-home-articles-object", :expires_in => 3.minutes) do %>
<div id="new-articles-object" data-articles="
<%=@new_stories.to_json(only:
[:title, :path, :id, :user_id, :comments_count, :positive_reactions_count],
[:title, :path, :id, :user_id, :comments_count, :positive_reactions_count, :organization_id],
methods:
[:readable_publish_date, :cached_tag_list_array, :flare_tag, :class_name],
include: [user: {only: [:username, :name], methods: [:profile_image_90]}]) %>">
include: {user: {only: [:username, :name], methods: [:profile_image_90]},
organization: {only: [:slug, :name], methods: [:profile_image_90]}}) %>">
</div>
<div id="home-articles-object" data-articles="
<%=@stories.to_json(only:
[:title, :path, :id, :user_id, :comments_count, :positive_reactions_count],
[:title, :path, :id, :user_id, :comments_count, :positive_reactions_count, :organization_id],
methods:
[:readable_publish_date, :cached_tag_list_array, :flare_tag, :class_name],
include: [user: {only: [:username, :name], methods: [:profile_image_90]}]) %>">
include: { user: {only: [:username, :name], methods: [:profile_image_90]},
organization: {only: [:slug, :name], methods: [:profile_image_90]}}) %>">
<% 3.times do %>
<div class="single-article single-article-small-pic">
<div class="small-pic" >

View file

@ -2,8 +2,10 @@
<% if story.video.present? %>
<%= render "articles/video_player", meta_tags: false, article: story %>
<% end %>
<% if @organization_article_index %>
<div id="organization-index-page"></div>
<% organization = story.organization %>
<% if organization && !@organization_article_index %>
<div class="article-organization-headline">
<a href="/<%= organization.slug %>" class="article-organization-headline-inner"><img src="<%= organization.profile_image_90 %>">Heroku</a><a class="org-headline-filler" href="/<%= story.path %>">&nbsp;</a></div>
<% end %>
<a href="<%=story.user.path%>" class="small-pic-link-wrapper">
<div class="small-pic" >

View file

@ -27,6 +27,13 @@
.sticky-box-connector{
background: <%= HexComparer.new([user_colors(@actor)[:bg], user_colors(@actor)[:text]]).brightness(0.88) %> !important;
}
.primary-sticky-nav-org-cta-link {
background-color: <%= user_colors(@actor)[:text] %> !important;
color: <%= user_colors(@actor)[:bg] %> !important;
<% if user_colors(@actor)[:text].downcase == "#ffffff" %>
border: 2px solid <%= user_colors(@actor)[:bg] %> !important;
<% end %>
}
</style>
<div class="primary-sticky-nav" id="article-show-primary-sticky-nav">
@ -50,14 +57,13 @@
<% elsif @actor.class.name == "Organization" && @actor.approved_and_filled_out_cta? %>
<div class="primary-sticky-nav-org-summary">
<%= @actor.cta_processed_html.html_safe %>
<% if @actor.cta_button_text.present? && @actor.cta_button_url.present? %>
<a href="<%= @actor.cta_button_url || "LEARN MORE" %>" class="primary-sticky-nav-org-cta-link">
<%= @actor.cta_button_text %>
<span class="primary-sticky-nav-org-cta-link-domain-small">
<%= Addressable::URI.parse(@actor.cta_button_url).domain %>
</span>
</a>
<% end %>
<div class="primary-sticky-nav-org-cta-link-wrapper">
<% if @actor.cta_button_text.present? && @actor.cta_button_url.present? %>
<a href="<%= @actor.cta_button_url || "LEARN MORE" %>" class="primary-sticky-nav-org-cta-link">
<%= @actor.cta_button_text %>
</a>
<% end %>
</div>
</div>
<% end %>
</div>