diff --git a/app/assets/javascripts/initializePage.js.erb b/app/assets/javascripts/initializePage.js.erb index ac7fda265..f5e91a7ed 100644 --- a/app/assets/javascripts/initializePage.js.erb +++ b/app/assets/javascripts/initializePage.js.erb @@ -28,6 +28,7 @@ function callInitalizers(){ initializeCommentsPage(); initEditorResize(); initLeaveEditorWarning(); + initializeArticleDate(); initializeArticleReactions(); initNotifications(); initializeSplitTestTracking(); diff --git a/app/assets/javascripts/initializers/initializeArticleDate.js b/app/assets/javascripts/initializers/initializeArticleDate.js new file mode 100644 index 000000000..eaf52f5f0 --- /dev/null +++ b/app/assets/javascripts/initializers/initializeArticleDate.js @@ -0,0 +1,10 @@ +/* Show article date/time according to user's locale */ +/* global addLocalizedDateTimeToElementsTitles */ + +function initializeArticleDate() { + var articlesDates = document.querySelectorAll( + '.single-article time, article time, .single-other-article time', + ); + + addLocalizedDateTimeToElementsTitles(articlesDates, 'datetime'); +} diff --git a/app/assets/javascripts/initializers/initializeCommentDate.js b/app/assets/javascripts/initializers/initializeCommentDate.js index f9c871ea6..f7e201a10 100644 --- a/app/assets/javascripts/initializers/initializeCommentDate.js +++ b/app/assets/javascripts/initializers/initializeCommentDate.js @@ -1,50 +1,8 @@ /* Show comment date/time according to user's locale */ -/* global timestampToLocalDateTime */ +/* global addLocalizedDateTimeToElementsTitles */ function initializeCommentDate() { - // example: "Wednesday, April 3, 2019, 2:55:14 PM" - var hoverTimeOptions = { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric', - hour: 'numeric', - minute: 'numeric', - second: 'numeric', - }; + var commentsDates = document.querySelectorAll('.comment-date time'); - // example: "Apr 3" - var visibleDateOptions = { - month: 'short', - day: 'numeric', - }; - - var commentDates = document.getElementsByClassName('comment-date'); - for (var i = 0; i < commentDates.length; i += 1) { - // get UTC timestamp set by the server - var ts = commentDates[i].getAttribute('data-published-timestamp'); - - // add a full datetime to the comment date string, visible on hover - // `navigator.language` is used for full date times to allow the hover date - // to be localized according to the user's locale - var hoverTime = timestampToLocalDateTime( - ts, - navigator.language, - hoverTimeOptions, - ); - commentDates[i].setAttribute('title', hoverTime); - - // replace the comment short visible date with the equivalent localized one - var visibleDate = commentDates[i].querySelector('a'); - if (visibleDate) { - var localVisibleDate = timestampToLocalDateTime( - ts, - 'en-US', // en-US because for now we want all users to see `Apr 3` - visibleDateOptions, - ); - if (localVisibleDate) { - visibleDate.innerHTML = localVisibleDate; - } - } - } + addLocalizedDateTimeToElementsTitles(commentsDates, 'datetime'); } diff --git a/app/assets/javascripts/utilities/buildArticleHTML.js.erb b/app/assets/javascripts/utilities/buildArticleHTML.js.erb index d8f525070..31ba2921c 100644 --- a/app/assets/javascripts/utilities/buildArticleHTML.js.erb +++ b/app/assets/javascripts/utilities/buildArticleHTML.js.erb @@ -90,7 +90,11 @@ function buildArticleHTML(article) { var publishDate = ''; if (article.readable_publish_date) { - publishDate = '・'+article.readable_publish_date + if (article.published_timestamp) { + publishDate = '・' + ''; + } else { + publishDate = '・' + ''; + } } var readingTimeHTML = ''; if (article.reading_time && article.class_name === "Article") { diff --git a/app/assets/javascripts/utilities/buildCommentHTML.js.erb b/app/assets/javascripts/utilities/buildCommentHTML.js.erb index 8156ff29e..5748ac56c 100644 --- a/app/assets/javascripts/utilities/buildCommentHTML.js.erb +++ b/app/assets/javascripts/utilities/buildCommentHTML.js.erb @@ -43,8 +43,12 @@ function buildCommentHTML(comment) { \ '+twitterIcon+'\ '+githubIcon+'\ -
\ - '+comment.readable_publish_date+'\ +
\ + \ + \ + \
\
diff --git a/app/views/articles/_single_story.html.erb b/app/views/articles/_single_story.html.erb index c2fd2df39..a6359592b 100644 --- a/app/views/articles/_single_story.html.erb +++ b/app/views/articles/_single_story.html.erb @@ -27,8 +27,10 @@

- <%= story.cached_user.name %>・<%= story.readable_publish_date %> - + + <%= story.cached_user.name %>・ + +

<% story.cached_tag_list_array.each do |tag| %> diff --git a/app/views/articles/index.html.erb b/app/views/articles/index.html.erb index eee3a6405..ca8a71337 100644 --- a/app/views/articles/index.html.erb +++ b/app/views/articles/index.html.erb @@ -31,7 +31,9 @@ data-algolia-tag="" data-feed="<%= params[:timeframe] || "base-feed" %>" data-articles-since="<%= Timeframer.new(params[:timeframe]).datetime.to_i %>"> + <%= render "articles/sidebar" %> +
@@ -80,10 +82,12 @@ " alt="right-sidebar-nav">
+ <% if @home_page %> <% @featured_story ||= @stories.where.not(main_image: nil).first&.decorate || Article.new %> <% @stories = @stories.decorate %> - <% end %> + <% end %> + <% if @featured_story.id %>
<%= @featured_story.title %> @@ -98,8 +102,12 @@ <%= @featured_story.title %> - + <% end %> +
+
<% if @stories.any? %> <%= render "stories/main_stories_feed" %> <% end %>
+
loading...
+ <%= render "articles/sidebar_additional" %>
diff --git a/app/views/articles/show.html.erb b/app/views/articles/show.html.erb index f1af1abb7..8e20d1b79 100644 --- a/app/views/articles/show.html.erb +++ b/app/views/articles/show.html.erb @@ -127,7 +127,9 @@ <% if @user.github_username.present? %> <%= image_tag_or_inline_svg "github" %> <% end %> - + <% if @article.published_timestamp.present? %> + + <% end %> <% if @second_user.present? %> with <%= @second_user.name %> <% end %> @@ -135,14 +137,16 @@ and <%= @third_user.name %> <% end %> <% if should_show_updated_on?(@article) %> - Updated on <%= @article.edited_at&.strftime("%b %d, %Y") %> + Updated on <% elsif should_show_crossposted_on?(@article) %> - + Originally published at <%= get_host_without_www(@article.canonical_url || @article.feed_source_url) %> on - <%= (@article.originally_published_at || @article.published_at).strftime("%b %d, %Y") if @article.crossposted_at %> + <% if @article.crossposted_at %> + + <% end %> <% end %> diff --git a/app/views/comments/_comment_date.erb b/app/views/comments/_comment_date.erb new file mode 100644 index 000000000..241e4d122 --- /dev/null +++ b/app/views/comments/_comment_date.erb @@ -0,0 +1,7 @@ + diff --git a/app/views/comments/_comment_proper.html.erb b/app/views/comments/_comment_proper.html.erb index a5dce38f6..df1f614aa 100644 --- a/app/views/comments/_comment_proper.html.erb +++ b/app/views/comments/_comment_proper.html.erb @@ -47,9 +47,7 @@ <% if commentable_author_is_op?(commentable, comment) %> <%= get_ama_or_op_banner(commentable) %> <% end %> - + <%= render "comments/comment_date", decorated_comment: decorated_comment %> diff --git a/app/views/comments/_liquid.html.erb b/app/views/comments/_liquid.html.erb index 27886835f..f29a580ac 100644 --- a/app/views/comments/_liquid.html.erb +++ b/app/views/comments/_liquid.html.erb @@ -1,24 +1,22 @@
- <%= comment.user.username %> profile image + <%= comment.user.username %> profile image <%= comment.user.name %> <% if comment.user.twitter_username.present? %> - twitter + twitter <% end %> <% if comment.user.github_username.present? %> - github + github <% end %> - + <%= render "comments/comment_date", decorated_comment: comment.decorate %>
<%= comment.processed_html.html_safe %> diff --git a/app/views/stories/_main_stories_feed.html.erb b/app/views/stories/_main_stories_feed.html.erb index d3e06b3ac..04340d3de 100644 --- a/app/views/stories/_main_stories_feed.html.erb +++ b/app/views/stories/_main_stories_feed.html.erb @@ -14,7 +14,8 @@ reading_time video_thumbnail_url video video_duration_in_minutes language experience_level_rating experience_level_rating_distribution cached_user cached_organization], methods: %i[readable_publish_date cached_tag_list_array flare_tag class_name - cloudinary_video_url video_duration_in_minutes published_at_int], + cloudinary_video_url video_duration_in_minutes published_at_int + published_timestamp], ) %>">
<% 3.times do %>
diff --git a/app/views/users/_comments_section.html.erb b/app/views/users/_comments_section.html.erb index 157498233..e591502d7 100644 --- a/app/views/users/_comments_section.html.erb +++ b/app/views/users/_comments_section.html.erb @@ -29,7 +29,9 @@
"> re: <%= comment.commentable.title %> - <%= comment.readable_publish_date %> + + +
<%= truncate(strip_tags(comment.processed_html), length: 64).html_safe %>
diff --git a/spec/models/article_spec.rb b/spec/models/article_spec.rb index 71cf00025..7e41a5b1b 100644 --- a/spec/models/article_spec.rb +++ b/spec/models/article_spec.rb @@ -507,5 +507,31 @@ RSpec.describe Article, type: :model do end end + describe "published_timestamp" do + it "returns empty string if the article is new" do + expect(Article.new.published_timestamp).to eq("") + end + + it "returns empty string if the article is not published" do + article.update_column(:published, false) + expect(article.published_timestamp).to eq("") + end + + it "returns the timestamp of the crossposting date over the publishing date" do + crossposted_at = 1.week.ago + published_at = 1.day.ago + article.update_columns( + published: true, crossposted_at: crossposted_at, published_at: published_at, + ) + expect(article.published_timestamp).to eq(crossposted_at.utc.iso8601) + end + + it "returns the timestamp of the publishing date if there is no crossposting date" do + published_at = 1.day.ago + article.update_columns(published: true, crossposted_at: nil, published_at: published_at) + expect(article.published_timestamp).to eq(published_at.utc.iso8601) + end + end + include_examples "#sync_reactions_count", :article end diff --git a/spec/system/articles/user_visits_an_article_spec.rb b/spec/system/articles/user_visits_an_article_spec.rb index 6d0ef5405..7c409af61 100644 --- a/spec/system/articles/user_visits_an_article_spec.rb +++ b/spec/system/articles/user_visits_an_article_spec.rb @@ -5,11 +5,9 @@ RSpec.describe "Views an article", type: :system do let(:dir) { "../../support/fixtures/sample_article.txt" } let(:template) { File.read(File.join(File.dirname(__FILE__), dir)) } let!(:article) do - create(:article, - user_id: user.id, - body_markdown: template.gsub("false", "true"), - body_html: "") + create(:article, user_id: user.id, body_markdown: template.gsub("false", "true"), body_html: "") end + let!(:timestamp) { "2019-03-04T10:00:00Z" } before do sign_in user @@ -25,4 +23,21 @@ RSpec.describe "Views an article", type: :system do visit "/#{user.username}/#{article.slug}" expect(page).to have_selector(".single-comment-node", visible: true, count: 3) end + + context "when showing the date" do + before do + article.update_column(:published_at, Time.zone.parse(timestamp)) + end + + it "shows the readable publish date" do + visit "/#{user.username}/#{article.slug}" + expect(page).to have_selector("article time", text: "Mar 4") + end + + it "embeds the published timestamp" do + visit "/#{user.username}/#{article.slug}" + selector = "article time[datetime='#{timestamp}']" + expect(page).to have_selector(selector) + end + end end diff --git a/spec/system/comments/user_views_a_comment_spec.rb b/spec/system/comments/user_views_a_comment_spec.rb index 378771588..414516c9a 100644 --- a/spec/system/comments/user_views_a_comment_spec.rb +++ b/spec/system/comments/user_views_a_comment_spec.rb @@ -18,11 +18,11 @@ RSpec.describe "Viewing a comment", type: :system, js: true do context "when showing the date" do it "shows the readable publish date" do - expect(page).to have_selector(".comment-date", text: "Mar 4") + expect(page).to have_selector(".comment-date time", text: "Mar 4") end it "embeds the published timestamp" do - selector = ".comment-date[data-published-timestamp='#{timestamp}']" + selector = ".comment-date time[datetime='#{timestamp}']" expect(page).to have_selector(selector) end end diff --git a/spec/system/homepage/user_visits_homepage_articles_spec.rb b/spec/system/homepage/user_visits_homepage_articles_spec.rb index c5112ee6a..d76005e40 100644 --- a/spec/system/homepage/user_visits_homepage_articles_spec.rb +++ b/spec/system/homepage/user_visits_homepage_articles_spec.rb @@ -5,21 +5,52 @@ RSpec.describe "User visits a homepage", type: :system do let!(:article2) { create(:article, reactions_count: 20, featured: true) } let!(:bad_article) { create(:article, reactions_count: 0) } let!(:user) { create(:user) } + let!(:timestamp) { "2019-03-04T10:00:00Z" } context "when no options specified" do - before { visit "/" } + context "when main featured article" do + before do + article.update_column(:published_at, Time.zone.parse(timestamp)) + article2.update_column(:published_at, Time.zone.parse(timestamp)) + visit "/" + end - it "shows the main article" do - expect(page).to have_selector(".big-article", visible: true) + it "shows the main article" do + expect(page).to have_selector(".big-article", visible: true) + end + + it "shows the main article readable date" do + expect(page).to have_selector(".big-article time", text: "Mar 4") + end + + it "embeds the main article published timestamp" do + selector = ".big-article time[datetime='#{timestamp}']" + expect(page).to have_selector(selector) + end end - it "shows correct articles" do - article.update_column(:score, 15) - article2.update_column(:score, 15) - expect(page).to have_selector(".single-article", count: 2) - expect(page).to have_text(article.title) - expect(page).to have_text(article2.title) - expect(page).not_to have_text(bad_article.title) + context "when all other articles" do + before do + article.update_columns(score: 15, published_at: Time.zone.parse(timestamp)) + article2.update_columns(score: 15, published_at: Time.zone.parse(timestamp)) + visit "/" + end + + it "shows correct articles" do + expect(page).to have_selector(".single-article", count: 2) + expect(page).to have_text(article.title) + expect(page).to have_text(article2.title) + expect(page).not_to have_text(bad_article.title) + end + + it "shows all articles dates" do + expect(page).to have_selector(".single-article time", text: "Mar 4", count: 2) + end + + it "embeds all articles published timestamps" do + selector = ".single-article time[datetime='#{timestamp}']" + expect(page).to have_selector(selector, count: 2) + end end end diff --git a/spec/system/user/view_user_index_spec.rb b/spec/system/user/view_user_index_spec.rb index 666198dd3..51c48d1ef 100644 --- a/spec/system/user/view_user_index_spec.rb +++ b/spec/system/user/view_user_index_spec.rb @@ -52,7 +52,7 @@ RSpec.describe "User index", type: :system do it "embeds comment timestamp" do within("#substories .index-comments .single-comment") do ts = comment.decorate.published_timestamp - timestamp_selector = ".comment-date[data-published-timestamp='#{ts}']" + timestamp_selector = ".comment-date time[datetime='#{ts}']" expect(page).to have_selector(timestamp_selector) end end