Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Category RootComponent Simple Re-Factor #1211

Merged
merged 14 commits into from
May 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions packages/peregrine/src/hooks/usePagination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useMemo, useState } from 'react';

export const usePagination = () => {
const [currentPage, setCurrentPage] = useState(0);
const [totalPages, setTotalPages] = useState(null);

const paginationState = { currentPage, totalPages };
const api = useMemo(() => ({ setCurrentPage, setTotalPages }), [
setCurrentPage,
setTotalPages
]);

return [paginationState, api];
tjwiebell marked this conversation as resolved.
Show resolved Hide resolved
};
1 change: 1 addition & 0 deletions packages/peregrine/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as Util from './util';
export { useApolloContext } from './hooks/useApolloContext';
export { useEventListener } from './hooks/useEventListener';
export { useDropdown } from './hooks/useDropdown';
export { usePagination } from './hooks/usePagination';
export { useQuery } from './hooks/useQuery';
export { useQueryResult } from './hooks/useQueryResult';
export { useSearchParam } from './hooks/useSearchParam';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders the correct tree 1`] = `
<article
className="a"
>
<h1
className="b"
>
<div
dangerouslySetInnerHTML={
Object {
"__html": "test",
}
}
/>
<div />
</h1>
<section
className="c"
>
<Classify(Gallery)
data={
Object {
"id": 1,
}
}
pageSize={6}
title="test"
/>
</section>
<div
className="d"
>
<withRouter(Classify(Pagination))
pageControl={Object {}}
/>
</div>
</article>
`;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { shallow } from 'enzyme';
import ShallowRenderer from 'react-test-renderer/shallow';

import CategoryContent from '../categoryContent';

Expand All @@ -21,15 +21,16 @@ const data = {
}
};

test('renders with props', () => {
const pageSize = 6;
const wrapper = shallow(
test('renders the correct tree', () => {
const shallowRenderer = new ShallowRenderer();
const tree = shallowRenderer.render(
<CategoryContent
pageControl={{}}
data={data}
pageSize={pageSize}
pageSize={6}
classes={classes}
/>
).dive();
expect(wrapper.hasClass(classes.root)).toBe(true);
);

expect(tree).toMatchSnapshot();
});
171 changes: 68 additions & 103 deletions packages/venia-concept/src/RootComponents/Category/category.js
Original file line number Diff line number Diff line change
@@ -1,119 +1,84 @@
import React, { Component } from 'react';
import React, { useEffect } from 'react';
import { string, number, shape } from 'prop-types';
import { compose } from 'redux';
import { connect, Query } from 'src/drivers';
import { usePagination, useQuery } from '@magento/peregrine';

import classify from 'src/classify';
import { setCurrentPage, setPrevPageTotal } from 'src/actions/catalog';
import { loadingIndicator } from 'src/components/LoadingIndicator';
import { mergeClasses } from 'src/classify';
import categoryQuery from 'src/queries/getCategory.graphql';
import CategoryContent from './categoryContent';
import { loadingIndicator } from 'src/components/LoadingIndicator';
import defaultClasses from './category.css';
import categoryQuery from 'src/queries/getCategory.graphql';

class Category extends Component {
static propTypes = {
id: number,
classes: shape({
gallery: string,
root: string,
title: string
}),
currentPage: number,
pageSize: number,
prevPageTotal: number
};
const Category = props => {
const { id, pageSize } = props;

// TODO: Should not be a default here, we just don't have
// the wiring in place to map route info down the tree (yet)
static defaultProps = {
id: 3
const [paginationValues, paginationApi] = usePagination();
const { currentPage, totalPages } = paginationValues;
const { setCurrentPage, setTotalPages } = paginationApi;

const pageControl = {
currentPage,
setPage: setCurrentPage,
updateTotalPages: setTotalPages,
totalPages
tjwiebell marked this conversation as resolved.
Show resolved Hide resolved
};

componentDidUpdate(prevProps) {
// If the current page has changed, scroll back up to the top.
if (this.props.currentPage !== prevProps.currentPage) {
window.scrollTo(0, 0);
}
}
const [queryResult, queryApi] = useQuery(categoryQuery);
const { data, error, loading } = queryResult;
const { runQuery, setLoading } = queryApi;
const classes = mergeClasses(defaultClasses, props.classes);

render() {
const {
id,
classes,
currentPage,
pageSize,
prevPageTotal,
setCurrentPage,
setPrevPageTotal
} = this.props;
useEffect(() => {
setLoading(true);
runQuery({
variables: {
id: Number(id),
onServer: false,
pageSize: Number(pageSize),
currentPage: Number(currentPage)
}
});

const pageControl = {
currentPage: currentPage,
setPage: setCurrentPage,
updateTotalPages: setPrevPageTotal,
totalPages: prevPageTotal
};
window.scrollTo({
left: 0,
top: 0,
behavior: 'smooth'
});
}, [id, pageSize, currentPage]);

return (
<Query
query={categoryQuery}
variables={{
id: Number(id),
onServer: false,
pageSize: Number(pageSize),
currentPage: Number(currentPage)
}}
>
{({ loading, error, data }) => {
if (error) return <div>Data Fetch Error</div>;
// If our pagination component has mounted, then we have
// a total page count in the store, so we continue to render
// with our last known total
if (loading)
return pageControl.totalPages ? (
<CategoryContent
pageControl={pageControl}
pageSize={pageSize}
/>
) : (
loadingIndicator
);
const totalPagesFromData = data
? data.category.products.page_info.total_pages
: null;
useEffect(() => {
setTotalPages(totalPagesFromData);
}, [totalPagesFromData]);

// TODO: Retrieve the page total from GraphQL when ready
const pageCount =
data.category.products.total_count / pageSize;
const totalPages = Math.ceil(pageCount);
const totalWrapper = {
...pageControl,
totalPages: totalPages
};
if (error) return <div>Data Fetch Error</div>;
// show loading indicator until our data has been fetched and pagination state has been updated
if (!totalPages) return loadingIndicator;

return (
<CategoryContent
classes={classes}
pageControl={totalWrapper}
data={data}
/>
);
}}
</Query>
);
}
}
// if our data is still loading, we want to reset our data state to null
return (
<CategoryContent
classes={classes}
pageControl={pageControl}
data={loading ? null : data}
/>
);
};

const mapStateToProps = ({ catalog }) => {
return {
currentPage: catalog.currentPage,
pageSize: catalog.pageSize,
prevPageTotal: catalog.prevPageTotal
};
Category.propTypes = {
id: number,
classes: shape({
gallery: string,
root: string,
title: string
}),
pageSize: number
};

Category.defaultProps = {
id: 3,
pageSize: 6
};
const mapDispatchToProps = { setCurrentPage, setPrevPageTotal };

export default compose(
classify(defaultClasses),
connect(
mapStateToProps,
mapDispatchToProps
)
)(Category);
export default Category;
Original file line number Diff line number Diff line change
@@ -1,36 +1,35 @@
import React, { Component } from 'react';
import classify from 'src/classify';
import React from 'react';
import { mergeClasses } from 'src/classify';
import Gallery from 'src/components/Gallery';
import Pagination from 'src/components/Pagination';
import defaultClasses from './category.css';

class CategoryContent extends Component {
render() {
const { classes, pageControl, data, pageSize } = this.props;
const items = data ? data.category.products.items : null;
const title = data ? data.category.description : null;
const categoryTitle = data ? data.category.name : null;
const CategoryContent = props => {
const { pageControl, data, pageSize } = props;
const classes = mergeClasses(defaultClasses, props.classes);
const items = data ? data.category.products.items : null;
const title = data ? data.category.description : null;
const categoryTitle = data ? data.category.name : null;

return (
<article className={classes.root}>
<h1 className={classes.title}>
{/* TODO: Switch to RichContent component from Peregrine when merged */}
<div
dangerouslySetInnerHTML={{
__html: title
}}
/>
<div className={classes.categoryTitle}>{categoryTitle}</div>
</h1>
<section className={classes.gallery}>
<Gallery data={items} title={title} pageSize={pageSize} />
</section>
<div className={classes.pagination}>
<Pagination pageControl={pageControl} />
</div>
</article>
);
}
}
return (
<article className={classes.root}>
<h1 className={classes.title}>
{/* TODO: Switch to RichContent component from Peregrine when merged */}
<div
dangerouslySetInnerHTML={{
__html: title
}}
/>
<div className={classes.categoryTitle}>{categoryTitle}</div>
</h1>
<section className={classes.gallery}>
<Gallery data={items} title={title} pageSize={pageSize} />
</section>
<div className={classes.pagination}>
<Pagination pageControl={pageControl} />
</div>
</article>
);
};

export default classify(defaultClasses)(CategoryContent);
export default CategoryContent;
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,3 @@ test('rightSkip skips toward last page', () => {
expect(setPage).toHaveBeenCalledTimes(1);
expect(setPage).toHaveBeenLastCalledWith(8);
});

test('updateTotalPages is called on component mount', () => {
TestRenderer.create(
<MemoryRouter>
<Pagination pageControl={defaultPageControl} />
</MemoryRouter>
);

expect(updateTotalPages).toHaveBeenCalledTimes(1);
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ class Pagination extends Component {
};

componentDidMount() {
// updateTotalPages pushes the current page count of a category query to
// redux so it knows how many tiles to render even in the Query
// component's loading state
const { updateTotalPages, totalPages } = this.props.pageControl;
updateTotalPages(totalPages);
tjwiebell marked this conversation as resolved.
Show resolved Hide resolved
this.syncPage();
}

Expand Down
3 changes: 3 additions & 0 deletions packages/venia-concept/src/queries/getCategory.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ query category($id: Int!, $pageSize: Int!, $currentPage: Int!, $onServer: Boolea
}
}
}
page_info {
total_pages
}
total_count
}
meta_title @include(if: $onServer)
Expand Down