Remove Hero, HeroSection and heroBanners reducer (#10170)

* Remove Hero, HeroSection and heroBanners reducer

* Remove unused dependency
This commit is contained in:
Bob Silverberg 2021-03-09 09:03:17 -05:00 коммит произвёл GitHub
Родитель 78d2da91b4
Коммит 3bf0f80f87
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
12 изменённых файлов: 0 добавлений и 497 удалений

Просмотреть файл

@ -178,7 +178,6 @@
"jed": "1.1.1",
"join-url": "2.0.0",
"jsdom": "16.5.0",
"knuth-shuffle": "1.0.8",
"localforage": "1.9.0",
"lodash.debounce": "4.0.8",
"moment": "2.29.1",

Просмотреть файл

@ -1,68 +0,0 @@
/* @flow */
import makeClassName from 'classnames';
import * as React from 'react';
import { connect } from 'react-redux';
import { compose } from 'redux';
import { setHeroBannerOrder } from 'amo/reducers/heroBanners';
import Card from 'amo/components/Card';
import HeroSection from 'amo/components/HeroSection';
import type { AppState } from 'amo/store';
import type { DispatchFunc } from 'amo/types/redux';
import './styles.scss';
export type HeroSectionsType = Array<React.Element<typeof HeroSection>>;
type Props = {|
name: string,
random?: boolean,
sections: HeroSectionsType,
|};
type InternalProps = {|
...Props,
dispatch: DispatchFunc,
heroBanners: Object,
|};
export class HeroBase extends React.Component<InternalProps> {
constructor(props: InternalProps) {
super(props);
const { dispatch, heroBanners, name, random, sections } = props;
if (!heroBanners[name]) {
dispatch(setHeroBannerOrder({ name, random, sections }));
}
}
render() {
const { heroBanners, name, sections } = this.props;
const orderStyle = heroBanners[name]
? `Hero-order-${heroBanners[name].order.join('-')}`
: null;
return (
<Card className={makeClassName('Hero', `Hero-name-${name}`, orderStyle)}>
<div className="Hero-contents">
{heroBanners[name]
? heroBanners[name].order.map((index) => {
return sections[index];
})
: null}
</div>
</Card>
);
}
}
export const mapStateToProps = (state: AppState) => {
return { heroBanners: state.heroBanners };
};
const Hero: React.ComponentType<Props> = compose(connect(mapStateToProps))(
HeroBase,
);
export default Hero;

Просмотреть файл

@ -1,17 +0,0 @@
@import '~amo/css/styles';
.Hero {
margin: 0 0 $padding-page;
@include respond-to(large) {
margin: 0 0 $padding-page-l;
}
}
.Hero .Card-contents {
padding: 12px;
@include respond-to(large) {
padding: $padding-page-l;
}
}

Просмотреть файл

@ -1,47 +0,0 @@
/* @flow */
import makeClassName from 'classnames';
import * as React from 'react';
import Link from 'amo/components/Link';
import './styles.scss';
type Props = {|
children?: any,
linkTo?: Object | string,
onClick?: () => void,
styleName?: string,
|};
export default class HeroSection extends React.Component<Props> {
static defaultProps = {
styleName: 'default',
};
render() {
const { children, linkTo, styleName } = this.props;
return (
<div
className={makeClassName(
'HeroSection',
`HeroSection-styleName--${String(styleName)}`,
)}
>
{linkTo ? (
<Link
className="HeroSection-link-wrapper"
onClick={this.props.onClick}
to={linkTo}
>
<div className="HeroSection-content">{children}</div>
</Link>
) : (
<div className="HeroSection-wrapper">
<div className="HeroSection-content">{children}</div>
</div>
)}
</div>
);
}
}

Просмотреть файл

@ -1,65 +0,0 @@
@import '~amo/css/styles';
.HeroSection {
border-radius: $border-radius-default;
position: relative;
}
.HeroSection-wrapper,
.HeroSection-link-wrapper,
.HeroSection-link-wrapper:link {
align-items: flex-end;
color: $white;
display: flex;
flex-flow: row wrap;
height: 100%;
min-height: 128px;
padding: $padding-page;
position: relative;
text-decoration: none;
@include respond-to(large) {
padding: $padding-page-l;
}
}
.HeroSection-link-wrapper:focus {
.HeroSection-content {
outline: 1px dotted $white;
outline: auto 5px -webkit-focus-ring-color;
}
}
.HeroSection-content {
margin: 0;
}
.HeroSection-content h3 {
@include font-light();
font-size: $font-size-m;
line-height: 1;
margin: 0;
padding: 0;
width: 100%;
@include respond-to(medium) {
font-size: $hero-title-font-size;
}
}
.HeroSection-content p {
@include font-light();
display: block;
font-size: $font-size-m-smaller;
line-height: initial;
margin: 10px 0 0;
padding: 0;
width: 100%;
@include respond-to(medium) {
font-size: $hero-subtitle-font-size;
margin: 20px 0 0;
}
}

Просмотреть файл

@ -43,10 +43,6 @@ $font-size-hero-heading: 38px;
$font-size-header-title: 34px;
// Hero
$hero-title-font-size: 33px;
$hero-subtitle-font-size: 22px;
// Animation Variables
$transition-short: 150ms;
$transition-medium: $transition-short * 3;

Просмотреть файл

@ -1,40 +0,0 @@
import { knuthShuffle } from 'knuth-shuffle';
// Hero banners have three items max, all the time :-)
const MAX_ITEMS = 3;
export const SET_HERO_BANNER_ORDER = 'SET_HERO_BANNER_ORDER';
export const setHeroBannerOrder = ({ name, random = false, sections }) => {
if (!name) {
throw new Error('name is required');
}
if (!sections) {
throw new Error('sections are required');
}
return {
payload: { name, random, sections },
type: SET_HERO_BANNER_ORDER,
};
};
export const initialState = {};
export default function heroBannerOrderReducer(state = initialState, action) {
switch (action.type) {
case SET_HERO_BANNER_ORDER: {
const { name, random, sections } = action.payload;
const orderArray = [...sections.keys()];
const order = random ? knuthShuffle(orderArray) : orderArray;
return {
...state,
[name]: {
order: order.slice(0, MAX_ITEMS),
},
};
}
default:
return state;
}
}

Просмотреть файл

@ -33,7 +33,6 @@ import categories from 'amo/reducers/categories';
import errors from 'amo/reducers/errors';
import errorPage from 'amo/reducers/errorPage';
import formOverlay from 'amo/reducers/formOverlay';
import heroBanners from 'amo/reducers/heroBanners';
import languageTools from 'amo/reducers/languageTools';
import infoDialog from 'amo/reducers/infoDialog';
import installations from 'amo/reducers/installations';
@ -145,7 +144,6 @@ type InternalAppState = {|
errorPage: ErrorPageState,
errors: Object,
formOverlay: FormOverlayState,
heroBanners: Object,
home: HomeState,
infoDialog: InfoDialogState,
installations: InstallationsState,
@ -203,7 +201,6 @@ export const reducers: AppReducersType = {
errors,
errorPage,
formOverlay,
heroBanners,
home,
infoDialog,
installations,

Просмотреть файл

@ -1,46 +0,0 @@
import { mount } from 'enzyme';
import * as React from 'react';
import { setHeroBannerOrder } from 'amo/reducers/heroBanners';
import Hero from 'amo/components/Hero';
import { dispatchClientMetadata } from 'tests/unit/helpers';
describe(__filename, () => {
const defaultProps = {
store: dispatchClientMetadata().store,
};
let dispatchSpy;
beforeEach(() => {
dispatchSpy = sinon.spy(defaultProps.store, 'dispatch');
});
// We mount certain tests to ensure lifecycle methods like componentDidMount
// are called.
// See: https://github.com/mozilla/addons-frontend/issues/3349
function mountRender({ ...props } = {}) {
return mount(<Hero {...defaultProps} {...props} />);
}
it('renders a Hero', () => {
const name = 'TestingPage';
const sections = [
<p className="something" key="something">
Hello!
</p>,
<p className="something-else" key="something-else">
Bonjour !
</p>,
];
const root = mountRender({ name, random: true, sections });
sinon.assert.calledWith(
dispatchSpy,
setHeroBannerOrder({ name, random: true, sections }),
);
expect(root.find('.Card.Hero')).toHaveLength(1);
expect(root.find('.Card.Hero-name-TestingPage')).toHaveLength(1);
expect(root.find('.something')).toHaveLength(1);
expect(root.find('.something-else')).toHaveLength(1);
});
});

Просмотреть файл

@ -1,64 +0,0 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import Link from 'amo/components/Link';
import HeroSection from 'amo/components/HeroSection';
describe(__filename, () => {
function shallowRender({ ...props } = {}) {
return shallow(<HeroSection {...props} />);
}
it('renders a HeroSection', () => {
const root = shallowRender();
expect(root).toHaveClassName('HeroSection');
});
it('renders a className for the styleName', () => {
const root = shallowRender({ styleName: 'Home-privacy-matters' });
expect(root).toHaveClassName('HeroSection-styleName--Home-privacy-matters');
});
it('renders default styleName className if styleName is undefined', () => {
const root = shallowRender({ styleName: undefined });
expect(root).toHaveClassName('HeroSection-styleName--default');
});
it('renders a Link if linkTo prop is supplied', () => {
const linkTo = '/somewhere/';
const root = shallowRender({ linkTo });
const link = root.find(Link);
expect(link).toHaveProp('className', 'HeroSection-link-wrapper');
expect(link).toHaveProp('to', linkTo);
expect(root.find('.HeroSection-wrapper')).toHaveLength(0);
});
it('renders children inside a Link when there is a linkTo prop', () => {
const root = shallowRender({ children: 'hello!', linkTo: '/homepage/' });
expect(root.find(Link)).toHaveLength(1);
expect(root.find(Link).find('.HeroSection-content')).toHaveProp(
'children',
'hello!',
);
});
it('renders a div if linkTo prop is not supplied', () => {
const root = shallowRender();
expect(root.find('.HeroSection-link-wrapper')).toHaveLength(0);
expect(root.find('.HeroSection-wrapper')).toHaveLength(1);
});
it('renders a children inside div with no links', () => {
const root = shallowRender({ children: 'hello!' });
expect(
root.find('.HeroSection-wrapper').find('.HeroSection-content'),
).toHaveText('hello!');
});
});

Просмотреть файл

@ -1,137 +0,0 @@
import knuthShuffle from 'knuth-shuffle';
import heroBannerOrderReducer, {
initialState,
setHeroBannerOrder,
} from 'amo/reducers/heroBanners';
describe(__filename, () => {
const defaultParams = { name: 'MegaHero', sections: ['1', '2', '3'] };
it('defaults to empty', () => {
const state = heroBannerOrderReducer(initialState, {});
expect(state).toEqual({});
});
it('creates a new key if one is not found', () => {
const knuthShuffleSpy = sinon.spy(knuthShuffle, 'knuthShuffle');
const state = heroBannerOrderReducer(
initialState,
setHeroBannerOrder({
name: 'NotAKnownKey1234',
sections: [1, 2, 3],
}),
);
sinon.assert.notCalled(knuthShuffleSpy);
expect(state).toMatchObject({
NotAKnownKey1234: { order: [0, 1, 2] },
});
});
it('randomizes the order if random prop is passed', () => {
const knuthShuffleSpy = sinon.spy(knuthShuffle, 'knuthShuffle');
const state = heroBannerOrderReducer(
initialState,
setHeroBannerOrder({
name: 'CoolPage',
random: true,
sections: [1, 2, 3],
}),
);
sinon.assert.called(knuthShuffleSpy);
expect(state).toMatchObject({
CoolPage: { order: expect.arrayContaining([0, 1, 2]) },
});
});
it('does not modify the original sections data', () => {
const knuthShuffleSpy = sinon.spy(knuthShuffle, 'knuthShuffle');
const sections = [1, 2, 3, 5];
heroBannerOrderReducer(
initialState,
setHeroBannerOrder({
name: 'CoolPage',
random: true,
sections,
}),
);
sinon.assert.called(knuthShuffleSpy);
expect(sections).toEqual([1, 2, 3, 5]);
});
it('limits the number of sections to three', () => {
const state = heroBannerOrderReducer(
initialState,
setHeroBannerOrder({
name: 'CoolPage',
sections: [1, 2, 3, 4, 5],
}),
);
expect(state).toMatchObject({
CoolPage: { order: expect.arrayContaining([0, 1, 2]) },
});
});
it('accepts fewer than three sections', () => {
const state = heroBannerOrderReducer(
initialState,
setHeroBannerOrder({
name: 'CoolPage',
sections: [1, 2],
}),
);
expect(state).toMatchObject({
CoolPage: { order: expect.arrayContaining([0, 1]) },
});
});
it('randomizes first and then picks three sections', () => {
const sections = [0, 1, 2, 3, 4, 5];
// Our sort algorithm is reverse ordering.
const knuthShuffleSpy = sinon
.stub(knuthShuffle, 'knuthShuffle')
.callsFake((sectionsToSort) => {
return sectionsToSort.reverse();
});
const state = heroBannerOrderReducer(
initialState,
setHeroBannerOrder({
name: 'CoolPage',
random: true,
sections,
}),
);
sinon.assert.called(knuthShuffleSpy);
expect(state).toMatchObject({
CoolPage: { order: [5, 4, 3] },
});
});
describe('carousel actions', () => {
it('requires name', () => {
const partialParams = { ...defaultParams };
delete partialParams.name;
expect(() => {
setHeroBannerOrder(partialParams);
}).toThrow(/name is required/);
});
it('requires sections', () => {
const partialParams = { ...defaultParams };
delete partialParams.sections;
expect(() => {
setHeroBannerOrder(partialParams);
}).toThrow(/sections are required/);
});
});
});

Просмотреть файл

@ -7523,11 +7523,6 @@ known-css-properties@^0.21.0:
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.21.0.tgz#15fbd0bbb83447f3ce09d8af247ed47c68ede80d"
integrity sha512-sZLUnTqimCkvkgRS+kbPlYW5o8q5w1cu+uIisKpEWkj31I8mx8kNG162DwRav8Zirkva6N5uoFsm9kzK4mUXjw==
knuth-shuffle@1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/knuth-shuffle/-/knuth-shuffle-1.0.8.tgz#929a467b0efd8d297bdcf318ca988a9f1037f80d"
integrity sha512-IdC4Hpp+mx53zTt6VAGsAtbGM0g4BV9fP8tTcviCosSwocHcRDw9uG5Rnv6wLWckF4r72qeXFoK9NkvV1gUJCQ==
language-subtag-registry@~0.3.2:
version "0.3.21"
resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a"