Skip to content

Commit

Permalink
[Dataset quality] Added dataQuality locator (#184588)
Browse files Browse the repository at this point in the history
Closes #183406

## πŸ“  Summary
This PR adds a basic locator to dataQuality plugin, where timeRange
filters can be shared

## πŸŽ₯ Demo


https://github.com/elastic/kibana/assets/1313018/47dabe6f-fe89-4075-8688-1e53332cdd9a

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
yngrdyn and kibanamachine authored May 31, 2024
1 parent 863c4f3 commit 9a6dacb
Show file tree
Hide file tree
Showing 14 changed files with 364 additions and 1 deletion.
3 changes: 3 additions & 0 deletions x-pack/plugins/data_quality/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Original file line number Diff line number Diff line change
@@ -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: {},
};
};
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions x-pack/plugins/data_quality/common/locators/index.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 77 additions & 0 deletions x-pack/plugins/data_quality/common/locators/locators.test.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 39 additions & 0 deletions x-pack/plugins/data_quality/common/locators/types.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions x-pack/plugins/data_quality/jest.config.js
Original file line number Diff line number Diff line change
@@ -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}'],
};
1 change: 1 addition & 0 deletions x-pack/plugins/data_quality/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"datasetQuality",
"management",
"features",
"share",
],
"optionalPlugins": [],
"requiredBundles": [
Expand Down
18 changes: 17 additions & 1 deletion x-pack/plugins/data_quality/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@

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,
AppPluginStartDependencies,
AppPluginSetupDependencies,
} from './types';
import { PLUGIN_ID, PLUGIN_NAME } from '../common';
import { DatasetQualityLocatorDefinition } from '../common/locators';

export class DataQualityPlugin
implements
Expand All @@ -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,
Expand All @@ -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 {};
}

Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/data_quality/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand All @@ -16,9 +17,11 @@ export interface DataQualityPluginStart {}

export interface AppPluginSetupDependencies {
management: ManagementSetup;
share: SharePluginSetup;
}

export interface AppPluginStartDependencies {
datasetQuality: DatasetQualityPluginStart;
management: ManagementStart;
share: SharePluginStart;
}
3 changes: 3 additions & 0 deletions x-pack/plugins/data_quality/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/**/*"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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',
}
);
Loading

0 comments on commit 9a6dacb

Please sign in to comment.