Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import React, { Component } from 'react';
import { StickyContainer } from 'react-sticky';
import styled from 'styled-components';
import {
APMQueryParams,
fromQuery,
history,
QueryParams,
toQuery
} from 'x-pack/plugins/apm/public/components/shared/Links/url_helpers';
import { IUrlParams } from '../../../../../../store/urlParams';
Expand Down Expand Up @@ -150,7 +150,7 @@ export class Waterfall extends Component<Props> {
);
}

private setQueryParams(params: QueryParams) {
private setQueryParams(params: APMQueryParams) {
const { location } = this.props;
history.replace({
...location,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import datemath from '@elastic/datemath';
import { EuiSuperDatePicker, EuiSuperDatePickerProps } from '@elastic/eui';
import { memoize } from 'lodash';
import React from 'react';
import { connect } from 'react-redux';
import { RouteComponentProps, withRouter } from 'react-router-dom';
Expand All @@ -21,36 +20,20 @@ interface Props extends RouteComponentProps {
dispatchUpdateTimePicker: typeof updateTimePicker;
}

interface DatePickerParams {
rangeFrom: string;
rangeTo: string;
refreshPaused: boolean;
refreshInterval: number;
}

const APM_DEFAULT_TIME_OPTIONS: DatePickerParams = {
rangeFrom: 'now-24h',
rangeTo: 'now',
refreshPaused: true,
refreshInterval: 0
};

class DatePickerComponent extends React.Component<Props> {
public refreshTimeoutId = 0;

public getParamsFromSearch = memoize((search: string) => {
const query = toQuery(search);
if ('refreshPaused' in query) {
query.refreshPaused = toBoolean(query.refreshPaused);
}
if ('refreshInterval' in query) {
query.refreshInterval = toNumber(query.refreshInterval as string);
}
public getParamsFromSearch = (search: string) => {
const { rangeFrom, rangeTo, refreshPaused, refreshInterval } = toQuery(
search
);
return {
...APM_DEFAULT_TIME_OPTIONS,
...query
} as DatePickerParams;
});
rangeFrom: rangeFrom || 'now-24h',
rangeTo: rangeTo || 'now',
refreshPaused: toBoolean(refreshPaused),
refreshInterval: toNumber(refreshInterval) || 0
};
};

public componentDidMount() {
this.dispatchTimeRangeUpdate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

import React from 'react';
import { KibanaLink } from '../KibanaLink';
import { QueryParamsDecoded } from '../url_helpers';
import { APMQueryParams, RisonDecoded } from '../url_helpers';
import { QueryWithIndexPattern } from './QueryWithIndexPattern';

interface Props {
query: QueryParamsDecoded;
query: APMQueryParams | RisonDecoded;
children: React.ReactNode;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@ import {
getAPMIndexPattern,
ISavedObject
} from 'x-pack/plugins/apm/public/services/rest/savedObjects';
import { QueryParamsDecoded } from '../url_helpers';
import { APMQueryParams, RisonDecoded } from '../url_helpers';

type Query = APMQueryParams & RisonDecoded;

export function getQueryWithIndexPattern(
query: QueryParamsDecoded,
query: Query,
indexPattern?: ISavedObject
) {
if ((query._a && query._a.index) || !indexPattern) {
return query;
}

const id = indexPattern && indexPattern.id;

return {
...query,
_a: {
Expand All @@ -31,8 +32,8 @@ export function getQueryWithIndexPattern(
}

interface Props {
query: QueryParamsDecoded;
children: (query: QueryParamsDecoded) => ReactElement<unknown>;
query: Query;
children: (query: Query) => ReactElement<unknown>;
}

interface State {
Expand Down
37 changes: 27 additions & 10 deletions x-pack/plugins/apm/public/components/shared/Links/url_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ import chrome from 'ui/chrome';
import url from 'url';
import { StringMap } from 'x-pack/plugins/apm/typings/common';

export function toQuery(search?: string): QueryParams {
export function toQuery(search?: string): APMQueryParamsRaw & RisonEncoded {
return search ? qs.parse(search.slice(1)) : {};
}

export function fromQuery(query: QueryParams) {
export function fromQuery(query: APMQueryParams & RisonEncoded) {
const encodedQuery = encodeQuery(query, ['_g', '_a']);
return stringifyWithoutEncoding(encodedQuery);
}

export function encodeQuery(query: QueryParams, exclude: string[] = []) {
export function encodeQuery(
query: APMQueryParams & RisonEncoded,
exclude: string[] = []
) {
return mapValues(query, (value, key) => {
if (exclude.includes(key as string)) {
return encodeURI(value);
Expand All @@ -31,7 +34,7 @@ export function encodeQuery(query: QueryParams, exclude: string[] = []) {
});
}

function stringifyWithoutEncoding(query: QueryParams) {
function stringifyWithoutEncoding(query: APMQueryParams & RisonEncoded) {
return qs.stringify(query, undefined, undefined, {
encodeURIComponent: (v: string) => v
});
Expand Down Expand Up @@ -94,7 +97,7 @@ export interface KibanaHrefArgs {
location: Location;
pathname?: string;
hash?: string;
query?: QueryParamsDecoded;
query?: APMQueryParams & RisonDecoded;
}

export function getKibanaHref({
Expand All @@ -116,7 +119,7 @@ export function getKibanaHref({
return href;
}

interface APMQueryParams {
interface APMQueryParamsRaw {
transactionId?: string;
traceId?: string;
detailTab?: string;
Expand All @@ -129,6 +132,23 @@ interface APMQueryParams {
kuery?: string;
rangeFrom?: string;
rangeTo?: string;
refreshPaused?: string;
refreshInterval?: string;
}

export interface APMQueryParams {
transactionId?: string;
traceId?: string;
detailTab?: string;
flyoutDetailTab?: string;
waterfallItemId?: string;
spanId?: string;
page?: string | number;
sortDirection?: string;
sortField?: string;
kuery?: string;
rangeFrom?: string;
rangeTo?: string;
refreshPaused?: string | boolean;
refreshInterval?: string | number;
}
Expand All @@ -138,14 +158,11 @@ interface RisonEncoded {
_a?: string;
}

interface RisonDecoded {
export interface RisonDecoded {
_g?: StringMap<any>;
_a?: StringMap<any>;
}

export type QueryParams = APMQueryParams & RisonEncoded;
export type QueryParamsDecoded = APMQueryParams & RisonDecoded;

// This is downright horrible 😭 💔
// Angular decodes encoded url tokens like "%2F" to "/" which causes the route to change.
// It was supposedly fixed in https://github.com/angular/angular.js/commit/1b779028fdd339febaa1fff5f3bd4cfcda46cc09 but still seeing the issue
Expand Down
15 changes: 5 additions & 10 deletions x-pack/plugins/apm/public/store/urlParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function urlParamsReducer(state = {}, action: AnyAction) {
detailTab: toString(detailTab),
flyoutDetailTab: toString(flyoutDetailTab),
spanId: toNumber(spanId),
kuery: legacyDecodeURIComponent(kuery as string | undefined),
kuery: legacyDecodeURIComponent(kuery),

// path params
processorEvent,
Expand All @@ -84,8 +84,8 @@ export function urlParamsReducer(state = {}, action: AnyAction) {
}
}

export function toNumber(value?: string | string[]) {
if (value !== undefined && !Array.isArray(value)) {
export function toNumber(value?: string) {
if (value !== undefined) {
return parseInt(value, 10);
}
}
Expand All @@ -102,13 +102,8 @@ function toString(str?: string | string[]) {
return str;
}

export function toBoolean(value?: string | boolean) {
if (value === 'true' || value === true) {
return true;
}
if (value === 'false' || value === false) {
return false;
}
export function toBoolean(value?: string) {
return value === 'true';
}

function getPathAsArray(pathname: string) {
Expand Down