Skip to content

Commit

Permalink
Merge branch 'master' into issue-44-configurable-header-links
Browse files Browse the repository at this point in the history
  • Loading branch information
tiffon committed Sep 26, 2017
2 parents c2b800a + 5139c7f commit a945c3b
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 68 deletions.
1 change: 1 addition & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
[include]

[libs]
./flow-typed/npm

[options]

Expand Down
148 changes: 148 additions & 0 deletions flow-typed/npm/react-router-dom_v4.x.x.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// flow-typed signature: 4d8e947f2e396ef2f26ecbd1ed7f04ab
// flow-typed version: 97d98ab83e/react-router-dom_v4.x.x/flow_>=v0.53.x

declare module 'react-router-dom' {
declare export class BrowserRouter extends React$Component<{
basename?: string,
forceRefresh?: boolean,
getUserConfirmation?: GetUserConfirmation,
keyLength?: number,
children?: React$Node,
}> {}

declare export class HashRouter extends React$Component<{
basename?: string,
getUserConfirmation?: GetUserConfirmation,
hashType?: 'slash' | 'noslash' | 'hashbang',
children?: React$Node,
}> {}

declare export class Link extends React$Component<{
to: string | LocationShape,
replace?: boolean,
children?: React$Node,
}> {}

declare export class NavLink extends React$Component<{
to: string | LocationShape,
activeClassName?: string,
className?: string,
activeStyle?: Object,
style?: Object,
isActive?: (match: Match, location: Location) => boolean,
children?: React$Node,
exact?: boolean,
strict?: boolean,
}> {}

// NOTE: Below are duplicated from react-router. If updating these, please
// update the react-router and react-router-native types as well.
declare export type Location = {
pathname: string,
search: string,
hash: string,
state?: any,
key?: string,
};

declare export type LocationShape = {
pathname?: string,
search?: string,
hash?: string,
state?: any,
};

declare export type HistoryAction = 'PUSH' | 'REPLACE' | 'POP';

declare export type RouterHistory = {
length: number,
location: Location,
action: HistoryAction,
listen(callback: (location: Location, action: HistoryAction) => void): () => void,
push(path: string | LocationShape, state?: any): void,
replace(path: string | LocationShape, state?: any): void,
go(n: number): void,
goBack(): void,
goForward(): void,
canGo?: (n: number) => boolean,
block(callback: (location: Location, action: HistoryAction) => boolean): void,
// createMemoryHistory
index?: number,
entries?: Array<Location>,
};

declare export type Match = {
params: { [key: string]: ?string },
isExact: boolean,
path: string,
url: string,
};

declare export type ContextRouter = {|
history: RouterHistory,
location: Location,
match: Match,
|};

declare export type GetUserConfirmation = (message: string, callback: (confirmed: boolean) => void) => void;

declare type StaticRouterContext = {
url?: string,
};

declare export class StaticRouter extends React$Component<{
basename?: string,
location?: string | Location,
context: StaticRouterContext,
children?: React$Node,
}> {}

declare export class MemoryRouter extends React$Component<{
initialEntries?: Array<LocationShape | string>,
initialIndex?: number,
getUserConfirmation?: GetUserConfirmation,
keyLength?: number,
children?: React$Node,
}> {}

declare export class Router extends React$Component<{
history: RouterHistory,
children?: React$Node,
}> {}

declare export class Prompt extends React$Component<{
message: string | ((location: Location) => string | true),
when?: boolean,
}> {}

declare export class Redirect extends React$Component<{
to: string | LocationShape,
push?: boolean,
}> {}

declare export class Route extends React$Component<{
component?: React$ComponentType<*>,
render?: (router: ContextRouter) => React$Node,
children?: React$ComponentType<ContextRouter> | React$Node,
path?: string,
exact?: boolean,
strict?: boolean,
}> {}

declare export class Switch extends React$Component<{
children?: React$Node,
}> {}

declare export function withRouter<P>(
Component: React$ComponentType<{| ...ContextRouter, ...P |}>
): React$ComponentType<P>;

declare type MatchPathOptions = {
path?: string,
exact?: boolean,
sensitive?: boolean,
strict?: boolean,
};

declare export function matchPath(pathname: string, options?: MatchPathOptions | string): null | Match;
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"test": "react-scripts test --env=jsdom",
"coverage": "npm run test -- --coverage",
"lint": "npm run eslint && npm run prettier && npm run flow",
"eslint": "eslint .",
"eslint": "eslint src",
"prettier": "prettier --single-quote --trailing-comma es5 --print-width 110 --write \"src/**/*.js\"",
"flow": "flow; test $? -eq 0 -o $? -eq 2",
"set-homepage": "json -I -f package.json -e 'this.homepage=process.env.HOMEPAGE'",
Expand Down
51 changes: 36 additions & 15 deletions src/components/App/Page.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,55 @@
import * as React from 'react';
import Helmet from 'react-helmet';
import { connect } from 'react-redux';
import type { Location } from 'react-router-dom';

import TopNav from './TopNav';
import type { Config } from '../../types/config';
import { trackPageView } from '../../utils/metrics';

import './Page.css';

type JaegerUIPageProps = {
type PageProps = {
location: Location,
children: React.Node,
config: { data: Config },
};

function JaegerUIPage({ config, children }: JaegerUIPageProps) {
const menu = config && config.data && config.data.menu;
return (
<section className="jaeger-ui-page" id="jaeger-ui">
<Helmet title="Jaeger UI" />
<TopNav menuConfig={menu} />
<div className="jaeger-ui--content">
{children}
</div>
</section>
);
class Page extends React.Component<PageProps> {
props: PageProps;

componentDidMount() {
const { pathname, search } = this.props.location;
trackPageView(pathname, search);
}

componentWillReceiveProps(nextProps: PageProps) {
const { pathname, search } = this.props.location;
const { pathname: nextPathname, search: nextSearch } = nextProps.location;
if (pathname !== nextPathname || search !== nextSearch) {
trackPageView(nextPathname, nextSearch);
}
}

render() {
const { children, config } = this.props;
const menu = config && config.data && config.data.menu;
return (
<section className="jaeger-ui-page" id="jaeger-ui">
<Helmet title="Jaeger UI" />
<TopNav menuConfig={menu} />
<div className="jaeger-ui--content">
{children}
</div>
</section>
);
}
}

function mapStateToProps(state, ownProps) {
const { config } = state;
const { children } = ownProps;
return { children, config };
const { location } = state.routing;
return { ...ownProps, config, location };
}

export default connect(mapStateToProps)(JaegerUIPage);
export default connect(mapStateToProps)(Page);
14 changes: 5 additions & 9 deletions src/components/App/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import React, { Component } from 'react';
import createHistory from 'history/createBrowserHistory';
import { metrics } from 'react-metrics';
import { Provider } from 'react-redux';
import { Route, Redirect, Switch } from 'react-router-dom';
import { ConnectedRouter } from 'react-router-redux';
Expand All @@ -35,28 +34,25 @@ import { ConnectedTracePage } from '../TracePage';
import { fetchConfig } from '../../actions/jaeger-api';
import JaegerAPI, { DEFAULT_API_ROOT } from '../../api/jaeger';
import configureStore from '../../utils/configure-store';
import metricConfig from '../../utils/metrics';
import prefixUrl from '../../utils/prefix-url';

import './App.css';

const PageWithMetrics = metrics(metricConfig)(Page);

const defaultHistory = createHistory();
const history = createHistory();

export default class JaegerUIApp extends Component {
constructor(props) {
super(props);
this.store = configureStore(defaultHistory);
this.store = configureStore(history);
JaegerAPI.apiRoot = DEFAULT_API_ROOT;
this.store.dispatch(fetchConfig());
}

render() {
return (
<Provider store={this.store}>
<ConnectedRouter history={defaultHistory}>
<PageWithMetrics>
<ConnectedRouter history={history}>
<Page>
<Switch>
<Route path={prefixUrl('/search')} component={ConnectedSearchTracePage} />
<Route path={prefixUrl('/trace/:id')} component={ConnectedTracePage} />
Expand All @@ -66,7 +62,7 @@ export default class JaegerUIApp extends Component {
<Redirect exact path={prefixUrl('/')} to={prefixUrl('/search')} />
<Route component={NotFound} />
</Switch>
</PageWithMetrics>
</Page>
</ConnectedRouter>
</Provider>
);
Expand Down
3 changes: 1 addition & 2 deletions src/components/SearchTracePage/TraceSearchForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,8 @@ const mapDispatchToProps = dispatch => {
minDuration,
maxDuration,
lookback,
traceIDs,
} = fields;
// Note: traceID is ignored when the form is submitted

store.set('lastSearch', { service, operation });

Expand Down Expand Up @@ -317,7 +317,6 @@ const mapDispatchToProps = dispatch => {
tag: tagsToQuery(tags) || undefined,
minDuration: minDuration || null,
maxDuration: maxDuration || null,
traceID: traceIDsToQuery(traceIDs) || undefined,
});
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ THE SOFTWARE.
width: 6px;
background-image: linear-gradient(to right, rgba(25, 25, 25, 0.25), rgba(32, 32, 32, 0.0));
left: 100%;
z-index: 1;
z-index: -1;
}

.span-name-wrapper {
Expand Down
6 changes: 4 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@ import { document } from 'global';
import 'basscss/css/basscss.css';

import JaegerUIApp from './components/App';
import { init as initTracking } from './utils/metrics';

/* istanbul ignore if */
if (process.env.NODE_ENV === 'development') {
require.ensure(['global/window', 'react-addons-perf'], require => {
const window = require('global/window');
/* eslint-disable import/no-extraneous-dependencies */
// eslint-disable-next-line import/no-extraneous-dependencies
window.Perf = require('react-addons-perf');
/* eslint-enable import/no-extraneous-dependencies */
});
}

initTracking();

const UI_ROOT_ID = 'jaeger-ui-root';

/* istanbul ignore if */
Expand Down
47 changes: 9 additions & 38 deletions src/utils/metrics.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,14 @@

import ReactGA from 'react-ga';

if (process.env.NODE_ENV === 'production' && process.env.REACT_APP_GA_TRACKING_ID) {
const GA_CODE = process.env.REACT_APP_GA_TRACKING_ID;
ReactGA.initialize(GA_CODE);
export function init() {
if (process.env.NODE_ENV === 'production' && process.env.REACT_APP_GA_TRACKING_ID) {
const GA_CODE = process.env.REACT_APP_GA_TRACKING_ID;
ReactGA.initialize(GA_CODE);
}
}

const GoogleAnalytics = {
pageView(event, fields) {
ReactGA.set({
page: fields.page,
});
ReactGA.pageview(fields.pathname);
},
track(eventName, params) {
ReactGA.event({
category: params.page,
action: eventName,
label: params.label,
value: params.value,
});
},
};

export default {
enabled: process.env.NODE_ENV === 'production',
debug: process.env.NODE_ENV === 'development',
vendors: [
{
name: 'Google Analytics',
api: GoogleAnalytics,
},
],
pageDefaults(routeState) {
const paths = routeState.pathname.substr(1).split('/');
return {
pathname: routeState.pathname,
query: routeState.query,
page: !paths[0] ? 'landing' : paths[0],
};
},
};
export function trackPageView(pathname, search) {
const pagePath = search ? `${pathname}?${search}` : pathname;
ReactGA.pageview(pagePath);
}

0 comments on commit a945c3b

Please sign in to comment.