Hide the buttons on the tag page (#20148)

* feat: step 1 - add the buttons to the html template

* refactor: renamed the class to be prepended with js-

* feat: add the js-tag-card class to the entire tag-card div

* feat: add the relevant data elements and tag-id to the tag-card div

* feat: add the required data elements for the top level js-tag-card

* feat: use @tag instead of tag

* refactor: rename the tag pack file

* refactor: rename the Tag file component

* feat: add a snackzone so that the snackbar can be added there

* feat: remove the follow-actions-button and the hide-actions-button from the tag pages so that it doesn't conflict with the 'followButtons' pack whne we need to add it

* spec: update the specs for tags

* chore: follow-action-button renamed to follow-tag-button and hide-action-button to hide-tag-button

* refactor: js-classes

* chore: add some comments

---------

Co-authored-by: Ben Halpern <bendhalpern@gmail.com>
This commit is contained in:
Ridhwana 2023-09-27 01:49:57 +02:00 committed by GitHub
parent 484821fe5e
commit ae9d1b5ace
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 20 deletions

View file

@ -4,10 +4,18 @@ import { getUserDataAndCsrfToken } from '@utilities/getUserDataAndCsrfToken';
/* global showLoginModal */
// This Pack file has some dependencies for it to function accurately:
// Copy and paste the FOllow and Hide button snippets from a tag card.
// An example can be found in app/views/tags/index.html.erb
// The tag card needs to contain a class .js-tag-card elements,
// with data attributes for the tag-id and name.
// The follow button and the hide button need to contain classes
// js-follow-tag-button and/or js-hide-tag-button respectively.
function renderPage(currentUser) {
import('../tags/Tag')
import('../tags/TagButtonContainer')
.then(({ Tag }) => {
const tagCards = document.getElementsByClassName('tag-card');
const tagCards = document.getElementsByClassName('js-tag-card');
const followedTags = JSON.parse(currentUser.followed_tags);
Array.from(tagCards).forEach((element) => {
@ -46,11 +54,11 @@ function listenForButtonClicks() {
function handleButtonClick({ target }) {
let trigger;
if (target.classList.contains('follow-action-button')) {
if (target.classList.contains('js-follow-tag-button')) {
trigger = 'follow_button';
}
if (target.classList.contains('hide-action-button')) {
if (target.classList.contains('js-hide-tag-button')) {
trigger = 'hide_button';
}
@ -64,8 +72,9 @@ function handleButtonClick({ target }) {
}
function loadSnackbar() {
const root = document.getElementsByClassName('tags-index');
if (root.length > 0) {
const snackZone = document.getElementById('snack-zone');
if (snackZone) {
render(<Snackbar lifespan="1" />, document.getElementById('snack-zone'));
}
}

View file

@ -4,7 +4,7 @@
<% expiry_minutes = params[:timeframe].blank? || params[:timeframe] == "latest" ? 4 : 20 %>
<% flag = true %>
<% cache("tag-stories-index-#{params}-#{flag}-#{@tag.updated_at}-#{user_signed_in?}", expires_in: expiry_minutes.minutes) do %>
<div class="crayons-layout">
<div data-tag-id="<%= @tag.id %>" data-tag-name="<%= @tag.name %>" id="tag-<%= @tag.id %>" class="crayons-layout js-tag-card">
<header class="crayons-card branded-4 p-4 l:p-6 spec__tag-header" style="border-top-color: <%= @tag.bg_color_hex %> ">
<div class="flex">
<% if @tag.badge_id && @tag.badge %>
@ -21,12 +21,20 @@
<% end %>
</h1>
<% if @tag %>
<button
id="user-follow-butt"
class="crayons-btn follow-action-button"
data-info='<%= DataInfo.to_json(object: @tag, class_name: "Tag", name: @tag.pretty_name || @tag.name) %>'>
<%= t("views.stories.follow") %>
</button>
<div id="tag-buttons-<%= @tag.id %>" class="mt-auto flex items-end justify-between">
<div class="flex gap-2">
<button
class="c-btn c-btn--primary js-follow-tag-button"
aria-label="<%= t("views.tags.aria_labels.follow", tag_name: @tag.name) %>">
<%= t("views.tags.follow") %>
</button>
<button
class="c-btn js-hide-tag-button"
aria-label="<%= t("views.tags.aria_labels.hide", tag_name: @tag.name) %>">
<%= t("views.tags.hide") %>
</button>
</div>
</div>
<% end %>
</div>
<% if @tag && @tag.short_summary.present? %>
@ -130,5 +138,5 @@
<%= render "stories/tagged_articles/sidebar_additional" %>
</div>
<%= javascript_packs_with_chunks_tag "storiesList", "followButtons", "feedPreviewCards", "hideBookmarkButtons", "drawerSliders", "localizeArticleDates", defer: true %>
<%= javascript_packs_with_chunks_tag "storiesList", "followButtons", "tagFollows", "feedPreviewCards", "hideBookmarkButtons", "drawerSliders", "localizeArticleDates", defer: true %>
<% end %>

View file

@ -53,7 +53,7 @@
<% else %>
<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 data-tag-id="<%= tag.id %>" data-tag-name="<%= tag.name %>" id="tag-<%= tag.id %>" class="tag-card crayons-card p-3 pt-2 m:p-5 m:pt-4 relative flex flex-col">
<div data-tag-id="<%= tag.id %>" data-tag-name="<%= tag.name %>" id="tag-<%= tag.id %>" class="js-tag-card 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">
@ -68,12 +68,12 @@
<div id="tag-buttons-<%= tag.id %>" class="mt-auto flex items-end justify-between">
<div class="flex gap-2">
<button
class="c-btn c-btn--primary follow-action-button"
class="c-btn c-btn--primary js-follow-tag-button"
aria-label="<%= t("views.tags.aria_labels.follow", tag_name: tag.name) %>">
<%= t("views.tags.follow") %>
</button>
<button
class="c-btn hide-action-button"
class="c-btn js-hide-tag-button"
aria-label="<%= t("views.tags.aria_labels.hide", tag_name: tag.name) %>">
<%= t("views.tags.hide") %>
</button>
@ -89,4 +89,4 @@
<% end %>
</main>
<%= javascript_packs_with_chunks_tag "TagsIndex", defer: true %>
<%= javascript_packs_with_chunks_tag "tagFollows", defer: true %>

View file

@ -103,12 +103,11 @@ describe('Follow tag', () => {
cy.get('@user').then((user) => {
cy.loginAndVisit(user, '/t/tag1').then(() => {
cy.findByRole('heading', { name: '# tag1' });
cy.get('[data-follow-clicks-initialized]');
});
});
});
it('follows and unfollows a tag from the tag feed page', () => {
it('follows and unfollows a tag', () => {
cy.intercept('/follows').as('followsRequest');
cy.findByRole('button', { name: 'Follow tag: tag1' }).as('followButton');
@ -116,11 +115,62 @@ describe('Follow tag', () => {
cy.wait('@followsRequest');
cy.get('@followButton').should('have.text', 'Following');
cy.get('@followButton').should('have.attr', 'aria-pressed', 'true');
cy.findByTestId('snackbar').within(() => {
cy.findByRole('alert').should('have.text', 'You have followed tag1.');
});
cy.get('@followButton').click();
cy.wait('@followsRequest');
cy.get('@followButton').should('have.text', 'Follow');
cy.get('@followButton').should('have.attr', 'aria-pressed', 'false');
cy.findByTestId('snackbar').within(() => {
cy.findByRole('alert').should('have.text', 'You have unfollowed tag1.');
});
});
it('hides and unhides a tag', () => {
cy.intercept('/follows').as('followsRequest');
cy.findByRole('button', { name: 'Follow tag: tag1' }).as(
'toBeHiddenFollowButton',
);
cy.findByRole('button', { name: 'Hide tag: tag1' }).as('hideButton');
cy.get('@hideButton').click();
cy.wait('@followsRequest');
// clicking on 'Hide' should change it to an 'Unhide'
// and remove the Follow button
cy.get('@hideButton').should('have.text', 'Unhide');
cy.get('@toBeHiddenFollowButton').should('not.exist');
cy.findByTestId('snackbar').within(() => {
cy.findByRole('alert').should('have.text', 'You have hidden tag1.');
});
// clicking on 'Unhide' should change it back to 'Hide'
// and show a 'Follow' button
cy.get('@hideButton').click();
cy.wait('@followsRequest');
cy.get('@hideButton').should('have.text', 'Hide');
cy.get('@toBeHiddenFollowButton').should('not.exist');
cy.findByRole('button', { name: 'Follow tag: tag1' }).as(
'toBeShownFollowButton',
);
cy.get('@toBeShownFollowButton').should('exist');
cy.get('@toBeShownFollowButton').should('have.text', 'Follow');
cy.get('@toBeShownFollowButton').should(
'have.attr',
'aria-pressed',
'false',
);
cy.findByTestId('snackbar').within(() => {
cy.findByRole('alert').should('have.text', 'You have unhidden tag1.');
});
});
});
});