diff --git a/src/components/RoutesProvider/RoutesProvider.js b/src/components/RoutesProvider/RoutesProvider.js
deleted file mode 100644
index 6173cffd..00000000
--- a/src/components/RoutesProvider/RoutesProvider.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React, { Component, PropTypes } from 'react';
-import * as propTypes from '../../util/propTypes';
-
-class RoutesProvider extends Component {
- getChildContext() {
- return { flattenedRoutes: this.props.flattenedRoutes };
- }
-
- render() {
- return React.Children.only(this.props.children);
- }
-}
-
-const { arrayOf, node } = PropTypes;
-
-RoutesProvider.childContextTypes = { flattenedRoutes: arrayOf(propTypes.route).isRequired };
-
-RoutesProvider.defaultProps = { children: {} };
-
-RoutesProvider.propTypes = { flattenedRoutes: arrayOf(propTypes.route).isRequired, children: node };
-
-export default RoutesProvider;
diff --git a/src/components/RoutesProvider/RoutesProvider.test.js b/src/components/RoutesProvider/RoutesProvider.test.js
deleted file mode 100644
index ccc8b705..00000000
--- a/src/components/RoutesProvider/RoutesProvider.test.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React from 'react';
-import { renderDeep } from '../../util/test-helpers';
-import RoutesProvider from './RoutesProvider';
-
-describe('RoutesProvider', () => {
- it('should contain routes from context', () => {
- const routesConf = [{ name: 'SomePage', path: 'some-page', component: () => null }];
- const Child = (props, context) => {
- return
{context.flattenedRoutes[0].name}
;
- };
- Child.contextTypes = { flattenedRoutes: React.PropTypes.array };
-
- const tree = renderDeep(
-
- );
- expect(tree.children).toContain('SomePage');
- });
-});
diff --git a/src/components/SaleDetailsPanel/__snapshots__/SaleDetailsPanel.test.js.snap b/src/components/SaleDetailsPanel/__snapshots__/SaleDetailsPanel.test.js.snap
index a807139c..ffd9f796 100644
--- a/src/components/SaleDetailsPanel/__snapshots__/SaleDetailsPanel.test.js.snap
+++ b/src/components/SaleDetailsPanel/__snapshots__/SaleDetailsPanel.test.js.snap
@@ -68,7 +68,7 @@ exports[`SaleDetailsPanel accepted matches snapshot 1`] = `
values={
Object {
"customerName": "customer1 display name",
- "listingLink":
listing1 title
- ,
+ ,
}
} />
@@ -422,7 +422,7 @@ exports[`SaleDetailsPanel autorejected matches snapshot 1`] = `
values={
Object {
"customerName": "customer1 display name",
- "listingLink":
listing1 title
- ,
+ ,
}
} />
@@ -776,7 +776,7 @@ exports[`SaleDetailsPanel canceled matches snapshot 1`] = `
values={
Object {
"customerName": "customer1 display name",
- "listingLink":
listing1 title
- ,
+ ,
}
} />
@@ -1142,7 +1142,7 @@ exports[`SaleDetailsPanel delivered matches snapshot 1`] = `
values={
Object {
"customerName": "customer1 display name",
- "listingLink":
listing1 title
- ,
+ ,
}
} />
@@ -1496,7 +1496,7 @@ exports[`SaleDetailsPanel preauthorized matches snapshot 1`] = `
values={
Object {
"customerName": "customer1 display name",
- "listingLink":
listing1 title
- ,
+ ,
}
} />
@@ -1862,7 +1862,7 @@ exports[`SaleDetailsPanel rejected matches snapshot 1`] = `
values={
Object {
"customerName": "customer1 display name",
- "listingLink":
listing1 title
- ,
+ ,
}
} />
diff --git a/src/components/SearchMapInfoCard/SearchMapInfoCard.js b/src/components/SearchMapInfoCard/SearchMapInfoCard.js
index 9648ea73..876541b7 100644
--- a/src/components/SearchMapInfoCard/SearchMapInfoCard.js
+++ b/src/components/SearchMapInfoCard/SearchMapInfoCard.js
@@ -5,10 +5,10 @@ import { withRouter } from 'react-router-dom';
import { injectIntl, intlShape } from 'react-intl';
import classNames from 'classnames';
import config from '../../config';
+import routeConfiguration from '../../routeConfiguration';
import * as propTypes from '../../util/propTypes';
import { formatMoney } from '../../util/currency';
import { ensureListing } from '../../util/data';
-import { withFlattenedRoutes } from '../../util/contextHelpers';
import { createResourceLocatorString } from '../../util/routes';
import { createSlug } from '../../util/urlHelpers';
import { ResponsiveImage } from '../../components';
@@ -21,23 +21,23 @@ const getPixelPositionOffset = (width, height) => {
return { x: -1 * (width / 2), y: -1 * (height + 3) };
};
-const createURL = (flattenedRoutes, history, listing) => {
+const createURL = (routes, history, listing) => {
const id = listing.id.uuid;
const slug = createSlug(listing.attributes.title);
const pathParams = { id, slug };
- return createResourceLocatorString('ListingPage', flattenedRoutes, pathParams, {});
+ return createResourceLocatorString('ListingPage', routes, pathParams, {});
};
// ListingCard is the listing info without overlayview or carousel controls
const ListingCard = props => {
- const { className, clickHandler, flattenedRoutes, history, intl, isInCarousel, listing } = props;
+ const { className, clickHandler, history, intl, isInCarousel, listing } = props;
const { title, price } = listing.attributes;
const formattedPrice = price && price.currency === config.currency
? formatMoney(intl, price)
: price.currency;
const firstImage = listing.images && listing.images.length > 0 ? listing.images[0] : null;
- const urlToListing = createURL(flattenedRoutes, history, listing);
+ const urlToListing = createURL(routeConfiguration(), history, listing);
// listing card anchor needs sometimes inherited border radius.
const classes = classNames(
@@ -100,7 +100,6 @@ ListingCard.propTypes = {
className: string,
listing: propTypes.listing.isRequired,
clickHandler: func.isRequired,
- flattenedRoutes: arrayOf(propTypes.route).isRequired,
history: shape({
push: func.isRequired,
}).isRequired,
@@ -127,7 +126,7 @@ class SearchMapInfoCard extends Component {
}
render() {
- const { className, rootClassName, intl, flattenedRoutes, history, listings } = this.props;
+ const { className, rootClassName, intl, history, listings } = this.props;
const currentListing = ensureListing(listings[this.state.currentListingIndex]);
const geolocation = currentListing.attributes.geolocation;
@@ -179,7 +178,6 @@ class SearchMapInfoCard extends Component {
- pathByRouteName(page, this.props.flattenedRoutes));
+ pathByRouteName(page, routes));
const isNotWhitelisted = !whitelistedPaths.includes(newLocation.pathname);
// Show reminder
@@ -126,16 +128,16 @@ class TopbarComponent extends Component {
handleSubmit(values) {
const { search, selectedPlace } = values.location;
- const { flattenedRoutes, history } = this.props;
+ const { history } = this.props;
const { origin, bounds, country } = selectedPlace;
const searchParams = { address: search, origin, bounds, country };
- history.push(createResourceLocatorString('SearchPage', flattenedRoutes, {}, searchParams));
+ history.push(createResourceLocatorString('SearchPage', routeConfiguration(), {}, searchParams));
}
handleLogout() {
- const { onLogout, history, flattenedRoutes } = this.props;
+ const { onLogout, history } = this.props;
onLogout().then(() => {
- const path = pathByRouteName('LandingPage', flattenedRoutes);
+ const path = pathByRouteName('LandingPage', routeConfiguration());
// In production we ensure that data is really lost,
// but in development mode we use stored values for debugging
@@ -349,7 +351,7 @@ TopbarComponent.defaultProps = {
sendVerificationEmailError: null,
};
-const { arrayOf, bool, func, instanceOf, number, shape, string } = PropTypes;
+const { bool, func, instanceOf, number, shape, string } = PropTypes;
TopbarComponent.propTypes = {
className: string,
@@ -384,14 +386,11 @@ TopbarComponent.propTypes = {
height: number.isRequired,
}).isRequired,
- // from withFlattenedRoutes
- flattenedRoutes: arrayOf(propTypes.route).isRequired,
-
// from injectIntl
intl: intlShape.isRequired,
};
-const Topbar = compose(withViewport, withFlattenedRoutes, injectIntl)(TopbarComponent);
+const Topbar = compose(withViewport, injectIntl)(TopbarComponent);
Topbar.displayName = 'Topbar';
diff --git a/src/components/TopbarDesktop/TopbarDesktop.js b/src/components/TopbarDesktop/TopbarDesktop.js
index caad8afc..8da8f7c4 100644
--- a/src/components/TopbarDesktop/TopbarDesktop.js
+++ b/src/components/TopbarDesktop/TopbarDesktop.js
@@ -1,7 +1,7 @@
import React, { PropTypes } from 'react';
import { FormattedMessage, intlShape } from 'react-intl';
import classNames from 'classnames';
-import { ACCOUNT_SETTINGS_PAGES } from '../../routesConfiguration';
+import { ACCOUNT_SETTINGS_PAGES } from '../../routeConfiguration';
import * as propTypes from '../../util/propTypes';
import {
Avatar,
diff --git a/src/components/TopbarDesktop/TopbarDesktop.test.js b/src/components/TopbarDesktop/TopbarDesktop.test.js
index cbe4653f..6ee1ac94 100644
--- a/src/components/TopbarDesktop/TopbarDesktop.test.js
+++ b/src/components/TopbarDesktop/TopbarDesktop.test.js
@@ -1,9 +1,6 @@
import React from 'react';
import { fakeIntl } from '../../util/test-data';
import { renderDeep } from '../../util/test-helpers';
-import { RoutesProvider } from '../../components';
-import routesConfiguration from '../../routesConfiguration';
-import { flattenRoutes } from '../../util/routes';
import TopbarDesktop from './TopbarDesktop';
const noop = () => null;
@@ -11,7 +8,6 @@ const noop = () => null;
describe('TopbarDesktop', () => {
it('data matches snapshot', () => {
window.google = { maps: {} };
- const flattenedRoutes = flattenRoutes(routesConfiguration);
const topbarProps = {
isAuthenticated: true,
currentUserHasListings: true,
@@ -20,11 +16,7 @@ describe('TopbarDesktop', () => {
intl: fakeIntl,
onLogout: noop,
};
- const tree = renderDeep(
-
-
-
- );
+ const tree = renderDeep();
delete window.google;
expect(tree).toMatchSnapshot();
});
diff --git a/src/components/TopbarMobileMenu/TopbarMobileMenu.js b/src/components/TopbarMobileMenu/TopbarMobileMenu.js
index 50acf0e9..2fcd1abb 100644
--- a/src/components/TopbarMobileMenu/TopbarMobileMenu.js
+++ b/src/components/TopbarMobileMenu/TopbarMobileMenu.js
@@ -5,7 +5,7 @@
import React, { PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
-import { ACCOUNT_SETTINGS_PAGES } from '../../routesConfiguration';
+import { ACCOUNT_SETTINGS_PAGES } from '../../routeConfiguration';
import * as propTypes from '../../util/propTypes';
import { ensureCurrentUser } from '../../util/data';
import { AvatarLarge, InlineTextButton, NamedLink, NotificationBadge } from '../../components';
diff --git a/src/components/UserNav/UserNav.js b/src/components/UserNav/UserNav.js
index a06b4c60..17d5959f 100644
--- a/src/components/UserNav/UserNav.js
+++ b/src/components/UserNav/UserNav.js
@@ -1,7 +1,7 @@
import React, { PropTypes } from 'react';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
-import { ACCOUNT_SETTINGS_PAGES } from '../../routesConfiguration';
+import { ACCOUNT_SETTINGS_PAGES } from '../../routeConfiguration';
import { TabNavHorizontal } from '../../components';
import css from './UserNav.css';
diff --git a/src/components/index.js b/src/components/index.js
index 527152d1..7850ae1c 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -1,159 +1,90 @@
-import AddImages from './AddImages/AddImages';
-import Avatar, { AvatarMedium, AvatarLarge } from './Avatar/Avatar';
-import BirthdayInputField from './BirthdayInputField/BirthdayInputField';
-import BookingBreakdown from './BookingBreakdown/BookingBreakdown';
-import Button, { PrimaryButton, SecondaryButton, InlineTextButton } from './Button/Button';
-import CurrencyInputField from './CurrencyInputField/CurrencyInputField';
-import DateInputField from './DateInputField/DateInputField';
-import DateRangeInputField from './DateRangeInputField/DateRangeInputField';
-import Discussion from './Discussion/Discussion';
-import EditListingDescriptionPanel from './EditListingDescriptionPanel/EditListingDescriptionPanel';
-import EditListingLocationPanel from './EditListingLocationPanel/EditListingLocationPanel';
-import EditListingPhotosPanel from './EditListingPhotosPanel/EditListingPhotosPanel';
-import EditListingPricingPanel from './EditListingPricingPanel/EditListingPricingPanel';
-import EditListingWizard from './EditListingWizard/EditListingWizard';
-import ExpandingTextarea from './ExpandingTextarea/ExpandingTextarea';
-import ExternalLink from './ExternalLink/ExternalLink';
-import FilterPanel from './FilterPanel/FilterPanel';
-import Form from './Form/Form';
-import HeroSection from './HeroSection/HeroSection';
-import IconBannedUser from './IconBannedUser/IconBannedUser';
-import IconCheckmark from './IconCheckmark/IconCheckmark';
-import IconClose from './IconClose/IconClose';
-import IconEmailAttention from './IconEmailAttention/IconEmailAttention';
-import IconEmailSent from './IconEmailSent/IconEmailSent';
-import IconEmailSuccess from './IconEmailSuccess/IconEmailSuccess';
-import IconKeys from './IconKeys/IconKeys';
-import IconKeysSuccess from './IconKeysSuccess/IconKeysSuccess';
-import IconSearch from './IconSearch/IconSearch';
-import IconSpinner from './IconSpinner/IconSpinner';
-import ImageCarousel from './ImageCarousel/ImageCarousel';
-import ImageFromFile from './ImageFromFile/ImageFromFile';
-import LayoutSideNavigation, {
+export { default as AddImages } from './AddImages/AddImages';
+export { default as Avatar, AvatarMedium, AvatarLarge } from './Avatar/Avatar';
+export { default as BirthdayInputField } from './BirthdayInputField/BirthdayInputField';
+export { default as BookingBreakdown } from './BookingBreakdown/BookingBreakdown';
+export {
+ default as Button,
+ PrimaryButton,
+ SecondaryButton,
+ InlineTextButton,
+} from './Button/Button';
+export { default as CurrencyInputField } from './CurrencyInputField/CurrencyInputField';
+export { default as DateInputField } from './DateInputField/DateInputField';
+export { default as DateRangeInputField } from './DateRangeInputField/DateRangeInputField';
+export { default as Discussion } from './Discussion/Discussion';
+export {
+ default as EditListingDescriptionPanel,
+} from './EditListingDescriptionPanel/EditListingDescriptionPanel';
+export {
+ default as EditListingLocationPanel,
+} from './EditListingLocationPanel/EditListingLocationPanel';
+export { default as EditListingPhotosPanel } from './EditListingPhotosPanel/EditListingPhotosPanel';
+export {
+ default as EditListingPricingPanel,
+} from './EditListingPricingPanel/EditListingPricingPanel';
+export { default as EditListingWizard } from './EditListingWizard/EditListingWizard';
+export { default as ExpandingTextarea } from './ExpandingTextarea/ExpandingTextarea';
+export { default as ExternalLink } from './ExternalLink/ExternalLink';
+export { default as FilterPanel } from './FilterPanel/FilterPanel';
+export { default as Form } from './Form/Form';
+export { default as HeroSection } from './HeroSection/HeroSection';
+export { default as IconBannedUser } from './IconBannedUser/IconBannedUser';
+export { default as IconCheckmark } from './IconCheckmark/IconCheckmark';
+export { default as IconClose } from './IconClose/IconClose';
+export { default as IconEmailAttention } from './IconEmailAttention/IconEmailAttention';
+export { default as IconEmailSent } from './IconEmailSent/IconEmailSent';
+export { default as IconEmailSuccess } from './IconEmailSuccess/IconEmailSuccess';
+export { default as IconKeys } from './IconKeys/IconKeys';
+export { default as IconKeysSuccess } from './IconKeysSuccess/IconKeysSuccess';
+export { default as IconSearch } from './IconSearch/IconSearch';
+export { default as IconSpinner } from './IconSpinner/IconSpinner';
+export { default as ImageCarousel } from './ImageCarousel/ImageCarousel';
+export { default as ImageFromFile } from './ImageFromFile/ImageFromFile';
+export {
+ default as LayoutSideNavigation,
ContentWrapper,
SideNavWrapper,
TopbarWrapper,
} from './LayoutSideNavigation/LayoutSideNavigation';
-import ListingCard from './ListingCard/ListingCard';
-import LocationAutocompleteInput, {
+export { default as ListingCard } from './ListingCard/ListingCard';
+export {
+ default as LocationAutocompleteInput,
LocationAutocompleteInputField,
} from './LocationAutocompleteInput/LocationAutocompleteInput';
-import ManageListingCard from './ManageListingCard/ManageListingCard';
-import Map from './Map/Map';
-import MapPanel from './MapPanel/MapPanel';
-import Menu from './Menu/Menu';
-import MenuContent from './MenuContent/MenuContent';
-import MenuItem from './MenuItem/MenuItem';
-import MenuLabel from './MenuLabel/MenuLabel';
-import Modal from './Modal/Modal';
-import ModalInMobile from './ModalInMobile/ModalInMobile';
-import NamedLink from './NamedLink/NamedLink';
-import NamedRedirect from './NamedRedirect/NamedRedirect';
-import NotificationBadge from './NotificationBadge/NotificationBadge';
-import OrderDetailsPanel from './OrderDetailsPanel/OrderDetailsPanel';
-import OrderDiscussionPanel from './OrderDiscussionPanel/OrderDiscussionPanel';
-import Page from './Page/Page';
-import PaginationLinks from './PaginationLinks/PaginationLinks';
-import Promised from './Promised/Promised';
-import ResponsiveImage from './ResponsiveImage/ResponsiveImage';
-import RoutesProvider from './RoutesProvider/RoutesProvider';
-import SaleDetailsPanel from './SaleDetailsPanel/SaleDetailsPanel';
-import SearchMap from './SearchMap/SearchMap';
-import SearchMapGroupLabel from './SearchMapGroupLabel/SearchMapGroupLabel';
-import SearchMapInfoCard from './SearchMapInfoCard/SearchMapInfoCard';
-import SearchMapPriceLabel from './SearchMapPriceLabel/SearchMapPriceLabel';
-import SearchResultsPanel from './SearchResultsPanel/SearchResultsPanel';
-import SelectField from './SelectField/SelectField';
-import StripeBankAccountTokenInputField
- from './StripeBankAccountTokenInputField/StripeBankAccountTokenInputField';
-import TabNav from './TabNav/TabNav';
-import TabNavHorizontal from './TabNavHorizontal/TabNavHorizontal';
-import Tabs from './Tabs/Tabs';
-import TextInputField from './TextInputField/TextInputField';
-import Topbar from './Topbar/Topbar';
-import TopbarDesktop from './TopbarDesktop/TopbarDesktop';
-import TopbarMobileMenu from './TopbarMobileMenu/TopbarMobileMenu';
-import UserNav from './UserNav/UserNav';
-import ValidationError from './ValidationError/ValidationError';
-
+export { default as ManageListingCard } from './ManageListingCard/ManageListingCard';
+export { default as Map } from './Map/Map';
+export { default as MapPanel } from './MapPanel/MapPanel';
+export { default as Menu } from './Menu/Menu';
+export { default as MenuContent } from './MenuContent/MenuContent';
+export { default as MenuItem } from './MenuItem/MenuItem';
+export { default as MenuLabel } from './MenuLabel/MenuLabel';
+export { default as Modal } from './Modal/Modal';
+export { default as ModalInMobile } from './ModalInMobile/ModalInMobile';
+export { default as NamedLink } from './NamedLink/NamedLink';
+export { default as NamedRedirect } from './NamedRedirect/NamedRedirect';
+export { default as NotificationBadge } from './NotificationBadge/NotificationBadge';
+export { default as OrderDetailsPanel } from './OrderDetailsPanel/OrderDetailsPanel';
+export { default as OrderDiscussionPanel } from './OrderDiscussionPanel/OrderDiscussionPanel';
+export { default as Page } from './Page/Page';
+export { default as PaginationLinks } from './PaginationLinks/PaginationLinks';
+export { default as Promised } from './Promised/Promised';
+export { default as ResponsiveImage } from './ResponsiveImage/ResponsiveImage';
+export { default as SaleDetailsPanel } from './SaleDetailsPanel/SaleDetailsPanel';
+export { default as SearchMap } from './SearchMap/SearchMap';
+export { default as SearchMapGroupLabel } from './SearchMapGroupLabel/SearchMapGroupLabel';
+export { default as SearchMapInfoCard } from './SearchMapInfoCard/SearchMapInfoCard';
+export { default as SearchMapPriceLabel } from './SearchMapPriceLabel/SearchMapPriceLabel';
+export { default as SearchResultsPanel } from './SearchResultsPanel/SearchResultsPanel';
+export { default as SelectField } from './SelectField/SelectField';
export {
- AddImages,
- Avatar,
- AvatarLarge,
- AvatarMedium,
- BirthdayInputField,
- BookingBreakdown,
- Button,
- ContentWrapper,
- CurrencyInputField,
- DateInputField,
- DateRangeInputField,
- Discussion,
- EditListingDescriptionPanel,
- EditListingLocationPanel,
- EditListingPhotosPanel,
- EditListingPricingPanel,
- EditListingWizard,
- ExpandingTextarea,
- ExternalLink,
- FilterPanel,
- Form,
- HeroSection,
- IconBannedUser,
- IconCheckmark,
- IconClose,
- IconEmailAttention,
- IconEmailSent,
- IconEmailSuccess,
- IconKeys,
- IconKeysSuccess,
- IconSearch,
- IconSpinner,
- ImageCarousel,
- ImageFromFile,
- InlineTextButton,
- LayoutSideNavigation,
- ListingCard,
- LocationAutocompleteInput,
- LocationAutocompleteInputField,
- ManageListingCard,
- Map,
- MapPanel,
- Menu,
- MenuContent,
- MenuItem,
- MenuLabel,
- Modal,
- ModalInMobile,
- NamedLink,
- NamedRedirect,
- NotificationBadge,
- OrderDetailsPanel,
- OrderDiscussionPanel,
- Page,
- PaginationLinks,
- PrimaryButton,
- Promised,
- ResponsiveImage,
- RoutesProvider,
- SaleDetailsPanel,
- SearchMap,
- SearchMapGroupLabel,
- SearchMapInfoCard,
- SearchMapPriceLabel,
- SearchResultsPanel,
- SecondaryButton,
- SelectField,
- SideNavWrapper,
- StripeBankAccountTokenInputField,
- TabNav,
- TabNavHorizontal,
- Tabs,
- TextInputField,
- Topbar,
- TopbarDesktop,
- TopbarMobileMenu,
- TopbarWrapper,
- UserNav,
- ValidationError,
-};
+ default as StripeBankAccountTokenInputField,
+} from './StripeBankAccountTokenInputField/StripeBankAccountTokenInputField';
+export { default as TabNav } from './TabNav/TabNav';
+export { default as TabNavHorizontal } from './TabNavHorizontal/TabNavHorizontal';
+export { default as Tabs } from './Tabs/Tabs';
+export { default as TextInputField } from './TextInputField/TextInputField';
+export { default as Topbar } from './Topbar/Topbar';
+export { default as TopbarDesktop } from './TopbarDesktop/TopbarDesktop';
+export { default as TopbarMobileMenu } from './TopbarMobileMenu/TopbarMobileMenu';
+export { default as UserNav } from './UserNav/UserNav';
+export { default as ValidationError } from './ValidationError/ValidationError';
diff --git a/src/containers/CheckoutPage/CheckoutPage.js b/src/containers/CheckoutPage/CheckoutPage.js
index 686523f3..4d1abd41 100644
--- a/src/containers/CheckoutPage/CheckoutPage.js
+++ b/src/containers/CheckoutPage/CheckoutPage.js
@@ -4,10 +4,10 @@ import { connect } from 'react-redux';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { withRouter } from 'react-router-dom';
import classNames from 'classnames';
+import routeConfiguration from '../../routeConfiguration';
import { pathByRouteName } from '../../util/routes';
import * as propTypes from '../../util/propTypes';
import { ensureListing, ensureUser, ensureTransaction, ensureBooking } from '../../util/data';
-import { withFlattenedRoutes } from '../../util/contextHelpers';
import { createSlug } from '../../util/urlHelpers';
import {
isTransactionInitiateAmountTooLowError,
@@ -99,7 +99,7 @@ export class CheckoutPageComponent extends Component {
}
this.setState({ submitting: true });
- const { flattenedRoutes, history, sendOrderRequest, speculatedTransaction } = this.props;
+ const { history, sendOrderRequest, speculatedTransaction } = this.props;
const requestParams = {
listingId: this.state.pageData.listing.id,
cardToken,
@@ -110,7 +110,7 @@ export class CheckoutPageComponent extends Component {
sendOrderRequest(requestParams)
.then(orderId => {
this.setState({ submitting: false });
- const orderDetailsPath = pathByRouteName('OrderDetailsPage', flattenedRoutes, {
+ const orderDetailsPath = pathByRouteName('OrderDetailsPage', routeConfiguration(), {
id: orderId.uuid,
});
clearData(STORAGE_KEY);
@@ -375,7 +375,7 @@ CheckoutPageComponent.defaultProps = {
currentUser: null,
};
-const { arrayOf, func, instanceOf, shape, string, bool } = PropTypes;
+const { func, instanceOf, shape, string, bool } = PropTypes;
CheckoutPageComponent.propTypes = {
authInfoError: instanceOf(Error),
@@ -404,9 +404,6 @@ CheckoutPageComponent.propTypes = {
history: shape({
push: func.isRequired,
}).isRequired,
-
- // from withFlattenedRoutes
- flattenedRoutes: arrayOf(propTypes.route).isRequired,
};
const mapStateToProps = state => {
@@ -439,12 +436,9 @@ const mapDispatchToProps = dispatch => ({
dispatch(speculateTransaction(listingId, bookingStart, bookingEnd)),
});
-const CheckoutPage = compose(
- withRouter,
- connect(mapStateToProps, mapDispatchToProps),
- withFlattenedRoutes,
- injectIntl
-)(CheckoutPageComponent);
+const CheckoutPage = compose(withRouter, connect(mapStateToProps, mapDispatchToProps), injectIntl)(
+ CheckoutPageComponent
+);
CheckoutPage.setInitialValues = initialValues => setInitialValues(initialValues);
diff --git a/src/containers/CheckoutPage/CheckoutPage.test.js b/src/containers/CheckoutPage/CheckoutPage.test.js
index 5cbb6652..a1b778bd 100644
--- a/src/containers/CheckoutPage/CheckoutPage.test.js
+++ b/src/containers/CheckoutPage/CheckoutPage.test.js
@@ -14,7 +14,6 @@ describe('CheckoutPage', () => {
bookingStart: new Date(Date.UTC(2017, 3, 14)),
bookingEnd: new Date(Date.UTC(2017, 3, 16)),
},
- flattenedRoutes: [],
history: { push: noop },
intl: fakeIntl,
listing,
diff --git a/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap b/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap
index 5f01f295..ac0c2869 100644
--- a/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap
+++ b/src/containers/CheckoutPage/__snapshots__/CheckoutPage.test.js.snap
@@ -4,7 +4,7 @@ exports[`CheckoutPage matches snapshot 1`] = `
logoutError={null}
title="CheckoutPage.title">
-
-
+
diff --git a/src/containers/EditListingPage/EditListingPage.js b/src/containers/EditListingPage/EditListingPage.js
index 471c0029..4fb797d1 100644
--- a/src/containers/EditListingPage/EditListingPage.js
+++ b/src/containers/EditListingPage/EditListingPage.js
@@ -59,7 +59,6 @@ export const EditListingPageComponent = props => {
currentUserHasOrders,
createStripeAccountError,
fetchInProgress,
- flattenedRoutes,
getListing,
history,
intl,
@@ -168,7 +167,6 @@ export const EditListingPageComponent = props => {
errors={errors}
fetchInProgress={fetchInProgress}
newListingCreated={newListingCreated}
- flattenedRoutes={flattenedRoutes}
history={history}
images={images}
listing={isNew ? page.listingDraft : currentListing}
@@ -211,7 +209,7 @@ EditListingPageComponent.defaultProps = {
sendVerificationEmailError: null,
};
-const { arrayOf, bool, func, instanceOf, number, object, shape, string, oneOf } = PropTypes;
+const { bool, func, instanceOf, number, object, shape, string, oneOf } = PropTypes;
EditListingPageComponent.propTypes = {
authInfoError: instanceOf(Error),
@@ -221,7 +219,6 @@ EditListingPageComponent.propTypes = {
currentUserHasListings: bool.isRequired,
currentUserHasOrders: bool,
fetchInProgress: bool.isRequired,
- flattenedRoutes: arrayOf(propTypes.route).isRequired,
getListing: func.isRequired,
isAuthenticated: bool.isRequired,
logoutError: instanceOf(Error),
diff --git a/src/containers/EditListingPage/EditListingPage.test.js b/src/containers/EditListingPage/EditListingPage.test.js
index 1fe2b1c9..d3c1f810 100644
--- a/src/containers/EditListingPage/EditListingPage.test.js
+++ b/src/containers/EditListingPage/EditListingPage.test.js
@@ -15,7 +15,6 @@ describe('EditListingPageComponent', () => {
isAuthenticated={false}
authInProgress={false}
fetchInProgress={false}
- flattenedRoutes={[]}
location={{ search: '' }}
history={{ push: noop }}
getListing={getListing}
diff --git a/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap b/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap
index 5c9b4c6e..4a18a710 100644
--- a/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap
+++ b/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap
@@ -38,7 +38,6 @@ exports[`EditListingPageComponent matches snapshot 1`] = `
}
}
fetchInProgress={false}
- flattenedRoutes={Array []}
history={
Object {
"push": [Function],
diff --git a/src/containers/InboxPage/InboxPage.test.js b/src/containers/InboxPage/InboxPage.test.js
index 6c99e39e..70ff35d3 100644
--- a/src/containers/InboxPage/InboxPage.test.js
+++ b/src/containers/InboxPage/InboxPage.test.js
@@ -9,15 +9,13 @@ import {
createBooking,
} from '../../util/test-data';
import { InboxPageComponent, InboxItem } from './InboxPage';
-import routesConfiguration from '../../routesConfiguration';
-import { flattenRoutes } from '../../util/routes';
+import routeConfiguration from '../../routeConfiguration';
import { TX_TRANSITION_PREAUTHORIZE } from '../../util/propTypes';
const noop = () => null;
describe('InboxPage', () => {
it('matches snapshot', () => {
- const flattenedRoutes = flattenRoutes(routesConfiguration);
const provider = createUser('provider-user-id');
const customer = createUser('customer-user-id');
const currentUserProvider = createCurrentUser('provider-user-id');
@@ -76,9 +74,7 @@ describe('InboxPage', () => {
// Deeply render one InboxItem
const orderItem = renderDeep(
-
-
-
+
);
expect(orderItem).toMatchSnapshot();
@@ -126,9 +122,7 @@ describe('InboxPage', () => {
// Deeply render one InboxItem
const saleItem = renderDeep(
-
-
-
+
);
expect(saleItem).toMatchSnapshot();
});
diff --git a/src/containers/LandingPage/LandingPage.js b/src/containers/LandingPage/LandingPage.js
index c7f7a26d..8395cff7 100644
--- a/src/containers/LandingPage/LandingPage.js
+++ b/src/containers/LandingPage/LandingPage.js
@@ -6,10 +6,9 @@ import { injectIntl, intlShape } from 'react-intl';
import { sendVerificationEmail } from '../../ducks/user.duck';
import { logout, authenticationInProgress } from '../../ducks/Auth.duck';
import { manageDisableScrolling, isScrollingDisabled } from '../../ducks/UI.duck';
-import { Page, HeroSection, Topbar } from '../../components';
import * as propTypes from '../../util/propTypes';
-import { withFlattenedRoutes } from '../../util/contextHelpers';
import config from '../../config';
+import { Page, HeroSection, Topbar } from '../../components';
import facebookImage from '../../assets/saunatimeFacebook-1200x630.jpg';
import twitterImage from '../../assets/saunatimeTwitter-600x314.jpg';
@@ -22,7 +21,6 @@ export const LandingPageComponent = props => {
currentUser,
currentUserHasListings,
currentUserHasOrders,
- flattenedRoutes,
history,
intl,
isAuthenticated,
@@ -87,12 +85,7 @@ export const LandingPageComponent = props => {
sendVerificationEmailError={sendVerificationEmailError}
/>
-
+
);
@@ -107,7 +100,7 @@ LandingPageComponent.defaultProps = {
sendVerificationEmailError: null,
};
-const { array, bool, func, instanceOf, number, object } = PropTypes;
+const { bool, func, instanceOf, number, object } = PropTypes;
LandingPageComponent.propTypes = {
authInfoError: instanceOf(Error),
@@ -125,9 +118,6 @@ LandingPageComponent.propTypes = {
sendVerificationEmailError: instanceOf(Error),
onResendVerificationEmail: func.isRequired,
- // from withFlattenedRoutes
- flattenedRoutes: array.isRequired,
-
// from withRouter
history: object.isRequired,
location: object.isRequired,
@@ -168,11 +158,8 @@ const mapDispatchToProps = dispatch => ({
onResendVerificationEmail: () => dispatch(sendVerificationEmail()),
});
-const LandingPage = compose(
- connect(mapStateToProps, mapDispatchToProps),
- injectIntl,
- withRouter,
- withFlattenedRoutes
-)(LandingPageComponent);
+const LandingPage = compose(connect(mapStateToProps, mapDispatchToProps), injectIntl, withRouter)(
+ LandingPageComponent
+);
export default LandingPage;
diff --git a/src/containers/LandingPage/LandingPage.test.js b/src/containers/LandingPage/LandingPage.test.js
index 06ed8f05..7e7c95ba 100644
--- a/src/containers/LandingPage/LandingPage.test.js
+++ b/src/containers/LandingPage/LandingPage.test.js
@@ -3,7 +3,7 @@ import { fakeIntl } from '../../util/test-data';
import { renderShallow } from '../../util/test-helpers';
import { LandingPageComponent } from './LandingPage';
import { RoutesProvider } from '../../components';
-import routesConfiguration from '../../routesConfiguration';
+import routeConfiguration from '../../routeConfiguration';
const noop = () => null;
@@ -11,7 +11,6 @@ describe('LandingPage', () => {
it('matches snapshot', () => {
const tree = renderShallow(
{
}
};
-const { arrayOf, bool, func, instanceOf, number, object, oneOf, shape, string } = PropTypes;
+const { bool, func, instanceOf, number, object, oneOf, shape, string } = PropTypes;
ActionBar.propTypes = {
isOwnListing: bool.isRequired,
@@ -114,7 +115,7 @@ export class ListingPageComponent extends Component {
}
handleSubmit(values) {
- const { flattenedRoutes, history, getListing, params, useInitialValues } = this.props;
+ const { history, getListing, params, useInitialValues } = this.props;
const listingId = new UUID(params.id);
const listing = getListing(listingId);
@@ -130,15 +131,16 @@ export class ListingPageComponent extends Component {
},
};
+ const routes = routeConfiguration();
// Customize checkout page state with current listing and selected bookingDates
- const { setInitialValues } = findRouteByRouteName('CheckoutPage', flattenedRoutes);
+ const { setInitialValues } = findRouteByRouteName('CheckoutPage', routes);
useInitialValues(setInitialValues, initialValues);
// Redirect to CheckoutPage
history.push(
createResourceLocatorString(
'CheckoutPage',
- flattenedRoutes,
+ routes,
{ id: listing.id.uuid, slug: createSlug(listing.attributes.title) },
{}
)
@@ -167,7 +169,6 @@ export class ListingPageComponent extends Component {
sendVerificationEmailInProgress,
sendVerificationEmailError,
onResendVerificationEmail,
- flattenedRoutes,
} = this.props;
const listingId = new UUID(params.id);
const currentListing = ensureListing(getListing(listingId));
@@ -345,9 +346,13 @@ export class ListingPageComponent extends Component {
{ title, price: formattedPrice, siteTitle }
);
- const canonicalPath = createResourceLocatorString('ListingPageCanonical', flattenedRoutes, {
- id: listingId.uuid,
- });
+ const canonicalPath = createResourceLocatorString(
+ 'ListingPageCanonical',
+ routeConfiguration(),
+ {
+ id: listingId.uuid,
+ }
+ );
return (
null;
@@ -16,17 +21,8 @@ describe('ListingPage', () => {
const currentUser = createCurrentUser('user-2');
const listing1 = createListing('listing1', {}, { author: createUser('user-1') });
const getListing = () => listing1;
+
const props = {
- flattenedRoutes: [
- // Fake route since a circular dependency prevents using the
- // full routesConfiguration here
- {
- path: '/l/:id',
- exact: true,
- name: 'ListingPageCanonical',
- component: noop,
- },
- ],
location: { search: '' },
history: {
push: () => console.log('HistoryPush called'),
diff --git a/src/containers/LoginForm/LoginForm.test.js b/src/containers/LoginForm/LoginForm.test.js
index c7aa9db3..bffa3a3b 100644
--- a/src/containers/LoginForm/LoginForm.test.js
+++ b/src/containers/LoginForm/LoginForm.test.js
@@ -1,18 +1,10 @@
import React from 'react';
import { renderDeep } from '../../util/test-helpers';
-import { RoutesProvider } from '../../components';
-import routesConfiguration from '../../routesConfiguration';
-import { flattenRoutes } from '../../util/routes';
import LoginForm from './LoginForm';
describe('LoginForm', () => {
it('matches snapshot', () => {
- const flattenedRoutes = flattenRoutes(routesConfiguration);
- const tree = renderDeep(
-
-
-
- );
+ const tree = renderDeep();
expect(tree).toMatchSnapshot();
});
});
diff --git a/src/containers/NotFoundPage/NotFoundPage.js b/src/containers/NotFoundPage/NotFoundPage.js
index a91f7cdc..71d12113 100644
--- a/src/containers/NotFoundPage/NotFoundPage.js
+++ b/src/containers/NotFoundPage/NotFoundPage.js
@@ -3,7 +3,7 @@ import { injectIntl, intlShape, FormattedMessage } from 'react-intl';
import { compose } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
-import { withFlattenedRoutes } from '../../util/contextHelpers';
+import routeConfiguration from '../../routeConfiguration';
import { createResourceLocatorString } from '../../util/routes';
import * as propTypes from '../../util/propTypes';
import { sendVerificationEmail } from '../../ducks/user.duck';
@@ -40,7 +40,6 @@ export class NotFoundPageComponent extends Component {
sendVerificationEmailInProgress,
sendVerificationEmailError,
onResendVerificationEmail,
- flattenedRoutes,
intl,
} = this.props;
@@ -52,7 +51,9 @@ export class NotFoundPageComponent extends Component {
const { search, selectedPlace } = values.location;
const { origin, bounds, country } = selectedPlace;
const searchParams = { address: search, origin, bounds, country };
- history.push(createResourceLocatorString('SearchPage', flattenedRoutes, {}, searchParams));
+ history.push(
+ createResourceLocatorString('SearchPage', routeConfiguration(), {}, searchParams)
+ );
};
return (
@@ -99,7 +100,7 @@ NotFoundPageComponent.defaultProps = {
sendVerificationEmailError: null,
};
-const { bool, func, instanceOf, number, object, shape, array } = PropTypes;
+const { bool, func, instanceOf, number, object, shape } = PropTypes;
NotFoundPageComponent.propTypes = {
authInfoError: instanceOf(Error),
@@ -127,9 +128,6 @@ NotFoundPageComponent.propTypes = {
push: func.isRequired,
}).isRequired,
location: shape({ state: object }).isRequired,
-
- // from withFlattenedRoutes
- flattenedRoutes: array.isRequired,
};
const mapStateToProps = state => {
@@ -166,11 +164,8 @@ const mapDispatchToProps = dispatch => ({
onResendVerificationEmail: () => dispatch(sendVerificationEmail()),
});
-const NotFoundPage = compose(
- connect(mapStateToProps, mapDispatchToProps),
- withRouter,
- injectIntl,
- withFlattenedRoutes
-)(NotFoundPageComponent);
+const NotFoundPage = compose(connect(mapStateToProps, mapDispatchToProps), withRouter, injectIntl)(
+ NotFoundPageComponent
+);
export default NotFoundPage;
diff --git a/src/containers/NotFoundPage/NotFoundPage.test.js b/src/containers/NotFoundPage/NotFoundPage.test.js
index 00f6c827..867e5f05 100644
--- a/src/containers/NotFoundPage/NotFoundPage.test.js
+++ b/src/containers/NotFoundPage/NotFoundPage.test.js
@@ -21,7 +21,6 @@ describe('NotFoundPageComponent', () => {
sendVerificationEmailInProgress={false}
onResendVerificationEmail={noop}
intl={fakeIntl}
- flattenedRoutes={[]}
/>
);
expect(tree).toMatchSnapshot();
diff --git a/src/containers/SearchPage/SearchPage.js b/src/containers/SearchPage/SearchPage.js
index cda69af3..3670ef6b 100644
--- a/src/containers/SearchPage/SearchPage.js
+++ b/src/containers/SearchPage/SearchPage.js
@@ -6,7 +6,7 @@ import { withRouter } from 'react-router-dom';
import { debounce, isEqual, unionWith } from 'lodash';
import classNames from 'classnames';
import config from '../../config';
-import { withFlattenedRoutes } from '../../util/contextHelpers';
+import routeConfiguration from '../../routeConfiguration';
import { googleLatLngToSDKLatLng, googleBoundsToSDKBounds } from '../../util/googleMaps';
import { createResourceLocatorString } from '../../util/routes';
import { createSlug, parse, stringify } from '../../util/urlHelpers';
@@ -77,7 +77,7 @@ export class SearchPageComponent extends Component {
// We are using Google Maps idle event instead of bounds_changed, since it will not be fired
// too often (in the middle of map's pan or zoom activity)
onIdle(googleMap) {
- const { flattenedRoutes, history, location } = this.props;
+ const { history, location } = this.props;
const { address, country, boundsChanged } = parse(location.search, {
latlng: ['origin'],
@@ -93,7 +93,9 @@ export class SearchPageComponent extends Component {
const origin = googleLatLngToSDKLatLng(viewportBounds.getCenter());
const searchParams = { address, origin, bounds, country, boundsChanged: true };
- history.push(createResourceLocatorString('SearchPage', flattenedRoutes, {}, searchParams));
+ history.push(
+ createResourceLocatorString('SearchPage', routeConfiguration(), {}, searchParams)
+ );
} else {
this.useLocationSearchBounds = false;
this.modalOpenedBoundsChange = false;
@@ -137,7 +139,6 @@ export class SearchPageComponent extends Component {
currentUser,
currentUserHasListings,
currentUserHasOrders,
- flattenedRoutes,
history,
intl,
isAuthenticated,
@@ -245,7 +246,7 @@ export class SearchPageComponent extends Component {
const schemaDescription = intl.formatMessage({ id: 'SearchPage.schemaDescription' });
const schemaListings = listings.map((l, i) => {
const title = l.attributes.title;
- const pathToItem = createResourceLocatorString('ListingPage', flattenedRoutes, {
+ const pathToItem = createResourceLocatorString('ListingPage', routeConfiguration(), {
id: l.id.uuid,
slug: createSlug(title),
});
@@ -368,7 +369,7 @@ SearchPageComponent.defaultProps = {
sendVerificationEmailError: null,
};
-const { array, arrayOf, bool, func, instanceOf, number, oneOf, object, shape, string } = PropTypes;
+const { array, bool, func, instanceOf, number, oneOf, object, shape, string } = PropTypes;
SearchPageComponent.propTypes = {
authInfoError: instanceOf(Error),
@@ -394,9 +395,6 @@ SearchPageComponent.propTypes = {
sendVerificationEmailError: instanceOf(Error),
onResendVerificationEmail: func.isRequired,
- // from withFlattenedRoutes
- flattenedRoutes: arrayOf(propTypes.route).isRequired,
-
// from withRouter
history: shape({
push: func.isRequired,
@@ -462,12 +460,9 @@ const mapDispatchToProps = dispatch => ({
onSearchMapListings: searchParams => dispatch(searchMapListings(searchParams)),
});
-const SearchPage = compose(
- connect(mapStateToProps, mapDispatchToProps),
- injectIntl,
- withFlattenedRoutes,
- withRouter
-)(SearchPageComponent);
+const SearchPage = compose(connect(mapStateToProps, mapDispatchToProps), injectIntl, withRouter)(
+ SearchPageComponent
+);
SearchPage.loadData = (params, search) => {
const queryParams = parse(search, {
diff --git a/src/containers/SearchPage/SearchPage.test.js b/src/containers/SearchPage/SearchPage.test.js
index e4c4d082..d6204994 100644
--- a/src/containers/SearchPage/SearchPage.test.js
+++ b/src/containers/SearchPage/SearchPage.test.js
@@ -39,7 +39,6 @@ describe('SearchPageComponent', () => {
onLogout: noop,
onManageDisableScrolling: noop,
onSearchMapListings: noop,
- flattenedRoutes: [],
sendVerificationEmailInProgress: false,
onResendVerificationEmail: noop,
};
diff --git a/src/containers/StyleguidePage/StyleguidePage.js b/src/containers/StyleguidePage/StyleguidePage.js
index 0598cfda..77c57646 100644
--- a/src/containers/StyleguidePage/StyleguidePage.js
+++ b/src/containers/StyleguidePage/StyleguidePage.js
@@ -2,7 +2,6 @@ import React, { PropTypes } from 'react';
import { isEmpty } from 'lodash';
import classNames from 'classnames';
import { NamedLink } from '../../components';
-import * as allExamples from '../../examples';
import css from './StyleguidePage.css';
@@ -161,6 +160,17 @@ const examplesFor = (examples, group, componentName, exampleName) => {
};
const StyleguidePage = props => {
+ // TODO: importing all the examples will affect the module bundling
+ // since examples call routeConfiguration without function wrapping
+ // Wurthermore, it would be nice to exclude styleguide away from actual app
+ let allExamples = [];
+ try {
+ allExamples = require('../../examples'); // eslint-disable-line global-require
+ } catch (e) {
+ // eslint-disable-next-line no-console
+ console.warn('require(): The file "../../examples.js" could not be loaded.');
+ }
+
const { params, raw } = props;
const group = params.group ? decodeURIComponent(params.group) : ALL;
const componentName = params.component || ALL;
diff --git a/src/containers/index.js b/src/containers/index.js
index 754bce7b..60e9f039 100644
--- a/src/containers/index.js
+++ b/src/containers/index.js
@@ -1,79 +1,42 @@
-import AuthenticationPage from './AuthenticationPage/AuthenticationPage';
-import BookingDatesForm from './BookingDatesForm/BookingDatesForm';
-import CheckoutPage from './CheckoutPage/CheckoutPage';
-import ContactDetailsForm from './ContactDetailsForm/ContactDetailsForm';
-import ContactDetailsPage from './ContactDetailsPage/ContactDetailsPage';
-import EditListingDescriptionForm from './EditListingDescriptionForm/EditListingDescriptionForm';
-import EditListingLocationForm from './EditListingLocationForm/EditListingLocationForm';
-import EditListingPage from './EditListingPage/EditListingPage';
-import EditListingPhotosForm from './EditListingPhotosForm/EditListingPhotosForm';
-import EditListingPricingForm from './EditListingPricingForm/EditListingPricingForm';
-import EmailVerificationForm from './EmailVerificationForm/EmailVerificationForm';
-import EmailVerificationPage from './EmailVerificationPage/EmailVerificationPage';
-import InboxPage from './InboxPage/InboxPage';
-import LandingPage from './LandingPage/LandingPage';
-import ListingPage from './ListingPage/ListingPage';
-import LocationSearchForm from './LocationSearchForm/LocationSearchForm';
-import LoginForm from './LoginForm/LoginForm';
-import ManageListingsPage from './ManageListingsPage/ManageListingsPage';
-import NotFoundPage from './NotFoundPage/NotFoundPage';
-import OrderPage from './OrderPage/OrderPage';
-import PasswordChangeForm from './PasswordChangeForm/PasswordChangeForm';
-import PasswordChangePage from './PasswordChangePage/PasswordChangePage';
-import PasswordRecoveryForm from './PasswordRecoveryForm/PasswordRecoveryForm';
-import PasswordRecoveryPage from './PasswordRecoveryPage/PasswordRecoveryPage';
-import PasswordResetForm from './PasswordResetForm/PasswordResetForm';
-import PasswordResetPage from './PasswordResetPage/PasswordResetPage';
-import PayoutDetailsForm from './PayoutDetailsForm/PayoutDetailsForm';
-import PayoutPreferencesPage from './PayoutPreferencesPage/PayoutPreferencesPage';
-import ProfilePage from './ProfilePage/ProfilePage';
-import ProfileSettingsForm from './ProfileSettingsForm/ProfileSettingsForm';
-import ProfileSettingsPage from './ProfileSettingsPage/ProfileSettingsPage';
-import SalePage from './SalePage/SalePage';
-import SearchPage from './SearchPage/SearchPage';
-import SecurityPage from './SecurityPage/SecurityPage';
-import SignupForm from './SignupForm/SignupForm';
-import StripePaymentForm from './StripePaymentForm/StripePaymentForm';
-import StyleguidePage from './StyleguidePage/StyleguidePage';
-import TopbarSearchForm from './TopbarSearchForm/TopbarSearchForm';
-
+export { default as AuthenticationPage } from './AuthenticationPage/AuthenticationPage';
+export { default as BookingDatesForm } from './BookingDatesForm/BookingDatesForm';
+export { default as CheckoutPage } from './CheckoutPage/CheckoutPage';
+export { default as ContactDetailsForm } from './ContactDetailsForm/ContactDetailsForm';
+export { default as ContactDetailsPage } from './ContactDetailsPage/ContactDetailsPage';
export {
- AuthenticationPage,
- BookingDatesForm,
- CheckoutPage,
- ContactDetailsForm,
- ContactDetailsPage,
- EditListingDescriptionForm,
- EditListingLocationForm,
- EditListingPage,
- EditListingPhotosForm,
- EditListingPricingForm,
- EmailVerificationForm,
- EmailVerificationPage,
- InboxPage,
- LandingPage,
- ListingPage,
- LocationSearchForm,
- LoginForm,
- ManageListingsPage,
- NotFoundPage,
- OrderPage,
- PasswordChangeForm,
- PasswordChangePage,
- PasswordRecoveryForm,
- PasswordRecoveryPage,
- PasswordResetForm,
- PasswordResetPage,
- PayoutDetailsForm,
- PayoutPreferencesPage,
- ProfilePage,
- ProfileSettingsForm,
- ProfileSettingsPage,
- SalePage,
- SearchPage,
- SecurityPage,
- SignupForm,
- StripePaymentForm,
- StyleguidePage,
- TopbarSearchForm,
-};
+ default as EditListingDescriptionForm,
+} from './EditListingDescriptionForm/EditListingDescriptionForm';
+export {
+ default as EditListingLocationForm,
+} from './EditListingLocationForm/EditListingLocationForm';
+export { default as EditListingPage } from './EditListingPage/EditListingPage';
+export { default as EditListingPhotosForm } from './EditListingPhotosForm/EditListingPhotosForm';
+export { default as EditListingPricingForm } from './EditListingPricingForm/EditListingPricingForm';
+export { default as EmailVerificationForm } from './EmailVerificationForm/EmailVerificationForm';
+export { default as EmailVerificationPage } from './EmailVerificationPage/EmailVerificationPage';
+export { default as InboxPage } from './InboxPage/InboxPage';
+export { default as LandingPage } from './LandingPage/LandingPage';
+export { default as ListingPage } from './ListingPage/ListingPage';
+export { default as LocationSearchForm } from './LocationSearchForm/LocationSearchForm';
+export { default as LoginForm } from './LoginForm/LoginForm';
+export { default as ManageListingsPage } from './ManageListingsPage/ManageListingsPage';
+export { default as NotFoundPage } from './NotFoundPage/NotFoundPage';
+export { default as OrderPage } from './OrderPage/OrderPage';
+export { default as PasswordChangeForm } from './PasswordChangeForm/PasswordChangeForm';
+export { default as PasswordChangePage } from './PasswordChangePage/PasswordChangePage';
+export { default as PasswordRecoveryForm } from './PasswordRecoveryForm/PasswordRecoveryForm';
+export { default as PasswordRecoveryPage } from './PasswordRecoveryPage/PasswordRecoveryPage';
+export { default as PasswordResetForm } from './PasswordResetForm/PasswordResetForm';
+export { default as PasswordResetPage } from './PasswordResetPage/PasswordResetPage';
+export { default as PayoutDetailsForm } from './PayoutDetailsForm/PayoutDetailsForm';
+export { default as PayoutPreferencesPage } from './PayoutPreferencesPage/PayoutPreferencesPage';
+export { default as ProfilePage } from './ProfilePage/ProfilePage';
+export { default as ProfileSettingsForm } from './ProfileSettingsForm/ProfileSettingsForm';
+export { default as ProfileSettingsPage } from './ProfileSettingsPage/ProfileSettingsPage';
+export { default as SalePage } from './SalePage/SalePage';
+export { default as SearchPage } from './SearchPage/SearchPage';
+export { default as SecurityPage } from './SecurityPage/SecurityPage';
+export { default as SignupForm } from './SignupForm/SignupForm';
+export { default as StripePaymentForm } from './StripePaymentForm/StripePaymentForm';
+export { default as StyleguidePage } from './StyleguidePage/StyleguidePage';
+export { default as TopbarSearchForm } from './TopbarSearchForm/TopbarSearchForm';
diff --git a/src/index.js b/src/index.js
index 3ac9263d..da2f9e30 100644
--- a/src/index.js
+++ b/src/index.js
@@ -22,7 +22,7 @@ import * as sample from './util/sample';
import config from './config';
import { authInfo } from './ducks/Auth.duck';
import { fetchCurrentUser } from './ducks/user.duck';
-import routeConfiguration from './routesConfiguration';
+import routeConfiguration from './routeConfiguration';
import * as log from './util/log';
import './marketplaceIndex.css';
@@ -81,7 +81,14 @@ if (typeof window !== 'undefined') {
if (config.dev) {
// Expose stuff for the browser REPL
- window.app = { config, sdk, sdkTypes: types, store, sample, routeConfiguration };
+ window.app = {
+ config,
+ sdk,
+ sdkTypes: types,
+ store,
+ sample,
+ routeConfiguration: routeConfiguration(),
+ };
}
}
diff --git a/src/routeConfiguration.js b/src/routeConfiguration.js
new file mode 100644
index 00000000..c7d75438
--- /dev/null
+++ b/src/routeConfiguration.js
@@ -0,0 +1,331 @@
+import React from 'react';
+import {
+ AuthenticationPage,
+ CheckoutPage,
+ ContactDetailsPage,
+ EditListingPage,
+ InboxPage,
+ LandingPage,
+ ListingPage,
+ ManageListingsPage,
+ NotFoundPage,
+ OrderPage,
+ PasswordChangePage,
+ PasswordResetPage,
+ PasswordRecoveryPage,
+ PayoutPreferencesPage,
+ ProfilePage,
+ ProfileSettingsPage,
+ SalePage,
+ SearchPage,
+ SecurityPage,
+ StyleguidePage,
+ EmailVerificationPage,
+} from './containers';
+
+// routeConfiguration needs to initialize containers first
+// Otherwise, components will import form container eventually and
+// at that point css bundling / imports will happen in wrong order.
+import { NamedRedirect } from './components';
+
+export const ACCOUNT_SETTINGS_PAGES = ['ContactDetailsPage', 'PasswordChangePage'];
+
+// https://en.wikipedia.org/wiki/Universally_unique_identifier#Nil_UUID
+const draftId = '00000000-0000-0000-0000-000000000000';
+const draftSlug = 'draft';
+
+const RedirectToLandingPage = () => ;
+
+const routeConfiguration = () => {
+ return [
+ { path: '/', exact: true, name: 'LandingPage', component: props => },
+ {
+ path: '/s',
+ exact: true,
+ name: 'SearchPage',
+ component: props => ,
+ loadData: SearchPage.loadData,
+ },
+ {
+ path: '/s/filters',
+ exact: true,
+ name: 'SearchFiltersPage',
+ component: props => ,
+ loadData: SearchPage.loadData,
+ },
+ {
+ path: '/s/listings',
+ exact: true,
+ name: 'SearchListingsPage',
+ component: props => ,
+ loadData: SearchPage.loadData,
+ },
+ {
+ path: '/s/map',
+ exact: true,
+ name: 'SearchMapPage',
+ component: props => ,
+ loadData: SearchPage.loadData,
+ },
+ {
+ path: '/l',
+ exact: true,
+ name: 'ListingBasePage',
+ component: RedirectToLandingPage,
+ },
+ {
+ path: '/l/:slug/:id',
+ exact: true,
+ name: 'ListingPage',
+ component: props => ,
+ loadData: ListingPage.loadData,
+ },
+ {
+ path: '/l/:slug/:id/book',
+ exact: true,
+ name: 'ListingPage',
+ component: props => ,
+ loadData: ListingPage.loadData,
+ },
+ {
+ path: '/l/:slug/:id/checkout',
+ auth: true,
+ exact: true,
+ name: 'CheckoutPage',
+ component: props => ,
+ setInitialValues: CheckoutPage.setInitialValues,
+ },
+ {
+ auth: true,
+ path: '/l/new',
+ exact: true,
+ name: 'NewListingPage',
+ component: () => (
+
+ ),
+ },
+ {
+ auth: true,
+ path: '/l/:slug/:id/:type/:tab',
+ exact: true,
+ name: 'EditListingPage',
+ component: props => ,
+ loadData: EditListingPage.loadData,
+ },
+
+ // Canonical path should be after the `/l/new` path since they
+ // conflict and `new` is not a valid listing UUID.
+ {
+ path: '/l/:id',
+ exact: true,
+ name: 'ListingPageCanonical',
+ component: props => ,
+ loadData: ListingPage.loadData,
+ },
+ {
+ path: '/u',
+ exact: true,
+ name: 'ProfileBasePage',
+ component: RedirectToLandingPage,
+ },
+ {
+ path: '/u/:displayName',
+ exact: true,
+ name: 'ProfilePage',
+ component: props => ,
+ },
+ {
+ path: '/profile-settings',
+ auth: true,
+ exact: true,
+ name: 'ProfileSettingsPage',
+ component: props => ,
+ },
+ {
+ path: '/login',
+ exact: true,
+ name: 'LoginPage',
+ component: props => ,
+ },
+ {
+ path: '/signup',
+ exact: true,
+ name: 'SignupPage',
+ component: props => ,
+ },
+ {
+ path: '/recover-password',
+ exact: true,
+ name: 'PasswordRecoveryPage',
+ component: props => ,
+ },
+ {
+ path: '/inbox',
+ auth: true,
+ exact: true,
+ name: 'InboxBasePage',
+ component: () => ,
+ },
+ {
+ path: '/inbox/:tab',
+ auth: true,
+ exact: true,
+ name: 'InboxPage',
+ component: props => ,
+ loadData: InboxPage.loadData,
+ },
+ {
+ path: '/order/:id',
+ auth: true,
+ exact: true,
+ name: 'OrderPage',
+ component: RedirectToLandingPage,
+ },
+ {
+ path: '/order/:id/details',
+ auth: true,
+ exact: true,
+ name: 'OrderDetailsPage',
+ component: props => ,
+ loadData: OrderPage.loadData,
+ },
+ {
+ path: '/order/:id/discussion',
+ auth: true,
+ exact: true,
+ name: 'OrderDiscussionPage',
+ component: props => ,
+ loadData: OrderPage.loadData,
+ },
+ {
+ path: '/sale/:id',
+ auth: true,
+ exact: true,
+ name: 'SalePage',
+ component: props => ,
+ },
+ {
+ path: '/sale/:id/details',
+ auth: true,
+ exact: true,
+ name: 'SaleDetailsPage',
+ component: props => ,
+ loadData: SalePage.loadData,
+ },
+ {
+ path: '/sale/:id/discussion',
+ auth: true,
+ exact: true,
+ name: 'SaleDiscussionPage',
+ component: props => ,
+ loadData: SalePage.loadData,
+ },
+ {
+ path: '/listings',
+ auth: true,
+ exact: true,
+ name: 'ManageListingsPage',
+ component: props => ,
+ loadData: ManageListingsPage.loadData,
+ },
+ {
+ path: '/account',
+ auth: true,
+ exact: true,
+ name: 'AccountSettingsPage',
+ component: () => ,
+ },
+ {
+ path: '/account/contact-details',
+ auth: true,
+ exact: true,
+ name: 'ContactDetailsPage',
+ component: props => ,
+ loadData: ContactDetailsPage.loadData,
+ },
+ {
+ path: '/account/change-password',
+ auth: true,
+ exact: true,
+ name: 'PasswordChangePage',
+ component: props => ,
+ },
+ {
+ path: '/account/payout-preferences',
+ auth: true,
+ exact: true,
+ name: 'PayoutPreferencesPage',
+ component: props => ,
+ },
+ {
+ path: '/account/security',
+ auth: true,
+ exact: true,
+ name: 'SecurityPage',
+ component: props => ,
+ },
+ {
+ path: '/styleguide',
+ exact: true,
+ name: 'Styleguide',
+ component: props => ,
+ },
+ {
+ path: '/styleguide/g/:group',
+ exact: true,
+ name: 'StyleguideGroup',
+ component: props => ,
+ },
+ {
+ path: '/styleguide/c/:component',
+ exact: true,
+ name: 'StyleguideComponent',
+ component: props => ,
+ },
+ {
+ path: '/styleguide/c/:component/:example',
+ exact: true,
+ name: 'StyleguideComponentExample',
+ component: props => ,
+ },
+ {
+ path: '/styleguide/c/:component/:example/raw',
+ exact: true,
+ name: 'StyleguideComponentExampleRaw',
+ component: props => ,
+ },
+ {
+ path: '/notfound',
+ exact: true,
+ name: 'NotFoundPage',
+ component: props => ,
+ },
+
+ // Do not change this path!
+ //
+ // The API expects that the Starter App implements /reset-password endpoint
+ {
+ path: '/reset-password',
+ exact: true,
+ name: 'PasswordResetPage',
+ component: props => ,
+ },
+
+ // Do not change this path!
+ //
+ // The API expects that the Starter App implements /verify-email endpoint
+ {
+ path: '/verify-email',
+ auth: true,
+ authPage: 'LoginPage',
+ exact: true,
+ name: 'EmailVerificationPage',
+ component: props => ,
+ },
+ ];
+};
+
+export default routeConfiguration;
diff --git a/src/routesConfiguration.js b/src/routesConfiguration.js
deleted file mode 100644
index 3f8a45b5..00000000
--- a/src/routesConfiguration.js
+++ /dev/null
@@ -1,337 +0,0 @@
-import React from 'react';
-import { NamedRedirect } from './components';
-import {
- AuthenticationPage,
- CheckoutPage,
- ContactDetailsPage,
- EditListingPage,
- InboxPage,
- LandingPage,
- ListingPage,
- ManageListingsPage,
- NotFoundPage,
- OrderPage,
- PasswordChangePage,
- PasswordResetPage,
- PasswordRecoveryPage,
- PayoutPreferencesPage,
- ProfilePage,
- ProfileSettingsPage,
- SalePage,
- SearchPage,
- SecurityPage,
- StyleguidePage,
- EmailVerificationPage,
-} from './containers';
-
-export const ACCOUNT_SETTINGS_PAGES = ['ContactDetailsPage', 'PasswordChangePage'];
-
-// https://en.wikipedia.org/wiki/Universally_unique_identifier#Nil_UUID
-const draftId = '00000000-0000-0000-0000-000000000000';
-const draftSlug = 'draft';
-
-const RedirectToLandingPage = () => ;
-
-const routesConfiguration = [
- { path: '/', exact: true, name: 'LandingPage', component: props => },
- {
- path: '/s',
- exact: true,
- name: 'SearchPage',
- component: props => ,
- loadData: (params, search) => SearchPage.loadData(params, search),
- routes: [
- {
- path: '/s/filters',
- exact: true,
- name: 'SearchFiltersPage',
- component: props => ,
- loadData: (params, search) => SearchPage.loadData(params, search),
- },
- {
- path: '/s/listings',
- exact: true,
- name: 'SearchListingsPage',
- component: props => ,
- loadData: (params, search) => SearchPage.loadData(params, search),
- },
- {
- path: '/s/map',
- exact: true,
- name: 'SearchMapPage',
- component: props => ,
- loadData: (params, search) => SearchPage.loadData(params, search),
- },
- ],
- },
- {
- path: '/l',
- exact: true,
- name: 'ListingBasePage',
- component: RedirectToLandingPage,
- routes: [
- {
- path: '/l/:slug/:id',
- exact: true,
- name: 'ListingPage',
- loadData: (params, search) => ListingPage.loadData(params, search),
- component: props => ,
- },
- {
- path: '/l/:slug/:id/book',
- exact: true,
- name: 'ListingPage',
- loadData: (params, search) => ListingPage.loadData(params, search),
- component: props => ,
- },
- {
- path: '/l/:slug/:id/checkout',
- auth: true,
- exact: true,
- name: 'CheckoutPage',
- setInitialValues: initialValues => CheckoutPage.setInitialValues(initialValues),
- component: props => ,
- },
- {
- auth: true,
- path: '/l/new',
- exact: true,
- name: 'NewListingPage',
- component: () => (
-
- ),
- },
- {
- auth: true,
- path: '/l/:slug/:id/:type/:tab',
- exact: true,
- name: 'EditListingPage',
- component: props => ,
- loadData: (params, search) => EditListingPage.loadData(params, search),
- },
-
- // Canonical path should be after the `/l/new` path since they
- // conflict and `new` is not a valid listing UUID.
- {
- path: '/l/:id',
- exact: true,
- name: 'ListingPageCanonical',
- loadData: (params, search) => ListingPage.loadData(params, search),
- component: props => ,
- },
- ],
- },
- {
- path: '/u',
- exact: true,
- name: 'ProfileBasePage',
- component: RedirectToLandingPage,
- routes: [
- {
- path: '/u/:displayName',
- exact: true,
- name: 'ProfilePage',
- component: props => ,
- },
- ],
- },
- {
- path: '/profile-settings',
- auth: true,
- exact: true,
- name: 'ProfileSettingsPage',
- component: props => ,
- },
- {
- path: '/login',
- exact: true,
- name: 'LoginPage',
- component: props => ,
- },
- {
- path: '/signup',
- exact: true,
- name: 'SignupPage',
- component: props => ,
- },
- {
- path: '/recover-password',
- exact: true,
- name: 'PasswordRecoveryPage',
- component: props => ,
- },
- {
- path: '/inbox',
- auth: true,
- exact: true,
- name: 'InboxBasePage',
- component: () => ,
- },
- {
- path: '/inbox/:tab',
- auth: true,
- exact: true,
- name: 'InboxPage',
- component: props => ,
- loadData: (params, search) => InboxPage.loadData(params, search),
- },
- {
- path: '/order/:id',
- auth: true,
- exact: true,
- name: 'OrderPage',
- component: RedirectToLandingPage,
- routes: [
- {
- path: '/order/:id/details',
- auth: true,
- exact: true,
- name: 'OrderDetailsPage',
- component: props => ,
- loadData: params => OrderPage.loadData(params),
- },
- {
- path: '/order/:id/discussion',
- auth: true,
- exact: true,
- name: 'OrderDiscussionPage',
- component: props => ,
- loadData: params => OrderPage.loadData(params),
- },
- ],
- },
- {
- path: '/sale/:id',
- auth: true,
- exact: true,
- name: 'SalePage',
- component: props => ,
- routes: [
- {
- path: '/sale/:id/details',
- auth: true,
- exact: true,
- name: 'SaleDetailsPage',
- component: props => ,
- loadData: params => SalePage.loadData(params),
- },
- {
- path: '/sale/:id/discussion',
- auth: true,
- exact: true,
- name: 'SaleDiscussionPage',
- component: props => ,
- loadData: params => SalePage.loadData(params),
- },
- ],
- },
- {
- path: '/listings',
- auth: true,
- exact: true,
- name: 'ManageListingsPage',
- component: props => ,
- loadData: (params, search) => ManageListingsPage.loadData(params, search),
- },
- {
- path: '/account',
- auth: true,
- exact: true,
- name: 'AccountSettingsPage',
- component: () => ,
- routes: [
- {
- path: '/account/contact-details',
- auth: true,
- exact: true,
- name: 'ContactDetailsPage',
- component: props => ,
- loadData: params => ContactDetailsPage.loadData(params),
- },
- {
- path: '/account/change-password',
- auth: true,
- exact: true,
- name: 'PasswordChangePage',
- component: props => ,
- },
- {
- path: '/account/payout-preferences',
- auth: true,
- exact: true,
- name: 'PayoutPreferencesPage',
- component: props => ,
- },
- {
- path: '/account/security',
- auth: true,
- exact: true,
- name: 'SecurityPage',
- component: props => ,
- },
- ],
- },
- {
- path: '/styleguide',
- exact: true,
- name: 'Styleguide',
- component: props => ,
- },
- {
- path: '/styleguide/g/:group',
- exact: true,
- name: 'StyleguideGroup',
- component: props => ,
- },
- {
- path: '/styleguide/c/:component',
- exact: true,
- name: 'StyleguideComponent',
- component: props => ,
- },
- {
- path: '/styleguide/c/:component/:example',
- exact: true,
- name: 'StyleguideComponentExample',
- component: props => ,
- },
- {
- path: '/styleguide/c/:component/:example/raw',
- exact: true,
- name: 'StyleguideComponentExampleRaw',
- component: props => ,
- },
- {
- path: '/notfound',
- exact: true,
- name: 'NotFoundPage',
- component: props => ,
- },
-
- // Do not change this path!
- //
- // The API expects that the Starter App implements /reset-password endpoint
- {
- path: '/reset-password',
- exact: true,
- name: 'PasswordResetPage',
- component: props => ,
- },
-
- // Do not change this path!
- //
- // The API expects that the Starter App implements /verify-email endpoint
- {
- path: '/verify-email',
- auth: true,
- authPage: 'LoginPage',
- exact: true,
- name: 'EmailVerificationPage',
- component: props => ,
- },
-];
-
-export default routesConfiguration;
diff --git a/src/util/__snapshots__/contextHelpers.test.js.snap b/src/util/__snapshots__/contextHelpers.test.js.snap
deleted file mode 100644
index b8186f2c..00000000
--- a/src/util/__snapshots__/contextHelpers.test.js.snap
+++ /dev/null
@@ -1,7 +0,0 @@
-exports[`util/contextHelpers.js withFlattenedRoutes should inject the provided routes 1`] = ``;
-
-exports[`util/contextHelpers.js withFlattenedRoutes should inject the provided routes 2`] = `
-
- SomePage
-
-`;
diff --git a/src/util/contextHelpers.js b/src/util/contextHelpers.js
index 4664a31e..a63b9028 100644
--- a/src/util/contextHelpers.js
+++ b/src/util/contextHelpers.js
@@ -1,29 +1,5 @@
import React, { PropTypes, Component as ReactComponent } from 'react';
import { throttle } from 'lodash';
-import * as propTypes from './propTypes';
-
-/**
- * A higher order component (HOC) to take the flattened routes from
- * the context that the RoutesProvider component has provided.
- *
- * Injects the routes as the `flattenedRoutes` prop in the given
- * component. Works similarly as `withRouter` in React Router.
- */
-export const withFlattenedRoutes = Component => {
- const WithFlattenedRoutesComponent = (props, context) => (
-
- );
-
- WithFlattenedRoutesComponent.displayName = `withFlattenedRoutes(${Component.displayName || Component.name})`;
-
- const { arrayOf } = PropTypes;
-
- WithFlattenedRoutesComponent.contextTypes = {
- flattenedRoutes: arrayOf(propTypes.route).isRequired,
- };
-
- return WithFlattenedRoutesComponent;
-};
/**
* A higher order component (HOC) to take the togglePageClassNames function from
diff --git a/src/util/contextHelpers.test.js b/src/util/contextHelpers.test.js
deleted file mode 100644
index 3c21e297..00000000
--- a/src/util/contextHelpers.test.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React, { PropTypes } from 'react';
-import { Page, RoutesProvider } from '../components';
-import routesConfiguration from '../routesConfiguration';
-import { flattenRoutes } from './routes';
-import { renderDeep, renderShallow } from './test-helpers';
-import * as propTypes from './propTypes';
-import { withFlattenedRoutes, withTogglePageClassNames } from './contextHelpers';
-
-const { arrayOf, func } = PropTypes;
-
-describe('util/contextHelpers.js', () => {
- describe('withFlattenedRoutes', () => {
- it('should inject the provided routes', () => {
- const CompComp = props => {props.flattenedRoutes[0].name}
;
- CompComp.propTypes = { flattenedRoutes: arrayOf(propTypes.route).isRequired };
- const Comp = withFlattenedRoutes(CompComp);
- const routes = [{ name: 'SomePage', path: 'some-page', component: () => null }];
- const shallowTree = renderShallow(
-
-
-
- );
- expect(shallowTree).toMatchSnapshot();
- const deepTree = renderDeep(
-
-
-
- );
- expect(deepTree).toMatchSnapshot();
- });
- });
-});
diff --git a/src/util/routes.js b/src/util/routes.js
index 581582f1..373ef07b 100644
--- a/src/util/routes.js
+++ b/src/util/routes.js
@@ -3,31 +3,14 @@ import { matchPath } from 'react-router-dom';
import pathToRegexp from 'path-to-regexp';
import { stringify } from './urlHelpers';
-// Flatten the routes config.
-// TODO: flatten the original config and remove this function
-export const flattenRoutes = routes =>
- routes.reduce(
- (flatRoutes, route) => {
- const r = { ...route };
- delete r.routes;
- flatRoutes.push(r);
- if (route.routes) {
- return flatRoutes.concat(flattenRoutes(route.routes));
- }
- return flatRoutes;
- },
- []
- );
-
-const findRouteByName = (nameToFind, flattenedRoutes) =>
- find(flattenedRoutes, route => route.name === nameToFind);
+const findRouteByName = (nameToFind, routes) => find(routes, route => route.name === nameToFind);
/**
* E.g. ```const toListingPath = toPathByRouteName('ListingPage', routes);```
* Then we can generate listing paths with given params (```toListingPath({ id: uuidX })```)
*/
-const toPathByRouteName = (nameToFind, flattenedRoutes) => {
- const route = findRouteByName(nameToFind, flattenedRoutes);
+const toPathByRouteName = (nameToFind, routes) => {
+ const route = findRouteByName(nameToFind, routes);
if (!route) {
throw new Error(`Path "${nameToFind}" was not found.`);
}
@@ -37,8 +20,8 @@ const toPathByRouteName = (nameToFind, flattenedRoutes) => {
/**
* Shorthand for single path call. (```pathByRouteName('ListingPage', routes, { id: uuidX });```)
*/
-export const pathByRouteName = (nameToFind, flattenedRoutes, params = {}) =>
- toPathByRouteName(nameToFind, flattenedRoutes)(params);
+export const pathByRouteName = (nameToFind, routes, params = {}) =>
+ toPathByRouteName(nameToFind, routes)(params);
/**
* Find the matching routes and their params for the given pathname
@@ -48,11 +31,8 @@ export const pathByRouteName = (nameToFind, flattenedRoutes, params = {}) =>
*
* @return {Array<{ route, params }>} - All matches as { route, params } objects
*/
-export const matchPathname = (pathname, routesConfiguration) => {
- // TODO: remove flattening when routesConfiguration is flat
- const flattenedRoutes = flattenRoutes(routesConfiguration);
-
- return flattenedRoutes.reduce(
+export const matchPathname = (pathname, routeConfiguration) => {
+ return routeConfiguration.reduce(
(matches, route) => {
const { path, exact = false } = route;
const match = matchPath(pathname, { path, exact });
@@ -74,13 +54,13 @@ export const matchPathname = (pathname, routesConfiguration) => {
*/
export const createResourceLocatorString = (
routeName,
- flattenedRoutes,
+ routes,
pathParams = {},
searchParams = {}
) => {
const searchQuery = stringify(searchParams);
const includeSearchQuery = searchQuery.length > 0 ? `?${searchQuery}` : '';
- const path = pathByRouteName(routeName, flattenedRoutes, pathParams);
+ const path = pathByRouteName(routeName, routes, pathParams);
return `${path}${includeSearchQuery}`;
};
@@ -91,12 +71,12 @@ export const createResourceLocatorString = (
* `dispatch(PageComponent.setInitialValues({ listing, bookingDates }));`
*
* @param {String} nameToFind - Route name
- * @param {Array<{ route }>} flattenedRoutes - Route configuration as flattened array.
+ * @param {Array<{ route }>} routes - Route configuration as flat array.
*
* @return {Route} - Route that matches the given route name.
*/
-export const findRouteByRouteName = (nameToFind, flattenedRoutes) => {
- const route = findRouteByName(nameToFind, flattenedRoutes);
+export const findRouteByRouteName = (nameToFind, routes) => {
+ const route = findRouteByName(nameToFind, routes);
if (!route) {
throw new Error(`Component "${nameToFind}" was not found.`);
}
diff --git a/src/util/routes.test.js b/src/util/routes.test.js
index eebb4a5d..a3f34e1b 100644
--- a/src/util/routes.test.js
+++ b/src/util/routes.test.js
@@ -1,64 +1,48 @@
import React, { PropTypes } from 'react';
import { RoutesProvider } from '../components';
-import routesConfiguration from '../routesConfiguration';
+import routeConfiguration from '../routeConfiguration';
import { renderDeep, renderShallow } from './test-helpers';
import * as propTypes from './propTypes';
-import { createResourceLocatorString, flattenRoutes, findRouteByRouteName } from './routes';
+import { createResourceLocatorString, findRouteByRouteName } from './routes';
const { arrayOf } = PropTypes;
describe('util/routes.js', () => {
describe('createResourceLocatorString', () => {
- const flattenedRoutes = flattenRoutes(routesConfiguration);
+ const routes = routeConfiguration();
it('should return meaningful strings if parameters are not needed', () => {
// default links without params in path or search query
- expect(
- createResourceLocatorString('SearchPage', flattenedRoutes, undefined, undefined)
- ).toEqual('/s');
- expect(createResourceLocatorString('SearchPage', flattenedRoutes, {}, {})).toEqual('/s');
+ expect(createResourceLocatorString('SearchPage', routes, undefined, undefined)).toEqual('/s');
+ expect(createResourceLocatorString('SearchPage', routes, {}, {})).toEqual('/s');
});
it('should return meaningful strings with path parameters', () => {
expect(
- createResourceLocatorString(
- 'ListingPage',
- flattenedRoutes,
- { id: '1234', slug: 'nice-listing' },
- {}
- )
+ createResourceLocatorString('ListingPage', routes, { id: '1234', slug: 'nice-listing' }, {})
).toEqual('/l/nice-listing/1234');
+ expect(() => createResourceLocatorString('ListingPage', routes, {}, {})).toThrowError(
+ TypeError('Expected "slug" to be defined')
+ );
expect(() =>
- createResourceLocatorString('ListingPage', flattenedRoutes, {}, {})).toThrowError(
+ createResourceLocatorString('ListingPage', routes, { id: '1234' }, {})).toThrowError(
TypeError('Expected "slug" to be defined')
);
expect(() =>
createResourceLocatorString(
'ListingPage',
- flattenedRoutes,
- { id: '1234' },
- {}
- )).toThrowError(TypeError('Expected "slug" to be defined'));
- expect(() =>
- createResourceLocatorString(
- 'ListingPage',
- flattenedRoutes,
+ routes,
{ slug: 'nice-listing' },
{}
)).toThrowError(TypeError('Expected "id" to be defined'));
});
it('should return meaningful strings with search parameters', () => {
- expect(createResourceLocatorString('SearchPage', flattenedRoutes, {}, { page: 2 })).toEqual(
+ expect(createResourceLocatorString('SearchPage', routes, {}, { page: 2 })).toEqual(
'/s?page=2'
);
expect(
- createResourceLocatorString(
- 'SearchPage',
- flattenedRoutes,
- {},
- { address: 'Helsinki', page: 2 }
- )
+ createResourceLocatorString('SearchPage', routes, {}, { address: 'Helsinki', page: 2 })
).toEqual('/s?address=Helsinki&page=2');
});
@@ -66,7 +50,7 @@ describe('util/routes.js', () => {
expect(
createResourceLocatorString(
'ListingPage',
- flattenedRoutes,
+ routes,
{ id: '1234', slug: 'nice-listing' },
{ extrainfo: true }
)
@@ -75,15 +59,15 @@ describe('util/routes.js', () => {
});
describe('findRouteByRouteName', () => {
- const flattenedRoutes = flattenRoutes(routesConfiguration);
+ const routes = routeConfiguration();
it('should return CheckoutPage route', () => {
- const foundRoute = findRouteByRouteName('CheckoutPage', flattenedRoutes);
+ const foundRoute = findRouteByRouteName('CheckoutPage', routes);
expect(foundRoute.name).toEqual('CheckoutPage');
expect(typeof foundRoute.setInitialValues).toEqual('function');
});
it('should throw exception for non-existing route (BlaaBlaaPage)', () => {
- expect(() => findRouteByRouteName('BlaaBlaaPage', flattenedRoutes)).toThrowError(
+ expect(() => findRouteByRouteName('BlaaBlaaPage', routes)).toThrowError(
'Component "BlaaBlaaPage" was not found.'
);
});