mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Dataset quality] Added dataQuality locator (#184588)
Closes https://github.com/elastic/kibana/issues/183406
## 📝 Summary
This PR adds a basic locator to dataQuality plugin, where timeRange
filters can be shared
## 🎥 Demo
47dabe6f
-fe89-4075-8688-1e53332cdd9a
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
863c4f3d04
commit
9a6dacb697
14 changed files with 364 additions and 1 deletions
|
@ -13,3 +13,6 @@ export const PLUGIN_NAME = i18n.translate('xpack.dataQuality.name', {
|
|||
});
|
||||
|
||||
export { DATA_QUALITY_URL_STATE_KEY, datasetQualityUrlSchemaV1 } from './url_schema';
|
||||
|
||||
export { DATA_QUALITY_LOCATOR_ID } from './locators';
|
||||
export type { DataQualityLocatorParams } from './locators';
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common';
|
||||
import { ManagementAppLocatorParams } from '@kbn/management-plugin/common/locator';
|
||||
import { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import { datasetQualityUrlSchemaV1, DATA_QUALITY_URL_STATE_KEY } from '../url_schema';
|
||||
import { deepCompactObject } from '../utils/deep_compact_object';
|
||||
import { DataQualityLocatorParams } from './types';
|
||||
|
||||
interface LocatorPathConstructionParams {
|
||||
locatorParams: DataQualityLocatorParams;
|
||||
useHash: boolean;
|
||||
managementLocator: LocatorPublic<ManagementAppLocatorParams>;
|
||||
}
|
||||
|
||||
export const constructDatasetQualityLocatorPath = async (params: LocatorPathConstructionParams) => {
|
||||
const {
|
||||
locatorParams: { filters },
|
||||
useHash,
|
||||
managementLocator,
|
||||
} = params;
|
||||
|
||||
const pageState = datasetQualityUrlSchemaV1.urlSchemaRT.encode(
|
||||
deepCompactObject({
|
||||
v: 1,
|
||||
filters,
|
||||
})
|
||||
);
|
||||
|
||||
const managementPath = await managementLocator.getLocation({
|
||||
sectionId: 'data',
|
||||
appId: 'data_quality',
|
||||
});
|
||||
|
||||
const path = setStateToKbnUrl(
|
||||
DATA_QUALITY_URL_STATE_KEY,
|
||||
pageState,
|
||||
{ useHash, storeInHashQuery: false },
|
||||
`${managementPath.app}${managementPath.path}`
|
||||
);
|
||||
|
||||
return {
|
||||
app: '',
|
||||
path,
|
||||
state: {},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
|
||||
import {
|
||||
DataQualityLocatorDependencies,
|
||||
DataQualityLocatorParams,
|
||||
DATA_QUALITY_LOCATOR_ID,
|
||||
} from './types';
|
||||
import { constructDatasetQualityLocatorPath } from './construct_dataset_quality_locator_path';
|
||||
|
||||
export type DatasetQualityLocator = LocatorPublic<DataQualityLocatorParams>;
|
||||
|
||||
export class DatasetQualityLocatorDefinition
|
||||
implements LocatorDefinition<DataQualityLocatorParams>
|
||||
{
|
||||
public readonly id = DATA_QUALITY_LOCATOR_ID;
|
||||
|
||||
constructor(protected readonly deps: DataQualityLocatorDependencies) {}
|
||||
|
||||
public readonly getLocation = async (params: DataQualityLocatorParams) => {
|
||||
const { useHash, managementLocator } = this.deps;
|
||||
return await constructDatasetQualityLocatorPath({
|
||||
useHash,
|
||||
managementLocator,
|
||||
locatorParams: params,
|
||||
});
|
||||
};
|
||||
}
|
15
x-pack/plugins/data_quality/common/locators/index.ts
Normal file
15
x-pack/plugins/data_quality/common/locators/index.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { DatasetQualityLocator } from './dataset_quality_locator';
|
||||
|
||||
export * from './dataset_quality_locator';
|
||||
export * from './types';
|
||||
|
||||
export interface DataQualityLocators {
|
||||
datasetQualityLocator: DatasetQualityLocator;
|
||||
}
|
77
x-pack/plugins/data_quality/common/locators/locators.test.ts
Normal file
77
x-pack/plugins/data_quality/common/locators/locators.test.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { DatasetQualityLocatorDefinition } from './dataset_quality_locator';
|
||||
import { DataQualityLocatorDependencies } from './types';
|
||||
|
||||
const createMockLocator = (id: string, section: string) => ({
|
||||
id,
|
||||
navigate: jest.fn(),
|
||||
getRedirectUrl: jest.fn(),
|
||||
getLocation: jest.fn().mockReturnValue({ app: id, path: `/${section}`, state: {} }),
|
||||
getUrl: jest.fn(),
|
||||
navigateSync: jest.fn(),
|
||||
useUrl: jest.fn(),
|
||||
telemetry: jest.fn(),
|
||||
inject: jest.fn(),
|
||||
extract: jest.fn(),
|
||||
migrations: jest.fn(),
|
||||
});
|
||||
|
||||
const setup = async () => {
|
||||
const dep: DataQualityLocatorDependencies = {
|
||||
useHash: false,
|
||||
managementLocator: createMockLocator('management', 'data/data_quality'),
|
||||
};
|
||||
|
||||
const datasetQualityLocator = new DatasetQualityLocatorDefinition(dep);
|
||||
|
||||
return {
|
||||
datasetQualityLocator,
|
||||
};
|
||||
};
|
||||
|
||||
describe('Data quality Locators', () => {
|
||||
const timeRange = { to: 'now', from: 'now-30m' };
|
||||
|
||||
describe('Dataset Quality Locator', () => {
|
||||
it('should create a link with correct path and no state', async () => {
|
||||
const { datasetQualityLocator } = await setup();
|
||||
const location = await datasetQualityLocator.getLocation({});
|
||||
|
||||
expect(location).toMatchObject({
|
||||
app: '',
|
||||
path: 'management/data/data_quality?pageState=(v:1)',
|
||||
state: {},
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a link with correct timeRange', async () => {
|
||||
const refresh = {
|
||||
pause: false,
|
||||
value: 0,
|
||||
};
|
||||
const locatorParams = {
|
||||
filters: {
|
||||
timeRange: {
|
||||
...timeRange,
|
||||
refresh,
|
||||
},
|
||||
},
|
||||
};
|
||||
const { datasetQualityLocator } = await setup();
|
||||
|
||||
const location = await datasetQualityLocator.getLocation(locatorParams);
|
||||
|
||||
expect(location).toMatchObject({
|
||||
app: '',
|
||||
path: 'management/data/data_quality?pageState=(filters:(timeRange:(from:now-30m,refresh:(pause:!f,value:0),to:now)),v:1)',
|
||||
state: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
39
x-pack/plugins/data_quality/common/locators/types.ts
Normal file
39
x-pack/plugins/data_quality/common/locators/types.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ManagementAppLocatorParams } from '@kbn/management-plugin/common/locator';
|
||||
import { LocatorPublic } from '@kbn/share-plugin/common';
|
||||
import { SerializableRecord } from '@kbn/utility-types';
|
||||
|
||||
export const DATA_QUALITY_LOCATOR_ID = 'DATA_QUALITY_LOCATOR';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
type RefreshInterval = {
|
||||
pause: boolean;
|
||||
value: number;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
type TimeRangeConfig = {
|
||||
from: string;
|
||||
to: string;
|
||||
refresh: RefreshInterval;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
type Filters = {
|
||||
timeRange: TimeRangeConfig;
|
||||
};
|
||||
|
||||
export interface DataQualityLocatorParams extends SerializableRecord {
|
||||
filters?: Filters;
|
||||
}
|
||||
|
||||
export interface DataQualityLocatorDependencies {
|
||||
useHash: boolean;
|
||||
managementLocator: LocatorPublic<ManagementAppLocatorParams>;
|
||||
}
|
15
x-pack/plugins/data_quality/jest.config.js
Normal file
15
x-pack/plugins/data_quality/jest.config.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../..',
|
||||
roots: ['<rootDir>/x-pack/plugins/data_quality'],
|
||||
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/x-pack/plugins/data_quality',
|
||||
coverageReporters: ['text', 'html'],
|
||||
collectCoverageFrom: ['<rootDir>/x-pack/plugins/datas_quality/{common,public}/**/*.{ts,tsx}'],
|
||||
};
|
|
@ -11,6 +11,7 @@
|
|||
"datasetQuality",
|
||||
"management",
|
||||
"features",
|
||||
"share",
|
||||
],
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": [
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||
import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants';
|
||||
import { ManagementAppLocatorParams } from '@kbn/management-plugin/common/locator';
|
||||
import {
|
||||
DataQualityPluginSetup,
|
||||
DataQualityPluginStart,
|
||||
|
@ -14,6 +16,7 @@ import {
|
|||
AppPluginSetupDependencies,
|
||||
} from './types';
|
||||
import { PLUGIN_ID, PLUGIN_NAME } from '../common';
|
||||
import { DatasetQualityLocatorDefinition } from '../common/locators';
|
||||
|
||||
export class DataQualityPlugin
|
||||
implements
|
||||
|
@ -28,7 +31,8 @@ export class DataQualityPlugin
|
|||
core: CoreSetup<AppPluginStartDependencies, DataQualityPluginStart>,
|
||||
plugins: AppPluginSetupDependencies
|
||||
): DataQualityPluginSetup {
|
||||
const { management } = plugins;
|
||||
const { management, share } = plugins;
|
||||
const useHash = core.uiSettings.get('state:storeInSessionStorage');
|
||||
|
||||
management.sections.section.data.registerApp({
|
||||
id: PLUGIN_ID,
|
||||
|
@ -46,6 +50,18 @@ export class DataQualityPlugin
|
|||
hideFromSidebar: true,
|
||||
});
|
||||
|
||||
const managementLocator =
|
||||
share.url.locators.get<ManagementAppLocatorParams>(MANAGEMENT_APP_LOCATOR);
|
||||
|
||||
if (managementLocator) {
|
||||
share.url.locators.create(
|
||||
new DatasetQualityLocatorDefinition({
|
||||
useHash,
|
||||
managementLocator,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { DatasetQualityPluginStart } from '@kbn/dataset-quality-plugin/public';
|
||||
import { ManagementSetup, ManagementStart } from '@kbn/management-plugin/public';
|
||||
import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface DataQualityPluginSetup {}
|
||||
|
@ -16,9 +17,11 @@ export interface DataQualityPluginStart {}
|
|||
|
||||
export interface AppPluginSetupDependencies {
|
||||
management: ManagementSetup;
|
||||
share: SharePluginSetup;
|
||||
}
|
||||
|
||||
export interface AppPluginStartDependencies {
|
||||
datasetQuality: DatasetQualityPluginStart;
|
||||
management: ManagementStart;
|
||||
share: SharePluginStart;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
"@kbn/i18n-react",
|
||||
"@kbn/core-chrome-browser",
|
||||
"@kbn/features-plugin",
|
||||
"@kbn/share-plugin",
|
||||
"@kbn/utility-types",
|
||||
"@kbn/deeplinks-management",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -57,3 +57,10 @@ export const feedbackLinkTitle = i18n.translate(
|
|||
export const createSLoLabel = i18n.translate('xpack.observabilityLogsExplorer.createSlo', {
|
||||
defaultMessage: 'Create SLO',
|
||||
});
|
||||
|
||||
export const datasetQualityLinkTitle = i18n.translate(
|
||||
'xpack.observabilityLogsExplorer.datasetQualityLinkTitle',
|
||||
{
|
||||
defaultMessage: 'Datasets',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EuiHeaderLink } from '@elastic/eui';
|
||||
import { LogsExplorerPublicState } from '@kbn/logs-explorer-plugin/public';
|
||||
import { getRouterLinkProps } from '@kbn/router-utils';
|
||||
import { BrowserUrlService } from '@kbn/share-plugin/public';
|
||||
import { MatchedStateFromActor } from '@kbn/xstate-utils';
|
||||
import { useActor } from '@xstate/react';
|
||||
import React from 'react';
|
||||
import { DataQualityLocatorParams, DATA_QUALITY_LOCATOR_ID } from '@kbn/data-quality-plugin/common';
|
||||
import { datasetQualityLinkTitle } from '../../common/translations';
|
||||
import {
|
||||
ObservabilityLogsExplorerService,
|
||||
useObservabilityLogsExplorerPageStateContext,
|
||||
} from '../state_machines/observability_logs_explorer/src';
|
||||
import { useKibanaContextForPlugin } from '../utils/use_kibana';
|
||||
|
||||
export const ConnectedDatasetQualityLink = React.memo(() => {
|
||||
const {
|
||||
services: {
|
||||
share: { url },
|
||||
},
|
||||
} = useKibanaContextForPlugin();
|
||||
const [pageState] = useActor(useObservabilityLogsExplorerPageStateContext());
|
||||
|
||||
if (pageState.matches({ initialized: 'validLogsExplorerState' })) {
|
||||
return <DatasetQualityLink urlService={url} pageState={pageState} />;
|
||||
} else {
|
||||
return <DatasetQualityLink urlService={url} />;
|
||||
}
|
||||
});
|
||||
|
||||
type InitializedPageState = MatchedStateFromActor<
|
||||
ObservabilityLogsExplorerService,
|
||||
{ initialized: 'validLogsExplorerState' }
|
||||
>;
|
||||
|
||||
const constructLocatorParams = (
|
||||
logsExplorerState: LogsExplorerPublicState
|
||||
): DataQualityLocatorParams => {
|
||||
const { time, refreshInterval } = logsExplorerState;
|
||||
const locatorParams: DataQualityLocatorParams = {
|
||||
filters: {
|
||||
timeRange: {
|
||||
from: time?.from || 'now-24h',
|
||||
to: time?.to || 'now',
|
||||
refresh: {
|
||||
pause: refreshInterval ? refreshInterval.pause : false,
|
||||
value: refreshInterval ? refreshInterval.value : 60000,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return locatorParams;
|
||||
};
|
||||
|
||||
export const DatasetQualityLink = React.memo(
|
||||
({
|
||||
urlService,
|
||||
pageState,
|
||||
}: {
|
||||
urlService: BrowserUrlService;
|
||||
pageState?: InitializedPageState;
|
||||
}) => {
|
||||
const locator = urlService.locators.get<DataQualityLocatorParams>(DATA_QUALITY_LOCATOR_ID);
|
||||
|
||||
const locatorParams: DataQualityLocatorParams = pageState
|
||||
? constructLocatorParams(pageState.context.logsExplorerState)
|
||||
: {};
|
||||
|
||||
const datasetQualityUrl = locator?.getRedirectUrl(locatorParams);
|
||||
|
||||
const navigateToDatasetQuality = () => {
|
||||
locator?.navigate(locatorParams);
|
||||
};
|
||||
|
||||
const datasetQualityLinkProps = getRouterLinkProps({
|
||||
href: datasetQualityUrl,
|
||||
onClick: navigateToDatasetQuality,
|
||||
});
|
||||
|
||||
return (
|
||||
<EuiHeaderLink
|
||||
{...datasetQualityLinkProps}
|
||||
color="primary"
|
||||
data-test-subj="logsExplorerDatasetQualityLink"
|
||||
>
|
||||
{datasetQualityLinkTitle}
|
||||
</EuiHeaderLink>
|
||||
);
|
||||
}
|
||||
);
|
|
@ -50,6 +50,7 @@
|
|||
"@kbn/analytics-client",
|
||||
"@kbn/core-analytics-browser",
|
||||
"@kbn/react-hooks",
|
||||
"@kbn/data-quality-plugin",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue