diff --git a/app/assets/javascripts/initializers/initScrolling.js.erb b/app/assets/javascripts/initializers/initScrolling.js.erb index 157e515ed..aba42fb17 100644 --- a/app/assets/javascripts/initializers/initScrolling.js.erb +++ b/app/assets/javascripts/initializers/initScrolling.js.erb @@ -1,18 +1,27 @@ function initScrolling() { - client = algoliasearch('<%= ENV["ALGOLIASEARCH_APPLICATION_ID"] %>', '<%= ENV["ALGOLIASEARCH_SEARCH_ONLY_KEY"] %>'); - articlesIndex = client.initIndex('ordered_articles_<%= Rails.env %>'); checkIfNearBottomOfPage(); } function checkIfNearBottomOfPage() { var elCheck = document.getElementById("index-container"); + if (elCheck) { + client = algoliasearch('<%= ENV["ALGOLIASEARCH_APPLICATION_ID"] %>', '<%= ENV["ALGOLIASEARCH_SEARCH_ONLY_KEY"] %>'); + + var homeEl = document.getElementById("index-container"); + if (homeEl.dataset.feed === "base-feed") { + articlesIndex = client.initIndex('ordered_articles_<%= Rails.env %>'); + } else if (homeEl.dataset.feed === "latest") { + articlesIndex = client.initIndex('ordered_articles_by_published_at_<%= Rails.env %>'); + } else { + articlesIndex = client.initIndex('ordered_articles_by_positive_reactions_count_<%= Rails.env %>'); + } + initScrolling.called = true; if (document.getElementsByClassName("single-article").length < 2 || location.search.indexOf("q=") > -1 ) { document.getElementById("loading-articles").style.display = "none" done = true; - } - else { + } else { document.getElementById("loading-articles").style.display = "block" } fetchNextPageIfNearBottom(); @@ -97,7 +106,7 @@ function algoliaPaginate(tag){ filters.push(tag); } articlesIndex.search("*", { - hitsPerPage: 30, + hitsPerPage: 15, page: nextPage, attributesToHighlight: [], tagFilters: filters, diff --git a/app/assets/javascripts/initializers/initializeDrawerSliders.js b/app/assets/javascripts/initializers/initializeDrawerSliders.js index 7d6dcd236..789c6119e 100644 --- a/app/assets/javascripts/initializers/initializeDrawerSliders.js +++ b/app/assets/javascripts/initializers/initializeDrawerSliders.js @@ -34,6 +34,21 @@ function initializeDrawerSliders() { slideSidebar("right","outOfView"); slideSidebar("left","outOfView"); }); - + listenForNarrowMenuClick(); } } + +function listenForNarrowMenuClick(event) { + var navLinks = document.getElementsByClassName("narrow-nav-menu"); + for (var i = 0; i < navLinks.length; i++) { + document.getElementById("narrow-nav-menu").classList.remove("showing"); + } + document.getElementById("narrow-feed-butt").onclick = function(){ + document.getElementById("narrow-nav-menu").classList.add("showing"); + } + for (var i = 0; i < navLinks.length; i++) { + navLinks[i].onclick = function(event){ + document.getElementById("narrow-nav-menu").classList.remove("showing"); + } + } +} \ No newline at end of file diff --git a/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb b/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb index dad60da76..f41310cac 100644 --- a/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb +++ b/app/assets/javascripts/initializers/initializeFetchFollowedArticles.js.erb @@ -22,6 +22,16 @@ function algoliaFollowedArticles(){ } var client = algoliasearch('<%= ENV["ALGOLIASEARCH_APPLICATION_ID"] %>', '<%= ENV["ALGOLIASEARCH_SEARCH_ONLY_KEY"] %>'); var index = client.initIndex('ordered_articles_<%= Rails.env %>'); + + var homeEl = document.getElementById("index-container"); + if (homeEl.dataset.feed === "base-feed") { + articlesIndex = client.initIndex('ordered_articles_<%= Rails.env %>'); + } else if (homeEl.dataset.feed === "latest") { + articlesIndex = client.initIndex('ordered_articles_by_published_at_<%= Rails.env %>'); + } else { + articlesIndex = client.initIndex('ordered_articles_by_positive_reactions_count_<%= Rails.env %>'); + } + index.search("*", { hitsPerPage: 20, page: "0", diff --git a/app/assets/javascripts/initializers/initializeReadingListPage.js.erb b/app/assets/javascripts/initializers/initializeReadingListPage.js.erb index 31469de14..e1691c042 100644 --- a/app/assets/javascripts/initializers/initializeReadingListPage.js.erb +++ b/app/assets/javascripts/initializers/initializeReadingListPage.js.erb @@ -1,7 +1,7 @@ function initializeReadingListPage(){ if ( getCurrentPage("reading_list_items-index") && checkUserLoggedIn() ) { client = algoliasearch('<%= ENV["ALGOLIASEARCH_APPLICATION_ID"] %>', '<%= ENV["ALGOLIASEARCH_SEARCH_ONLY_KEY"] %>'); - articlesIndex = client.initIndex('ordered_articles_<%= Rails.env %>'); + readinglistIndex = client.initIndex('ordered_articles_<%= Rails.env %>'); commentsIndex = client.initIndex('ordered_comments_<%= Rails.env %>'); var params = getQueryParams(document.location.search); document.getElementById('substories').dataset.tabs = '{"v": "'+(params.v || '')+'", "t": "'+(params.t || '')+'" }' @@ -22,7 +22,7 @@ function getArticles(tag, num){ var algoliaIds = user.reading_list_ids.map(function(id){return "articles-"+id}); var resultDivs = [] var tags = {} - articlesIndex.getObjects(algoliaIds, function(err, content) { + readinglistIndex.getObjects(algoliaIds, function(err, content) { var results = num ? content.results.slice(0, num) : content.results ; results.forEach(function(story, i){ if (story) { diff --git a/app/assets/javascripts/utilities/buildArticleHTML.js.erb b/app/assets/javascripts/utilities/buildArticleHTML.js.erb index 9b993423c..f3c064882 100644 --- a/app/assets/javascripts/utilities/buildArticleHTML.js.erb +++ b/app/assets/javascripts/utilities/buildArticleHTML.js.erb @@ -104,7 +104,7 @@ function buildArticleHTML(article) { '+searchSnippetHTML+'\ \ \ -

'+filterXSS(article.user.name)+'

\ +

'+filterXSS(article.user.name)+'・'+article.readable_publish_date+'

\
'+tagString+'
\ '+commentsCountHTML+reactionsCountHTML+'\ '+saveButton+''; diff --git a/app/assets/stylesheets/articles.scss b/app/assets/stylesheets/articles.scss index 468662b53..5f2038c9d 100644 --- a/app/assets/stylesheets/articles.scss +++ b/app/assets/stylesheets/articles.scss @@ -13,7 +13,7 @@ margin-top:22px; } &.sub-home{ - margin-top:25px; + margin-top:39px; .side-bar{ @media screen and ( min-width: 950px ){ margin-top:12px; @@ -83,6 +83,9 @@ &.on-page-nav-butt-right{ right: 3%; } + @media screen and ( min-width: 950px ){ + display:none; + } } .on-page-nav-label{ position:absolute; @@ -92,10 +95,55 @@ font-stretch:condensed; top:18px; font-weight:600; + &.sub-home-nav{ + top:12px; + } + .wide-nav-links{ + display: none; + } + @media screen and ( min-width: 650px ){ + .narrow-nav-select{ + display: none; + } + .wide-nav-links{ + display: block; + } + } + @media screen and ( min-width: 950px ){ + top:9px; + &.sub-home-nav{ + top:8px; + } + } } - - @media screen and ( min-width: 950px ){ - display:none; + .separator{ + border-left: 2px solid $light-medium-gray; + display: inline-block; + margin: 0px 7px; + height:15px; + } + .nav-chronofiter-link{ + display: inline-block; + padding: 2px 8px; + font-size:0.95em; + &.selected{ + background: $purple; + box-shadow: 3px 4px 0px darken($purple, 6%); + } + &:hover{ + opacity:1; + } + } + .narrow-nav-select{ + button { + all: unset; + background: transparent; + border:0; + font-family: $helvetica-condensed; + font-stretch:condensed; + font-weight:600; + cursor: pointer; + } } } a{ @@ -1203,6 +1251,35 @@ } } +.narrow-nav-menu{ + position:absolute; + top:40px; + left: 0; + right:0; + background: white; + z-index:500; + font-family: $helvetica-condensed; + font-stretch:condensed; + font-weight:600; + box-shadow: 0px 20px 50px rgba(0,0,0,0.3); + padding: 5px 0px 15px; + display: none; + font-size: 1.1em; + a{ + display: block; + text-align: center; + color: $black; + padding: 20px 0px; + &.selected { + background: $purple; + } + } + &.showing { + display: block; + } +} + + .load-more-cta{ margin: 35px auto; border: 0px; diff --git a/app/controllers/stories_controller.rb b/app/controllers/stories_controller.rb index 45b4b706f..5cf86afa4 100644 --- a/app/controllers/stories_controller.rb +++ b/app/controllers/stories_controller.rb @@ -82,25 +82,28 @@ class StoriesController < ApplicationController redirect_to "/t/#{@tag_model.alias_for}" return end + @stories = Article.where(published: true). + includes(:user). + limited_column_select. + page(@page). + per(8). + filter_excluded_tags(@tag) + if @tag_model && @tag_model.requires_approval - @stories = ArticleDecorator.decorate_collection(Article. - where(published: true, approved: true). - order("#{@tag_model.requires_approval ? "featured_number" : "hotness_score"} DESC"). - includes(:user). - limited_column_select. - page(@page). - per(8). - filter_excluded_tags(@tag)) - else - @stories = ArticleDecorator.decorate_collection(Article. - where(published: true). - order("hotness_score DESC"). - includes(:user). - limited_column_select. - page(@page). - per(user_signed_in? ? 4 : 10). - filter_excluded_tags(@tag)) + @stories = @stories.where(approved: true) end + + if ["week", "month", "year", "infinity"].include?(params[:timeframe]) + @stories = @stories.where("published_at > ?", Timeframer.new(params[:timeframe]).datetime). + order("positive_reactions_count DESC") + elsif params[:timeframe] == "latest" + @stories = @stories.order("published_at DESC") + else + @stories = @stories.order("hotness_score DESC") + end + + @stories = @stories.decorate + @featured_story = Article.new @article_index = true set_surrogate_key_header "articles-#{@tag}", @stories.map(&:record_key) @@ -112,17 +115,25 @@ class StoriesController < ApplicationController @home_page = true @page = (params[:page] || 1).to_i num_articles = user_signed_in? ? 3 : 15 - @stories = ArticleDecorator.decorate_collection(Article.where(published: true, featured: true). - order("hotness_score DESC"). + @stories = Article.where(published: true). includes(:user). limited_column_select. page(@page). per(num_articles). - filter_excluded_tags(params[:tag])) - @featured_story = Article.where(published: true, featured: true). - where.not(main_image: nil). - limited_column_select. - order("hotness_score DESC").first&.decorate || Article.new + filter_excluded_tags(params[:tag]) + if ["week", "month", "year", "infinity"].include?(params[:timeframe]) + @stories = @stories.where("published_at > ?", Timeframer.new(params[:timeframe]).datetime). + order("positive_reactions_count DESC") + @featured_story = @stories.where.not(main_image: nil).first&.decorate || Article.new + elsif params[:timeframe] == "latest" + @stories = @stories.order("published_at DESC"). + where("featured_number > ?", 1449999999) + @featured_story = Article.new + else + @stories = @stories.where(featured: true).order("hotness_score DESC") + @featured_story = @stories.where.not(main_image: nil).first&.decorate || Article.new + end + @stories = @stories.decorate @podcast_episodes = PodcastEpisode. includes(:podcast). order("published_at desc"). @@ -203,7 +214,6 @@ class StoriesController < ApplicationController end end - def handle_article_show @article_show = true @comment = Comment.new @@ -261,4 +271,5 @@ class StoriesController < ApplicationController find_by_slug(params[:slug])&. decorate end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a0045505b..85c517638 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -216,5 +216,17 @@ module ApplicationHelper }, ] colors[user.id % 10] - end + end + + def timeframe_check(given_timeframe) + params[:timeframe] == given_timeframe + end + + def list_path + if params[:tag].present? + "/t/#{params[:tag]}" + else + "" + end + end end diff --git a/app/labor/cache_buster.rb b/app/labor/cache_buster.rb index 13f8c3191..8904e8676 100644 --- a/app/labor/cache_buster.rb +++ b/app/labor/cache_buster.rb @@ -45,23 +45,61 @@ class CacheBuster if article.organization.present? bust("/#{article.organization.slug}") end + bust_home_pages(article) + bust_tag_pages(article) + + if article.collection + article.collection.articles.each do |a| + bust(a.path) + end + end + end + + def bust_home_pages(article) if article.featured_number.to_i > Time.now.to_i bust("/") bust("?i=i") end - begin + [[1.week.ago, "week"],[1.month.ago, "month"],[1.year.ago, "year"],[5.years.ago, "infinity"]].each do |timeframe| + if Article.where(published: true).where("published_at > ?", timeframe[0]). + order("positive_reactions_count DESC").limit(4).pluck(:id).include?(article.id) + bust("/top/#{timeframe[1]}") + bust("/top/#{timeframe[1]}?i=i") + bust("/top/#{timeframe[1]}/?i=i") + end + if Article.where(published: true).where("published_at > ?", timeframe[0]). + order("hotness_score DESC").limit(3).pluck(:id).include?(article.id) + bust("/") + bust("?i=i") + end + end + if article.published && article.published_at > 1.hour.ago + bust("/latest") + bust("/latest?i=i") + end + end + + def bust_tag_pages(article) + return unless article.published + article.tag_list.each do |tag| if article.published_at.to_i > 3.minutes.ago.to_i - article.tag_list.each do |tag| - bust("/t/#{tag}") + bust("/t/#{tag}/latest") + bust("/t/#{tag}/latest?i=i") + end + [[1.week.ago, "week"],[1.month.ago, "month"],[1.year.ago, "year"],[5.years.ago, "infinity"]]. + each do |timeframe| + if Article.where(published: true).where("published_at > ?", timeframe[0]).tagged_with(tag). + order("positive_reactions_count DESC").limit(3).pluck(:id).include?(article.id) + bust("/top/#{timeframe[1]}") + bust("/top/#{timeframe[1]}?i=i") + bust("/top/#{timeframe[1]}/?i=i") + end + if Article.where(published: true).where("published_at > ?", timeframe[0]).tagged_with(tag). + order("hotness_score DESC").limit(3).pluck(:id).include?(article.id) + bust("/") + bust("?i=i") end end - if article.collection - article.collection.articles.each do |a| - bust(a.path) - end - end - rescue - puts "Tag issue" end end end diff --git a/app/labor/hex_comparer.rb b/app/labor/hex_comparer.rb index fe603e5d9..3bd9a09a2 100644 --- a/app/labor/hex_comparer.rb +++ b/app/labor/hex_comparer.rb @@ -1,8 +1,9 @@ class HexComparer - attr_accessor :hexes - def initialize(hexes) + attr_accessor :hexes, :amount + def initialize(hexes, amount=1) @hexes = hexes + @amount = amount end def order @@ -23,26 +24,26 @@ class HexComparer "#%02x%02x%02x" % rgb rescue smallest - end + end end - def accent - if brightness(1.14).size == 7 - brightness(1.14) - elsif brightness(1.08).size == 7 - brightness(1.08) - elsif brightness(1.06).size == 7 - brightness(1.06) - elsif brightness(0.96).size == 7 - brightness(0.96) - elsif brightness(0.9).size == 7 - brightness(0.9) - elsif brightness(0.8).size == 7 - brightness(0.8) - elsif brightness(0.7).size == 7 - brightness(0.7) - elsif brightness(0.6).size == 7 - brightness(0.6) + def accent() + if brightness(1.14 ** amount).size == 7 + brightness(1.14 ** amount) + elsif brightness(1.08 ** amount).size == 7 + brightness(1.08 ** amount) + elsif brightness(1.06 ** amount).size == 7 + brightness(1.06 ** amount) + elsif brightness(0.96 ** amount).size == 7 + brightness(0.96 ** amount) + elsif brightness(0.9 ** amount).size == 7 + brightness(0.9 ** amount) + elsif brightness(0.8 ** amount).size == 7 + brightness(0.8 ** amount) + elsif brightness(0.7 ** amount).size == 7 + brightness(0.7 ** amount) + elsif brightness(0.6 ** amount).size == 7 + brightness(0.6 ** amount) end end diff --git a/app/labor/timeframer.rb b/app/labor/timeframer.rb new file mode 100644 index 000000000..7e8905c01 --- /dev/null +++ b/app/labor/timeframer.rb @@ -0,0 +1,22 @@ +class Timeframer + + attr_accessor :timeframe + def initialize(timeframe) + @timeframe = timeframe + end + + def datetime + if timeframe == "infinity" + 5.years.ago + elsif timeframe == "week" + 1.week.ago + elsif timeframe == "month" + 1.month.ago + elsif timeframe == "year" + 1.year.ago + elsif timeframe == "latest" + "latest" + end + end + +end \ No newline at end of file diff --git a/app/models/article.rb b/app/models/article.rb index 8489ecdff..1a6480e2c 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -57,7 +57,7 @@ class Article < ApplicationRecord :comments_count, :positive_reactions_count, :cached_tag_list, :main_image, :main_image_background_hex_color, :updated_at, :video, :user_id, :organization_id, :video_source_url, :video_code, - :video_thumbnail_url, :video_closed_caption_track_url) + :video_thumbnail_url, :video_closed_caption_track_url, :published_at) } scope :limited_columns_internal_select, -> { @@ -80,7 +80,7 @@ class Article < ApplicationRecord :featured, :published, :published_at, :featured_number, :comments_count, :reactions_count, :positive_reactions_count, :path, :class_name, :user_name, :user_username, :comments_blob, - :body_text, :tag_keywords_for_search, :search_score + :body_text, :tag_keywords_for_search, :search_score, :readable_publish_date attribute :user do { username: user.username, name: user.name, @@ -112,7 +112,8 @@ class Article < ApplicationRecord per_environment: true, enqueue: :trigger_delayed_index do attributes :title, :path, :class_name, :comments_count, - :tag_list, :positive_reactions_count, :id, :hotness_score + :tag_list, :positive_reactions_count, :id, :hotness_score, + :readable_publish_date attribute :user do { username: user.username, name: user.name, @@ -129,6 +130,12 @@ class Article < ApplicationRecord ("organization_#{organization_id}" if organization)].flatten.compact end ranking ["desc(hotness_score)"] + add_replica "ordered_articles_by_positive_reactions_count", inherit: true, per_environment: true do + ranking ["desc(positive_reactions_count)"] + end + add_replica "ordered_articles_by_published_at", inherit: true, per_environment: true do + ranking ["desc(published_at)"] + end end end @@ -143,13 +150,23 @@ class Article < ApplicationRecord end end - def self.active_discuss_threads(tag) - where(published:true). - where("published_at > ?", 7.days.ago). - tagged_with(["discuss", tag]). - order("last_comment_at DESC"). - limit(8). - pluck(:path, :title, :comments_count, :created_at) + def self.active_discuss_threads(tag=nil, time_ago=nil) + stories = where(published:true). + limit(8) + if time_ago == "latest" + stories = stories.order("published_at DESC") + elsif time_ago + stories = stories.order("comments_count DESC"). + where("published_at > ?", time_ago) + else + stories = stories.order("last_comment_at DESC"). + where("published_at > ?", (tag.present? ? 5 : 2).days.ago) + end + + stories = stories.tagged_with(["discuss", tag]) if tag + stories = stories.tagged_with("discuss") unless tag + + stories.pluck(:path, :title, :comments_count, :created_at) end def body_text @@ -264,9 +281,9 @@ class Article < ApplicationRecord def readable_publish_date if published_at && published_at.year == Time.now.year - published_at.strftime("%b %e") + published_at&.strftime("%b %e") else - published_at.strftime("%b %e '%y") + published_at&.strftime("%b %e '%y") end end diff --git a/app/views/articles/_sidebar.html.erb b/app/views/articles/_sidebar.html.erb index 2daf75e44..9827c6b37 100644 --- a/app/views/articles/_sidebar.html.erb +++ b/app/views/articles/_sidebar.html.erb @@ -257,81 +257,83 @@ <% elsif @podcast %> <% else %> - <%= render "articles/sidebar_nav" %> -
" id="sponsorship-widget"> -
- <COMMUNITY SPONSORS - " /> - > -
-
-