* Add delayed behavior * Add special behavior to billboards * Fix order for test * Test clicking outside element when close event is present * Update app/javascript/packs/billboardAfterRenderActions.js
248 lines
13 KiB
Text
248 lines
13 KiB
Text
<% title @article.title_with_query_preamble(user_signed_in?) %>
|
|
|
|
<%= render "shared/payment_pointer", user: @article.user %>
|
|
|
|
<style>
|
|
.html-variant-wrapper { display: none}
|
|
</style>
|
|
|
|
<%= render "shared/webcomponents_loader_script" %>
|
|
<% if user_signed_in? %>
|
|
<%= javascript_include_tag "webShare", "articlePage", "articleModerationTools", "commentDropdowns", defer: true %>
|
|
<% else %>
|
|
<%= javascript_include_tag "webShare", "articlePage", "commentDropdowns", defer: true %>
|
|
<% end %>
|
|
|
|
<% cache("content-related-optional-scripts-#{@article.id}-#{@article.updated_at}-#{internal_navigation?}-#{user_signed_in?}", expires_in: 30.hours) do %>
|
|
<% unless internal_navigation? || user_signed_in? %>
|
|
<script type="application/ld+json">
|
|
<%= @article_json_ld.to_json.html_safe %>
|
|
</script>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<% if internal_navigation? %>
|
|
<!-- You may be seeing the canonical URL in the body for human inspection -->
|
|
<!-- This is because of navigation via InstantClick, instantclick.io -->
|
|
<!-- However, the crawled version of the page has the canonical in the head. -->
|
|
<!-- This is confirmed by the canonical url inspector. See https://github.com/forem/forem/issues/9509#issuecomment-732259221. -->
|
|
<link rel="canonical" href="<%= @article.canonical_url.presence || app_url(@article.path) %>" />
|
|
<meta name="description" content="<%= @article.description_and_tags %>">
|
|
<%= meta_keywords_article(@article.cached_tag_list) %>
|
|
<% else %>
|
|
<%= content_for :page_meta do %>
|
|
<link rel="canonical" href="<%= @article.canonical_url.presence || app_url(@article.path) %>" />
|
|
<meta name="description" content="<%= @article.description_and_tags %>">
|
|
<%= meta_keywords_article(@article.cached_tag_list) %>
|
|
|
|
<meta property="og:type" content="article" />
|
|
<meta property="og:url" content="<%= article_url(@article) %>" />
|
|
<meta property="og:title" content="<%= @article.title %>" />
|
|
<meta property="og:description" content="<%= @article.description || t("views.articles.meta.description") %>" />
|
|
<meta property="og:site_name" content="<%= community_name %>" />
|
|
<meta name="twitter:site" content="@<%= Settings::General.social_media_handles["twitter"] %>">
|
|
<meta name="twitter:creator" content="@<%= @user.twitter_username %>">
|
|
<meta name="twitter:title" content="<%= @article.title %>">
|
|
<meta name="twitter:description" content="<%= @article.description || t("views.articles.meta.description") %>">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:widgets:new-embed-design" content="on">
|
|
<meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1">
|
|
<% if @article.published %>
|
|
<meta property="og:image" content="<%= article_social_image_url(@article) %>" />
|
|
<meta name="twitter:image:src" content="<%= article_social_image_url(@article) %>">
|
|
<% end %>
|
|
<% if @article.skip_indexing? %>
|
|
<meta name="robots" content="noindex">
|
|
<meta name="robots" content="nofollow">
|
|
<% end %>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<div class="crayons-layout crayons-layout--3-cols crayons-layout--article">
|
|
<aside class="crayons-layout__sidebar-left" aria-label="<%= t("views.articles.actions.aria_label") %>">
|
|
<%= render "articles/actions" %>
|
|
</aside>
|
|
|
|
<main id="main-content" class="crayons-layout__content grid gap-4">
|
|
<div class="article-wrapper">
|
|
<% unless @article.current_state.published? %>
|
|
<div class="crayons-notice crayons-notice--danger mb-4" aria-live="polite">
|
|
<strong><%= t("views.articles.#{@article.current_state}.subtitle") %></strong><%= t("views.articles.#{@article.current_state}.text") %>
|
|
<% if user_signed_in? %>
|
|
<a id="author-click-to-edit" href="<%= @article.path %>/edit" class="fw-bold" style="display: none;"><%= t("views.articles.#{@article.current_state}.edit") %></a>
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
|
|
<% if @article.video_state == "PROGRESSING" %>
|
|
<div class="crayons-notice crayons-notice--warning mb-4" aria-live="polite"><%= t("views.editor.video.progress.heading") %></div>
|
|
<% end %>
|
|
|
|
<article class="crayons-card crayons-article mb-4"
|
|
id="article-show-container"
|
|
data-article-id="<%= @article.id %>"
|
|
data-article-slug="<%= @article.slug %>"
|
|
data-author-id="<%= @article.user_id %>"
|
|
data-author-name="<%= @article.cached_user_name %>"
|
|
data-author-username="<%= @article.username %>"
|
|
data-co-author-ids="<%= @article.co_author_ids.join(",") %>"
|
|
data-path="<%= @article.path %>"
|
|
data-pin-path="<%= stories_feed_pinned_article_path %>"
|
|
data-pinned-article-id="<%= @pinned_article_id %>"
|
|
data-published="<%= @article.published? %>"
|
|
data-scheduled="<%= @article.scheduled? %>"
|
|
<%= @article.language? ? "lang=#{@article.language}" : " " %>
|
|
<%= @article.pinned? ? "data-pinned" : " " %>>
|
|
<header class="crayons-article__header" id="main-title">
|
|
<% if @article.video.present? %>
|
|
<%= render "articles/video_player", meta_tags: true, article: @article %>
|
|
<% elsif @article.main_image.present? %>
|
|
<a class="crayons-article__cover" href="<%= cloud_cover_url(@article.main_image) %>">
|
|
<img
|
|
src="<%= cloud_cover_url(@article.main_image) %>"
|
|
style="aspect-ratio: auto 1000 / <%= @article.main_image_height %>;"
|
|
width="1000" height="<%= @article.main_image_height %>"
|
|
class="crayons-article__cover__image" alt="Cover image for <%= @article.title %>">
|
|
</a>
|
|
<% end %>
|
|
|
|
<div class="crayons-article__header__meta">
|
|
<div class="flex s:items-start flex-col s:flex-row">
|
|
<div id="action-space" class="crayons-article__actions mb-4 s:mb-0 s:order-last"></div>
|
|
<div class="flex flex-1 mb-5 items-start">
|
|
<div class="relative">
|
|
<% if @organization %>
|
|
<a href="<%= @organization.path %>"><img src="<%= @organization.profile_image_url_for(length: 50) %>" class="radius-default align-middle" width="40" height="40" alt="<%= @organization.name %> profile image"></a>
|
|
<a href="/<%= @user.username %>" class="absolute -right-2 -bottom-2 radius-full border border-solid border-2 border-base-inverted inline-flex">
|
|
<img class="radius-full align-middle" src="<%= @user.profile_image_url_for(length: 50) %>" width="24" height="24" alt="<%= @user.name %>" />
|
|
</a>
|
|
<% else %>
|
|
<a href="/<%= @user.username %>"><img class="radius-full align-middle" src="<%= @user.profile_image_url_for(length: 50) %>" width="40" height="40" alt="<%= @user.name %>" /></a>
|
|
<% end %>
|
|
</div>
|
|
<div class="pl-3 flex-1">
|
|
<a href="/<%= @user.username %>" class="crayons-link fw-bold"><%= @user.name %></a>
|
|
<% if @organization %>
|
|
<%= t("views.articles.for_org_html",
|
|
start: tag("span", { class: "color-base-60" }, true),
|
|
end: "</span>".html_safe,
|
|
org: tag.a(@organization.name, href: @organization.path, class: "crayons-link")) %>
|
|
<% end %>
|
|
<p class="fs-xs color-base-60">
|
|
<% if @article.published_timestamp.present? %>
|
|
<%= t("views.articles.#{@article.current_state}_html", date: local_date(@article.published_timestamp, show_year: @article.displayable_published_at.year != Time.current.year)) %>
|
|
<% end %>
|
|
<% if @article.co_author_ids.present? %>
|
|
<%= t("views.articles.co_authors_html", names: @article.co_author_name_and_path.html_safe) %>
|
|
<% end %>
|
|
|
|
<% if should_show_updated_on?(@article) %>
|
|
• <%= t("views.articles.edited_html", date: local_date(@article.edited_at, show_year: @article.edited_at.year != Time.current.year)) %>
|
|
<% end %>
|
|
|
|
<% if should_show_crossposted_on?(@article) %>
|
|
• <%= t("views.articles.crossposted.text_html",
|
|
url: link_to(get_host_without_www(@article.canonical_url || @article.feed_source_url), @article.canonical_url || @article.feed_source_url, style: "color:#1395b8"),
|
|
on: if @article.crossposted_at
|
|
t("views.articles.crossposted.on_html",
|
|
date: local_date(@article.originally_published_at || @article.published_at, show_year: (@article.originally_published_at || @article.published_at).year != Time.current.year))
|
|
else
|
|
""
|
|
end) %>
|
|
<% end %>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<%= render "articles/multiple_engagements" unless @article.public_reactions_count.zero? %>
|
|
|
|
<h1 class="fs-3xl m:fs-4xl l:fs-5xl fw-bold s:fw-heavy lh-tight mb-2 <%= @article.title_length_classification %>">
|
|
<% if @article.search_optimized_title_preamble.present? && !user_signed_in? %>
|
|
<span class="fs-xl color-base-70 block"><%= @article.search_optimized_title_preamble %></span>
|
|
<% end %>
|
|
<%= @article.title %>
|
|
</h1>
|
|
|
|
<% cache("main-article-tags-#{@article.cached_tag_list}", expires_in: 30.hours) do %>
|
|
<div class="spec__tags flex flex-wrap">
|
|
<% @article.cached_tag_list_array.each do |tag| %>
|
|
<%= render_tag_link(tag) %>
|
|
<% end %>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="crayons-article__main">
|
|
<% if @collection %>
|
|
<%= render "articles/collection",
|
|
rendered_article: @article,
|
|
collection: @collection,
|
|
articles: @collection_articles %>
|
|
<% end %>
|
|
|
|
<div class="crayons-article__body text-styles spec__body" data-article-id="<%= @article.id %>" id="article-body">
|
|
<%= @article.processed_html.html_safe %>
|
|
</div>
|
|
|
|
<% if @article.long_markdown? && @collection %>
|
|
<%= render "articles/collection",
|
|
rendered_article: @article,
|
|
collection: @collection,
|
|
articles: @collection_articles %>
|
|
<% end %>
|
|
</div>
|
|
<%= render "articles/full_comment_area" %>
|
|
|
|
</article>
|
|
|
|
<div class="pb-4 crayons-layout__comments-billboard">
|
|
<div class="js-billboard-container pb-4 crayons-layout__comments-billboard" data-async-url="<%= article_billboard_path(username: @article.username, slug: @article.slug, placement_area: :post_comments) %>"></div>
|
|
</div>
|
|
|
|
<% cache("article-bottom-content-#{@article.id}-#{user_signed_in?}-#{(@organization || @user).latest_article_updated_at}", expires_in: 18.hours) do %>
|
|
<% suggested_articles = Articles::Suggest.call(@article, max: 4) %>
|
|
<%= render "articles/bottom_content", articles: suggested_articles %>
|
|
<% end %>
|
|
</div>
|
|
</main>
|
|
|
|
<aside class="crayons-layout__sidebar-right" aria-label="<%= t("views.articles.right_nav") %>">
|
|
<%= render "articles/sticky_nav" %>
|
|
</aside>
|
|
</div>
|
|
|
|
<% cache("specific-article-extra-scripts-#{@article.id}-#{@article.updated_at}", expires_in: 24.hours) do %>
|
|
<% if has_vid?(@article) %>
|
|
<%= render "articles/fitvids" %>
|
|
<% end %>
|
|
<% if @article.processed_html.include?('class="twitter-tweet"') ||
|
|
@article.processed_html.include?("ltag_twitter_timeline-liquid-tag") %>
|
|
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
<% end %>
|
|
<% if @article.processed_html.include? "instagram-media" %>
|
|
<script async defer src="//platform.instagram.com/en_US/embeds.js"></script>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<div class="mod-actions-menu print-hidden"></div>
|
|
<div data-testid="unpublish-post-modal-container" class="unpublish-post-modal-container hidden"></div>
|
|
<%= render "moderations/modals/suspend_user_modal" %>
|
|
<%= render "moderations/modals/unsuspend_user_modal" %>
|
|
<%= render "moderations/modals/unpublish_all_posts" %>
|
|
<%= render "moderations/modals/unpublish_post_modal" %>
|
|
<%= render "moderations/modals/flag_user_modal" %>
|
|
<%= render "moderations/modals/unflag_user_modal" %>
|
|
|
|
<div class="fullscreen-code js-fullscreen-code"></div>
|
|
<%= javascript_include_tag "followButtons", "billboard", "localizeArticleDates", "articleReactions", defer: true %>
|
|
|
|
<script>
|
|
<%# we consider these scripts safe for embedding as they come from our code %>
|
|
<%== PodcastTag.script %>
|
|
<%== PollTag.script %>
|
|
<%== RunkitTag.script %>
|
|
<%== TweetTag.script %>
|
|
</script>
|
|
<div class="js-billboard-container pb-4 crayons-layout__comments-billboard" data-async-url="<%= article_billboard_path(username: @article.username, slug: @article.slug, placement_area: :post_fixed_bottom) %>"></div>
|