mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	fix(router): Upgrade to react-router v. 4.x.
This is rather big change to react-router and required a lot of rewrites. Mostly followed this guide: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/guides/migrating.md
This commit is contained in:
		
							parent
							
								
									791aed23b5
								
							
						
					
					
						commit
						59bcabe331
					
				| @ -50,8 +50,7 @@ | ||||
|     "react-mdl": "^1.11.0", | ||||
|     "react-modal": "^3.1.13", | ||||
|     "react-redux": "^5.0.6", | ||||
|     "react-router": "^3.0.0", | ||||
|     "react-router-scroll": "^0.4.1", | ||||
|     "react-router-dom": "^4.3.1", | ||||
|     "redux": "^3.6.0", | ||||
|     "redux-thunk": "^2.1.0", | ||||
|     "whatwg-fetch": "^2.0.0" | ||||
|  | ||||
							
								
								
									
										3
									
								
								frontend/src/__mocks__/react-mdl.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								frontend/src/__mocks__/react-mdl.js
									
									
									
									
										vendored
									
									
								
							| @ -5,6 +5,7 @@ module.exports = { | ||||
|     CardText: 'react-mdl-CardText', | ||||
|     CardMenu: 'react-mdl-CardMenu', | ||||
|     DataTable: 'react-mdl-DataTable', | ||||
|     Drawer: 'react-mdl-Drawer', | ||||
|     Cell: 'react-mdl-Cell', | ||||
|     Chip: 'react-mdl-Chip', | ||||
|     Grid: 'react-mdl-Grid', | ||||
| @ -16,12 +17,14 @@ module.exports = { | ||||
|     ListItemAction: 'react-mdl-ListItemAction', | ||||
|     Menu: 'react-mdl-Menu', | ||||
|     MenuItem: 'react-mdl-MenuItem', | ||||
|     Navigation: 'react-mdl-Navigation', | ||||
|     ProgressBar: 'react-mdl-ProgressBar', | ||||
|     Switch: 'react-mdl-Switch', | ||||
|     Tab: 'react-mdl-Tab', | ||||
|     Tabs: 'react-mdl-Tabs', | ||||
|     TableHeader: 'react-mdl-TableHeader', | ||||
|     Textfield: 'react-mdl-Textfield', | ||||
|     FooterDropDownSection: 'react-mdl-FooterDropDownSection', | ||||
|     FooterSection: 'react-mdl-FooterSection', | ||||
|     FooterLinkList: 'react-mdl-FooterLinkList', | ||||
| }; | ||||
|  | ||||
| @ -1,43 +1,23 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { | ||||
|     Layout, | ||||
|     Drawer, | ||||
|     Header, | ||||
|     Navigation, | ||||
|     Content, | ||||
|     Footer, | ||||
|     FooterSection, | ||||
|     FooterDropDownSection, | ||||
|     FooterLinkList, | ||||
|     Grid, | ||||
|     Cell, | ||||
|     Icon, | ||||
| } from 'react-mdl'; | ||||
| import { Link } from 'react-router'; | ||||
| import { Layout, Header, Navigation, Content, Footer, Grid, Cell } from 'react-mdl'; | ||||
| import { Route, Redirect, Switch } from 'react-router-dom'; | ||||
| import styles from './styles.scss'; | ||||
| import ErrorContainer from './error/error-container'; | ||||
| 
 | ||||
| import AuthenticationContainer from './user/authentication-container'; | ||||
| import ShowUserContainer from './user/show-user-container'; | ||||
| import ShowApiDetailsContainer from './api/show-api-details-container'; | ||||
| import { ScrollContainer } from 'react-router-scroll'; | ||||
| 
 | ||||
| function replace(input, params) { | ||||
|     if (!params) { | ||||
|         return input; | ||||
|     } | ||||
|     Object.keys(params).forEach(key => { | ||||
|         input = input.replace(`:${key}`, params[key]); | ||||
|     }); | ||||
|     return input; | ||||
| } | ||||
| import Features from '../page/features'; | ||||
| import { DrawerMenu } from './menu/drawer'; | ||||
| import { FooterMenu } from './menu/footer'; | ||||
| import Breadcrum from './menu/breadcrumb'; | ||||
| import { routes } from './menu/routes'; | ||||
| 
 | ||||
| export default class App extends Component { | ||||
|     static propTypes = { | ||||
|         location: PropTypes.object.isRequired, | ||||
|         params: PropTypes.object.isRequired, | ||||
|         routes: PropTypes.array.isRequired, | ||||
|         match: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     static contextTypes = { | ||||
| @ -58,152 +38,38 @@ export default class App extends Component { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     getSections() { | ||||
|         const { routes, params } = this.props; | ||||
|         const unique = {}; | ||||
|         const result = routes | ||||
|             .splice(1) | ||||
|             .map(routeEntry => ({ | ||||
|                 name: replace(routeEntry.pageTitle, params), | ||||
|                 link: replace(routeEntry.link || routeEntry.path, params), | ||||
|             })) | ||||
|             .filter(entry => { | ||||
|                 if (!unique[entry.link]) { | ||||
|                     unique[entry.link] = true; | ||||
|                     return true; | ||||
|                 } | ||||
|                 return false; | ||||
|             }); | ||||
| 
 | ||||
|         // mutate document.title: | ||||
|         document.title = result | ||||
|             .map(e => e.name) | ||||
|             .reverse() | ||||
|             .concat('Unleash') | ||||
|             .join(' – '); | ||||
| 
 | ||||
|         return result; | ||||
|     } | ||||
| 
 | ||||
|     getTitleWithLinks() { | ||||
|         const result = this.getSections(); | ||||
|         return ( | ||||
|             <span> | ||||
|                 {result.map((entry, index) => ( | ||||
|                     <span key={entry.link + index} className={index > 0 ? 'mdl-layout--large-screen-only' : ''}> | ||||
|                         {index > 0 ? ' › ' : null} | ||||
|                         <Link | ||||
|                             className={[styles.headerTitleLink, 'mdl-color-text--primary-contrast'].join(' ')} | ||||
|                             to={entry.link} | ||||
|                         > | ||||
|                             {entry.name} | ||||
|                         </Link> | ||||
|                     </span> | ||||
|                 ))} | ||||
|             </span> | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|         const shouldUpdateScroll = (prevRouterProps, { location }) => { | ||||
|             if (prevRouterProps && location.pathname !== prevRouterProps.location.pathname) { | ||||
|                 return location.action === 'POP'; | ||||
|             } else { | ||||
|                 return [0, 0]; | ||||
|             } | ||||
|         }; | ||||
|         const createListItem = (path, caption, icon, isDrawerNavigation = false) => { | ||||
|             const linkColor = | ||||
|                 isDrawerNavigation && this.context.router.isActive(path) | ||||
|                     ? 'mdl-color-text--black' | ||||
|                     : 'mdl-color-text--grey-900'; | ||||
|             const iconColor = | ||||
|                 isDrawerNavigation && this.context.router.isActive(path) | ||||
|                     ? 'mdl-color-text--black' | ||||
|                     : 'mdl-color-text--grey-600'; | ||||
|             const renderIcon = ( | ||||
|                 <Icon | ||||
|                     name={icon} | ||||
|                     className={isDrawerNavigation ? [styles.navigationIcon, iconColor].join(' ') : undefined} | ||||
|                 /> | ||||
|             ); | ||||
|             return ( | ||||
|                 <Link | ||||
|                     to={path} | ||||
|                     className={isDrawerNavigation ? [styles.navigationLink, linkColor].join(' ') : undefined} | ||||
|                 > | ||||
|                     {icon && renderIcon} | ||||
|                     {caption} | ||||
|                 </Link> | ||||
|             ); | ||||
|         }; | ||||
| 
 | ||||
|         return ( | ||||
|             <div className={styles.container}> | ||||
|                 <AuthenticationContainer /> | ||||
|                 <Layout fixedHeader> | ||||
|                     <Header title={this.getTitleWithLinks()}> | ||||
|                     <Header title={<Route path="/:path" component={Breadcrum} />}> | ||||
|                         <Navigation> | ||||
|                             <ShowUserContainer /> | ||||
|                         </Navigation> | ||||
|                     </Header> | ||||
|                     <Drawer className="mdl-color--white"> | ||||
|                         <span className={[styles.drawerTitle, 'mdl-layout-title'].join(' ')}> | ||||
|                             <img src="public/logo.png" width="32" height="32" className={styles.drawerTitleLogo} /> | ||||
|                             <span className={styles.drawerTitleText}>Unleash</span> | ||||
|                         </span> | ||||
|                         <hr /> | ||||
|                         <Navigation className={styles.navigation}> | ||||
|                             {createListItem('/features', 'Feature Toggles', 'list', true)} | ||||
|                             {createListItem('/strategies', 'Strategies', 'extension', true)} | ||||
|                             {createListItem('/history', 'Event History', 'history', true)} | ||||
|                             {createListItem('/archive', 'Archived Toggles', 'archive', true)} | ||||
|                             {createListItem('/applications', 'Applications', 'apps', true)} | ||||
|                             {createListItem('logout', 'Sign out', 'exit_to_app', true)} | ||||
|                         </Navigation> | ||||
|                         <hr /> | ||||
|                         <Navigation className={styles.navigation}> | ||||
|                             <a | ||||
|                                 href="https://github.com/Unleash" | ||||
|                                 target="_blank" | ||||
|                                 className={[styles.navigationLink, 'mdl-color-text--grey-900'].join(' ')} | ||||
|                             > | ||||
|                                 <i className={['material-icons', styles.navigationIcon, styles.iconGitHub].join(' ')} />GitHub | ||||
|                             </a> | ||||
|                         </Navigation> | ||||
|                     </Drawer> | ||||
|                     <ScrollContainer scrollKey="container" shouldUpdateScroll={shouldUpdateScroll}> | ||||
|                         <Content className="mdl-color--grey-50"> | ||||
|                             <Grid noSpacing className={styles.content}> | ||||
|                                 <Cell col={12}> | ||||
|                                     {this.props.children} | ||||
|                                     <ErrorContainer /> | ||||
|                                 </Cell> | ||||
|                             </Grid> | ||||
|                             <Footer size="mega"> | ||||
|                                 <FooterSection type="middle"> | ||||
|                                     <FooterDropDownSection title="Menu"> | ||||
|                                         <FooterLinkList> | ||||
|                                             {createListItem('/features', 'Feature Toggles', '')} | ||||
|                                             {createListItem('/strategies', 'Strategies', '')} | ||||
|                                             {createListItem('/history', 'Event History', '')} | ||||
|                                             {createListItem('/archive', 'Archived Toggles', '')} | ||||
|                                             {createListItem('/applications', 'Applications', '')} | ||||
|                                             {createListItem('/logout', 'Sign out', '')} | ||||
|                                         </FooterLinkList> | ||||
|                                     </FooterDropDownSection> | ||||
|                                     <FooterDropDownSection title="Clients"> | ||||
|                                         <FooterLinkList> | ||||
|                                             <a href="https://github.com/Unleash/unleash-client-node/">Node.js</a> | ||||
|                                             <a href="https://github.com/Unleash/unleash-client-java/">Java</a> | ||||
|                                             <a href="https://github.com/Unleash/unleash-client-go/">Go</a> | ||||
|                                         </FooterLinkList> | ||||
|                                     </FooterDropDownSection> | ||||
|                                 </FooterSection> | ||||
|                                 <ShowApiDetailsContainer /> | ||||
|                             </Footer> | ||||
|                         </Content> | ||||
|                     </ScrollContainer> | ||||
|                     <DrawerMenu /> | ||||
|                     <Content className="mdl-color--grey-50"> | ||||
|                         <Grid noSpacing className={styles.content}> | ||||
|                             <Cell col={12}> | ||||
|                                 <Switch> | ||||
|                                     <Route | ||||
|                                         exact | ||||
|                                         path="/" | ||||
|                                         render={() => <Redirect to="/features" component={Features} />} | ||||
|                                     /> | ||||
|                                     {routes.map(route => ( | ||||
|                                         <Route key={route.path} path={route.path} component={route.component} /> | ||||
|                                     ))} | ||||
|                                 </Switch> | ||||
|                                 <ErrorContainer /> | ||||
|                             </Cell> | ||||
|                         </Grid> | ||||
|                         <Footer size="mega"> | ||||
|                             <FooterMenu /> | ||||
|                             <ShowApiDetailsContainer /> | ||||
|                         </Footer> | ||||
|                     </Content> | ||||
|                 </Layout> | ||||
|             </div> | ||||
|         ); | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| import React, { Component, PureComponent } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| import { Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { | ||||
|     Grid, | ||||
|     Cell, | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { List, ListItem, ListItemContent, Button, Icon, Switch, MenuItem } from 'react-mdl'; | ||||
| import styles from './common.scss'; | ||||
| 
 | ||||
|  | ||||
| @ -32,8 +32,8 @@ exports[`renders correctly with one feature 1`] = ` | ||||
|   > | ||||
|     <a | ||||
|       className="listLink truncate" | ||||
|       href="/features/strategies/Another" | ||||
|       onClick={[Function]} | ||||
|       style={Object {}} | ||||
|     > | ||||
|       Another | ||||
|       <span | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| import React from 'react'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
| 
 | ||||
| import Feature from './../feature-list-item-component'; | ||||
| import renderer from 'react-test-renderer'; | ||||
| @ -23,14 +24,16 @@ test('renders correctly with one feature', () => { | ||||
|     const featureMetrics = { lastHour: {}, lastMinute: {}, seenApps: {} }; | ||||
|     const settings = { sort: 'name' }; | ||||
|     const tree = renderer.create( | ||||
|         <Feature | ||||
|             key={0} | ||||
|             settings={settings} | ||||
|             metricsLastHour={featureMetrics.lastHour[feature.name]} | ||||
|             metricsLastMinute={featureMetrics.lastMinute[feature.name]} | ||||
|             feature={feature} | ||||
|             toggleFeature={jest.fn()} | ||||
|         /> | ||||
|         <MemoryRouter> | ||||
|             <Feature | ||||
|                 key={0} | ||||
|                 settings={settings} | ||||
|                 metricsLastHour={featureMetrics.lastHour[feature.name]} | ||||
|                 metricsLastMinute={featureMetrics.lastMinute[feature.name]} | ||||
|                 feature={feature} | ||||
|                 toggleFeature={jest.fn()} | ||||
|             /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { Switch, Chip, ListItem, ListItemAction, Icon } from 'react-mdl'; | ||||
| import Progress from './progress'; | ||||
| import { calc, styles as commonStyles } from '../common'; | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import { connect } from 'react-redux'; | ||||
| import { hashHistory } from 'react-router'; | ||||
| import { createFeatureToggles, validateName } from './../../../store/feature-actions'; | ||||
| import { createMapper, createActions } from './../../input-helpers'; | ||||
| import AddFeatureComponent from './form-add-feature-component'; | ||||
| @ -31,13 +30,13 @@ const prepare = (methods, dispatch) => { | ||||
| 
 | ||||
|         createFeatureToggles(input)(dispatch) | ||||
|             .then(() => methods.clear()) | ||||
|             .then(() => hashHistory.push(`/features/strategies/${input.name}`)); | ||||
|             .then(() => this.props.history.push(`/features/strategies/${input.name}`)); | ||||
|     }; | ||||
| 
 | ||||
|     methods.onCancel = evt => { | ||||
|         evt.preventDefault(); | ||||
|         methods.clear(); | ||||
|         hashHistory.push('/features'); | ||||
|         this.props.history.push('/features'); | ||||
|     }; | ||||
| 
 | ||||
|     methods.addStrategy = v => { | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import { connect } from 'react-redux'; | ||||
| import { hashHistory } from 'react-router'; | ||||
| 
 | ||||
| import { requestUpdateFeatureToggle } from '../../../store/feature-actions'; | ||||
| import { createMapper, createActions } from '../../input-helpers'; | ||||
| @ -42,13 +41,13 @@ const prepare = (methods, dispatch) => { | ||||
|         // TODO: should add error handling | ||||
|         requestUpdateFeatureToggle(input)(dispatch) | ||||
|             .then(() => methods.clear()) | ||||
|             .then(() => hashHistory.push(`/features`)); | ||||
|             .then(() => this.props.history.push(`/features`)); | ||||
|     }; | ||||
| 
 | ||||
|     methods.onCancel = evt => { | ||||
|         evt.preventDefault(); | ||||
|         methods.clear(); | ||||
|         hashHistory.push(`/features`); | ||||
|         this.props.history.push(`/features`); | ||||
|     }; | ||||
| 
 | ||||
|     methods.addStrategy = v => { | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| import { connect } from 'react-redux'; | ||||
| import { createMapper, createActions } from '../../input-helpers'; | ||||
| import ViewFeatureToggleComponent from './form-view-feature-component'; | ||||
| import { hashHistory } from 'react-router'; | ||||
| 
 | ||||
| const ID = 'view-feature-toggle'; | ||||
| function getId(props) { | ||||
| @ -27,7 +26,7 @@ const prepare = methods => { | ||||
|     methods.onCancel = evt => { | ||||
|         evt.preventDefault(); | ||||
|         methods.clear(); | ||||
|         hashHistory.push(`/archive`); | ||||
|         this.props.history.push(`/archive`); | ||||
|     }; | ||||
|     return methods; | ||||
| }; | ||||
|  | ||||
| @ -2,7 +2,7 @@ import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { Textfield, Button, Card, CardTitle, CardText, CardActions, CardMenu, IconButton, Icon } from 'react-mdl'; | ||||
| import { DragSource, DropTarget } from 'react-dnd'; | ||||
| import { Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import StrategyInputPercentage from './strategy-input-percentage'; | ||||
| import StrategyInputList from './strategy-input-list'; | ||||
| import styles from './strategy.scss'; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import Feature from './feature-list-item-component'; | ||||
| import { hashHistory, Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { Icon, FABButton, Textfield, Menu, MenuItem, Card, CardActions, List } from 'react-mdl'; | ||||
| import { MenuItemWithIcon, DropdownButton, styles as commonStyles } from '../common'; | ||||
| import styles from './feature.scss'; | ||||
| @ -18,6 +18,7 @@ export default class FeatureListComponent extends React.Component { | ||||
|         updateSetting: PropTypes.func.isRequired, | ||||
|         toggleFeature: PropTypes.func, | ||||
|         settings: PropTypes.object, | ||||
|         history: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     static contextTypes = { | ||||
| @ -27,7 +28,7 @@ export default class FeatureListComponent extends React.Component { | ||||
|     componentDidMount() { | ||||
|         if (this.props.logout) { | ||||
|             this.props.logoutUser(); | ||||
|             hashHistory.push(`/`); | ||||
|             this.props.history.push(`/`); | ||||
|         } | ||||
|         if (this.props.fetchFeatureToggles) { | ||||
|             this.props.fetchFeatureToggles(); | ||||
|  | ||||
| @ -2,7 +2,7 @@ import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { Grid, Cell, Icon, Chip, ChipContact } from 'react-mdl'; | ||||
| import Progress from './progress'; | ||||
| import { Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { AppsLinkList, calc } from '../common'; | ||||
| import { formatFullDateTimeWithLocale } from '../common/util'; | ||||
| import styles from './metrics.scss'; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { Tabs, Tab, ProgressBar, Button, Card, CardText, CardTitle, CardActions, Textfield, Switch } from 'react-mdl'; | ||||
| import { hashHistory, Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| 
 | ||||
| import HistoryComponent from '../history/history-list-toggle-container'; | ||||
| import MetricComponent from './metric-container'; | ||||
| @ -33,6 +33,7 @@ export default class ViewFeatureToggleComponent extends React.Component { | ||||
|         fetchFeatureToggles: PropTypes.func, | ||||
|         editFeatureToggle: PropTypes.func, | ||||
|         featureToggle: PropTypes.object, | ||||
|         history: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     componentWillMount() { | ||||
| @ -62,7 +63,7 @@ export default class ViewFeatureToggleComponent extends React.Component { | ||||
| 
 | ||||
|     goToTab(tabName, featureToggleName) { | ||||
|         let view = this.props.fetchFeatureToggles ? 'features' : 'archive'; | ||||
|         hashHistory.push(`/${view}/${tabName}/${featureToggleName}`); | ||||
|         this.props.history.push(`/${view}/${tabName}/${featureToggleName}`); | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
| @ -105,12 +106,12 @@ export default class ViewFeatureToggleComponent extends React.Component { | ||||
|                 window.confirm('Are you sure you want to remove this toggle?') | ||||
|             ) { | ||||
|                 removeFeatureToggle(featureToggle.name); | ||||
|                 hashHistory.push('/features'); | ||||
|                 this.props.history.push('/features'); | ||||
|             } | ||||
|         }; | ||||
|         const reviveToggle = () => { | ||||
|             revive(featureToggle.name); | ||||
|             hashHistory.push('/features'); | ||||
|             this.props.history.push('/features'); | ||||
|         }; | ||||
|         const updateFeatureToggle = () => { | ||||
|             let feature = { ...featureToggle }; | ||||
|  | ||||
							
								
								
									
										5
									
								
								frontend/src/component/menu/__tests__/.eslintrc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								frontend/src/component/menu/__tests__/.eslintrc
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| { | ||||
|     "env": { | ||||
|         "jest": true | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,49 @@ | ||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
| 
 | ||||
| exports[`breadcrumb for /features 1`] = ` | ||||
| <span | ||||
|   className="mdl-layout--large-screen-only" | ||||
| > | ||||
|   <span | ||||
|     className="headerTitleLink mdl-color-text--primary-contrast" | ||||
|   > | ||||
|     Feature Toggles | ||||
|   </span> | ||||
| </span> | ||||
| `; | ||||
| 
 | ||||
| exports[`breadcrumb for /features/view/Demo 1`] = ` | ||||
| <span> | ||||
|   <a | ||||
|     className="headerTitleLink mdl-color-text--primary-contrast" | ||||
|     href="/features" | ||||
|     onClick={[Function]} | ||||
|   > | ||||
|     Feature Toggles | ||||
|   </a> | ||||
|   <span | ||||
|     className="mdl-layout--large-screen-only" | ||||
|   > | ||||
|     <span> | ||||
|        ›  | ||||
|     </span> | ||||
|     <span | ||||
|       className="headerTitleLink mdl-color-text--primary-contrast" | ||||
|     > | ||||
|       Demo | ||||
|     </span> | ||||
|   </span> | ||||
| </span> | ||||
| `; | ||||
| 
 | ||||
| exports[`breadcrumb for /strategies 1`] = ` | ||||
| <span | ||||
|   className="mdl-layout--large-screen-only" | ||||
| > | ||||
|   <span | ||||
|     className="headerTitleLink mdl-color-text--primary-contrast" | ||||
|   > | ||||
|     Strategies | ||||
|   </span> | ||||
| </span> | ||||
| `; | ||||
| @ -0,0 +1,253 @@ | ||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
| 
 | ||||
| exports[`should render DrawerMenu 1`] = ` | ||||
| <react-mdl-Drawer | ||||
|   className="mdl-color--white" | ||||
| > | ||||
|   <span | ||||
|     className="drawerTitle mdl-layout-title" | ||||
|   > | ||||
|     <img | ||||
|       className="drawerTitleLogo" | ||||
|       height="32" | ||||
|       src="public/logo.png" | ||||
|       width="32" | ||||
|     /> | ||||
|     <span | ||||
|       className="drawerTitleText" | ||||
|     > | ||||
|       Unleash | ||||
|     </span> | ||||
|   </span> | ||||
|   <hr /> | ||||
|   <react-mdl-Navigation | ||||
|     className="navigation" | ||||
|   > | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/features" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="list" | ||||
|       /> | ||||
|         | ||||
|       Feature Toggles | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/strategies" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="extension" | ||||
|       /> | ||||
|         | ||||
|       Strategies | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/history" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="history" | ||||
|       /> | ||||
|         | ||||
|       Event History | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/archive" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="archive" | ||||
|       /> | ||||
|         | ||||
|       Archived Toggles | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/applications" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="apps" | ||||
|       /> | ||||
|         | ||||
|       Applications | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/logout" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="exit_to_app" | ||||
|       /> | ||||
|         | ||||
|       Sign out | ||||
|     </a> | ||||
|   </react-mdl-Navigation> | ||||
|   <hr /> | ||||
|   <react-mdl-Navigation | ||||
|     className="navigation" | ||||
|   > | ||||
|     <a | ||||
|       className="navigationLink mdl-color-text--grey-900" | ||||
|       href="https://github.com/Unleash" | ||||
|       target="_blank" | ||||
|     > | ||||
|       <i | ||||
|         className="material-icons navigationIcon iconGitHub" | ||||
|       /> | ||||
|       GitHub | ||||
|     </a> | ||||
|   </react-mdl-Navigation> | ||||
| </react-mdl-Drawer> | ||||
| `; | ||||
| 
 | ||||
| exports[`should render DrawerMenu with "features" selected 1`] = ` | ||||
| <react-mdl-Drawer | ||||
|   className="mdl-color--white" | ||||
| > | ||||
|   <span | ||||
|     className="drawerTitle mdl-layout-title" | ||||
|   > | ||||
|     <img | ||||
|       className="drawerTitleLogo" | ||||
|       height="32" | ||||
|       src="public/logo.png" | ||||
|       width="32" | ||||
|     /> | ||||
|     <span | ||||
|       className="drawerTitleText" | ||||
|     > | ||||
|       Unleash | ||||
|     </span> | ||||
|   </span> | ||||
|   <hr /> | ||||
|   <react-mdl-Navigation | ||||
|     className="navigation" | ||||
|   > | ||||
|     <a | ||||
|       aria-current="page" | ||||
|       className="navigationLink mdl-color-text--grey-600 navigationLink mdl-color-text--black" | ||||
|       href="/features" | ||||
|       onClick={[Function]} | ||||
|       style={Object {}} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="list" | ||||
|       /> | ||||
|         | ||||
|       Feature Toggles | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/strategies" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="extension" | ||||
|       /> | ||||
|         | ||||
|       Strategies | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/history" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="history" | ||||
|       /> | ||||
|         | ||||
|       Event History | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/archive" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="archive" | ||||
|       /> | ||||
|         | ||||
|       Archived Toggles | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/applications" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="apps" | ||||
|       /> | ||||
|         | ||||
|       Applications | ||||
|     </a> | ||||
|     <a | ||||
|       aria-current={null} | ||||
|       className="navigationLink mdl-color-text--grey-600" | ||||
|       href="/logout" | ||||
|       onClick={[Function]} | ||||
|       style={undefined} | ||||
|     > | ||||
|       <react-mdl-Icon | ||||
|         className="navigationIcon" | ||||
|         name="exit_to_app" | ||||
|       /> | ||||
|         | ||||
|       Sign out | ||||
|     </a> | ||||
|   </react-mdl-Navigation> | ||||
|   <hr /> | ||||
|   <react-mdl-Navigation | ||||
|     className="navigation" | ||||
|   > | ||||
|     <a | ||||
|       className="navigationLink mdl-color-text--grey-900" | ||||
|       href="https://github.com/Unleash" | ||||
|       target="_blank" | ||||
|     > | ||||
|       <i | ||||
|         className="material-icons navigationIcon iconGitHub" | ||||
|       /> | ||||
|       GitHub | ||||
|     </a> | ||||
|   </react-mdl-Navigation> | ||||
| </react-mdl-Drawer> | ||||
| `; | ||||
| @ -0,0 +1,177 @@ | ||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
| 
 | ||||
| exports[`should render DrawerMenu 1`] = ` | ||||
| <react-mdl-FooterSection | ||||
|   type="middle" | ||||
| > | ||||
|   <react-mdl-FooterDropDownSection | ||||
|     title="Menu" | ||||
|   > | ||||
|     <react-mdl-FooterLinkList> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/features" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Feature Toggles | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/strategies" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Strategies | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/history" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Event History | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/archive" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Archived Toggles | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/applications" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Applications | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/logout" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Sign out | ||||
|       </a> | ||||
|     </react-mdl-FooterLinkList> | ||||
|   </react-mdl-FooterDropDownSection> | ||||
|   <react-mdl-FooterDropDownSection | ||||
|     title="Clients" | ||||
|   > | ||||
|     <react-mdl-FooterLinkList> | ||||
|       <a | ||||
|         href="https://github.com/Unleash/unleash-client-node/" | ||||
|       > | ||||
|         Node.js | ||||
|       </a> | ||||
|       <a | ||||
|         href="https://github.com/Unleash/unleash-client-java/" | ||||
|       > | ||||
|         Java | ||||
|       </a> | ||||
|       <a | ||||
|         href="https://github.com/Unleash/unleash-client-go/" | ||||
|       > | ||||
|         Go | ||||
|       </a> | ||||
|     </react-mdl-FooterLinkList> | ||||
|   </react-mdl-FooterDropDownSection> | ||||
| </react-mdl-FooterSection> | ||||
| `; | ||||
| 
 | ||||
| exports[`should render DrawerMenu with "features" selected 1`] = ` | ||||
| <react-mdl-FooterSection | ||||
|   type="middle" | ||||
| > | ||||
|   <react-mdl-FooterDropDownSection | ||||
|     title="Menu" | ||||
|   > | ||||
|     <react-mdl-FooterLinkList> | ||||
|       <a | ||||
|         aria-current="page" | ||||
|         className="active" | ||||
|         href="/features" | ||||
|         onClick={[Function]} | ||||
|         style={Object {}} | ||||
|       > | ||||
|         Feature Toggles | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/strategies" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Strategies | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/history" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Event History | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/archive" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Archived Toggles | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/applications" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Applications | ||||
|       </a> | ||||
|       <a | ||||
|         aria-current={null} | ||||
|         className={undefined} | ||||
|         href="/logout" | ||||
|         onClick={[Function]} | ||||
|         style={undefined} | ||||
|       > | ||||
|         Sign out | ||||
|       </a> | ||||
|     </react-mdl-FooterLinkList> | ||||
|   </react-mdl-FooterDropDownSection> | ||||
|   <react-mdl-FooterDropDownSection | ||||
|     title="Clients" | ||||
|   > | ||||
|     <react-mdl-FooterLinkList> | ||||
|       <a | ||||
|         href="https://github.com/Unleash/unleash-client-node/" | ||||
|       > | ||||
|         Node.js | ||||
|       </a> | ||||
|       <a | ||||
|         href="https://github.com/Unleash/unleash-client-java/" | ||||
|       > | ||||
|         Java | ||||
|       </a> | ||||
|       <a | ||||
|         href="https://github.com/Unleash/unleash-client-go/" | ||||
|       > | ||||
|         Go | ||||
|       </a> | ||||
|     </react-mdl-FooterLinkList> | ||||
|   </react-mdl-FooterDropDownSection> | ||||
| </react-mdl-FooterSection> | ||||
| `; | ||||
| @ -0,0 +1,123 @@ | ||||
| // Jest Snapshot v1, https://goo.gl/fbAQLP | ||||
| 
 | ||||
| exports[`returns all baseRoutes 1`] = ` | ||||
| Array [ | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "list", | ||||
|     "path": "/features", | ||||
|     "title": "Feature Toggles", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "extension", | ||||
|     "path": "/strategies", | ||||
|     "title": "Strategies", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "history", | ||||
|     "path": "/history", | ||||
|     "title": "Event History", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "archive", | ||||
|     "path": "/archive", | ||||
|     "title": "Archived Toggles", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "apps", | ||||
|     "path": "/applications", | ||||
|     "title": "Applications", | ||||
|   }, | ||||
|   Object { | ||||
|     "icon": "exit_to_app", | ||||
|     "path": "logout", | ||||
|     "title": "Sign out", | ||||
|   }, | ||||
| ] | ||||
| `; | ||||
| 
 | ||||
| exports[`returns all defined routes 1`] = ` | ||||
| Array [ | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "parent": "/features", | ||||
|     "path": "/features/create", | ||||
|     "title": "Create", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "parent": "/features", | ||||
|     "path": "/features/:activeTab/:name", | ||||
|     "title": ":name", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "list", | ||||
|     "path": "/features", | ||||
|     "title": "Feature Toggles", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "parent": "/strategies", | ||||
|     "path": "/strategies/create", | ||||
|     "title": "Create", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "parent": "/strategies", | ||||
|     "path": "/strategies/:activeTab/:strategyName", | ||||
|     "title": ":strategyName", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "extension", | ||||
|     "path": "/strategies", | ||||
|     "title": "Strategies", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "parent": "/history", | ||||
|     "path": "/history/:toggleName", | ||||
|     "title": ":toggleName", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "history", | ||||
|     "path": "/history", | ||||
|     "title": "Event History", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "parent": "/archive", | ||||
|     "path": "/archive/:activeTab/:name", | ||||
|     "title": ":name", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "archive", | ||||
|     "path": "/archive", | ||||
|     "title": "Archived Toggles", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "parent": "/applications", | ||||
|     "path": "/applications/:name", | ||||
|     "title": ":name", | ||||
|   }, | ||||
|   Object { | ||||
|     "component": [Function], | ||||
|     "icon": "apps", | ||||
|     "path": "/applications", | ||||
|     "title": "Applications", | ||||
|   }, | ||||
|   Object { | ||||
|     "icon": "exit_to_app", | ||||
|     "path": "logout", | ||||
|     "title": "Sign out", | ||||
|   }, | ||||
| ] | ||||
| `; | ||||
							
								
								
									
										37
									
								
								frontend/src/component/menu/__tests__/breadcrumb-test.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								frontend/src/component/menu/__tests__/breadcrumb-test.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| import React from 'react'; | ||||
| import renderer from 'react-test-renderer'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
| 
 | ||||
| import Breadcrumb from '../breadcrumb'; | ||||
| 
 | ||||
| jest.mock('react-mdl'); | ||||
| 
 | ||||
| test('breadcrumb for /features', () => { | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter initialEntries={['/features']}> | ||||
|             <Breadcrumb /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
| }); | ||||
| 
 | ||||
| test('breadcrumb for /features/view/Demo', () => { | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter initialEntries={['/features/view/Demo']}> | ||||
|             <Breadcrumb /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
| }); | ||||
| 
 | ||||
| test('breadcrumb for /strategies', () => { | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter initialEntries={['/strategies']}> | ||||
|             <Breadcrumb /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
| }); | ||||
							
								
								
									
										27
									
								
								frontend/src/component/menu/__tests__/drawer-test.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								frontend/src/component/menu/__tests__/drawer-test.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| import React from 'react'; | ||||
| import renderer from 'react-test-renderer'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
| 
 | ||||
| import { DrawerMenu } from '../drawer'; | ||||
| 
 | ||||
| jest.mock('react-mdl'); | ||||
| 
 | ||||
| test('should render DrawerMenu', () => { | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter> | ||||
|             <DrawerMenu /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
| }); | ||||
| 
 | ||||
| test('should render DrawerMenu with "features" selected', () => { | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter initialEntries={['/features']}> | ||||
|             <DrawerMenu /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
| }); | ||||
							
								
								
									
										27
									
								
								frontend/src/component/menu/__tests__/footer-test.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								frontend/src/component/menu/__tests__/footer-test.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| import React from 'react'; | ||||
| import renderer from 'react-test-renderer'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
| 
 | ||||
| import { FooterMenu } from '../footer'; | ||||
| 
 | ||||
| jest.mock('react-mdl'); | ||||
| 
 | ||||
| test('should render DrawerMenu', () => { | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter> | ||||
|             <FooterMenu /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
| }); | ||||
| 
 | ||||
| test('should render DrawerMenu with "features" selected', () => { | ||||
|     const tree = renderer.create( | ||||
|         <MemoryRouter initialEntries={['/features']}> | ||||
|             <FooterMenu /> | ||||
|         </MemoryRouter> | ||||
|     ); | ||||
| 
 | ||||
|     expect(tree).toMatchSnapshot(); | ||||
| }); | ||||
							
								
								
									
										16
									
								
								frontend/src/component/menu/__tests__/routes-test.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								frontend/src/component/menu/__tests__/routes-test.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| import { routes, baseRoutes, getRoute } from '../routes'; | ||||
| 
 | ||||
| test('returns all defined routes', () => { | ||||
|     expect(routes.length).toEqual(13); | ||||
|     expect(routes).toMatchSnapshot(); | ||||
| }); | ||||
| 
 | ||||
| test('returns all baseRoutes', () => { | ||||
|     expect(baseRoutes.length).toEqual(6); | ||||
|     expect(baseRoutes).toMatchSnapshot(); | ||||
| }); | ||||
| 
 | ||||
| test('getRoute() returns named route', () => { | ||||
|     const featuresRoute = getRoute('/features'); | ||||
|     expect(featuresRoute.path).toEqual('/features'); | ||||
| }); | ||||
							
								
								
									
										69
									
								
								frontend/src/component/menu/breadcrumb.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								frontend/src/component/menu/breadcrumb.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | ||||
| import React from 'react'; | ||||
| import { Link, Route, Switch } from 'react-router-dom'; | ||||
| 
 | ||||
| import { routes, getRoute } from './routes'; | ||||
| 
 | ||||
| import styles from '../styles.scss'; | ||||
| 
 | ||||
| const renderDoubleBread = (currentTitle, parentRoute) => { | ||||
|     document.title = `${currentTitle} -  ${parentRoute.title} - Unleash`; | ||||
|     return ( | ||||
|         <span> | ||||
|             <Link | ||||
|                 className={[styles.headerTitleLink, 'mdl-color-text--primary-contrast'].join(' ')} | ||||
|                 to={parentRoute.path} | ||||
|             > | ||||
|                 {parentRoute.title} | ||||
|             </Link> | ||||
|             <span className="mdl-layout--large-screen-only"> | ||||
|                 <span> › </span> | ||||
|                 <span className={[styles.headerTitleLink, 'mdl-color-text--primary-contrast'].join(' ')}> | ||||
|                     {currentTitle} | ||||
|                 </span> | ||||
|             </span> | ||||
|         </span> | ||||
|     ); | ||||
| }; | ||||
| 
 | ||||
| const renderBread = route => { | ||||
|     document.title = `${route.title} - Unleash`; | ||||
|     return ( | ||||
|         <span className="mdl-layout--large-screen-only"> | ||||
|             <span className={[styles.headerTitleLink, 'mdl-color-text--primary-contrast'].join(' ')}> | ||||
|                 {route.title} | ||||
|             </span> | ||||
|         </span> | ||||
|     ); | ||||
| }; | ||||
| 
 | ||||
| const renderRoute = (params, route) => { | ||||
|     if (!route) { | ||||
|         return null; | ||||
|     } | ||||
|     const title = route.title.startsWith(':') ? params[route.title.substring(1)] : route.title; | ||||
|     return route.parent ? renderDoubleBread(title, getRoute(route.parent)) : renderBread(route); | ||||
| }; | ||||
| 
 | ||||
| /* | ||||
|     Render the breadcrumb. | ||||
| 
 | ||||
|     We only support two levels. | ||||
| 
 | ||||
|     Examples: | ||||
|      - Features | ||||
|      - Features > Create | ||||
|      - Features > SomeToggle | ||||
|  */ | ||||
| const Breadcrumb = () => ( | ||||
|     <Switch> | ||||
|         {routes.map(route => ( | ||||
|             <Route | ||||
|                 key={route.path} | ||||
|                 path={route.path} | ||||
|                 render={({ match: { params } } = this.props) => renderRoute(params, route)} | ||||
|             /> | ||||
|         ))} | ||||
|     </Switch> | ||||
| ); | ||||
| 
 | ||||
| export default Breadcrumb; | ||||
							
								
								
									
										38
									
								
								frontend/src/component/menu/drawer.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								frontend/src/component/menu/drawer.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,38 @@ | ||||
| import React from 'react'; | ||||
| import { Drawer, Icon, Navigation } from 'react-mdl'; | ||||
| import { NavLink } from 'react-router-dom'; | ||||
| import styles from '../styles.scss'; | ||||
| 
 | ||||
| import { baseRoutes as routes } from './routes'; | ||||
| 
 | ||||
| export const DrawerMenu = () => ( | ||||
|     <Drawer className="mdl-color--white"> | ||||
|         <span className={[styles.drawerTitle, 'mdl-layout-title'].join(' ')}> | ||||
|             <img src="public/logo.png" width="32" height="32" className={styles.drawerTitleLogo} /> | ||||
|             <span className={styles.drawerTitleText}>Unleash</span> | ||||
|         </span> | ||||
|         <hr /> | ||||
|         <Navigation className={styles.navigation}> | ||||
|             {routes.map(item => ( | ||||
|                 <NavLink | ||||
|                     key={item.path} | ||||
|                     to={item.path} | ||||
|                     className={[styles.navigationLink, 'mdl-color-text--grey-600'].join(' ')} | ||||
|                     activeClassName={[styles.navigationLink, 'mdl-color-text--black'].join(' ')} | ||||
|                 > | ||||
|                     <Icon name={item.icon} className={styles.navigationIcon} /> {item.title} | ||||
|                 </NavLink> | ||||
|             ))} | ||||
|         </Navigation> | ||||
|         <hr /> | ||||
|         <Navigation className={styles.navigation}> | ||||
|             <a | ||||
|                 href="https://github.com/Unleash" | ||||
|                 target="_blank" | ||||
|                 className={[styles.navigationLink, 'mdl-color-text--grey-900'].join(' ')} | ||||
|             > | ||||
|                 <i className={['material-icons', styles.navigationIcon, styles.iconGitHub].join(' ')} />GitHub | ||||
|             </a> | ||||
|         </Navigation> | ||||
|     </Drawer> | ||||
| ); | ||||
							
								
								
									
										26
									
								
								frontend/src/component/menu/footer.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								frontend/src/component/menu/footer.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,26 @@ | ||||
| import React from 'react'; | ||||
| import { FooterDropDownSection, FooterLinkList, FooterSection } from 'react-mdl'; | ||||
| import { NavLink } from 'react-router-dom'; | ||||
| 
 | ||||
| import { baseRoutes as routes } from './routes'; | ||||
| 
 | ||||
| export const FooterMenu = () => ( | ||||
|     <FooterSection type="middle"> | ||||
|         <FooterDropDownSection title="Menu"> | ||||
|             <FooterLinkList> | ||||
|                 {routes.map(item => ( | ||||
|                     <NavLink key={item.path} to={item.path}> | ||||
|                         {item.title} | ||||
|                     </NavLink> | ||||
|                 ))} | ||||
|             </FooterLinkList> | ||||
|         </FooterDropDownSection> | ||||
|         <FooterDropDownSection title="Clients"> | ||||
|             <FooterLinkList> | ||||
|                 <a href="https://github.com/Unleash/unleash-client-node/">Node.js</a> | ||||
|                 <a href="https://github.com/Unleash/unleash-client-java/">Java</a> | ||||
|                 <a href="https://github.com/Unleash/unleash-client-go/">Go</a> | ||||
|             </FooterLinkList> | ||||
|         </FooterDropDownSection> | ||||
|     </FooterSection> | ||||
| ); | ||||
							
								
								
									
										47
									
								
								frontend/src/component/menu/routes.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								frontend/src/component/menu/routes.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| import CreateFeatureToggle from '../../page/features/create'; | ||||
| import ViewFeatureToggle from '../../page/features/show'; | ||||
| import Features from '../../page/features'; | ||||
| import CreateStrategies from '../../page/strategies/create'; | ||||
| import StrategyView from '../../page/strategies/show'; | ||||
| import Strategies from '../../page/strategies'; | ||||
| import HistoryPage from '../../page/history'; | ||||
| import HistoryTogglePage from '../../page/history/toggle'; | ||||
| import ShowArchive from '../../page/archive/show'; | ||||
| import Archive from '../../page/archive'; | ||||
| import Applications from '../../page/applications'; | ||||
| import ApplicationView from '../../page/applications/view'; | ||||
| 
 | ||||
| export const routes = [ | ||||
|     // Features
 | ||||
|     { path: '/features/create', parent: '/features', title: 'Create', component: CreateFeatureToggle }, | ||||
|     { path: '/features/:activeTab/:name', parent: '/features', title: ':name', component: ViewFeatureToggle }, | ||||
|     { path: '/features', title: 'Feature Toggles', icon: 'list', component: Features }, | ||||
| 
 | ||||
|     // Strategies
 | ||||
|     { path: '/strategies/create', title: 'Create', parent: '/strategies', component: CreateStrategies }, | ||||
|     { | ||||
|         path: '/strategies/:activeTab/:strategyName', | ||||
|         title: ':strategyName', | ||||
|         parent: '/strategies', | ||||
|         component: StrategyView, | ||||
|     }, | ||||
|     { path: '/strategies', title: 'Strategies', icon: 'extension', component: Strategies }, | ||||
| 
 | ||||
|     // History
 | ||||
|     { path: '/history/:toggleName', title: ':toggleName', parent: '/history', component: HistoryTogglePage }, | ||||
|     { path: '/history', title: 'Event History', icon: 'history', component: HistoryPage }, | ||||
| 
 | ||||
|     // Archive
 | ||||
|     { path: '/archive/:activeTab/:name', title: ':name', parent: '/archive', component: ShowArchive }, | ||||
|     { path: '/archive', title: 'Archived Toggles', icon: 'archive', component: Archive }, | ||||
| 
 | ||||
|     // Applications
 | ||||
|     { path: '/applications/:name', title: ':name', parent: '/applications', component: ApplicationView }, | ||||
|     { path: '/applications', title: 'Applications', icon: 'apps', component: Applications }, | ||||
| 
 | ||||
|     { path: 'logout', title: 'Sign out', icon: 'exit_to_app' }, | ||||
| ]; | ||||
| 
 | ||||
| export const getRoute = path => routes.find(route => route.path === path); | ||||
| 
 | ||||
| export const baseRoutes = routes.filter(route => !route.parent); | ||||
							
								
								
									
										21
									
								
								frontend/src/component/scroll-to-top.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								frontend/src/component/scroll-to-top.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| import { Component } from 'react'; | ||||
| import { withRouter } from 'react-router-dom'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| class ScrollToTop extends Component { | ||||
|     static propTypes = { | ||||
|         location: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     componentDidUpdate(prevProps) { | ||||
|         if (this.props.location !== prevProps.location) { | ||||
|             window.scrollTo(0, 0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|         return this.props.children; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export default withRouter(ScrollToTop); | ||||
| @ -1,5 +1,4 @@ | ||||
| import { connect } from 'react-redux'; | ||||
| import { hashHistory } from 'react-router'; | ||||
| import { createMapper, createActions } from '../input-helpers'; | ||||
| import { updateStrategy } from '../../store/strategy/actions'; | ||||
| 
 | ||||
| @ -41,7 +40,7 @@ const prepare = (methods, dispatch) => { | ||||
|             parameters, | ||||
|         })(dispatch) | ||||
|             .then(() => methods.clear()) | ||||
|             .then(() => hashHistory.push(`/strategies/view/${input.name}`)); | ||||
|             .then(() => this.props.history.push(`/strategies/view/${input.name}`)); | ||||
|     }; | ||||
| 
 | ||||
|     methods.onCancel = e => { | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { Link } from 'react-router'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| 
 | ||||
| import { List, ListItem, ListItemContent, IconButton, Grid, Cell } from 'react-mdl'; | ||||
| import { HeaderTitle } from '../common'; | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import React, { Component } from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { hashHistory } from 'react-router'; | ||||
| import { Tabs, Tab, ProgressBar, Grid, Cell } from 'react-mdl'; | ||||
| import ShowStrategy from './show-strategy-component'; | ||||
| import EditStrategy from './edit-container'; | ||||
| @ -21,6 +20,7 @@ export default class StrategyDetails extends Component { | ||||
|         fetchStrategies: PropTypes.func.isRequired, | ||||
|         fetchApplications: PropTypes.func.isRequired, | ||||
|         fetchFeatureToggles: PropTypes.func.isRequired, | ||||
|         history: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     componentDidMount() { | ||||
| @ -50,7 +50,7 @@ export default class StrategyDetails extends Component { | ||||
|     } | ||||
| 
 | ||||
|     goToTab(tabName) { | ||||
|         hashHistory.push(`/strategies/${tabName}/${this.props.strategyName}`); | ||||
|         this.props.history.push(`/strategies/${tabName}/${this.props.strategyName}`); | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|  | ||||
| @ -1,6 +1,5 @@ | ||||
| import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import { hashHistory } from 'react-router'; | ||||
| import { CardActions, Button, Textfield } from 'react-mdl'; | ||||
| 
 | ||||
| class SimpleAuthenticationComponent extends React.Component { | ||||
| @ -8,6 +7,7 @@ class SimpleAuthenticationComponent extends React.Component { | ||||
|         authDetails: PropTypes.object.isRequired, | ||||
|         unsecureLogin: PropTypes.func.isRequired, | ||||
|         fetchFeatureToggles: PropTypes.func.isRequired, | ||||
|         history: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     handleSubmit = evt => { | ||||
| @ -20,7 +20,7 @@ class SimpleAuthenticationComponent extends React.Component { | ||||
|             .unsecureLogin(path, user) | ||||
|             .then(this.props.fetchFeatureToggles) | ||||
|             .then(() => { | ||||
|                 hashHistory.push('/features'); | ||||
|                 this.props.history.push('/features'); | ||||
|             }); | ||||
|     }; | ||||
| 
 | ||||
|  | ||||
| @ -4,8 +4,7 @@ import 'react-mdl/extra/material.js'; | ||||
| 
 | ||||
| import React from 'react'; | ||||
| import ReactDOM from 'react-dom'; | ||||
| import { applyRouterMiddleware, Router, Route, IndexRedirect, hashHistory } from 'react-router'; | ||||
| import { useScroll } from 'react-router-scroll'; | ||||
| import { HashRouter, Route } from 'react-router-dom'; | ||||
| import { Provider } from 'react-redux'; | ||||
| import thunkMiddleware from 'redux-thunk'; | ||||
| import { createStore, applyMiddleware, compose } from 'redux'; | ||||
| @ -13,20 +12,7 @@ import { createStore, applyMiddleware, compose } from 'redux'; | ||||
| import store from './store'; | ||||
| import MetricsPoller from './metrics-poller'; | ||||
| import App from './component/app'; | ||||
| 
 | ||||
| import Features from './page/features'; | ||||
| import CreateFeatureToggle from './page/features/create'; | ||||
| import ViewFeatureToggle from './page/features/show'; | ||||
| import Strategies from './page/strategies'; | ||||
| import StrategyView from './page/strategies/show'; | ||||
| import CreateStrategies from './page/strategies/create'; | ||||
| import HistoryPage from './page/history'; | ||||
| import HistoryTogglePage from './page/history/toggle'; | ||||
| import Archive from './page/archive'; | ||||
| import ShowArchive from './page/archive/show'; | ||||
| import Applications from './page/applications'; | ||||
| import ApplicationView from './page/applications/view'; | ||||
| import LogoutFeatures from './page/user/logout'; | ||||
| import ScrollToTop from './component/scroll-to-top'; | ||||
| 
 | ||||
| let composeEnhancers; | ||||
| 
 | ||||
| @ -40,48 +26,13 @@ const unleashStore = createStore(store, composeEnhancers(applyMiddleware(thunkMi | ||||
| const metricsPoller = new MetricsPoller(unleashStore); | ||||
| metricsPoller.start(); | ||||
| 
 | ||||
| // "pageTitle" and "link" attributes are for internal usage only | ||||
| 
 | ||||
| ReactDOM.render( | ||||
|     <Provider store={unleashStore}> | ||||
|         <Router history={hashHistory} render={applyRouterMiddleware(useScroll())}> | ||||
|             <Route path="/" component={App}> | ||||
|                 <IndexRedirect to="/features" /> | ||||
| 
 | ||||
|                 <Route pageTitle="Feature Toggles" link="/features"> | ||||
|                     <Route pageTitle="Feature toggles" path="/features" component={Features} /> | ||||
|                     <Route pageTitle="New" path="/features/create" component={CreateFeatureToggle} /> | ||||
|                     <Route pageTitle=":name" path="/features/:activeTab/:name" component={ViewFeatureToggle} /> | ||||
|                 </Route> | ||||
| 
 | ||||
|                 <Route pageTitle="Strategies" link="/strategies"> | ||||
|                     <Route pageTitle="Strategies" path="/strategies" component={Strategies} /> | ||||
|                     <Route pageTitle="New" path="/strategies/create" component={CreateStrategies} /> | ||||
|                     <Route | ||||
|                         pageTitle=":strategyName" | ||||
|                         path="/strategies/:activeTab/:strategyName" | ||||
|                         component={StrategyView} | ||||
|                     /> | ||||
|                 </Route> | ||||
| 
 | ||||
|                 <Route pageTitle="Event History" link="/history"> | ||||
|                     <Route pageTitle="Event history" path="/history" component={HistoryPage} /> | ||||
|                     <Route pageTitle=":toggleName" path="/history/:toggleName" component={HistoryTogglePage} /> | ||||
|                 </Route> | ||||
|                 <Route pageTitle="Archived Toggles" link="/archive"> | ||||
|                     <Route pageTitle="Archived Toggles" path="/archive" component={Archive} /> | ||||
|                     <Route pageTitle=":name" path="/archive/:activeTab/:name" component={ShowArchive} /> | ||||
|                 </Route> | ||||
| 
 | ||||
|                 <Route pageTitle="Applications" link="/applications"> | ||||
|                     <Route pageTitle="Applications" path="/applications" component={Applications} /> | ||||
|                     <Route pageTitle=":name" path="/applications/:name" component={ApplicationView} /> | ||||
|                 </Route> | ||||
|                 <Route pageTitle="Logout" link="/logout"> | ||||
|                     <Route pageTitle="Logout" path="/logout" component={LogoutFeatures} /> | ||||
|                 </Route> | ||||
|             </Route> | ||||
|         </Router> | ||||
|         <HashRouter> | ||||
|             <ScrollToTop> | ||||
|                 <Route path="/" component={App} /> | ||||
|             </ScrollToTop> | ||||
|         </HashRouter> | ||||
|     </Provider>, | ||||
|     document.getElementById('app') | ||||
| ); | ||||
|  | ||||
| @ -2,10 +2,10 @@ import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import ApplicationEditComponent from '../../component/application/application-edit-container'; | ||||
| 
 | ||||
| const render = ({ params }) => <ApplicationEditComponent appName={params.name} />; | ||||
| const render = ({ match: { params } }) => <ApplicationEditComponent appName={params.name} />; | ||||
| 
 | ||||
| render.propTypes = { | ||||
|     params: PropTypes.object.isRequired, | ||||
|     match: PropTypes.object.isRequired, | ||||
| }; | ||||
| 
 | ||||
| export default render; | ||||
|  | ||||
| @ -2,9 +2,9 @@ import React from 'react'; | ||||
| import Archive from '../../component/archive/archive-list-container'; | ||||
| import PropTypes from 'prop-types'; | ||||
| 
 | ||||
| const render = ({ params }) => <Archive name={params.name} />; | ||||
| const render = ({ match }) => <Archive name={match.params.name} />; | ||||
| render.propTypes = { | ||||
|     params: PropTypes.object, | ||||
|     match: PropTypes.object, | ||||
| }; | ||||
| 
 | ||||
| export default render; | ||||
|  | ||||
| @ -4,11 +4,18 @@ import ViewFeatureToggle from './../../component/archive/view-container'; | ||||
| 
 | ||||
| export default class Features extends PureComponent { | ||||
|     static propTypes = { | ||||
|         params: PropTypes.object.isRequired, | ||||
|         match: PropTypes.object.isRequired, | ||||
|         history: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     render() { | ||||
|         const { params } = this.props; | ||||
|         return <ViewFeatureToggle featureToggleName={params.name} activeTab={params.activeTab} />; | ||||
|         const { match, history } = this.props; | ||||
|         return ( | ||||
|             <ViewFeatureToggle | ||||
|                 history={history} | ||||
|                 featureToggleName={match.params.name} | ||||
|                 activeTab={match.params.activeTab} | ||||
|             /> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -4,11 +4,12 @@ import ViewFeatureToggle from './../../component/feature/view-container'; | ||||
| 
 | ||||
| export default class Features extends PureComponent { | ||||
|     static propTypes = { | ||||
|         params: PropTypes.object.isRequired, | ||||
|         match: PropTypes.object.isRequired, | ||||
|         history: PropTypes.object.isRequired, | ||||
|     }; | ||||
| 
 | ||||
|     render() { | ||||
|         const { params } = this.props; | ||||
|         return <ViewFeatureToggle featureToggleName={params.name} activeTab={params.activeTab} />; | ||||
|         const { match: { params }, history } = this.props; | ||||
|         return <ViewFeatureToggle featureToggleName={params.name} activeTab={params.activeTab} history={history} />; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,10 +2,10 @@ import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import HistoryListToggle from '../../component/history/history-list-toggle-container'; | ||||
| 
 | ||||
| const render = ({ params }) => <HistoryListToggle toggleName={params.toggleName} />; | ||||
| const render = ({ match: { params } }) => <HistoryListToggle toggleName={params.toggleName} />; | ||||
| 
 | ||||
| render.propTypes = { | ||||
|     params: PropTypes.object.isRequired, | ||||
|     match: PropTypes.object.isRequired, | ||||
| }; | ||||
| 
 | ||||
| export default render; | ||||
|  | ||||
| @ -2,10 +2,12 @@ import React from 'react'; | ||||
| import PropTypes from 'prop-types'; | ||||
| import ShowStrategy from '../../component/strategies/strategy-details-container'; | ||||
| 
 | ||||
| const render = ({ params }) => <ShowStrategy strategyName={params.strategyName} activeTab={params.activeTab} />; | ||||
| const render = ({ match: { params } }) => ( | ||||
|     <ShowStrategy strategyName={params.strategyName} activeTab={params.activeTab} /> | ||||
| ); | ||||
| 
 | ||||
| render.propTypes = { | ||||
|     params: PropTypes.object.isRequired, | ||||
|     match: PropTypes.object.isRequired, | ||||
| }; | ||||
| 
 | ||||
| export default render; | ||||
|  | ||||
| @ -1732,14 +1732,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: | ||||
|     safe-buffer "^5.0.1" | ||||
|     sha.js "^2.4.8" | ||||
| 
 | ||||
| create-react-class@^15.5.1: | ||||
|   version "15.6.3" | ||||
|   resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.3.tgz#2d73237fb3f970ae6ebe011a9e66f46dbca80036" | ||||
|   dependencies: | ||||
|     fbjs "^0.8.9" | ||||
|     loose-envify "^1.3.1" | ||||
|     object-assign "^4.1.1" | ||||
| 
 | ||||
| cross-spawn@^3.0.0: | ||||
|   version "3.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" | ||||
| @ -2030,10 +2022,6 @@ doctrine@^2.1.0: | ||||
|   dependencies: | ||||
|     esutils "^2.0.2" | ||||
| 
 | ||||
| dom-helpers@^3.2.1: | ||||
|   version "3.3.1" | ||||
|   resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6" | ||||
| 
 | ||||
| dom-serializer@0, dom-serializer@~0.1.0: | ||||
|   version "0.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" | ||||
| @ -2674,7 +2662,7 @@ fbjs@^0.8.1: | ||||
|     setimmediate "^1.0.5" | ||||
|     ua-parser-js "^0.7.18" | ||||
| 
 | ||||
| fbjs@^0.8.16, fbjs@^0.8.9: | ||||
| fbjs@^0.8.16: | ||||
|   version "0.8.16" | ||||
|   resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" | ||||
|   dependencies: | ||||
| @ -3188,13 +3176,14 @@ hawk@~6.0.2: | ||||
|     hoek "4.x.x" | ||||
|     sntp "2.x.x" | ||||
| 
 | ||||
| history@^3.0.0: | ||||
|   version "3.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/history/-/history-3.3.0.tgz#fcedcce8f12975371545d735461033579a6dae9c" | ||||
| history@^4.7.2: | ||||
|   version "4.7.2" | ||||
|   resolved "https://registry.yarnpkg.com/history/-/history-4.7.2.tgz#22b5c7f31633c5b8021c7f4a8a954ac139ee8d5b" | ||||
|   dependencies: | ||||
|     invariant "^2.2.1" | ||||
|     loose-envify "^1.2.0" | ||||
|     query-string "^4.2.2" | ||||
|     resolve-pathname "^2.2.0" | ||||
|     value-equal "^0.4.0" | ||||
|     warning "^3.0.0" | ||||
| 
 | ||||
| hmac-drbg@^1.0.0: | ||||
| @ -3213,10 +3202,6 @@ hoek@4.x.x: | ||||
|   version "4.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d" | ||||
| 
 | ||||
| hoist-non-react-statics@^1.2.0: | ||||
|   version "1.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" | ||||
| 
 | ||||
| hoist-non-react-statics@^2.2.1: | ||||
|   version "2.3.1" | ||||
|   resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0" | ||||
| @ -3699,6 +3684,10 @@ is-wsl@^1.1.0: | ||||
|   version "1.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" | ||||
| 
 | ||||
| isarray@0.0.1: | ||||
|   version "0.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" | ||||
| 
 | ||||
| isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: | ||||
|   version "1.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" | ||||
| @ -5062,6 +5051,12 @@ path-to-regexp@0.1.7: | ||||
|   version "0.1.7" | ||||
|   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" | ||||
| 
 | ||||
| path-to-regexp@^1.7.0: | ||||
|   version "1.7.0" | ||||
|   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" | ||||
|   dependencies: | ||||
|     isarray "0.0.1" | ||||
| 
 | ||||
| path-to-regexp@^2.1.0: | ||||
|   version "2.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-2.1.0.tgz#7e30f9f5b134bd6a28ffc2e3ef1e47075ac5259b" | ||||
| @ -5238,7 +5233,7 @@ promise@^7.1.1: | ||||
|   dependencies: | ||||
|     asap "~2.0.3" | ||||
| 
 | ||||
| prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.6.0: | ||||
| prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.6.0: | ||||
|   version "15.6.0" | ||||
|   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" | ||||
|   dependencies: | ||||
| @ -5246,7 +5241,7 @@ prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6, | ||||
|     loose-envify "^1.3.1" | ||||
|     object-assign "^4.1.1" | ||||
| 
 | ||||
| prop-types@^15.6.2: | ||||
| prop-types@^15.6.1, prop-types@^15.6.2: | ||||
|   version "15.6.2" | ||||
|   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" | ||||
|   dependencies: | ||||
| @ -5302,13 +5297,6 @@ qs@~6.4.0: | ||||
|   version "6.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" | ||||
| 
 | ||||
| query-string@^4.2.2: | ||||
|   version "4.3.4" | ||||
|   resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" | ||||
|   dependencies: | ||||
|     object-assign "^4.1.0" | ||||
|     strict-uri-encode "^1.0.0" | ||||
| 
 | ||||
| querystring-es3@^0.2.0: | ||||
|   version "0.2.1" | ||||
|   resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" | ||||
| @ -5465,25 +5453,28 @@ react-redux@^5.0.6: | ||||
|     loose-envify "^1.1.0" | ||||
|     prop-types "^15.5.10" | ||||
| 
 | ||||
| react-router-scroll@^0.4.1: | ||||
|   version "0.4.4" | ||||
|   resolved "https://registry.yarnpkg.com/react-router-scroll/-/react-router-scroll-0.4.4.tgz#4d7b71c75b45ff296e4adca1e029a86e898a155d" | ||||
| react-router-dom@^4.3.1: | ||||
|   version "4.3.1" | ||||
|   resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" | ||||
|   dependencies: | ||||
|     prop-types "^15.6.0" | ||||
|     scroll-behavior "^0.9.5" | ||||
|     warning "^3.0.0" | ||||
|     history "^4.7.2" | ||||
|     invariant "^2.2.4" | ||||
|     loose-envify "^1.3.1" | ||||
|     prop-types "^15.6.1" | ||||
|     react-router "^4.3.1" | ||||
|     warning "^4.0.1" | ||||
| 
 | ||||
| react-router@^3.0.0: | ||||
|   version "3.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.2.0.tgz#62b6279d589b70b34e265113e4c0a9261a02ed36" | ||||
| react-router@^4.3.1: | ||||
|   version "4.3.1" | ||||
|   resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e" | ||||
|   dependencies: | ||||
|     create-react-class "^15.5.1" | ||||
|     history "^3.0.0" | ||||
|     hoist-non-react-statics "^1.2.0" | ||||
|     invariant "^2.2.1" | ||||
|     loose-envify "^1.2.0" | ||||
|     prop-types "^15.5.6" | ||||
|     warning "^3.0.0" | ||||
|     history "^4.7.2" | ||||
|     hoist-non-react-statics "^2.5.0" | ||||
|     invariant "^2.2.4" | ||||
|     loose-envify "^1.3.1" | ||||
|     path-to-regexp "^1.7.0" | ||||
|     prop-types "^15.6.1" | ||||
|     warning "^4.0.1" | ||||
| 
 | ||||
| react-test-renderer@^16.0.0-0, react-test-renderer@^16.2.0: | ||||
|   version "16.2.0" | ||||
| @ -5852,6 +5843,10 @@ resolve-from@^3.0.0: | ||||
|   version "3.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" | ||||
| 
 | ||||
| resolve-pathname@^2.2.0: | ||||
|   version "2.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.2.0.tgz#7e9ae21ed815fd63ab189adeee64dc831eefa879" | ||||
| 
 | ||||
| resolve-url@^0.2.1: | ||||
|   version "0.2.1" | ||||
|   resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" | ||||
| @ -5967,13 +5962,6 @@ schema-utils@^0.4.5: | ||||
|     ajv "^6.1.0" | ||||
|     ajv-keywords "^3.1.0" | ||||
| 
 | ||||
| scroll-behavior@^0.9.5: | ||||
|   version "0.9.9" | ||||
|   resolved "https://registry.yarnpkg.com/scroll-behavior/-/scroll-behavior-0.9.9.tgz#ebfe0658455b82ad885b66195215416674dacce2" | ||||
|   dependencies: | ||||
|     dom-helpers "^3.2.1" | ||||
|     invariant "^2.2.2" | ||||
| 
 | ||||
| scss-tokenizer@^0.2.3: | ||||
|   version "0.2.3" | ||||
|   resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" | ||||
| @ -6351,10 +6339,6 @@ stream-http@^2.7.2: | ||||
|     to-arraybuffer "^1.0.0" | ||||
|     xtend "^4.0.0" | ||||
| 
 | ||||
| strict-uri-encode@^1.0.0: | ||||
|   version "1.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" | ||||
| 
 | ||||
| string-length@^2.0.0: | ||||
|   version "2.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" | ||||
| @ -6795,6 +6779,10 @@ validate-npm-package-license@^3.0.1: | ||||
|     spdx-correct "~1.0.0" | ||||
|     spdx-expression-parse "~1.0.0" | ||||
| 
 | ||||
| value-equal@^0.4.0: | ||||
|   version "0.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" | ||||
| 
 | ||||
| vary@~1.1.2: | ||||
|   version "1.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" | ||||
| @ -6831,6 +6819,12 @@ warning@^3.0.0: | ||||
|   dependencies: | ||||
|     loose-envify "^1.0.0" | ||||
| 
 | ||||
| warning@^4.0.1: | ||||
|   version "4.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.1.tgz#66ce376b7fbfe8a887c22bdf0e7349d73d397745" | ||||
|   dependencies: | ||||
|     loose-envify "^1.0.0" | ||||
| 
 | ||||
| watch@~0.18.0: | ||||
|   version "0.18.0" | ||||
|   resolved "https://registry.yarnpkg.com/watch/-/watch-0.18.0.tgz#28095476c6df7c90c963138990c0a5423eb4b986" | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user