Fix Data Streams and Rollups Jobs deep-link bugs (#70903) (#70949)

* Add extractQueryParams to es_ui_shared/public/url. Update CCR, Remote Clusters, and Rollup to consume this service via shared_imports.
* Fix Data Streams bug in which clicking a data stream would apply a deep-link filter to the table.
* Fix Rollup Job deep-link bug.
This commit is contained in:
CJ Cenizal 2020-07-07 07:30:21 -07:00 committed by GitHub
parent 54c106a280
commit c495d1fa21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 89 additions and 82 deletions

View file

@ -68,6 +68,8 @@ export {
export { Monaco, Forms };
export { extractQueryParams } from './url';
/** dummy plugin, we just want esUiShared to have its own bundle */
export function plugin() {
return new (class EsUiSharedPlugin {

View file

@ -0,0 +1,29 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { parse, ParsedQuery } from 'query-string';
export function extractQueryParams(queryString: string = ''): ParsedQuery<string> {
const hrefSplit = queryString.split('?');
if (!hrefSplit.length) {
return {};
}
return parse(hrefSplit[1], { sort: false });
}

View file

@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
export { extractQueryParams } from './extract_query_params';

View file

@ -29,11 +29,10 @@ import {
EuiTitle,
} from '@elastic/eui';
import { indices } from '../../../../../../src/plugins/es_ui_shared/public';
import { indexPatterns } from '../../../../../../src/plugins/data/public';
import { extractQueryParams, indices } from '../../shared_imports';
import { routing } from '../services/routing';
import { extractQueryParams } from '../services/query_params';
import { getRemoteClusterName } from '../services/get_remote_cluster_name';
import { API_STATUS } from '../constants';
import { SectionError } from './section_error';

View file

@ -28,12 +28,14 @@ import {
EuiTitle,
} from '@elastic/eui';
import { indices } from '../../../../../../../src/plugins/es_ui_shared/public';
import { extractQueryParams, indices } from '../../../shared_imports';
import { indexNameValidator, leaderIndexValidator } from '../../services/input_validation';
import { routing } from '../../services/routing';
import { getFatalErrors } from '../../services/notifications';
import { loadIndices } from '../../services/api';
import { API_STATUS } from '../../constants';
import { getRemoteClusterName } from '../../services/get_remote_cluster_name';
import { RemoteClustersFormField } from '../remote_clusters_form_field';
import { SectionError } from '../section_error';
import { FormEntryRow } from '../form_entry_row';
import {
@ -41,9 +43,6 @@ import {
emptyAdvancedSettings,
areAdvancedSettingsEdited,
} from './advanced_settings_fields';
import { extractQueryParams } from '../../services/query_params';
import { getRemoteClusterName } from '../../services/get_remote_cluster_name';
import { RemoteClustersFormField } from '../remote_clusters_form_field';
import { FollowerIndexRequestFlyout } from './follower_index_request_flyout';

View file

@ -18,7 +18,7 @@ import {
} from '@elastic/eui';
import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public';
import { extractQueryParams } from '../../../services/query_params';
import { extractQueryParams } from '../../../../shared_imports';
import { trackUiMetric, METRIC_TYPE } from '../../../services/track_ui_metric';
import { API_STATUS, UIM_AUTO_FOLLOW_PATTERN_LIST_LOAD } from '../../../constants';
import { SectionLoading, SectionError, SectionUnauthorized } from '../../../components';

View file

@ -18,7 +18,7 @@ import {
} from '@elastic/eui';
import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public';
import { extractQueryParams } from '../../../services/query_params';
import { extractQueryParams } from '../../../../shared_imports';
import { trackUiMetric, METRIC_TYPE } from '../../../services/track_ui_metric';
import { API_STATUS, UIM_FOLLOWER_INDEX_LIST_LOAD } from '../../../constants';
import { SectionLoading, SectionError, SectionUnauthorized } from '../../../components';

View file

@ -8,8 +8,8 @@ import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { indices } from '../../../../../../src/plugins/es_ui_shared/public';
import { indexPatterns } from '../../../../../../src/plugins/data/public';
import { indices } from '../../shared_imports';
const {
indexNameBeginsWithPeriod,

View file

@ -6,7 +6,8 @@
import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { indices } from '../../../../../../src/plugins/es_ui_shared/public';
import { indices } from '../../shared_imports';
const isEmpty = (value) => {
return !value || !value.trim().length;

View file

@ -4,13 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { parse } from 'query-string';
export function extractQueryParams(queryString) {
const hrefSplit = queryString.split('?');
if (!hrefSplit.length) {
return {};
}
return parse(hrefSplit[1], { sort: false });
}
export { extractQueryParams, indices } from '../../../../src/plugins/es_ui_shared/public';

View file

@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n';
import { EuiTitle, EuiText, EuiSpacer, EuiEmptyPrompt, EuiLink } from '@elastic/eui';
import { ScopedHistory } from 'kibana/public';
import { reactRouterNavigate } from '../../../../shared_imports';
import { reactRouterNavigate, extractQueryParams } from '../../../../shared_imports';
import { useAppContext } from '../../../app_context';
import { SectionError, SectionLoading, Error } from '../../../components';
import { useLoadDataStreams } from '../../../services/api';
@ -28,8 +28,11 @@ export const DataStreamList: React.FunctionComponent<RouteComponentProps<MatchPa
match: {
params: { dataStreamName },
},
location: { search },
history,
}) => {
const { isDeepLink } = extractQueryParams(search);
const {
core: { getUrlForApp },
plugins: { ingestManager },
@ -144,7 +147,9 @@ export const DataStreamList: React.FunctionComponent<RouteComponentProps<MatchPa
<DataStreamTable
filters={
dataStreamName !== undefined ? `name=${decodePathFromReactRouter(dataStreamName)}` : ''
isDeepLink && dataStreamName !== undefined
? `name=${decodePathFromReactRouter(dataStreamName)}`
: ''
}
dataStreams={dataStreams}
reload={reload}

View file

@ -277,6 +277,7 @@ export class IndexTable extends Component {
data-test-subj="dataStreamLink"
{...reactRouterNavigate(history, {
pathname: `/data_streams/${encodePathForReactRouter(value)}`,
search: '?isDeepLink=true',
})}
>
{value}

View file

@ -11,6 +11,7 @@ export {
sendRequest,
useRequest,
Forms,
extractQueryParams,
} from '../../../../src/plugins/es_ui_shared/public/';
export {

View file

@ -10,7 +10,8 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { EuiPageContent } from '@elastic/eui';
import { getRouter, redirect, extractQueryParams } from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { getRouter, redirect } from '../../services';
import { setBreadcrumbs } from '../../services/breadcrumb';
import { RemoteClusterPageTitle, RemoteClusterForm } from '../components';

View file

@ -21,7 +21,8 @@ import {
} from '@elastic/eui';
import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public';
import { extractQueryParams, getRouter, redirect } from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { getRouter, redirect } from '../../services';
import { setBreadcrumbs } from '../../services/breadcrumb';
import { RemoteClusterPageTitle, RemoteClusterForm, ConfiguredByNodeWarning } from '../components';

View file

@ -29,7 +29,7 @@ import {
} from '@elastic/eui';
import { reactRouterNavigate } from '../../../../../../../src/plugins/kibana_react/public';
import { extractQueryParams } from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { setBreadcrumbs } from '../../services/breadcrumb';
import { RemoteClusterTable } from './remote_cluster_table';

View file

@ -12,8 +12,6 @@ export { initRedirect, redirect } from './redirect';
export { isAddressValid, isPortValid } from './validate_address';
export { extractQueryParams } from './query_params';
export { setUserHasLeftApp, getUserHasLeftApp, registerRouter, getRouter } from './routing';
export { trackUiMetric, METRIC_TYPE } from './ui_metric';

View file

@ -6,12 +6,8 @@
import { i18n } from '@kbn/i18n';
import {
addCluster as sendAddClusterRequest,
getRouter,
extractQueryParams,
redirect,
} from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { addCluster as sendAddClusterRequest, getRouter, redirect } from '../../services';
import { fatalError, toasts } from '../../services/notification';
import {

View file

@ -4,7 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { extractQueryParams, getRouter } from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { getRouter } from '../../services';
import { OPEN_DETAIL_PANEL, CLOSE_DETAIL_PANEL } from '../action_types';
export const openDetailPanel = ({ name }) => (dispatch) => {

View file

@ -9,12 +9,8 @@ import { i18n } from '@kbn/i18n';
import { toasts, fatalError } from '../../services/notification';
import { loadClusters } from './load_clusters';
import {
editCluster as sendEditClusterRequest,
extractQueryParams,
getRouter,
redirect,
} from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { editCluster as sendEditClusterRequest, getRouter, redirect } from '../../services';
import {
EDIT_CLUSTER_START,

View file

@ -4,13 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { parse } from 'query-string';
export function extractQueryParams(queryString) {
const hrefSplit = queryString.split('?');
if (!hrefSplit.length) {
return {};
}
return parse(hrefSplit[1], { sort: false });
}
export { extractQueryParams, indices } from '../../../../src/plugins/es_ui_shared/public';

View file

@ -27,10 +27,9 @@ import {
import { withKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { getRouterLinkProps, extractQueryParams, listBreadcrumb } from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { getRouterLinkProps, listBreadcrumb } from '../../services';
import { JobTable } from './job_table';
import { DetailPanel } from './detail_panel';
const REFRESH_RATE_MS = 30000;

View file

@ -265,7 +265,7 @@ export class JobTable extends Component {
<EuiLink
onClick={() => {
trackUiMetric(METRIC_TYPE.CLICK, UIM_SHOW_DETAILS_CLICK);
openDetailPanel(job.id);
openDetailPanel(encodeURIComponent(job.id));
}}
>
{value}

View file

@ -33,8 +33,6 @@ export { serializeJob, deserializeJob, deserializeJobs } from './jobs';
export { createNoticeableDelay } from './noticeable_delay';
export { extractQueryParams } from './query_params';
export {
setUserHasLeftApp,
getUserHasLeftApp,

View file

@ -1,23 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export function extractQueryParams(queryString) {
if (!queryString || queryString.trim().length === 0) {
return {};
}
const extractedQueryParams = {};
const queryParamPairs = queryString
.split('?')[1]
.split('&')
.map((paramString) => paramString.split('='));
queryParamPairs.forEach(([key, value]) => {
extractedQueryParams[key] = decodeURIComponent(value);
});
return extractedQueryParams;
}

View file

@ -102,7 +102,7 @@ export const createJob = (jobConfig) => async (dispatch) => {
// here, because it would partially obscure the detail panel.
getRouter().history.push({
pathname: `/job_list`,
search: `?job=${jobConfig.id}`,
search: `?job=${encodeURIComponent(jobConfig.id)}`,
});
};

View file

@ -4,7 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { extractQueryParams, getRouter } from '../../services';
import { extractQueryParams } from '../../../shared_imports';
import { getRouter } from '../../services';
import { OPEN_DETAIL_PANEL, CLOSE_DETAIL_PANEL } from '../action_types';
export const openDetailPanel = ({ panelType, jobId }) => (dispatch) => {

View file

@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { indices } from '../../../../src/plugins/es_ui_shared/public';
export { extractQueryParams, indices } from '../../../../src/plugins/es_ui_shared/public';