mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-19 18:18:27 -05:00
fix(client): expose donate button on navigation bar (#48820)
* feat: expose donate nav button * feat: add the ignores * fix: adjust tests * feat: adjust nav button styles
This commit is contained in:
@@ -4,6 +4,7 @@ client/public/**
|
||||
api-server/src/public/**
|
||||
api-server/lib/**
|
||||
config/i18n.js
|
||||
config/misc.js
|
||||
config/certification-settings.js
|
||||
config/donation-settings.js
|
||||
config/superblock-order.js
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -163,6 +163,7 @@ config/client/frame-runner.json
|
||||
config/client/test-evaluator.json
|
||||
config/curriculum.json
|
||||
config/i18n.js
|
||||
config/misc.js
|
||||
config/certification-settings.js
|
||||
config/donation-settings.js
|
||||
config/superblock-order.js
|
||||
|
||||
@@ -7,6 +7,7 @@ curriculum/challenges/_meta/*/*
|
||||
curriculum/challenges/**/*
|
||||
config/**/*.json
|
||||
config/i18n.js
|
||||
config/misc.js
|
||||
config/certification-settings.js
|
||||
config/donation-settings.js
|
||||
config/superblock-order.js
|
||||
|
||||
@@ -339,7 +339,6 @@
|
||||
"title": "Support our charity",
|
||||
"processing": "We are processing your donation.",
|
||||
"redirecting": "Redirecting...",
|
||||
"thanks": "Thanks for donating",
|
||||
"thank-you": "Thank you for being a supporter.",
|
||||
"additional": "You can make an additional one-time donation of any amount using this link: <0>{{url}}</0>",
|
||||
"help-more": "Help us do more",
|
||||
|
||||
@@ -43,7 +43,7 @@ const MenuButton = ({
|
||||
return (
|
||||
<button
|
||||
aria-expanded={displayMenu}
|
||||
className={`toggle-button-nav${
|
||||
className={`exposed-button-nav${
|
||||
displayMenu ? ' reverse-toggle-color' : ''
|
||||
}`}
|
||||
id='toggle-button-nav'
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
// @ts-nocheck
|
||||
import {
|
||||
faCheckSquare,
|
||||
faHeart,
|
||||
faSquare,
|
||||
faExternalLinkAlt
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import Media from 'react-responsive';
|
||||
import React, { Component, Fragment, createRef } from 'react';
|
||||
import { TFunction, withTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import envData from '../../../../../config/env.json';
|
||||
import { DONATE_NAV_EXPOSED_WIDTH } from '../../../../../config/misc';
|
||||
import {
|
||||
availableLangs,
|
||||
LangNames,
|
||||
@@ -296,7 +297,7 @@ export class NavLinks extends Component<NavLinksProps, NavlinkStates> {
|
||||
fetchState,
|
||||
t,
|
||||
toggleNightMode,
|
||||
user: { isDonating = false, username, theme }
|
||||
user: { username, theme }
|
||||
}: NavLinksProps = this.props;
|
||||
|
||||
const { pending } = fetchState;
|
||||
@@ -310,25 +311,20 @@ export class NavLinks extends Component<NavLinksProps, NavlinkStates> {
|
||||
isLanguageMenuDisplayed ? ' display-lang-menu' : ''
|
||||
}`}
|
||||
>
|
||||
{isDonating ? (
|
||||
<li key='donate'>
|
||||
<div className='nav-link nav-link-flex nav-link-header'>
|
||||
<span>{t('donate.thanks')}</span>
|
||||
<FontAwesomeIcon icon={faHeart} />
|
||||
</div>
|
||||
</li>
|
||||
) : (
|
||||
<Media maxWidth={DONATE_NAV_EXPOSED_WIDTH}>
|
||||
<li key='donate'>
|
||||
<Link
|
||||
className='nav-link'
|
||||
onKeyDown={this.handleMenuKeyDown}
|
||||
sameTab={false}
|
||||
to='/donate'
|
||||
data-test-label='dropdown-donate-button'
|
||||
nav-donate-button
|
||||
>
|
||||
{t('buttons.donate')}
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
</Media>
|
||||
<li key='learn'>
|
||||
<Link
|
||||
className='nav-link'
|
||||
|
||||
@@ -323,7 +323,7 @@ button.nav-link[aria-disabled='true'] {
|
||||
margin-inline-end: 25px;
|
||||
}
|
||||
|
||||
.toggle-button-nav {
|
||||
.exposed-button-nav {
|
||||
padding: 2px 14px;
|
||||
border: 1px solid var(--gray-00);
|
||||
font-family: 'lato', sans-serif;
|
||||
@@ -336,18 +336,21 @@ button.nav-link[aria-disabled='true'] {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.toggle-button-nav:hover {
|
||||
background-color: var(--theme-color);
|
||||
color: var(--gray-00);
|
||||
.exposed-button-nav:hover,
|
||||
.exposed-button-nav:hover:focus {
|
||||
background-color: var(--gray-00);
|
||||
color: var(--gray-90);
|
||||
border: 1px solid var(--gray-00);
|
||||
}
|
||||
|
||||
.toggle-button-nav:focus {
|
||||
.exposed-button-nav:focus {
|
||||
outline: 3px solid var(--blue-mid);
|
||||
outline-offset: 0;
|
||||
background-color: var(--gray-90);
|
||||
color: var(--gray-00);
|
||||
}
|
||||
|
||||
.toggle-button-nav:focus:not(:focus-visible) {
|
||||
.exposed-button-nav:focus:not(:focus-visible) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@@ -411,12 +414,12 @@ button.nav-link[aria-disabled='true'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.reverse-toggle-color {
|
||||
.exposed-button-nav.reverse-toggle-color {
|
||||
background-color: var(--gray-00);
|
||||
color: var(--theme-color);
|
||||
}
|
||||
|
||||
.reverse-toggle-color:hover {
|
||||
.exposed-button-nav.reverse-toggle-color:hover {
|
||||
background-color: var(--gray-00);
|
||||
color: var(--theme-color);
|
||||
}
|
||||
@@ -583,7 +586,7 @@ button.nav-link[aria-disabled='true'] {
|
||||
#universal-nav .login-btn-icon {
|
||||
display: inline-block;
|
||||
}
|
||||
.toggle-button-nav {
|
||||
.exposed-button-nav {
|
||||
padding: 2px 8px;
|
||||
}
|
||||
#universal-nav-logo svg {
|
||||
|
||||
@@ -4,6 +4,10 @@ import { useTranslation } from 'react-i18next';
|
||||
import Media from 'react-responsive';
|
||||
import { isLanding } from '../../../utils/path-parsers';
|
||||
import { Link, SkeletonSprite } from '../../helpers';
|
||||
import {
|
||||
SEARCH_EXPOSED_WIDTH,
|
||||
DONATE_NAV_EXPOSED_WIDTH
|
||||
} from '../../../../../config/misc';
|
||||
import { User } from '../../../redux/prop-types';
|
||||
import MenuButton from './menu-button';
|
||||
import NavLinks from './nav-links';
|
||||
@@ -16,8 +20,6 @@ const SearchBarOptimized = Loadable(
|
||||
() => import('../../search/searchBar/search-bar-optimized')
|
||||
);
|
||||
|
||||
const MAX_MOBILE_WIDTH = 980;
|
||||
|
||||
interface UniversalNavProps {
|
||||
displayMenu: boolean;
|
||||
isLanguageMenuDisplayed: boolean;
|
||||
@@ -61,7 +63,7 @@ export const UniversalNav = ({
|
||||
<div
|
||||
className={`universal-nav-left${displayMenu ? ' display-search' : ''}`}
|
||||
>
|
||||
<Media minWidth={MAX_MOBILE_WIDTH + 1}>{search}</Media>
|
||||
<Media minWidth={SEARCH_EXPOSED_WIDTH + 1}>{search}</Media>
|
||||
</div>
|
||||
<div className='universal-nav-middle'>
|
||||
<Link id='universal-nav-logo' to='/learn'>
|
||||
@@ -75,6 +77,17 @@ export const UniversalNav = ({
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Media minWidth={DONATE_NAV_EXPOSED_WIDTH + 1}>
|
||||
{' '}
|
||||
<Link
|
||||
sameTab={false}
|
||||
to='/donate'
|
||||
data-test-label='nav-donate-button'
|
||||
className='exposed-button-nav'
|
||||
>
|
||||
{t('buttons.donate')}
|
||||
</Link>
|
||||
</Media>
|
||||
<MenuButton
|
||||
displayMenu={displayMenu}
|
||||
hideMenu={hideMenu}
|
||||
@@ -82,7 +95,7 @@ export const UniversalNav = ({
|
||||
showMenu={showMenu}
|
||||
user={user}
|
||||
/>
|
||||
<Media maxWidth={MAX_MOBILE_WIDTH}>{search}</Media>
|
||||
<Media maxWidth={SEARCH_EXPOSED_WIDTH}>{search}</Media>
|
||||
<NavLinks
|
||||
displayMenu={displayMenu}
|
||||
fetchState={fetchState}
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
exports.defaultUserImage = 'https://freecodecamp.com/sample-image.png';
|
||||
exports.MAX_MOBILE_WIDTH = 767;
|
||||
4
config/misc.ts
Normal file
4
config/misc.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export const defaultUserImage = 'https://freecodecamp.com/sample-image.png';
|
||||
export const MAX_MOBILE_WIDTH = 767;
|
||||
export const SEARCH_EXPOSED_WIDTH = 980;
|
||||
export const DONATE_NAV_EXPOSED_WIDTH = 600;
|
||||
@@ -4,7 +4,7 @@ const selectors = {
|
||||
navigationLinks: '.nav-list',
|
||||
avatarContainer: '.avatar-container',
|
||||
defaultAvatar: '.avatar-container',
|
||||
menuButton: '.toggle-button-nav',
|
||||
menuButton: '#toggle-button-nav',
|
||||
avatarImage: '.avatar-container .avatar'
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ const { clientLocale } = envData;
|
||||
|
||||
const selectors = {
|
||||
'navigation-list': '.nav-list',
|
||||
'toggle-button': '.toggle-button-nav',
|
||||
'toggle-button': '#toggle-button-nav',
|
||||
'language-menu': '.nav-lang-menu',
|
||||
'exit-lang-menu': "[data-value='exit-lang-menu']",
|
||||
'lang-menu-option': 'button.nav-lang-menu-option',
|
||||
@@ -18,7 +18,9 @@ const selectors = {
|
||||
'avatar-container': '.avatar-container',
|
||||
'sign-out-button': "[data-value='sign-out-button']",
|
||||
signout: "[data-test-label='signout']",
|
||||
'cancel-signout': "[data-test-label='cancel-signout']"
|
||||
'cancel-signout': "[data-test-label='cancel-signout']",
|
||||
'navigation-donate-button': "[data-test-label='nav-donate-button']",
|
||||
'dropwodn-donate-button': "[data-test-label='dropdown-donate-button']"
|
||||
};
|
||||
|
||||
const links = {
|
||||
@@ -39,7 +41,6 @@ describe('Default Navigation Menu', () => {
|
||||
cy.get(selectors['language-menu']).should('not.be.visible');
|
||||
cy.get(selectors['toggle-button']).should('be.visible').click();
|
||||
cy.get(selectors['navigation-list']).contains('Sign in to change theme.');
|
||||
testLink('Donate');
|
||||
testLink('Curriculum');
|
||||
testLink('Forum');
|
||||
testLink('News');
|
||||
@@ -214,8 +215,20 @@ describe('Donor Navigation Menu', () => {
|
||||
it('should show donor avatar border.', () => {
|
||||
cy.get(selectors['avatar-container']).should('have.class', 'gold-border');
|
||||
});
|
||||
it('should show thank you message.', () => {
|
||||
cy.get(selectors['navigation-list']).contains('Thanks for donating');
|
||||
});
|
||||
|
||||
describe('Donate button', () => {
|
||||
it('should render in the toggle menu in small screens', () => {
|
||||
cy.viewport(550, 750);
|
||||
cy.visit('/learn');
|
||||
testLink('Donate');
|
||||
cy.get(selectors['navigation-donate-button']).should('not.exist');
|
||||
});
|
||||
it('should render in the universal nav in large screens', () => {
|
||||
cy.viewport(1550, 750);
|
||||
cy.visit('/learn');
|
||||
cy.get(selectors['dropdown-donate-button']).should('not.exist');
|
||||
cy.get(selectors['navigation-donate-button']).should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user