Tag Page partial UI updates (#19866)

* feat: remove the top card color branding

* feat: update the heading

* feat: remove the rotation on the badge

* feat: remove rotation and justify-between the badge

* feat: add number_with_delimiter to the tag count

* feat: change the follow button to be 'primary'

* feat: add a flex column so that the buttons row sticks to the card bottom

* feat: add the posts to the right hand side on the header

* refactor: move the styles to teh css page

* feat: spacing

* fix: tests

* fix: test

* Exclude Page from ReservedWords checks (#19853)

* move initializeSettings to webpack (#19737)

* move initializeSettings to webpack + add tests

* add initializeSettings to InstantClick change block

* dont use classes, use modules

---------

Co-authored-by: PJ <pj@forem.com>

* Renamed leftover @hero_display_ad => @hero_billboard (#19874)

* Reorganize devDependencies & revert strong_migrations (#19870)

* ruby: Upgrade to v3.1.4 (pt. 1, base image only) (#19871)

In #19776 we discovered that basing both the base container *and* the
app container off of `.ruby-version` causes a chicken-and-egg problem
wherein upgrading Ruby versions requires a few stop-and-gos. Let's make
those stops reviewable as separate chunks instead: use a new
`.ruby-version-next` for building base images, not the `.ruby-version`,
thus allowing GitHub Actions to fire off an automated build (which, when
complete, we can take the SHA sum from and use it to open a second PR
updating the app image to use it, and `.ruby-version` can be updated to
match `.ruby-version-next`).

* feat: add the bullet unused_eager_loading query

* feta: update the seeds

* feat: add a smaller gap and make the grid-col 4 on large screens

* feat: do not let the button take the height of the container

* sway the search with the following tags

* feat: keep the description at font size 14px

* tweak elements to ensure an ideal card height of 195px

---------

Co-authored-by: Mac Siri <mac@forem.com>
Co-authored-by: zhangted <tedcbook@gmail.com>
Co-authored-by: PJ <pj@forem.com>
Co-authored-by: Anna Buianova <lightallloy@gmail.com>
Co-authored-by: Josh Klar <jklar@forem.com>
Co-authored-by: Duke Greene <dukegreene@gmail.com>
This commit is contained in:
Ridhwana 2023-08-08 18:57:14 +02:00 committed by GitHub
parent e5c1a2d7ba
commit 399a0158da
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 65 additions and 49 deletions

View file

@ -40,3 +40,17 @@
}
}
}
.tag-card {
height: 195px;
.crayons-tag {
padding-top: 0;
padding-bottom: 0;
}
&__badge {
width: 48px;
height: 48px;
}
}

View file

@ -30,13 +30,13 @@
</h1>
<form accept-charset="UTF-8" method="get" action="<%= tags_path %>" role="search">
<div class="crayons-fields crayons-fields--horizontal">
<%= link_to t("views.tags.following_tags"), dashboard_following_tags_path, class: "crayons-btn crayons-btn--ghost" %>
<div class="crayons-field flex-1 relative">
<input class="crayons-header--search-input crayons-textfield js-search-input" type="text" id="nav-search" aria-label="<%= t("views.tags.search.aria_labels.search_input") %>" name="q" placeholder="<%= t("views.tags.search.placeholder") %>" autocomplete="off" />
<button type="submit" aria-label="<%= t("views.tags.search.aria_labels.submit") %>" class="c-btn c-btn--icon-alone absolute inset-px left-auto mt-0 py-0">
<%= crayons_icon_tag(:search, aria_hidden: true, title: t("views.search.icon.title")) %>
</button>
</div>
<%= link_to t("views.tags.following_tags"), dashboard_following_tags_path, class: "crayons-btn crayons-btn--ghost" %>
</div>
</form>
</header>
@ -46,32 +46,32 @@
<div class="substories search-results-loaded" id="substories"><div class="p-9 align-center crayons-card">No results match that query</div></div>
</div>
<% else %>
<div class="grid gap-3 m:gap-4 l:gap-6 m:grid-cols-2 l:grid-cols-3 px-3 m:px-0 pb-3" data-follow-button-container="true">
<% @tags.each do |tag| %>
<div class="tag-card crayons-card branded-4 p-3 pt-2 m:p-6 m:pt-4 relative" style="border-top-color: <%= tag.bg_color_hex %>; ">
<h3 class="mb-1 -ml-2">
<%= render_tag_link(tag.accessible_name) %>
</h3>
<% if tag.short_summary.present? %>
<p class="mb-2 color-base-70 truncate-at-3"><%= sanitize tag.short_summary %></p>
<% end %>
<p class="mb-3 fs-s color-base-60">
<%= t("views.tags.published", count: tag.taggings_count) %>
</p>
<div class="grid gap-3 m:gap-4 l:gap-4 m:grid-cols-2 l:grid-cols-4 px-3 m:px-0 pb-3" data-follow-button-container="true">
<% @tags.includes([:badge]).each do |tag| %>
<div class="tag-card crayons-card p-3 pt-2 m:p-5 m:pt-4 relative flex flex-col">
<div>
<div class="mb-1 flex items-center justify-between">
<h4 class="-ml-2">
<%= render_tag_link(tag.accessible_name) %>
</h4>
<div class="fs-xs color-base-60"><%= t("views.tags.published", count: number_with_delimiter(tag.taggings_count, delimiter: ",")) %></div>
</div>
<% if tag.short_summary.present? %>
<p class="mb-6 fs-s color-base-70 truncate-at-3"><%= sanitize tag.short_summary %></p>
<% end %>
</div>
<% if tag %>
<div class="mt-auto">
<div class="mt-auto flex items-end justify-between">
<button
class="crayons-btn crayons-btn--secondary follow-action-button"
data-info='<%= DataInfo.to_json(object: tag, class_name: "Tag", followStyle: "secondary") %>'>
class="crayons-btn crayons-btn--primary follow-action-button"
data-info='<%= DataInfo.to_json(object: tag, class_name: "Tag", followStyle: "primary") %>'>
<%= t("views.tags.follow") %>
</button>
<% if tag.badge_id && tag.badge %>
<img src="<%= optimized_image_url(tag.badge.badge_image_url, width: 180) %>" class="tag-card__badge" alt="" loading="lazy" />
<% end %>
</div>
<% end %>
<% if tag.badge_id && tag.badge %>
<img src="<%= optimized_image_url(tag.badge.badge_image_url, width: 180) %>" style="width: 64px; height: 64px; transform: rotate(<%= -25 + (tag.id.digits.first * 5) %>deg);" class="right-1 bottom-1 absolute" alt="" loading="lazy" />
<% end %>
</div>
<% end %>
</div>

View file

@ -151,6 +151,7 @@ Rails.application.configure do
Bullet.add_safelist(type: :unused_eager_loading, class_name: "FeedbackMessage", association: :reporter)
Bullet.add_safelist(type: :unused_eager_loading, class_name: "Article", association: :reactions)
Bullet.add_safelist(type: :unused_eager_loading, class_name: "Reaction", association: :user)
Bullet.add_safelist(type: :unused_eager_loading, class_name: "Tag", association: :badge)
# Check if there are any data update scripts to run during startup
if %w[Console Server DBConsole].any? { |const| Rails.const_defined?(const) } && DataUpdateScript.scripts_to_run?

View file

@ -8,7 +8,7 @@ en:
og:
description: "%{community} is great!"
heading:
default: Top tags
default: Tags
search_results: Search results for %{q}
search:
aria_labels:
@ -44,8 +44,8 @@ en:
code: 123
placeholder: "comma separated, space is optional. Example: 1,2,3"
published:
one: 1 post published
other: "%{count} posts published"
one: 1 post
other: "%{count} posts"
sidebar:
about: 'about #%{tag}'
admin: Admin

View file

@ -8,7 +8,7 @@ fr:
og:
description: "%{community} est super"
heading:
default: Sujets les plus utilisées
default: Tags
search_results: Search results for %{q}
search:
aria_labels:
@ -45,8 +45,8 @@ fr:
code: 123
placeholder: "comma separated, space is optional. Example: 1,2,3"
published:
one: 1 post published
other: "%{count} posts published"
one: 1 post
other: "%{count} posts"
sidebar:
about: 'about #%{tag}'
admin: Admin

View file

@ -79,7 +79,7 @@ describe('Show log in modal', () => {
it('should show login modal for tag follow button click', () => {
cy.visit('/tags');
cy.findByRole('heading', { name: 'Top tags' });
cy.findByRole('heading', { name: 'Tags' });
cy.get('[data-follow-clicks-initialized]');
verifyLoginModalBehavior(() =>

View file

@ -6,7 +6,7 @@ describe('Follow tag', () => {
cy.get('@user').then((user) => {
cy.loginAndVisit(user, '/tags').then(() => {
cy.findByRole('heading', { name: 'Top tags' });
cy.findByRole('heading', { name: 'Tags' });
cy.get('[data-follow-clicks-initialized]');
});
});

View file

@ -212,6 +212,24 @@ Users::CreateMascotAccount.call unless Settings::General.mascot_user_id
##############################################################################
seeder.create_if_none(Badge) do
5.times do
Badge.create!(
title: "#{Faker::Lorem.word} #{rand(100)}",
description: Faker::Lorem.sentence,
badge_image: Rails.root.join("app/assets/images/#{rand(1..40)}.png").open,
)
end
users_in_random_order.limit(10).each do |user|
user.badge_achievements.create!(
badge: Badge.order(Arel.sql("RANDOM()")).limit(1).take,
rewarding_context_message_markdown: Faker::Markdown.random,
)
end
end
##############################################################################
seeder.create_if_none(Tag) do
tags = %w[beginners career computerscience git go
java javascript linux productivity python security webdev]
@ -219,9 +237,11 @@ seeder.create_if_none(Tag) do
tags.each do |tag_name|
Tag.create!(
name: tag_name,
short_summary: Faker::Lorem.sentence,
bg_color_hex: Faker::Color.hex_color,
text_color_hex: Faker::Color.hex_color,
supported: true,
badge: Badge.order(Arel.sql("RANDOM()")).limit(1).take,
)
end
end
@ -420,25 +440,6 @@ end
##############################################################################
seeder.create_if_none(Badge) do
5.times do
Badge.create!(
title: "#{Faker::Lorem.word} #{rand(100)}",
description: Faker::Lorem.sentence,
badge_image: Rails.root.join("app/assets/images/#{rand(1..40)}.png").open,
)
end
users_in_random_order.limit(10).each do |user|
user.badge_achievements.create!(
badge: Badge.order(Arel.sql("RANDOM()")).limit(1).take,
rewarding_context_message_markdown: Faker::Markdown.random,
)
end
end
##############################################################################
seeder.create_if_none(FeedbackMessage) do
mod = User.with_role(:trusted).take

View file

@ -7,7 +7,7 @@ RSpec.describe "Tags", proper_status: true do
create(:tag, name: "javascript", alias_for: "")
get tags_path
expect(response.body).to include("Top tags", "ruby", "javascript")
expect(response.body).to include("Tags", "ruby", "javascript")
end
it "does not include tags with alias" do