diff --git a/app/assets/javascripts/initializePage.js.erb b/app/assets/javascripts/initializePage.js.erb index 575dc4b3785d..ff7d34f945ea 100644 --- a/app/assets/javascripts/initializePage.js.erb +++ b/app/assets/javascripts/initializePage.js.erb @@ -32,7 +32,6 @@ function callInitalizers(){ initNotifications(); initializeSplitTestTracking(); initializeStylesheetAppend(); - initializeAnalytics(); initializeCommentDropdown(); initializeSettings(); initializeFooterMod(); diff --git a/app/assets/javascripts/initializers/initializeAnalytics.js b/app/assets/javascripts/initializers/initializeAnalytics.js deleted file mode 100644 index aaff7ec04dab..000000000000 --- a/app/assets/javascripts/initializers/initializeAnalytics.js +++ /dev/null @@ -1,32 +0,0 @@ -function initializeAnalytics() { - if (getCurrentPage("dashboards-show")) { - var els = document.querySelectorAll('[data-analytics-pageviews]'); - if (els.length === 0) { return; } - var ids = []; - for(var i = 0; i < els.length; i++) { - ids.push(els[i].dataset.articleId) - } - // .map(function() {return this.dataset.reactableId}); - window.fetch('/analytics?article_ids='+ids.join(","), {headers: {Accept: 'application/json'}, credentials: 'same-origin'}) - .then(function(response) { - response.json().then(function(json) { - var total = 0; - for (var k in json){ - total = total + Number(json[k]); - var numString = parseInt(json[k]) < 100 ? "< 100 " : numberWithCommas(json[k]) ; - var totalString = parseInt(total) < 100 ? "< 100 " : numberWithCommas(total) ; - document.getElementById("pageviews-"+k).innerHTML = numString + " Views"; - document.getElementById("pageviews-"+k).classList.add("loaded"); - document.getElementById("dashboard-analytics").innerHTML = totalString+ " Total Views"; - } - document.getElementById("dashboard-analytics-header").classList.add("loaded"); - }); - }).catch(function(err) { - console.log(err); - }); - } -} - -function numberWithCommas(x) { - return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); -} diff --git a/app/assets/stylesheets/dashboard.scss b/app/assets/stylesheets/dashboard.scss index 0a30ef3a5e04..2c49b176ff32 100644 --- a/app/assets/stylesheets/dashboard.scss +++ b/app/assets/stylesheets/dashboard.scss @@ -6,18 +6,21 @@ max-width:96%; margin:auto; h1{ - font-size:30px; + font-size:22px; font-family: $helvetica-condensed; font-stretch:condensed; padding-bottom: 20px; a{ - padding: 0px 20px; - border-radius: 3px; + padding: 6px 25px; + border-radius: 100px; margin-right: 18px; display: inline-block; color: $black; + &:hover{ + background: lighten($light-medium-gray, 3%); + } &.active{ - background: $black; + background: $dark-gray; color:white; } } @@ -70,39 +73,49 @@ .dashboard-analytics-header-wrapper{ text-align: center; margin-bottom: 28px; + background: $dark-gray; + box-shadow: $bold-shadow; + padding: 15px 0px; } .dashboard-analytics-header{ - color:$black; + color: white; margin:5px auto; - font-size:calc(0.77em + 0.22vw); - padding: 20px 0px; + font-size:calc(1.1em + 0.1vw); + padding: 18px 0px 7px; padding-left: 10px; text-align: left; font-family: $monospace; - border-radius: 200px; - border: 1px solid $light-medium-gray; - box-shadow: $bold-shadow; + // border-radius: 200px; + border: 1px solid $light-gray; + // box-shadow: $bold-shadow; display: inline-block; width: 90%; + text-align: center; margin: 1.1%; @media screen and ( min-width: 800px ) { width: 43%; margin: 1.2%; } span{ - opacity:0.3; + font-size: 1.8em; + font-weight: bold; + margin-left: 8px; + display: inline-block; } img{ - width: calc(0.9em + 1.2vw); - height: calc(0.9em + 1.2vw); - margin-right: 0.4em; - margin-left: 1.1em; - vertical-align: calc(-0.6vw - 2px); - } - &.loaded{ - span{ - opacity:1; - } + width: calc(1.2em + 0.2vw); + height: calc(1.2em + 0.2vw); + margin-left: 0.4em; + vertical-align: calc(-0.2vw - 0.3em); + background: $sky-blue; + border-radius: 100px; + border: 2px solid darken($light-gray, 7%); + } + .dashboard-analytics-sub-indicator{ + color: darken($light-gray, 7%); + padding: 10px 0px; + font-weight: bold; + font-size:0.66em; } } @@ -152,7 +165,7 @@ color:rgb(67, 78, 87); } .dashboard-actions{ - padding: 8px 0px; + padding: 5px 0px; } .pill{ background:$bold-blue; @@ -173,22 +186,16 @@ background:$red; } &.black{ - background: $black; + background: $dark-gray; } } .dashboard-pageviews-indicator{ display:inline-block; font-family: $monospace; - color: $black; + color: $dark-gray; background: white; text-align:center; - opacity:0.4; - height: 23px; - line-height: 22px; padding: 2px 8px; - &.loaded{ - opacity:1; - } } form{ padding: 10px 0px; @@ -241,4 +248,4 @@ min-height: 350px; } } -} +} \ No newline at end of file diff --git a/app/black_box/google_analytics.rb b/app/black_box/google_analytics.rb index 2c88af89b36f..6a32c6bfbec7 100644 --- a/app/black_box/google_analytics.rb +++ b/app/black_box/google_analytics.rb @@ -72,8 +72,6 @@ def fetch_analytics_for(*report_requests) grr = GetReportsRequest.new(report_requests: report_requests, quota_user: @user_id.to_s) response = @client.batch_get_reports(grr) response.reports.map do |report| - p report.data - p report.data (report.data.maximums || report.data.totals)[0].values[0] end end @@ -84,4 +82,4 @@ def create_service_account_credential scope: [AUTH_ANALYTICS_READONLY], ) end -end +end \ No newline at end of file diff --git a/app/controllers/analytics_controller.rb b/app/controllers/analytics_controller.rb deleted file mode 100644 index 0300813acf01..000000000000 --- a/app/controllers/analytics_controller.rb +++ /dev/null @@ -1,58 +0,0 @@ -class AnalyticsController < ApplicationController - caches_action :index, - cache_path: Proc.new { "#{request.params}___#{current_user.id}" }, - expires_in: 12.minutes - after_action :verify_authorized - - def index - @article_ids = analytics_params.split(",") - articles_to_check = Article.where(id: @article_ids) - authorize articles_to_check, :analytics_index? - - qualified_articles = get_articles_that_qualify(articles_to_check) - fetch_and_update_page_views_and_reaction_counts(qualified_articles) - - render_finalized_json - end - - def get_articles_that_qualify(articles_to_check) - qualified_articles = [] - articles_to_check.each do |article| - if should_fetch(article) - qualified_articles << article - end - end - qualified_articles - end - - def fetch_and_update_page_views_and_reaction_counts(qualified_articles) - qualified_articles.each_slice(25).to_a.each do |chunk| - pageviews = GoogleAnalytics.new(chunk.pluck(:id), current_user.id).get_pageviews - page_views_obj = pageviews.to_h - chunk.each do |article| - next if article.page_views_count > page_views_obj[article.id].to_i - article.update_columns(page_views_count: page_views_obj[article.id].to_i, - previous_positive_reactions_count: article.positive_reactions_count) - end - end - end - - def render_finalized_json - finalized_object = {} - Article.where(id: @article_ids). - pluck(:id, :page_views_count).map { |a| finalized_object[a[0]] = a[1].to_s } - render json: finalized_object.to_json - end - - def should_fetch(article) - new_reactions = (article.positive_reactions_count > article.previous_positive_reactions_count) - random = (rand(80) == 1) - new_reactions || random - end - - private - - def analytics_params - params.require(:article_ids) - end -end diff --git a/app/controllers/async_info_controller.rb b/app/controllers/async_info_controller.rb index 1227264afbe1..8a14d3cafef9 100644 --- a/app/controllers/async_info_controller.rb +++ b/app/controllers/async_info_controller.rb @@ -17,6 +17,8 @@ def base_data remember_me(current_user) end @user = current_user.decorate + # Updates article analytics periodically: + ArticleAnalyticsFetcher.new.delay.update_analytics(@user.id) if rand(20) == 1 respond_to do |format| format.json do render json: { @@ -60,4 +62,4 @@ def user_cache_key #{current_user&.articles_count}__ #{cookies[:remember_user_token]}" end -end +end \ No newline at end of file diff --git a/app/controllers/dashboards_controller.rb b/app/controllers/dashboards_controller.rb index 915082532b08..b5cf9cda6127 100644 --- a/app/controllers/dashboards_controller.rb +++ b/app/controllers/dashboards_controller.rb @@ -16,10 +16,15 @@ def show elsif params[:which] == "user_followers" @follows = Follow.where(followable_id: @user.id, followable_type: "User"). includes(:follower).order("created_at DESC").limit(80) + elsif params[:which] == "organization_user_followers" + @follows = Follow.where(followable_id: @user.organization_id, followable_type: "Organization"). + includes(:follower).order("created_at DESC").limit(80) elsif @user&.organization && @user&.org_admin && params[:which] == "organization" @articles = @user.organization.articles.order("created_at DESC").decorate elsif @user @articles = @user.articles.order("created_at DESC").decorate end + # Updates analytics in background if appropriate: + ArticleAnalyticsFetcher.new.delay.update_analytics(current_user.id) if @articles end -end +end \ No newline at end of file diff --git a/app/labor/article_analytics_fetcher.rb b/app/labor/article_analytics_fetcher.rb new file mode 100644 index 000000000000..8982dd8d7710 --- /dev/null +++ b/app/labor/article_analytics_fetcher.rb @@ -0,0 +1,34 @@ +class ArticleAnalyticsFetcher + def update_analytics(user_id) + articles_to_check = Article.where(user_id: user_id, published: true) + qualified_articles = get_articles_that_qualify(articles_to_check) + return if qualified_articles.none? + fetch_and_update_page_views_and_reaction_counts(qualified_articles, user_id) + end + + def fetch_and_update_page_views_and_reaction_counts(qualified_articles, user_id) + qualified_articles.each_slice(15).to_a.each do |chunk| + pageviews = GoogleAnalytics.new(chunk.pluck(:id), user_id).get_pageviews + page_views_obj = pageviews.to_h + chunk.each do |article| + article.update_columns(previous_positive_reactions_count: article.positive_reactions_count) + next if article.page_views_count > page_views_obj[article.id].to_i + article.update_columns(page_views_count: page_views_obj[article.id].to_i) + end + end + end + + def get_articles_that_qualify(articles_to_check) + qualified_articles = [] + articles_to_check.each do |article| + if should_fetch(article) + qualified_articles << article + end + end + qualified_articles + end + + def should_fetch(article) + article.positive_reactions_count > article.previous_positive_reactions_count + end +end \ No newline at end of file diff --git a/app/views/dashboards/_analytics.html.erb b/app/views/dashboards/_analytics.html.erb new file mode 100644 index 000000000000..a088c234babc --- /dev/null +++ b/app/views/dashboards/_analytics.html.erb @@ -0,0 +1,18 @@ +<% num_views = @articles.sum(&:page_views_count) %> + +