[ML] Transforms: Migrate client plugin to NP. (#59443)

Migrates the client side plugin of transforms to NP.
- Gets rid of the last parts of the shim (http, documentation links)
- Moves the plugin from x-pack/legacy/plugins/transform/public to x-pack/plugins/transform
- Creates a custom mock for appDependencies based on NP services
- Fixes jest tests to get rid of all act() related warnings
This commit is contained in:
Walter Rafelsberger 2020-03-06 17:44:35 +01:00 committed by GitHub
parent 708d92a00e
commit f4f956dfeb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
217 changed files with 456 additions and 650 deletions

View file

@ -39,7 +39,7 @@
"xpack.snapshotRestore": "plugins/snapshot_restore",
"xpack.spaces": ["legacy/plugins/spaces", "plugins/spaces"],
"xpack.taskManager": "legacy/plugins/task_manager",
"xpack.transform": ["legacy/plugins/transform", "plugins/transform"],
"xpack.transform": "plugins/transform",
"xpack.triggersActionsUI": "plugins/triggers_actions_ui",
"xpack.upgradeAssistant": "plugins/upgrade_assistant",
"xpack.uptime": "legacy/plugins/uptime",

View file

@ -4,19 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { resolve } from 'path';
import { PLUGIN } from './common/constants';
export function transform(kibana: any) {
return new kibana.Plugin({
id: PLUGIN.ID,
id: 'transform',
configPrefix: 'xpack.transform',
publicDir: resolve(__dirname, 'public'),
require: ['kibana', 'elasticsearch', 'xpack_main'],
uiExports: {
styleSheetPaths: resolve(__dirname, 'public/app/index.scss'),
managementSections: ['plugins/transform'],
},
});
}

View file

@ -1,102 +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.
*/
import { useAppDependencies } from '../app_dependencies';
import { PreviewRequestBody, TransformId } from '../common';
import { httpFactory, Http } from '../services/http_service';
import { EsIndex, TransformEndpointRequest, TransformEndpointResult } from './use_api_types';
const apiFactory = (basePath: string, indicesBasePath: string, http: Http) => ({
getTransforms(transformId?: TransformId): Promise<any> {
const transformIdString = transformId !== undefined ? `/${transformId}` : '';
return http({
url: `${basePath}/transforms${transformIdString}`,
method: 'GET',
});
},
getTransformsStats(transformId?: TransformId): Promise<any> {
if (transformId !== undefined) {
return http({
url: `${basePath}/transforms/${transformId}/_stats`,
method: 'GET',
});
}
return http({
url: `${basePath}/transforms/_stats`,
method: 'GET',
});
},
createTransform(transformId: TransformId, transformConfig: any): Promise<any> {
return http({
url: `${basePath}/transforms/${transformId}`,
method: 'PUT',
data: transformConfig,
});
},
deleteTransforms(transformsInfo: TransformEndpointRequest[]) {
return http({
url: `${basePath}/delete_transforms`,
method: 'POST',
data: transformsInfo,
}) as Promise<TransformEndpointResult>;
},
getTransformsPreview(obj: PreviewRequestBody): Promise<any> {
return http({
url: `${basePath}/transforms/_preview`,
method: 'POST',
data: obj,
});
},
startTransforms(transformsInfo: TransformEndpointRequest[]) {
return http({
url: `${basePath}/start_transforms`,
method: 'POST',
data: {
transformsInfo,
},
}) as Promise<TransformEndpointResult>;
},
stopTransforms(transformsInfo: TransformEndpointRequest[]) {
return http({
url: `${basePath}/stop_transforms`,
method: 'POST',
data: {
transformsInfo,
},
}) as Promise<TransformEndpointResult>;
},
getTransformAuditMessages(transformId: TransformId): Promise<any> {
return http({
url: `${basePath}/transforms/${transformId}/messages`,
method: 'GET',
});
},
esSearch(payload: any) {
return http({
url: `${basePath}/es_search`,
method: 'POST',
data: payload,
}) as Promise<any>;
},
getIndices() {
return http({
url: `${indicesBasePath}/index_management/indices`,
method: 'GET',
}) as Promise<EsIndex[]>;
},
});
export const useApi = () => {
const appDeps = useAppDependencies();
const basePath = '/api/transform';
const indicesBasePath = '/api';
const http = httpFactory(appDeps.core.http);
return apiFactory(basePath, indicesBasePath, http);
};

View file

@ -1,25 +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.
*/
import { TransformId, TRANSFORM_STATE } from '../common';
export interface EsIndex {
name: string;
}
export interface TransformEndpointRequest {
id: TransformId;
state?: TRANSFORM_STATE;
}
export interface ResultData {
success: boolean;
error?: any;
}
export interface TransformEndpointResult {
[key: string]: ResultData;
}

View file

@ -1,66 +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.
*/
import React, { FC } from 'react';
import ReactDOM from 'react-dom';
import { act } from 'react-dom/test-utils';
import { SimpleQuery } from '../../../../common';
import {
SOURCE_INDEX_STATUS,
useSourceIndexData,
UseSourceIndexDataReturnType,
} from './use_source_index_data';
jest.mock('../../../../hooks/use_api');
type Callback = () => void;
interface TestHookProps {
callback: Callback;
}
const TestHook: FC<TestHookProps> = ({ callback }) => {
callback();
return null;
};
const testHook = (callback: Callback) => {
const container = document.createElement('div');
document.body.appendChild(container);
act(() => {
ReactDOM.render(<TestHook callback={callback} />, container);
});
};
const query: SimpleQuery = {
query_string: {
query: '*',
default_operator: 'AND',
},
};
let sourceIndexObj: UseSourceIndexDataReturnType;
describe('useSourceIndexData', () => {
test('indexPattern set triggers loading', () => {
testHook(() => {
act(() => {
sourceIndexObj = useSourceIndexData(
{ id: 'the-id', title: 'the-title', fields: [] },
query,
{ pageIndex: 0, pageSize: 10 }
);
});
});
expect(sourceIndexObj.errorMessage).toBe('');
expect(sourceIndexObj.status).toBe(SOURCE_INDEX_STATUS.LOADING);
expect(sourceIndexObj.tableItems).toEqual([]);
});
// TODO add more tests to check data retrieved via `api.esSearch()`.
// This needs more investigation in regards to jest/enzyme's React Hooks support.
});

View file

@ -1,51 +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.
*/
import { HttpSetup } from 'kibana/public';
// service for interacting with the server
import { Dictionary } from '../../../common/types/common';
export type Http = (options: Dictionary<any>) => Promise<unknown>;
export function httpFactory(httpSetup: HttpSetup) {
return function http(options: Dictionary<any>) {
return new Promise((resolve, reject) => {
if (options && options.url) {
let url = '';
url = url + (options.url || '');
const headers = {
'Content-Type': 'application/json',
...options.headers,
};
const allHeaders =
options.headers === undefined ? headers : { ...options.headers, ...headers };
const body = options.data === undefined ? null : JSON.stringify(options.data);
const payload: Dictionary<any> = {
method: options.method || 'GET',
headers: allHeaders,
credentials: 'same-origin',
};
if (body !== null) {
payload.body = body;
}
httpSetup
.fetch(url, payload)
.then(resp => {
resolve(resp);
})
.catch(resp => {
reject(resp);
});
} else {
reject();
}
});
};
}

View file

@ -1,25 +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.
*/
import { UIM_APP_NAME } from '../../constants';
import {
createUiStatsReporter,
METRIC_TYPE,
} from '../../../../../../../../src/legacy/core_plugins/ui_metric/public';
class UiMetricService {
track?: ReturnType<typeof createUiStatsReporter>;
public init = (getReporter: typeof createUiStatsReporter): void => {
this.track = getReporter(UIM_APP_NAME);
};
public trackUiMetric = (eventName: string): void => {
if (!this.track) throw Error('UiMetricService not initialized.');
return this.track(METRIC_TYPE.COUNT, eventName);
};
}
export const uiMetricService = new UiMetricService();

View file

@ -1,80 +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.
*/
import { i18n } from '@kbn/i18n';
import { renderApp } from './app/app';
import { ShimCore, ShimPlugins } from './shim';
import { breadcrumbService } from './app/services/navigation';
import { docTitleService } from './app/services/navigation';
import { textService } from './app/services/text';
import { uiMetricService } from './app/services/ui_metric';
export class Plugin {
public start(core: ShimCore, plugins: ShimPlugins): void {
const {
http,
chrome,
documentation,
docLinks,
docTitle,
injectedMetadata,
notifications,
uiSettings,
savedObjects,
overlays,
} = core;
const { data, management, uiMetric } = plugins;
// AppCore/AppPlugins to be passed on as React context
const appDependencies = {
core: {
chrome,
documentation,
docLinks,
http,
i18n: core.i18n,
injectedMetadata,
notifications,
uiSettings,
savedObjects,
overlays,
},
plugins: {
data,
management,
},
};
// Register management section
const esSection = management.sections.getSection('elasticsearch');
if (esSection !== undefined) {
esSection.registerApp({
id: 'transform',
title: i18n.translate('xpack.transform.appTitle', {
defaultMessage: 'Transforms',
}),
order: 3,
mount(params) {
breadcrumbService.setup(params.setBreadcrumbs);
params.setBreadcrumbs([
{
text: i18n.translate('xpack.transform.breadcrumbsTitle', {
defaultMessage: 'Transforms',
}),
},
]);
return renderApp(params.element, appDependencies);
},
});
}
// Initialize services
textService.init();
uiMetricService.init(uiMetric.createUiStatsReporter);
docTitleService.init(docTitle.change);
}
}

View file

@ -1,91 +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.
*/
import { npStart } from 'ui/new_platform';
import { docTitle } from 'ui/doc_title/doc_title';
// @ts-ignore: allow traversal to fail on x-pack build
import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public';
import { TRANSFORM_DOC_PATHS } from './app/constants';
export type NpCore = typeof npStart.core;
export type NpPlugins = typeof npStart.plugins;
// AppCore/AppPlugins is the set of core features/plugins
// we pass on via context/hooks to the app and its components.
export type AppCore = Pick<
ShimCore,
| 'chrome'
| 'documentation'
| 'docLinks'
| 'http'
| 'i18n'
| 'injectedMetadata'
| 'savedObjects'
| 'uiSettings'
| 'overlays'
| 'notifications'
>;
export type AppPlugins = Pick<ShimPlugins, 'data' | 'management'>;
export interface AppDependencies {
core: AppCore;
plugins: AppPlugins;
}
export interface ShimCore extends NpCore {
documentation: Record<
| 'esDocBasePath'
| 'esIndicesCreateIndex'
| 'esPluginDocBasePath'
| 'esQueryDsl'
| 'esStackOverviewDocBasePath'
| 'esTransform'
| 'esTransformPivot'
| 'mlDocBasePath',
string
>;
docTitle: {
change: typeof docTitle.change;
};
}
export interface ShimPlugins extends NpPlugins {
uiMetric: {
createUiStatsReporter: typeof createUiStatsReporter;
};
}
export function createPublicShim(): { core: ShimCore; plugins: ShimPlugins } {
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = npStart.core.docLinks;
return {
core: {
...npStart.core,
documentation: {
esDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`,
esIndicesCreateIndex: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/indices-create-index.html#indices-create-index`,
esPluginDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/plugins/${DOC_LINK_VERSION}/`,
esQueryDsl: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/query-dsl.html`,
esStackOverviewDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack-overview/${DOC_LINK_VERSION}/`,
esTransform: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/${TRANSFORM_DOC_PATHS.transforms}`,
esTransformPivot: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/put-transform.html#put-transform-request-body`,
mlDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/`,
},
docTitle: {
change: docTitle.change,
},
},
plugins: {
...npStart.plugins,
uiMetric: {
createUiStatsReporter,
},
},
};
}

View file

@ -6,7 +6,7 @@
import { i18n } from '@kbn/i18n';
import { LICENSE_TYPE_BASIC, LicenseType } from '../../../common/constants';
import { LICENSE_TYPE_BASIC, LicenseType } from '../../../legacy/common/constants';
export const DEFAULT_REFRESH_INTERVAL_MS = 30000;
export const MINIMUM_REFRESH_INTERVAL_MS = 1000;

View file

@ -0,0 +1,40 @@
/*
* 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 interface MissingPrivileges {
[key: string]: string[] | undefined;
}
export interface Privileges {
hasAllPrivileges: boolean;
missingPrivileges: MissingPrivileges;
}
export type TransformId = string;
// reflects https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/dataframe/transforms/DataFrameTransformStats.java#L243
export enum TRANSFORM_STATE {
ABORTING = 'aborting',
FAILED = 'failed',
INDEXING = 'indexing',
STARTED = 'started',
STOPPED = 'stopped',
STOPPING = 'stopping',
}
export interface TransformEndpointRequest {
id: TransformId;
state?: TRANSFORM_STATE;
}
export interface ResultData {
success: boolean;
error?: any;
}
export interface TransformEndpointResult {
[key: string]: ResultData;
}

View file

@ -2,13 +2,15 @@
"id": "transform",
"version": "kibana",
"server": true,
"ui": false,
"ui": true,
"requiredPlugins": [
"data",
"home",
"licensing",
"management"
],
"optionalPlugins": [
"security",
"usageCollection"
],
"configPath": ["xpack", "transform"]

View file

@ -14,6 +14,6 @@ export const useRequest = jest.fn(() => ({
error: null,
data: undefined,
}));
export { mlInMemoryTableBasicFactory } from '../../../ml/public/application/components/ml_in_memory_table';
export { mlInMemoryTableBasicFactory } from '../../../../legacy/plugins/ml/public/application/components/ml_in_memory_table';
export const SORT_DIRECTION = { ASC: 'asc' };
export const KqlFilterBar = jest.fn(() => null);

View file

@ -14,7 +14,7 @@ import { SectionError } from './components';
import { CLIENT_BASE_PATH, SECTION_SLUG } from './constants';
import { getAppProviders } from './app_dependencies';
import { AuthorizationContext } from './lib/authorization';
import { AppDependencies } from '../shim';
import { AppDependencies } from './app_dependencies';
import { CloneTransformSection } from './sections/clone_transform';
import { CreateTransformSection } from './sections/create_transform';

View file

@ -0,0 +1,28 @@
/*
* 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.
*/
import { coreMock } from '../../../../../src/core/public/mocks';
import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks';
import { getAppProviders, AppDependencies } from './app_dependencies';
const coreSetup = coreMock.createSetup();
const coreStart = coreMock.createStart();
const dataStart = dataPluginMock.createStartContract();
const appDependencies: AppDependencies = {
chrome: coreStart.chrome,
data: dataStart,
docLinks: coreStart.docLinks,
i18n: coreStart.i18n,
notifications: coreStart.notifications,
uiSettings: coreStart.uiSettings,
savedObjects: coreStart.savedObjects,
overlays: coreStart.overlays,
http: coreSetup.http,
};
export const Providers = getAppProviders(appDependencies);

View file

@ -7,25 +7,39 @@
import React, { createContext, useContext, ReactNode } from 'react';
import { HashRouter } from 'react-router-dom';
import { CoreSetup, CoreStart } from 'src/core/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { API_BASE_PATH } from '../../common/constants';
import { setDependencyCache } from '../shared_imports';
import { AppDependencies } from '../shim';
import { AuthorizationProvider } from './lib/authorization';
export interface AppDependencies {
chrome: CoreStart['chrome'];
data: DataPublicPluginStart;
docLinks: CoreStart['docLinks'];
http: CoreSetup['http'];
i18n: CoreStart['i18n'];
notifications: CoreStart['notifications'];
uiSettings: CoreStart['uiSettings'];
savedObjects: CoreStart['savedObjects'];
overlays: CoreStart['overlays'];
}
let DependenciesContext: React.Context<AppDependencies>;
const setAppDependencies = (deps: AppDependencies) => {
const legacyBasePath = {
prepend: deps.core.http.basePath.prepend,
get: deps.core.http.basePath.get,
prepend: deps.http.basePath.prepend,
get: deps.http.basePath.get,
remove: () => {},
};
setDependencyCache({
autocomplete: deps.plugins.data.autocomplete,
docLinks: deps.core.docLinks,
autocomplete: deps.data.autocomplete,
docLinks: deps.docLinks,
basePath: legacyBasePath as any,
});
DependenciesContext = createContext<AppDependencies>(deps);
@ -40,24 +54,15 @@ export const useAppDependencies = () => {
return useContext<AppDependencies>(DependenciesContext);
};
export const useDocumentationLinks = () => {
const {
core: { documentation },
} = useAppDependencies();
return documentation;
};
export const useToastNotifications = () => {
const {
core: {
notifications: { toasts: toastNotifications },
},
notifications: { toasts: toastNotifications },
} = useAppDependencies();
return toastNotifications;
};
export const getAppProviders = (deps: AppDependencies) => {
const I18nContext = deps.core.i18n.Context;
const I18nContext = deps.i18n.Context;
// Create App dependencies context and get its provider
const AppDependenciesProvider = setAppDependencies(deps);

View file

@ -4,7 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { composeValidators, patternValidator } from '../../../../ml/common/util/validators';
import {
composeValidators,
patternValidator,
} from '../../../../../legacy/plugins/ml/common/util/validators';
export type AggName = string;

View file

@ -22,7 +22,6 @@ export {
useRefreshTransformList,
CreateRequestBody,
PreviewRequestBody,
TransformId,
TransformPivotConfig,
IndexName,
IndexPattern,
@ -35,7 +34,6 @@ export {
isTransformStats,
TransformStats,
TRANSFORM_MODE,
TRANSFORM_STATE,
} from './transform_stats';
export { getDiscoverUrl } from './navigation';
export {

View file

@ -5,7 +5,7 @@
*/
import { Dictionary } from '../../../common/types/common';
import { KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/common';
import { KBN_FIELD_TYPES } from '../../../../../../src/plugins/data/common';
import { AggName } from './aggregations';
import { EsFieldName } from './fields';

View file

@ -5,7 +5,7 @@
*/
import { Dictionary } from '../../../common/types/common';
import { KBN_FIELD_TYPES } from '../../../../../../../src/plugins/data/common';
import { KBN_FIELD_TYPES } from '../../../../../../src/plugins/data/common';
import { AggName } from './aggregations';
import { EsFieldName } from './fields';

View file

@ -12,7 +12,7 @@ import { SavedSearchQuery } from '../hooks/use_search_items';
import { StepDefineExposedState } from '../sections/create_transform/components/step_define/step_define_form';
import { StepDetailsExposedState } from '../sections/create_transform/components/step_details/step_details_form';
import { IndexPattern } from '../../../../../../../src/plugins/data/public';
import { IndexPattern } from '../../../../../../src/plugins/data/public';
import {
getEsAggFromAggConfig,

View file

@ -9,12 +9,13 @@ import { BehaviorSubject } from 'rxjs';
import { filter, distinctUntilChanged } from 'rxjs/operators';
import { Subscription } from 'rxjs';
import { TransformId } from '../../../common';
import { PivotAggDict } from './pivot_aggs';
import { PivotGroupByDict } from './pivot_group_by';
export type IndexName = string;
export type IndexPattern = string;
export type TransformId = string;
// Transform name must contain lowercase alphanumeric (a-z and 0-9), hyphens or underscores;
// It must also start and end with an alphanumeric character.

View file

@ -4,7 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { TransformId, TransformPivotConfig } from './transform';
import { TransformId } from '../../../common';
import { TransformPivotConfig } from './transform';
import { TransformStats } from './transform_stats';
// Used to pass on attribute names to table columns

View file

@ -4,18 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { TransformId } from './transform';
import { TransformListRow } from './transform_list';
import { TransformId, TRANSFORM_STATE } from '../../../common';
// reflects https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/dataframe/transforms/DataFrameTransformStats.java#L243
export enum TRANSFORM_STATE {
ABORTING = 'aborting',
FAILED = 'failed',
INDEXING = 'indexing',
STARTED = 'started',
STOPPED = 'stopped',
STOPPING = 'stopping',
}
import { TransformListRow } from './transform_list';
export enum TRANSFORM_MODE {
BATCH = 'batch',

View file

@ -7,8 +7,7 @@
import React from 'react';
import { render } from '@testing-library/react';
import { createPublicShim } from '../../shim';
import { getAppProviders } from '../app_dependencies';
import { Providers } from '../app_dependencies.mock';
import { ToastNotificationText } from './toast_notification_text';
@ -17,7 +16,6 @@ jest.mock('ui/new_platform');
describe('ToastNotificationText', () => {
test('should render the text as plain text', () => {
const Providers = getAppProviders(createPublicShim());
const props = {
text: 'a short text message',
};
@ -30,7 +28,6 @@ describe('ToastNotificationText', () => {
});
test('should render the text within a modal', () => {
const Providers = getAppProviders(createPublicShim());
const props = {
text:
'a text message that is longer than 140 characters. a text message that is longer than 140 characters. a text message that is longer than 140 characters. ',

View file

@ -18,16 +18,14 @@ import {
import { i18n } from '@kbn/i18n';
import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public';
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
import { useAppDependencies } from '../app_dependencies';
const MAX_SIMPLE_MESSAGE_LENGTH = 140;
export const ToastNotificationText: FC<{ text: any }> = ({ text }) => {
const {
core: { overlays },
} = useAppDependencies();
const { overlays } = useAppDependencies();
if (typeof text === 'string' && text.length <= MAX_SIMPLE_MESSAGE_LENGTH) {
return text;

View file

@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { PreviewRequestBody, TransformId } from '../../common';
import { TransformId, TransformEndpointRequest } from '../../../../common';
import { TransformEndpointRequest } from '../use_api_types';
import { PreviewRequestBody } from '../../common';
const apiFactory = () => ({
getTransforms(transformId?: TransformId): Promise<any> {

View file

@ -0,0 +1,63 @@
/*
* 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.
*/
import { TransformId, TransformEndpointRequest, TransformEndpointResult } from '../../../common';
import { API_BASE_PATH } from '../../../common/constants';
import { useAppDependencies } from '../app_dependencies';
import { PreviewRequestBody } from '../common';
import { EsIndex } from './use_api_types';
export const useApi = () => {
const { http } = useAppDependencies();
return {
getTransforms(transformId?: TransformId): Promise<any> {
const transformIdString = transformId !== undefined ? `/${transformId}` : '';
return http.get(`${API_BASE_PATH}transforms${transformIdString}`);
},
getTransformsStats(transformId?: TransformId): Promise<any> {
if (transformId !== undefined) {
return http.get(`${API_BASE_PATH}transforms/${transformId}/_stats`);
}
return http.get(`${API_BASE_PATH}transforms/_stats`);
},
createTransform(transformId: TransformId, transformConfig: any): Promise<any> {
return http.put(`${API_BASE_PATH}transforms/${transformId}`, {
body: JSON.stringify(transformConfig),
});
},
deleteTransforms(transformsInfo: TransformEndpointRequest[]): Promise<TransformEndpointResult> {
return http.post(`${API_BASE_PATH}delete_transforms`, {
body: JSON.stringify(transformsInfo),
});
},
getTransformsPreview(obj: PreviewRequestBody): Promise<any> {
return http.post(`${API_BASE_PATH}transforms/_preview`, { body: JSON.stringify(obj) });
},
startTransforms(transformsInfo: TransformEndpointRequest[]): Promise<TransformEndpointResult> {
return http.post(`${API_BASE_PATH}start_transforms`, {
body: JSON.stringify(transformsInfo),
});
},
stopTransforms(transformsInfo: TransformEndpointRequest[]): Promise<TransformEndpointResult> {
return http.post(`${API_BASE_PATH}stop_transforms`, {
body: JSON.stringify(transformsInfo),
});
},
getTransformAuditMessages(transformId: TransformId): Promise<any> {
return http.get(`${API_BASE_PATH}transforms/${transformId}/messages`);
},
esSearch(payload: any): Promise<any> {
return http.post(`${API_BASE_PATH}es_search`, { body: JSON.stringify(payload) });
},
getIndices(): Promise<EsIndex[]> {
return http.get(`/api/index_management/indices`);
},
};
};

View file

@ -3,4 +3,7 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { uiMetricService } from './ui_metric';
export interface EsIndex {
name: string;
}

View file

@ -7,14 +7,15 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { toMountPoint } from '../../../../../../../src/plugins/kibana_react/public';
import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
import { TransformEndpointRequest, TransformEndpointResult } from '../../../common';
import { useToastNotifications } from '../app_dependencies';
import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common';
import { ToastNotificationText } from '../components';
import { useApi } from './use_api';
import { TransformEndpointRequest, TransformEndpointResult } from './use_api_types';
export const useDeleteTransforms = () => {
const toastNotifications = useToastNotifications();

View file

@ -0,0 +1,24 @@
/*
* 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.
*/
import { useAppDependencies } from '../app_dependencies';
import { TRANSFORM_DOC_PATHS } from '../constants';
export const useDocumentationLinks = () => {
const deps = useAppDependencies();
const { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = deps.docLinks;
return {
esDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`,
esIndicesCreateIndex: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/indices-create-index.html#indices-create-index`,
esPluginDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/plugins/${DOC_LINK_VERSION}/`,
esQueryDsl: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/query-dsl.html`,
esStackOverviewDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/elastic-stack-overview/${DOC_LINK_VERSION}/`,
esTransform: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/${TRANSFORM_DOC_PATHS.transforms}`,
esTransformPivot: `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/put-transform.html#put-transform-request-body`,
mlDocBasePath: `${ELASTIC_WEBSITE_URL}guide/en/machine-learning/${DOC_LINK_VERSION}/`,
};
};

View file

@ -9,8 +9,6 @@ import { UseRequestConfig, useRequest as _useRequest } from '../../shared_import
import { useAppDependencies } from '../app_dependencies';
export const useRequest = (config: UseRequestConfig) => {
const {
core: { http },
} = useAppDependencies();
const { http } = useAppDependencies();
return _useRequest(http, config);
};

View file

@ -10,7 +10,7 @@ import {
esQuery,
IndexPatternsContract,
IndexPatternAttributes,
} from '../../../../../../../../src/plugins/data/public';
} from '../../../../../../../src/plugins/data/public';
import { matchAllQuery } from '../../common';

View file

@ -23,14 +23,14 @@ export const useSearchItems = (defaultSavedObjectId: string | undefined) => {
const [savedObjectId, setSavedObjectId] = useState(defaultSavedObjectId);
const appDeps = useAppDependencies();
const indexPatterns = appDeps.plugins.data.indexPatterns;
const uiSettings = appDeps.core.uiSettings;
const savedObjectsClient = appDeps.core.savedObjects.client;
const indexPatterns = appDeps.data.indexPatterns;
const uiSettings = appDeps.uiSettings;
const savedObjectsClient = appDeps.savedObjects.client;
const savedSearches = createSavedSearchesLoader({
savedObjectsClient,
indexPatterns,
chrome: appDeps.core.chrome,
overlays: appDeps.core.overlays,
chrome: appDeps.chrome,
overlays: appDeps.overlays,
});
const [searchItems, setSearchItems] = useState<SearchItems | undefined>(undefined);

View file

@ -6,11 +6,12 @@
import { i18n } from '@kbn/i18n';
import { TransformEndpointRequest, TransformEndpointResult } from '../../../common';
import { useToastNotifications } from '../app_dependencies';
import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common';
import { useApi } from './use_api';
import { TransformEndpointRequest, TransformEndpointResult } from './use_api_types';
export const useStartTransforms = () => {
const toastNotifications = useToastNotifications();

View file

@ -6,11 +6,12 @@
import { i18n } from '@kbn/i18n';
import { TransformEndpointRequest, TransformEndpointResult } from '../../../common';
import { useToastNotifications } from '../app_dependencies';
import { TransformListRow, refreshTransformList$, REFRESH_TRANSFORM_LIST_STATE } from '../common';
import { useApi } from './use_api';
import { TransformEndpointRequest, TransformEndpointResult } from './use_api_types';
export const useStopTransforms = () => {
const toastNotifications = useToastNotifications();

View file

@ -5,8 +5,12 @@
*/
import React, { createContext } from 'react';
import { Privileges } from '../../../../../common';
import { useRequest } from '../../../hooks';
import { hasPrivilegeFactory, Capabilities, Privileges } from './common';
import { hasPrivilegeFactory, Capabilities } from './common';
interface Authorization {
isLoading: boolean;

View file

@ -6,6 +6,8 @@
import { i18n } from '@kbn/i18n';
import { Privileges } from '../../../../../common';
export interface Capabilities {
canGetTransform: boolean;
canDeleteTransform: boolean;
@ -16,11 +18,6 @@ export interface Capabilities {
export type Privilege = [string, string];
export interface Privileges {
hasAllPrivileges: boolean;
missingPrivileges: MissingPrivileges;
}
function isPrivileges(arg: any): arg is Privileges {
return (
typeof arg === 'object' &&
@ -33,9 +30,6 @@ function isPrivileges(arg: any): arg is Privileges {
);
}
export interface MissingPrivileges {
[key: string]: string[] | undefined;
}
export const toArray = (value: string | string[]): string[] =>
Array.isArray(value) ? value : [value];

View file

@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { createCapabilityFailureMessage, Privileges } from './common';
export { createCapabilityFailureMessage } from './common';
export { AuthorizationProvider, AuthorizationContext } from './authorization_provider';
export { PrivilegesWrapper } from './with_privileges';
export { NotAuthorizedSection } from './not_authorized_section';

View file

@ -10,11 +10,13 @@ import { EuiPageContent } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { MissingPrivileges } from '../../../../../common';
import { SectionLoading } from '../../../components';
import { AuthorizationContext } from './authorization_provider';
import { NotAuthorizedSection } from './not_authorized_section';
import { hasPrivilegeFactory, toArray, MissingPrivileges, Privilege } from './common';
import { hasPrivilegeFactory, toArray, Privilege } from './common';
interface Props {
/**

View file

@ -22,11 +22,12 @@ import {
} from '@elastic/eui';
import { useApi } from '../../hooks/use_api';
import { useDocumentationLinks } from '../../hooks/use_documentation_links';
import { useSearchItems } from '../../hooks/use_search_items';
import { APP_CREATE_TRANSFORM_CLUSTER_PRIVILEGES } from '../../../../common/constants';
import { useAppDependencies, useDocumentationLinks } from '../../app_dependencies';
import { useAppDependencies } from '../../app_dependencies';
import { TransformPivotConfig } from '../../common';
import { breadcrumbService, docTitleService, BREADCRUMB_SECTION } from '../../services/navigation';
import { PrivilegesWrapper } from '../../lib/authorization';
@ -65,8 +66,8 @@ export const CloneTransformSection: FC<Props> = ({ match }) => {
const api = useApi();
const appDeps = useAppDependencies();
const savedObjectsClient = appDeps.core.savedObjects.client;
const indexPatterns = appDeps.plugins.data.indexPatterns;
const savedObjectsClient = appDeps.savedObjects.client;
const indexPatterns = appDeps.data.indexPatterns;
const { esTransform } = useDocumentationLinks();

Some files were not shown because too many files have changed in this diff Show more