2017-08-28 21:30:12 +02:00
|
|
|
|
import React, { Component } from 'react';
|
|
|
|
|
import PropTypes from 'prop-types';
|
2017-08-28 19:15:47 +02:00
|
|
|
|
import {
|
|
|
|
|
Layout,
|
|
|
|
|
Drawer,
|
|
|
|
|
Header,
|
|
|
|
|
Navigation,
|
|
|
|
|
Content,
|
|
|
|
|
Footer,
|
|
|
|
|
FooterSection,
|
|
|
|
|
FooterDropDownSection,
|
|
|
|
|
FooterLinkList,
|
|
|
|
|
Grid,
|
|
|
|
|
Cell,
|
|
|
|
|
Icon,
|
2016-12-04 11:56:41 +01:00
|
|
|
|
} from 'react-mdl';
|
2016-12-05 17:04:00 +01:00
|
|
|
|
import { Link } from 'react-router';
|
2017-01-20 12:57:05 +01:00
|
|
|
|
import styles from './styles.scss';
|
2016-11-10 14:26:24 +01:00
|
|
|
|
import ErrorContainer from './error/error-container';
|
|
|
|
|
|
2017-11-04 14:22:31 +01:00
|
|
|
|
import AuthenticationContainer from './user/authentication-container';
|
2016-11-25 15:37:06 +01:00
|
|
|
|
import ShowUserContainer from './user/show-user-container';
|
2017-11-24 08:41:36 +01:00
|
|
|
|
import ShowApiDetailsContainer from './api/show-api-details-container';
|
2016-12-29 11:55:25 +01:00
|
|
|
|
import { ScrollContainer } from 'react-router-scroll';
|
2016-11-24 21:32:29 +01:00
|
|
|
|
|
2017-08-28 19:15:47 +02:00
|
|
|
|
function replace(input, params) {
|
2016-12-05 17:04:00 +01:00
|
|
|
|
if (!params) {
|
|
|
|
|
return input;
|
|
|
|
|
}
|
|
|
|
|
Object.keys(params).forEach(key => {
|
|
|
|
|
input = input.replace(`:${key}`, params[key]);
|
|
|
|
|
});
|
|
|
|
|
return input;
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-10 14:26:24 +01:00
|
|
|
|
export default class App extends Component {
|
2017-07-10 23:38:44 +02:00
|
|
|
|
static propTypes = {
|
|
|
|
|
location: PropTypes.object.isRequired,
|
|
|
|
|
params: PropTypes.object.isRequired,
|
|
|
|
|
routes: PropTypes.array.isRequired,
|
2017-08-28 19:15:47 +02:00
|
|
|
|
};
|
2016-11-10 14:26:24 +01:00
|
|
|
|
|
2016-12-04 11:56:41 +01:00
|
|
|
|
static contextTypes = {
|
2017-08-28 21:30:12 +02:00
|
|
|
|
router: PropTypes.object,
|
2017-08-28 19:15:47 +02:00
|
|
|
|
};
|
2016-11-10 14:26:24 +01:00
|
|
|
|
|
2017-08-28 19:15:47 +02:00
|
|
|
|
componentWillReceiveProps(nextProps) {
|
2016-12-05 17:10:32 +01:00
|
|
|
|
if (this.props.location.pathname !== nextProps.location.pathname) {
|
2016-12-11 19:30:56 +01:00
|
|
|
|
clearTimeout(this.timer);
|
|
|
|
|
this.timer = setTimeout(() => {
|
|
|
|
|
const layout = document.querySelector('.mdl-js-layout');
|
|
|
|
|
const drawer = document.querySelector('.mdl-layout__drawer');
|
|
|
|
|
// hack, might get a built in alternative later
|
|
|
|
|
if (drawer.classList.contains('is-visible')) {
|
|
|
|
|
layout.MaterialLayout.toggleDrawer();
|
|
|
|
|
}
|
|
|
|
|
}, 10);
|
2016-12-05 17:10:32 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 19:15:47 +02:00
|
|
|
|
getSections() {
|
2016-12-05 17:04:00 +01:00
|
|
|
|
const { routes, params } = this.props;
|
|
|
|
|
const unique = {};
|
2017-08-28 19:15:47 +02:00
|
|
|
|
const result = routes
|
|
|
|
|
.splice(1)
|
|
|
|
|
.map(routeEntry => ({
|
2017-01-20 14:09:44 +01:00
|
|
|
|
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;
|
|
|
|
|
});
|
2016-12-05 17:04:00 +01:00
|
|
|
|
|
2016-12-05 17:15:55 +01:00
|
|
|
|
// mutate document.title:
|
|
|
|
|
document.title = result
|
|
|
|
|
.map(e => e.name)
|
2016-12-05 17:16:51 +01:00
|
|
|
|
.reverse()
|
2017-01-20 14:09:44 +01:00
|
|
|
|
.concat('Unleash')
|
|
|
|
|
.join(' – ');
|
2016-12-05 17:15:55 +01:00
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 19:15:47 +02:00
|
|
|
|
getTitleWithLinks() {
|
2016-12-05 17:15:55 +01:00
|
|
|
|
const result = this.getSections();
|
2016-12-05 17:04:00 +01:00
|
|
|
|
return (
|
|
|
|
|
<span>
|
|
|
|
|
{result.map((entry, index) => (
|
2017-08-28 21:40:44 +02:00
|
|
|
|
<span key={entry.link + index} className={index > 0 ? 'mdl-layout--large-screen-only' : ''}>
|
2017-01-20 14:09:44 +01:00
|
|
|
|
{index > 0 ? ' › ' : null}
|
2017-08-28 19:15:47 +02:00
|
|
|
|
<Link
|
2017-08-28 21:40:44 +02:00
|
|
|
|
className={[styles.headerTitleLink, 'mdl-color-text--primary-contrast'].join(' ')}
|
2017-08-28 19:15:47 +02:00
|
|
|
|
to={entry.link}
|
|
|
|
|
>
|
2017-01-20 14:09:44 +01:00
|
|
|
|
{entry.name}
|
|
|
|
|
</Link>
|
|
|
|
|
</span>
|
2016-12-05 17:04:00 +01:00
|
|
|
|
))}
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-28 19:15:47 +02:00
|
|
|
|
render() {
|
2016-12-29 14:01:03 +01:00
|
|
|
|
const shouldUpdateScroll = (prevRouterProps, { location }) => {
|
2017-08-28 21:40:44 +02:00
|
|
|
|
if (prevRouterProps && location.pathname !== prevRouterProps.location.pathname) {
|
2016-12-29 14:01:03 +01:00
|
|
|
|
return location.action === 'POP';
|
|
|
|
|
} else {
|
|
|
|
|
return [0, 0];
|
|
|
|
|
}
|
|
|
|
|
};
|
2018-02-24 18:11:09 +01:00
|
|
|
|
const createListItem = (path, caption, icon, isDrawerNavigation = false, isAnchor = false) => {
|
2017-08-28 19:15:47 +02:00
|
|
|
|
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';
|
2018-02-24 18:11:09 +01:00
|
|
|
|
const renderIcon = (
|
|
|
|
|
<Icon
|
|
|
|
|
name={icon}
|
|
|
|
|
className={isDrawerNavigation ? [styles.navigationIcon, iconColor].join(' ') : undefined}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
return isAnchor ? (
|
|
|
|
|
<a
|
|
|
|
|
href={path}
|
|
|
|
|
className={isDrawerNavigation ? [styles.navigationLink, linkColor].join(' ') : undefined}
|
|
|
|
|
>
|
|
|
|
|
{icon && renderIcon}
|
|
|
|
|
{caption}
|
|
|
|
|
</a>
|
|
|
|
|
) : (
|
2018-02-05 09:33:51 +01:00
|
|
|
|
<Link
|
|
|
|
|
to={path}
|
|
|
|
|
className={isDrawerNavigation ? [styles.navigationLink, linkColor].join(' ') : undefined}
|
|
|
|
|
>
|
2018-02-24 18:11:09 +01:00
|
|
|
|
{icon && renderIcon}
|
2017-08-28 19:15:47 +02:00
|
|
|
|
{caption}
|
2017-01-20 12:57:05 +01:00
|
|
|
|
</Link>
|
|
|
|
|
);
|
|
|
|
|
};
|
2016-12-04 11:56:41 +01:00
|
|
|
|
|
|
|
|
|
return (
|
2017-03-01 21:53:25 +01:00
|
|
|
|
<div className={styles.container}>
|
2017-11-04 14:22:31 +01:00
|
|
|
|
<AuthenticationContainer />
|
2016-12-04 11:56:41 +01:00
|
|
|
|
<Layout fixedHeader>
|
2016-12-05 17:04:00 +01:00
|
|
|
|
<Header title={this.getTitleWithLinks()}>
|
2016-12-04 11:56:41 +01:00
|
|
|
|
<Navigation>
|
|
|
|
|
<ShowUserContainer />
|
|
|
|
|
</Navigation>
|
|
|
|
|
</Header>
|
2017-01-20 12:57:05 +01:00
|
|
|
|
<Drawer className="mdl-color--white">
|
2017-08-28 21:40:44 +02:00
|
|
|
|
<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>
|
2017-03-07 11:39:10 +01:00
|
|
|
|
</span>
|
2017-08-28 19:15:47 +02:00
|
|
|
|
<hr />
|
2017-01-20 12:57:05 +01:00
|
|
|
|
<Navigation className={styles.navigation}>
|
2017-08-28 21:40:44 +02:00
|
|
|
|
{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)}
|
2018-02-24 18:11:09 +01:00
|
|
|
|
{createListItem('/api/admin/user/logout', 'Sign out', 'exit_to_app', true, true)}
|
2017-01-20 12:57:05 +01:00
|
|
|
|
</Navigation>
|
2017-08-28 19:15:47 +02:00
|
|
|
|
<hr />
|
2017-01-20 12:57:05 +01:00
|
|
|
|
<Navigation className={styles.navigation}>
|
2017-08-28 19:15:47 +02:00
|
|
|
|
<a
|
|
|
|
|
href="https://github.com/Unleash"
|
|
|
|
|
target="_blank"
|
2017-08-28 21:40:44 +02:00
|
|
|
|
className={[styles.navigationLink, 'mdl-color-text--grey-900'].join(' ')}
|
2017-08-28 19:15:47 +02:00
|
|
|
|
>
|
2017-11-11 09:12:39 +01:00
|
|
|
|
<i className={['material-icons', styles.navigationIcon, styles.iconGitHub].join(' ')} />GitHub
|
2017-01-20 12:57:05 +01:00
|
|
|
|
</a>
|
2016-12-04 11:56:41 +01:00
|
|
|
|
</Navigation>
|
|
|
|
|
</Drawer>
|
2017-08-28 21:40:44 +02:00
|
|
|
|
<ScrollContainer scrollKey="container" shouldUpdateScroll={shouldUpdateScroll}>
|
2017-06-29 08:36:10 +02:00
|
|
|
|
<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>
|
2017-08-28 21:40:44 +02:00
|
|
|
|
{createListItem('/features', 'Feature Toggles')}
|
|
|
|
|
{createListItem('/strategies', 'Strategies')}
|
|
|
|
|
{createListItem('/history', 'Event History')}
|
|
|
|
|
{createListItem('/archive', 'Archived Toggles')}
|
|
|
|
|
{createListItem('/applications', 'Applications')}
|
2018-01-17 09:45:38 +01:00
|
|
|
|
<a href="/api/admin/user/logout">Sign out</a>
|
2017-06-29 08:36:10 +02:00
|
|
|
|
</FooterLinkList>
|
|
|
|
|
</FooterDropDownSection>
|
|
|
|
|
<FooterDropDownSection title="Clients">
|
|
|
|
|
<FooterLinkList>
|
2017-08-28 21:40:44 +02:00
|
|
|
|
<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>
|
2017-06-29 08:36:10 +02:00
|
|
|
|
</FooterLinkList>
|
|
|
|
|
</FooterDropDownSection>
|
|
|
|
|
</FooterSection>
|
2017-11-24 08:41:36 +01:00
|
|
|
|
<ShowApiDetailsContainer />
|
2017-06-29 08:36:10 +02:00
|
|
|
|
</Footer>
|
|
|
|
|
</Content>
|
2016-12-29 11:55:25 +01:00
|
|
|
|
</ScrollContainer>
|
2016-12-04 11:56:41 +01:00
|
|
|
|
</Layout>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2016-11-10 14:26:24 +01:00
|
|
|
|
}
|
2017-08-28 19:15:47 +02:00
|
|
|
|
}
|