Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[6.x] [APM] Fixes rare cases where KibanaLink is loaded outside of React context (#24705) #24737

Merged
merged 1 commit into from
Oct 29, 2018
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 @@ -33,7 +33,7 @@ import {

import { XPACK_DOCS } from '../../../../utils/documentation/xpack';

import { KibanaLink } from '../../../../utils/url';
import { UnconnectedKibanaLink } from '../../../../utils/url';
import { createErrorGroupWatch } from './createErrorGroupWatch';
import chrome from 'ui/chrome';

Expand Down Expand Up @@ -187,12 +187,13 @@ export default class WatcherFlyout extends Component {
<p>
The watch is now ready and will send error reports for{' '}
{this.props.serviceName}.{' '}
<KibanaLink
<UnconnectedKibanaLink
location={this.props.location}
pathname={'/app/kibana'}
hash={`/management/elasticsearch/watcher/watches/watch/${id}`}
>
View watch.
</KibanaLink>
</UnconnectedKibanaLink>
</p>
)
});
Expand Down Expand Up @@ -419,6 +420,7 @@ export default class WatcherFlyout extends Component {
}

WatcherFlyout.propTypes = {
location: PropTypes.object.isRequired,
isOpen: PropTypes.bool.isRequired,
serviceName: PropTypes.string,
onClose: PropTypes.func.isRequired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class ErrorGroupOverview extends Component {
/>

<WatcherFlyout
location={location}
serviceName={serviceName}
isOpen={this.state.isFlyoutOpen}
onClose={this.onCloseFlyout}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`KibanaLinkComponent should render correct markup 1`] = `
exports[`RelativeLinkComponent should render correct markup 1`] = `
<a
className="euiLink euiLink--primary"
href="myBasePath/app/kibana#/discover?_a=(interval:auto,query:(language:lucene,query:'context.service.name:myServiceName AND error.grouping_key:myGroupId'),sort:('@timestamp':desc))&_g="
className="euiLink euiLink--primary "
href="/opbeans-node/errors?foo=bar&foo2=bar2"
onClick={[Function]}
>
Go to Discover
</a>
`;

exports[`RelativeLinkComponent should render correct markup 1`] = `
exports[`UnconnectedKibanaLink should render correct markup 1`] = `
<a
className="euiLink euiLink--primary "
href="/opbeans-node/errors?foo=bar&foo2=bar2"
onClick={[Function]}
className="euiLink euiLink--primary"
href="myBasePath/app/kibana#/discover?_a=(interval:auto,query:(language:lucene,query:'context.service.name:myServiceName AND error.grouping_key:myGroupId'),sort:('@timestamp':desc))&_g="
>
Go to Discover
</a>
`;

exports[`ViewMLJob should render component 1`] = `
<Connect(KibanaLinkComponent)
<Component
hash="/timeseriesexplorer"
location={
Object {
"search": "",
}
}
pathname="/app/ml"
query={
Object {
Expand All @@ -37,5 +42,5 @@ exports[`ViewMLJob should render component 1`] = `
}
>
View Job
</Connect(KibanaLinkComponent)>
</Component>
`;
8 changes: 4 additions & 4 deletions x-pack/plugins/apm/public/utils/__test__/url.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import createHistory from 'history/createMemoryHistory';
import {
toQuery,
fromQuery,
KibanaLinkComponent,
UnconnectedKibanaLink,
RelativeLinkComponent,
encodeKibanaSearchParams,
decodeKibanaSearchParams,
Expand Down Expand Up @@ -182,7 +182,7 @@ describe('RelativeLinkComponent', () => {
});
});

describe('KibanaLinkComponent', () => {
describe('UnconnectedKibanaLink', () => {
let wrapper;

beforeEach(() => {
Expand All @@ -198,14 +198,14 @@ describe('KibanaLinkComponent', () => {
};

wrapper = mount(
<KibanaLinkComponent
<UnconnectedKibanaLink
location={{ search: '' }}
pathname={'/app/kibana'}
hash={'/discover'}
query={discoverQuery}
>
Go to Discover
</KibanaLinkComponent>
</UnconnectedKibanaLink>
);
});

Expand Down
17 changes: 12 additions & 5 deletions x-pack/plugins/apm/public/utils/url.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export function ViewMLJob({
};

return (
<KibanaLink
<UnconnectedKibanaLink
location={location}
pathname={pathname}
hash={hash}
query={query}
Expand Down Expand Up @@ -164,13 +165,19 @@ export interface KibanaLinkArgs {
className?: string;
}

export function KibanaLinkComponent({
/**
* NOTE: Use this component directly if you have to use a link that is
* going to be rendered outside of React, e.g. in the Kibana global toast loader.
*
* You must remember to pass in location in that case.
*/
export const UnconnectedKibanaLink: React.SFC<KibanaLinkArgs> = ({
location,
pathname,
hash,
query = {},
...props
}: KibanaLinkArgs) {
}) => {
// Preserve current _g and _a
const currentQuery = toQuery(location.search);
const nextQuery = {
Expand All @@ -186,14 +193,14 @@ export function KibanaLinkComponent({
});

return <EuiLink {...props} href={href} />;
}
};

const withLocation = connect(
({ location }: { location: any }) => ({ location }),
{}
);
export const RelativeLink = withLocation(RelativeLinkComponent);
export const KibanaLink = withLocation(KibanaLinkComponent);
export const KibanaLink = withLocation(UnconnectedKibanaLink);

// This is downright horrible 😭 💔
// Angular decodes encoded url tokens like "%2F" to "/" which causes the route to change.
Expand Down