Introduce I18nService core service and I18nContext. (#29379)

This commit is contained in:
Aleh Zasypkin 2019-02-04 13:38:00 +01:00 committed by GitHub
parent 7966b2ff78
commit d05437703d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
167 changed files with 3807 additions and 3894 deletions

View file

@ -163,7 +163,7 @@ import { i18n } from '@kbn/i18n';
export const HELLO_WORLD = i18n.translate('hello.wonderful.world', {
defaultMessage: 'Greetings, planet Earth!',
}),
});
```
One more example with a parameter:
@ -254,18 +254,7 @@ Optionally we can pass `description` prop into `FormattedMessage` component.
This prop is optional context comment that will be extracted by i18n tools
and added as a comment next to translation message at `defaultMessages.json`
In case when ReactJS component is rendered with the help of `reactDirective` AngularJS service, it's necessary to use React HOC `injectI18nProvider` to pass `intl` object to `FormattedMessage` component via context.
```js
import { injectI18nProvider } from '@kbn/i18n/react';
import { Header } from './components/header';
module.directive('headerGlobalNav', (reactDirective) => {
return reactDirective(injectI18nProvider(Header));
});
```
**NOTE:** To minimize the chance of having multiple `I18nProvider` components in the React tree, try to use `injectI18nProvider` or `I18nProvider` only to wrap the topmost component that you render, e.g. the one that's passed to `reactDirective` or `ReactDOM.render`.
**NOTE:** To minimize the chance of having multiple `I18nProvider` components in the React tree, try to use `I18nProvider` only to wrap the topmost component that you render, e.g. the one that's passed to `reactDirective` or `ReactDOM.render`.
### FormattedRelative

View file

@ -1,110 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`injectI18nProvider provides with context 1`] = `
Object {
"defaultFormats": Object {},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {
"date": Object {
"full": Object {
"day": "numeric",
"month": "long",
"weekday": "long",
"year": "numeric",
},
"long": Object {
"day": "numeric",
"month": "long",
"year": "numeric",
},
"medium": Object {
"day": "numeric",
"month": "short",
"year": "numeric",
},
"short": Object {
"day": "numeric",
"month": "numeric",
"year": "2-digit",
},
},
"number": Object {
"currency": Object {
"style": "currency",
},
"percent": Object {
"style": "percent",
},
},
"relative": Object {
"days": Object {
"units": "day",
},
"hours": Object {
"units": "hour",
},
"minutes": Object {
"units": "minute",
},
"months": Object {
"units": "month",
},
"seconds": Object {
"units": "second",
},
"years": Object {
"units": "year",
},
},
"time": Object {
"full": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"long": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
"timeZoneName": "short",
},
"medium": Object {
"hour": "numeric",
"minute": "numeric",
"second": "numeric",
},
"short": Object {
"hour": "numeric",
"minute": "numeric",
},
},
},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"onError": [Function],
"textComponent": Symbol(react.fragment),
"timeZone": null,
}
`;
exports[`injectI18nProvider renders children 1`] = `
<I18nProvider>
<ChildrenMock />
</I18nProvider>
`;

View file

@ -30,5 +30,4 @@ export {
} from 'react-intl';
export { I18nProvider } from './provider';
export { injectI18nProvider } from './inject_i18n_provider';
export { injectI18n } from './inject';

View file

@ -1,47 +0,0 @@
/*
* 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 { mount, shallow } from 'enzyme';
import * as React from 'react';
import { intlShape } from 'react-intl';
import { injectI18n } from './inject';
import { injectI18nProvider } from './inject_i18n_provider';
describe('injectI18nProvider', () => {
test('renders children', () => {
const ChildrenMock = () => null;
const Injected = injectI18nProvider(ChildrenMock);
expect(shallow(<Injected />)).toMatchSnapshot();
});
test('provides with context', () => {
const ChildrenMock = () => <div />;
const WithIntl = injectI18n(ChildrenMock);
const Injected = injectI18nProvider(WithIntl);
const wrapper = mount(<Injected />, {
childContextTypes: {
intl: intlShape,
},
});
expect(wrapper.find(ChildrenMock).prop('intl')).toMatchSnapshot();
});
});

View file

@ -20,6 +20,7 @@
import { BasePathService } from './base_path';
import { ChromeService } from './chrome';
import { FatalErrorsService } from './fatal_errors';
import { I18nService } from './i18n';
import { InjectedMetadataService } from './injected_metadata';
import { LegacyPlatformService } from './legacy_platform';
import { LoadingCountService } from './loading_count';
@ -57,6 +58,15 @@ jest.mock('./fatal_errors', () => ({
FatalErrorsService: MockFatalErrorsService,
}));
const mockI18nStartContract = {};
const MockI18nService = jest.fn<I18nService>(function _MockI18nService(this: any) {
this.start = jest.fn().mockReturnValue(mockI18nStartContract);
this.stop = jest.fn();
});
jest.mock('./i18n', () => ({
I18nService: MockI18nService,
}));
const mockNotificationStartContract = {};
const MockNotificationsService = jest.fn<NotificationsService>(function _MockNotificationsService(
this: any
@ -130,6 +140,7 @@ describe('constructor', () => {
expect(MockInjectedMetadataService).toHaveBeenCalledTimes(1);
expect(MockLegacyPlatformService).toHaveBeenCalledTimes(1);
expect(MockI18nService).toHaveBeenCalledTimes(1);
expect(MockFatalErrorsService).toHaveBeenCalledTimes(1);
expect(MockNotificationsService).toHaveBeenCalledTimes(1);
expect(MockLoadingCountService).toHaveBeenCalledTimes(1);
@ -265,6 +276,17 @@ describe('#stop', () => {
expect(uiSettings.stop).toHaveBeenCalled();
});
it('calls i18n.stop()', () => {
const coreSystem = new CoreSystem({
...defaultCoreSystemParams,
});
const [i18n] = MockI18nService.mock.instances;
expect(i18n.stop).not.toHaveBeenCalled();
coreSystem.stop();
expect(i18n.stop).toHaveBeenCalled();
});
it('clears the rootDomElement', () => {
const rootDomElement = document.createElement('div');
const coreSystem = new CoreSystem({
@ -333,18 +355,25 @@ describe('#start()', () => {
});
});
it('calls i18n#start()', () => {
startCore();
const [mockInstance] = MockI18nService.mock.instances;
expect(mockInstance.start).toHaveBeenCalledTimes(1);
expect(mockInstance.start).toHaveBeenCalledWith();
});
it('calls fatalErrors#start()', () => {
startCore();
const [mockInstance] = MockFatalErrorsService.mock.instances;
expect(mockInstance.start).toHaveBeenCalledTimes(1);
expect(mockInstance.start).toHaveBeenCalledWith();
expect(mockInstance.start).toHaveBeenCalledWith({ i18n: mockI18nStartContract });
});
it('calls notifications#start()', () => {
startCore();
const [mockInstance] = MockNotificationsService.mock.instances;
expect(mockInstance.start).toHaveBeenCalledTimes(1);
expect(mockInstance.start).toHaveBeenCalledWith();
expect(mockInstance.start).toHaveBeenCalledWith({ i18n: mockI18nStartContract });
});
it('calls chrome#start()', () => {

View file

@ -22,6 +22,7 @@ import './core.css';
import { BasePathService } from './base_path';
import { ChromeService } from './chrome';
import { FatalErrorsService } from './fatal_errors';
import { I18nService } from './i18n';
import { InjectedMetadataParams, InjectedMetadataService } from './injected_metadata';
import { LegacyPlatformParams, LegacyPlatformService } from './legacy_platform';
import { LoadingCountService } from './loading_count';
@ -50,6 +51,7 @@ export class CoreSystem {
private readonly uiSettings: UiSettingsService;
private readonly basePath: BasePathService;
private readonly chrome: ChromeService;
private readonly i18n: I18nService;
private readonly rootDomElement: HTMLElement;
private readonly notificationsTargetDomElement: HTMLDivElement;
@ -60,6 +62,8 @@ export class CoreSystem {
this.rootDomElement = rootDomElement;
this.i18n = new I18nService();
this.injectedMetadata = new InjectedMetadataService({
injectedMetadata,
});
@ -98,9 +102,10 @@ export class CoreSystem {
this.rootDomElement.appendChild(this.notificationsTargetDomElement);
this.rootDomElement.appendChild(this.legacyPlatformTargetDomElement);
const notifications = this.notifications.start();
const i18n = this.i18n.start();
const notifications = this.notifications.start({ i18n });
const injectedMetadata = this.injectedMetadata.start();
const fatalErrors = this.fatalErrors.start();
const fatalErrors = this.fatalErrors.start({ i18n });
const loadingCount = this.loadingCount.start({ fatalErrors });
const basePath = this.basePath.start({ injectedMetadata });
const uiSettings = this.uiSettings.start({
@ -112,6 +117,7 @@ export class CoreSystem {
const chrome = this.chrome.start();
this.legacyPlatform.start({
i18n,
injectedMetadata,
fatalErrors,
notifications,
@ -133,6 +139,7 @@ export class CoreSystem {
this.loadingCount.stop();
this.uiSettings.stop();
this.chrome.stop();
this.i18n.stop();
this.rootDomElement.textContent = '';
}
}

View file

@ -3,13 +3,13 @@
exports[`#add() deletes all children of rootDomElement and renders <FatalErrorScreen /> into it: fatal error screen component 1`] = `
Array [
Array [
<I18nProvider>
<React.Fragment>
<FatalErrorsScreen
buildNumber="kibanaBuildNumber"
errorInfo$={Rx.Observable}
kibanaVersion="kibanaVersion"
/>
</I18nProvider>,
</React.Fragment>,
<div />,
],
]
@ -20,3 +20,24 @@ exports[`#add() deletes all children of rootDomElement and renders <FatalErrorSc
<div />
</div>
`;
exports[`start.add() deletes all children of rootDomElement and renders <FatalErrorScreen /> into it: fatal error screen component 1`] = `
Array [
Array [
<I18nContext>
<FatalErrorsScreen
buildNumber="kibanaBuildNumber"
errorInfo$={Rx.Observable}
kibanaVersion="kibanaVersion"
/>
</I18nContext>,
<div />,
],
]
`;
exports[`start.add() deletes all children of rootDomElement and renders <FatalErrorScreen /> into it: fatal error screen container 1`] = `
<div>
<div />
</div>
`;

View file

@ -43,9 +43,16 @@ function setup() {
const stopCoreSystem = jest.fn();
const i18n: any = {
Context: function I18nContext() {
return '';
},
};
return {
rootDomElement,
injectedMetadata,
i18n,
stopCoreSystem,
fatalErrors: new FatalErrorsService({
injectedMetadata: injectedMetadata as any,
@ -91,25 +98,43 @@ describe('#add()', () => {
describe('start.add()', () => {
it('exposes a function that passes its two arguments to fatalErrors.add()', () => {
const { fatalErrors } = setup();
const { fatalErrors, i18n } = setup();
jest.spyOn(fatalErrors, 'add').mockImplementation(() => {
/* noop */
});
expect(fatalErrors.add).not.toHaveBeenCalled();
const { add } = fatalErrors.start();
const { add } = fatalErrors.start({ i18n });
add('foo', 'bar');
expect(fatalErrors.add).toHaveBeenCalledTimes(1);
expect(fatalErrors.add).toHaveBeenCalledWith('foo', 'bar');
});
it('deletes all children of rootDomElement and renders <FatalErrorScreen /> into it', () => {
const { fatalErrors, i18n, rootDomElement } = setup();
rootDomElement.innerHTML = `
<h1>Loading...</h1>
<div class="someSpinner"></div>
`;
expect(mockRender).not.toHaveBeenCalled();
expect(rootDomElement.children).toHaveLength(2);
const { add } = fatalErrors.start({ i18n });
expect(() => add(new Error('foo'))).toThrowError();
expect(rootDomElement).toMatchSnapshot('fatal error screen container');
expect(mockRender.mock.calls).toMatchSnapshot('fatal error screen component');
});
});
describe('start.get$()', () => {
it('provides info about the errors passed to fatalErrors.add()', () => {
const { fatalErrors } = setup();
const { fatalErrors, i18n } = setup();
const startContract = fatalErrors.start();
const startContract = fatalErrors.start({ i18n });
const onError = jest.fn();
startContract.get$().subscribe(onError);

View file

@ -22,20 +22,24 @@ import { render } from 'react-dom';
import * as Rx from 'rxjs';
import { first, tap } from 'rxjs/operators';
import { I18nStartContract } from '../i18n';
import { InjectedMetadataService } from '../injected_metadata';
import { FatalErrorsScreen } from './fatal_errors_screen';
import { ErrorInfo, getErrorInfo } from './get_error_info';
import { I18nProvider } from '@kbn/i18n/react';
export interface FatalErrorsParams {
rootDomElement: HTMLElement;
injectedMetadata: InjectedMetadataService;
stopCoreSystem: () => void;
}
interface Deps {
i18n: I18nStartContract;
}
export class FatalErrorsService {
private readonly errorInfo$ = new Rx.ReplaySubject<ErrorInfo>();
private i18n?: I18nStartContract;
constructor(private params: FatalErrorsParams) {
this.errorInfo$
@ -65,7 +69,9 @@ export class FatalErrorsService {
throw error;
};
public start() {
public start({ i18n }: Deps) {
this.i18n = i18n;
return {
add: this.add,
get$: () => {
@ -86,14 +92,18 @@ export class FatalErrorsService {
const container = document.createElement('div');
this.params.rootDomElement.appendChild(container);
// If error occurred before I18nService has been started we don't have any
// i18n context to provide.
const I18nContext = this.i18n ? this.i18n.Context : React.Fragment;
render(
<I18nProvider>
<I18nContext>
<FatalErrorsScreen
buildNumber={this.params.injectedMetadata.getKibanaBuildNumber()}
kibanaVersion={this.params.injectedMetadata.getKibanaVersion()}
errorInfo$={this.errorInfo$}
/>
</I18nProvider>,
</I18nContext>,
container
);
}

View file

@ -0,0 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`#start() returns \`Context\` component 1`] = `
<MockI18nProvider>
<MockEuiContext
i18n={
Object {
"mapping": Object {
"euiTablePagination.rowsPerPage": "Rows per page",
},
}
}
>
content
</MockEuiContext>
</MockI18nProvider>
`;

View file

@ -16,23 +16,40 @@
* specific language governing permissions and limitations
* under the License.
*/
import { shallow } from 'enzyme';
jest.mock('@elastic/eui', () => {
return {
EuiContext: function MockEuiContext() {
// no-op
},
};
});
jest.mock('@kbn/i18n/react', () => {
return {
I18nProvider: function MockI18nProvider() {
// no-op
},
};
});
import React from 'react';
import { I18nProvider } from './provider';
import { I18nService } from './i18n_service';
export function injectI18nProvider<P>(WrappedComponent: React.ComponentType<P>) {
const I18nProviderWrapper: React.SFC<P> = props => {
return (
<I18nProvider>
<WrappedComponent {...props} />
</I18nProvider>
);
};
afterEach(() => {
jest.clearAllMocks();
jest.resetModules();
});
// Original propTypes from the wrapped component should be re-exposed
// since it will be used by reactDirective Angular service
// that will rely on propTypes to watch attributes with these names
I18nProviderWrapper.propTypes = WrappedComponent.propTypes;
describe('#start()', () => {
it('returns `Context` component', () => {
const i18nService = new I18nService();
return I18nProviderWrapper;
}
const i18n = i18nService.start();
expect(shallow(<i18n.Context>content</i18n.Context>)).toMatchSnapshot();
});
});

View file

@ -0,0 +1,57 @@
/*
* 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 React from 'react';
import { EuiContext } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n/react';
/**
* Service that is responsible for i18n capabilities.
*/
export class I18nService {
public start() {
const mapping = {
'euiTablePagination.rowsPerPage': i18n.translate('core.euiTablePagination.rowsPerPage', {
defaultMessage: 'Rows per page',
}),
};
return {
/**
* I18n context is required by any localizable React component from @kbn/i18n and @elastic/eui packages
* and is supposed to be used as the topmost component for any i18n-compatible React tree.
*/
Context: function I18nContext({ children }: { children: React.ReactNode }) {
return (
<I18nProvider>
<EuiContext i18n={{ mapping }}>{children}</EuiContext>
</I18nProvider>
);
},
};
}
public stop() {
// nothing to do here currently
}
}
export type I18nStartContract = ReturnType<I18nService['start']>;

View file

@ -17,14 +17,4 @@
* under the License.
*/
import { uiModules } from 'ui/modules';
import {
I18nProvider,
i18nFilter,
i18nDirective,
} from '@kbn/i18n/angular';
uiModules.get('i18n')
.provider('i18n', I18nProvider)
.filter('i18n', i18nFilter)
.directive('i18nId', i18nDirective);
export { I18nService, I18nStartContract } from './i18n_service';

View file

@ -3,6 +3,7 @@
exports[`#start() load order useLegacyTestHarness = false loads ui/modules before ui/chrome, and both before legacy files 1`] = `
Array [
"ui/metadata",
"ui/i18n",
"ui/notify/fatal_error",
"ui/notify/toasts",
"ui/chrome/api/loading_count",
@ -22,6 +23,7 @@ Array [
exports[`#start() load order useLegacyTestHarness = true loads ui/modules before ui/test_harness, and both before legacy files 1`] = `
Array [
"ui/metadata",
"ui/i18n",
"ui/notify/fatal_error",
"ui/notify/toasts",
"ui/chrome/api/loading_count",

View file

@ -46,6 +46,14 @@ jest.mock('ui/test_harness', () => {
};
});
const mockI18nContextInit = jest.fn();
jest.mock('ui/i18n', () => {
mockLoadOrder.push('ui/i18n');
return {
__newPlatformInit__: mockI18nContextInit,
};
});
const mockFatalErrorInit = jest.fn();
jest.mock('ui/notify/fatal_error', () => {
mockLoadOrder.push('ui/notify/fatal_error');
@ -159,6 +167,7 @@ const basePathStartContract = {
const uiSettingsStartContract: any = {};
const chromeStartContract: any = {};
const i18nStartContract: any = { Context: () => '' };
const defaultParams = {
targetDomElement: document.createElement('div'),
@ -168,6 +177,7 @@ const defaultParams = {
};
const defaultStartDeps = {
i18n: i18nStartContract,
fatalErrors: fatalErrorsStartContract,
injectedMetadata: injectedMetadataStartContract,
notifications: notificationsStartContract,
@ -200,6 +210,17 @@ describe('#start()', () => {
expect(mockUiMetadataInit).toHaveBeenCalledWith(legacyMetadata);
});
it('passes i18n.Context to ui/i18n', () => {
const legacyPlatform = new LegacyPlatformService({
...defaultParams,
});
legacyPlatform.start(defaultStartDeps);
expect(mockI18nContextInit).toHaveBeenCalledTimes(1);
expect(mockI18nContextInit).toHaveBeenCalledWith(i18nStartContract.Context);
});
it('passes fatalErrors service to ui/notify/fatal_errors', () => {
const legacyPlatform = new LegacyPlatformService({
...defaultParams,

View file

@ -21,12 +21,14 @@ import angular from 'angular';
import { BasePathStartContract } from '../base_path';
import { ChromeStartContract } from '../chrome';
import { FatalErrorsStartContract } from '../fatal_errors';
import { I18nStartContract } from '../i18n';
import { InjectedMetadataStartContract } from '../injected_metadata';
import { LoadingCountStartContract } from '../loading_count';
import { NotificationsStartContract } from '../notifications';
import { UiSettingsClient } from '../ui_settings';
interface Deps {
i18n: I18nStartContract;
injectedMetadata: InjectedMetadataStartContract;
fatalErrors: FatalErrorsStartContract;
notifications: NotificationsStartContract;
@ -46,13 +48,14 @@ export interface LegacyPlatformParams {
* The LegacyPlatformService is responsible for initializing
* the legacy platform by injecting parts of the new platform
* services into the legacy platform modules, like ui/modules,
* and then bootstraping the ui/chrome or ui/test_harness to
* and then bootstrapping the ui/chrome or ui/test_harness to
* start either the app or browser tests.
*/
export class LegacyPlatformService {
constructor(private readonly params: LegacyPlatformParams) {}
public start({
i18n,
injectedMetadata,
fatalErrors,
notifications,
@ -64,6 +67,7 @@ export class LegacyPlatformService {
// Inject parts of the new platform into parts of the legacy platform
// so that legacy APIs/modules can mimic their new platform counterparts
require('ui/metadata').__newPlatformInit__(injectedMetadata.getLegacyMetadata());
require('ui/i18n').__newPlatformInit__(i18n.Context);
require('ui/notify/fatal_error').__newPlatformInit__(fatalErrors);
require('ui/notify/toasts').__newPlatformInit__(notifications.toasts);
require('ui/chrome/api/loading_count').__newPlatformInit__(loadingCount);

View file

@ -17,12 +17,17 @@
* under the License.
*/
import { I18nStartContract } from '../i18n';
import { ToastsService } from './toasts';
interface Params {
targetDomElement: HTMLElement;
}
interface Deps {
i18n: I18nStartContract;
}
export class NotificationsService {
private readonly toasts: ToastsService;
@ -35,11 +40,11 @@ export class NotificationsService {
});
}
public start() {
public start({ i18n }: Deps) {
this.params.targetDomElement.appendChild(this.toastsContainer);
return {
toasts: this.toasts.start(),
toasts: this.toasts.start({ i18n }),
};
}

View file

@ -3,7 +3,7 @@
exports[`#start() renders the GlobalToastList into the targetDomElement param 1`] = `
Array [
Array [
<I18nProvider>
<I18nContext>
<GlobalToastList
dismissToast={[Function]}
toasts$={
@ -21,7 +21,7 @@ Array [
}
}
/>
</I18nProvider>,
</I18nContext>,
<div
test="target-dom-element"
/>,

View file

@ -27,6 +27,12 @@ jest.mock('react-dom', () => ({
import { ToastsService } from './toasts_service';
import { ToastsStartContract } from './toasts_start_contract';
const mockI18nContract: any = {
Context: function I18nContext() {
return '';
},
};
describe('#start()', () => {
it('renders the GlobalToastList into the targetDomElement param', async () => {
const targetDomElement = document.createElement('div');
@ -34,7 +40,7 @@ describe('#start()', () => {
const toasts = new ToastsService({ targetDomElement });
expect(mockReactDomRender).not.toHaveBeenCalled();
toasts.start();
toasts.start({ i18n: mockI18nContract });
expect(mockReactDomRender.mock.calls).toMatchSnapshot();
});
@ -43,7 +49,7 @@ describe('#start()', () => {
targetDomElement: document.createElement('div'),
});
expect(toasts.start()).toBeInstanceOf(ToastsStartContract);
expect(toasts.start({ i18n: mockI18nContract })).toBeInstanceOf(ToastsStartContract);
});
});
@ -53,7 +59,7 @@ describe('#stop()', () => {
targetDomElement.setAttribute('test', 'target-dom-element');
const toasts = new ToastsService({ targetDomElement });
toasts.start();
toasts.start({ i18n: mockI18nContract });
expect(mockReactDomUnmount).not.toHaveBeenCalled();
toasts.stop();

View file

@ -21,7 +21,7 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { Toast } from '@elastic/eui';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nStartContract } from '../../i18n';
import { GlobalToastList } from './global_toast_list';
import { ToastsStartContract } from './toasts_start_contract';
@ -29,19 +29,23 @@ interface Params {
targetDomElement: HTMLElement;
}
interface Deps {
i18n: I18nStartContract;
}
export class ToastsService {
constructor(private readonly params: Params) {}
public start() {
public start({ i18n }: Deps) {
const toasts = new ToastsStartContract();
render(
<I18nProvider>
<i18n.Context>
<GlobalToastList
dismissToast={(toast: Toast) => toasts.remove(toast)}
toasts$={toasts.get$()}
/>
</I18nProvider>,
</i18n.Context>,
this.params.targetDomElement
);

View file

@ -127,7 +127,6 @@ export const TEMPORARILY_IGNORED_PATHS = [
'src/legacy/core_plugins/timelion/server/series_functions/__tests__/fixtures/tlConfig.js',
'src/fixtures/config_upgrade_from_4.0.0_to_4.0.1-snapshot.json',
'src/fixtures/vislib/mock_data/terms/_seriesMultiple.js',
'src/ui/i18n/__tests__/fixtures/translations/test_plugin_1/es-ES.json',
'src/ui/public/angular-bootstrap/accordion/accordion-group.html',
'src/ui/public/angular-bootstrap/bindHtml/bindHtml.js',
'src/ui/public/angular-bootstrap/tooltip/tooltip-html-unsafe-popup.html',

View file

@ -19,12 +19,11 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nContext } from 'ui/i18n';
import { InputControlVis } from './components/vis/input_control_vis';
import { controlFactory } from './control/control_factory';
import { getLineageMap } from './lineage';
import { I18nProvider } from '@kbn/i18n/react';
class VisController {
constructor(el, vis) {
this.el = el;
@ -52,7 +51,7 @@ class VisController {
drawVis = () => {
render(
<I18nProvider>
<I18nContext>
<InputControlVis
updateFiltersOnChange={this.vis.params.updateFiltersOnChange}
controls={this.controls}
@ -64,7 +63,7 @@ class VisController {
hasValues={this.hasValues}
refreshControl={this.refreshControl}
/>
</I18nProvider>,
</I18nContext>,
this.el);
}

View file

@ -22,6 +22,7 @@ import React from 'react';
import angular from 'angular';
import { uiModules } from 'ui/modules';
import chrome from 'ui/chrome';
import { wrapInI18nContext } from 'ui/i18n';
import { toastNotifications } from 'ui/notify';
import 'ui/search_bar';
@ -66,7 +67,7 @@ const app = uiModules.get('app/dashboard', [
]);
app.directive('dashboardViewportProvider', function (reactDirective) {
return reactDirective(DashboardViewportProvider);
return reactDirective(wrapInI18nContext(DashboardViewportProvider));
});
app.directive('dashboardApp', function ($injector) {

View file

@ -17,12 +17,12 @@
* under the License.
*/
import { injectI18nProvider } from '@kbn/i18n/react';
import './dashboard_app';
import './saved_dashboard/saved_dashboards';
import './dashboard_config';
import uiRoutes from 'ui/routes';
import chrome from 'ui/chrome';
import { wrapInI18nContext } from 'ui/i18n';
import { toastNotifications } from 'ui/notify';
import dashboardTemplate from './dashboard_app.html';
@ -43,7 +43,7 @@ const app = uiModules.get('app/dashboard', [
]);
app.directive('dashboardListing', function (reactDirective) {
return reactDirective(injectI18nProvider(DashboardListing));
return reactDirective(wrapInI18nContext(DashboardListing));
});
function createNewDashboardCtrl($scope, i18n) {

View file

@ -17,7 +17,7 @@
* under the License.
*/
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { DashboardAddPanel } from './add_panel';
import React from 'react';
import ReactDOM from 'react-dom';
@ -44,14 +44,14 @@ export function showAddPanel(addNewPanel, addNewVis, visTypes) {
document.body.appendChild(container);
const element = (
<I18nProvider>
<I18nContext>
<DashboardAddPanel
onClose={onClose}
visTypes={visTypes}
addNewPanel={addNewPanel}
addNewVis={addNewVisWithCleanup}
/>
</I18nProvider>
</I18nContext>
);
ReactDOM.render(element, container);
}

View file

@ -17,7 +17,7 @@
* under the License.
*/
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { DashboardCloneModal } from './clone_modal';
import React from 'react';
import ReactDOM from 'react-dom';
@ -39,7 +39,7 @@ export function showCloneModal(onClone, title) {
};
document.body.appendChild(container);
const element = (
<I18nProvider>
<I18nContext>
<DashboardCloneModal
onClone={onCloneConfirmed}
onClose={closeModal}
@ -48,7 +48,7 @@ export function showCloneModal(onClone, title) {
values: { title },
})}
/>
</I18nProvider>
</I18nContext>
);
ReactDOM.render(element, container);
}

View file

@ -19,7 +19,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { OptionsMenu } from './options';
@ -52,7 +52,7 @@ export function showOptionsPopover({
document.body.appendChild(container);
const element = (
<I18nProvider>
<I18nContext>
<EuiWrappingPopover
id="popover"
button={anchorElement}
@ -66,7 +66,7 @@ export function showOptionsPopover({
onHidePanelTitlesChange={onHidePanelTitlesChange}
/>
</EuiWrappingPopover>
</I18nProvider>
</I18nContext>
);
ReactDOM.render(element, container);
}

View file

@ -19,7 +19,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { I18nProvider } from '@kbn/i18n/react';
import { store } from '../../store';
import { Provider } from 'react-redux';
import { DashboardViewportContainer } from './dashboard_viewport_container';
@ -27,9 +26,7 @@ import { DashboardViewportContainer } from './dashboard_viewport_container';
export function DashboardViewportProvider(props) {
return (
<Provider store={store}>
<I18nProvider>
<DashboardViewportContainer {...props} />
</I18nProvider>
<DashboardViewportContainer {...props} />
</Provider>
);
}

View file

@ -21,7 +21,8 @@ import 'ngreact';
import React, { Fragment } from 'react';
import { uiModules } from 'ui/modules';
import chrome from 'ui/chrome';
import { FormattedMessage, injectI18nProvider } from '@kbn/i18n/react';
import { wrapInI18nContext } from 'ui/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiFlexGroup,
@ -95,4 +96,4 @@ const DiscoverFetchError = ({ fetchError }) => {
const app = uiModules.get('apps/discover', ['react']);
app.directive('discoverFetchError', reactDirective => reactDirective(injectI18nProvider(DiscoverFetchError)));
app.directive('discoverFetchError', reactDirective => reactDirective(wrapInI18nContext(DiscoverFetchError)));

View file

@ -18,8 +18,8 @@
*/
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
import { injectI18nProvider } from '@kbn/i18n/react';
import {
DiscoverNoResults,
@ -33,9 +33,9 @@ import './timechart';
const app = uiModules.get('apps/discover', ['react']);
app.directive('discoverNoResults', reactDirective => reactDirective(injectI18nProvider(DiscoverNoResults)));
app.directive('discoverNoResults', reactDirective => reactDirective(wrapInI18nContext(DiscoverNoResults)));
app.directive(
'discoverUnsupportedIndexPattern',
reactDirective => reactDirective(injectI18nProvider(DiscoverUnsupportedIndexPattern), ['unsupportedType'])
reactDirective => reactDirective(wrapInI18nContext(DiscoverUnsupportedIndexPattern), ['unsupportedType'])
);

View file

@ -20,7 +20,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { OpenSearchPanel } from './open_search_panel';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
let isOpen = false;
@ -39,12 +39,12 @@ export function showOpenSearchPanel({ makeUrl }) {
document.body.appendChild(container);
const element = (
<I18nProvider>
<I18nContext>
<OpenSearchPanel
onClose={onClose}
makeUrl={makeUrl}
/>
</I18nProvider>
</I18nContext>
);
ReactDOM.render(element, container);
}

View file

@ -31,7 +31,6 @@ import {
import { getTutorial } from '../load_tutorials';
import { replaceTemplateStrings } from './tutorial/replace_template_strings';
import chrome from 'ui/chrome';
import { I18nProvider } from '@kbn/i18n/react';
export function HomeApp({
directories,
@ -69,41 +68,39 @@ export function HomeApp({
};
return (
<I18nProvider>
<Router>
<Switch>
<Route
path="/home/tutorial/:id"
render={renderTutorial}
<Router>
<Switch>
<Route
path="/home/tutorial/:id"
render={renderTutorial}
/>
<Route
path="/home/tutorial_directory/:tab?"
render={renderTutorialDirectory}
/>
<Route
path="/home/feature_directory"
>
<FeatureDirectory
addBasePath={chrome.addBasePath}
directories={directories}
/>
<Route
path="/home/tutorial_directory/:tab?"
render={renderTutorialDirectory}
</Route>
<Route
path="/home"
>
<Home
addBasePath={chrome.addBasePath}
directories={directories}
apmUiEnabled={apmUiEnabled}
mlEnabled={mlEnabled}
find={savedObjectsClient.find}
localStorage={localStorage}
urlBasePath={chrome.getBasePath()}
/>
<Route
path="/home/feature_directory"
>
<FeatureDirectory
addBasePath={chrome.addBasePath}
directories={directories}
/>
</Route>
<Route
path="/home"
>
<Home
addBasePath={chrome.addBasePath}
directories={directories}
apmUiEnabled={apmUiEnabled}
mlEnabled={mlEnabled}
find={savedObjectsClient.find}
localStorage={localStorage}
urlBasePath={chrome.getBasePath()}
/>
</Route>
</Switch>
</Router>
</I18nProvider>
</Route>
</Switch>
</Router>
);
}

View file

@ -21,6 +21,7 @@ import chrome from 'ui/chrome';
import routes from 'ui/routes';
import template from './home_ng_wrapper.html';
import { FeatureCatalogueRegistryProvider } from 'ui/registry/feature_catalogue';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
import {
HomeApp
@ -30,7 +31,7 @@ import { i18n } from '@kbn/i18n';
const app = uiModules.get('apps/home', []);
app.directive('homeApp', function (reactDirective) {
return reactDirective(HomeApp);
return reactDirective(wrapInI18nContext(HomeApp));
});
const homeTitle = i18n.translate('kbn.home.breadcrumbs.homeTitle', { defaultMessage: 'Home' });

View file

@ -19,12 +19,13 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
import { FormattedMessage } from '@kbn/i18n/react';
import './sections';
import 'ui/filters/start_from';
import 'ui/field_editor';
import uiRoutes from 'ui/routes';
import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
import appTemplate from './app.html';
import landingTemplate from './landing.html';
@ -62,7 +63,7 @@ export function updateLandingPage(version) {
render(
<EuiPageContent horizontalPosition="center">
<I18nProvider>
<I18nContext>
<div>
<div className="eui-textCenter">
<EuiIcon type="managementApp" size="xxl" />
@ -95,7 +96,7 @@ export function updateLandingPage(version) {
</p>
</EuiText>
</div>
</I18nProvider>
</I18nContext>
</EuiPageContent>,
node,
);
@ -110,13 +111,13 @@ export function updateSidebar(
}
render(
<I18nProvider>
<I18nContext>
<SidebarNav
sections={items}
selectedId={id}
className="mgtSideNav"
/>
</I18nProvider>,
</I18nContext>,
node,
);
}

View file

@ -35,6 +35,10 @@ jest.mock('ui/chrome', () => ({
addBasePath: () => { },
}));
jest.mock('ui/i18n', () => ({
I18nContext: () => {},
}));
const { renderCreateIndexPatternWizard, destroyCreateIndexPatternWizard } = require('../render');
describe('CreateIndexPatternWizardRender', () => {

View file

@ -21,7 +21,7 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { CreateIndexPatternWizard } from './create_index_pattern_wizard';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
const CREATE_INDEX_PATTERN_DOM_ELEMENT_ID = 'createIndexPatternReact';
@ -35,12 +35,12 @@ export function renderCreateIndexPatternWizard(
}
render(
<I18nProvider>
<I18nContext>
<CreateIndexPatternWizard
initialQuery={initialQuery}
services={services}
/>
</I18nProvider>,
</I18nContext>,
node,
);
}

View file

@ -29,7 +29,7 @@ import { getEditFieldBreadcrumbs, getCreateFieldBreadcrumbs } from '../../breadc
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { FieldEditor } from 'ui/field_editor';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { i18n } from '@kbn/i18n';
const REACT_FIELD_EDITOR_ID = 'reactFieldEditor';
@ -47,7 +47,7 @@ const renderFieldEditor = ($scope, indexPattern, field, {
}
render(
<I18nProvider>
<I18nContext>
<FieldEditor
indexPattern={indexPattern}
field={field}
@ -59,7 +59,7 @@ const renderFieldEditor = ($scope, indexPattern, field, {
redirectAway,
}}
/>
</I18nProvider>,
</I18nContext>,
node,
);
});

View file

@ -33,9 +33,9 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { SourceFiltersTable } from './source_filters_table';
import { IndexedFieldsTable } from './indexed_fields_table';
import { ScriptedFieldsTable } from './scripted_fields_table';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import chrome from 'ui/chrome';
import { I18nContext } from 'ui/i18n';
import { getEditBreadcrumbs } from '../breadcrumbs';
@ -52,7 +52,7 @@ function updateSourceFiltersTable($scope, $state) {
}
render(
<I18nProvider>
<I18nContext>
<SourceFiltersTable
indexPattern={$scope.indexPattern}
filterFilter={$scope.fieldFilter}
@ -63,7 +63,7 @@ function updateSourceFiltersTable($scope, $state) {
$scope.$apply();
}}
/>
</I18nProvider>,
</I18nContext>,
node,
);
});
@ -87,7 +87,7 @@ function updateScriptedFieldsTable($scope, $state) {
}
render(
<I18nProvider>
<I18nContext>
<ScriptedFieldsTable
indexPattern={$scope.indexPattern}
fieldFilter={$scope.fieldFilter}
@ -104,7 +104,7 @@ function updateScriptedFieldsTable($scope, $state) {
$scope.refreshFilters();
}}
/>
</I18nProvider>,
</I18nContext>,
node,
);
});
@ -127,7 +127,7 @@ function updateIndexedFieldsTable($scope, $state) {
}
render(
<I18nProvider>
<I18nContext>
<IndexedFieldsTable
fields={$scope.fields}
indexPattern={$scope.indexPattern}
@ -142,7 +142,7 @@ function updateIndexedFieldsTable($scope, $state) {
getFieldInfo: $scope.getFieldInfo,
}}
/>
</I18nProvider>,
</I18nContext>,
node,
);
});

View file

@ -1,108 +1,102 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`IndexedFieldsTable should filter based on the query bar 1`] = `
<I18nProvider>
<div>
<Table
editField={[Function]}
indexPattern={
<div>
<Table
editField={[Function]}
indexPattern={
Object {
"getNonScriptedFields": [Function],
}
}
items={
Array [
Object {
"getNonScriptedFields": [Function],
}
}
items={
Array [
Object {
"displayName": "Elastic",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "Elastic",
"routes": undefined,
"searchable": true,
},
]
}
/>
</div>
</I18nProvider>
"displayName": "Elastic",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "Elastic",
"routes": undefined,
"searchable": true,
},
]
}
/>
</div>
`;
exports[`IndexedFieldsTable should filter based on the type filter 1`] = `
<I18nProvider>
<div>
<Table
editField={[Function]}
indexPattern={
<div>
<Table
editField={[Function]}
indexPattern={
Object {
"getNonScriptedFields": [Function],
}
}
items={
Array [
Object {
"getNonScriptedFields": [Function],
}
}
items={
Array [
Object {
"displayName": "timestamp",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "timestamp",
"routes": undefined,
"type": "date",
},
]
}
/>
</div>
</I18nProvider>
"displayName": "timestamp",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "timestamp",
"routes": undefined,
"type": "date",
},
]
}
/>
</div>
`;
exports[`IndexedFieldsTable should render normally 1`] = `
<I18nProvider>
<div>
<Table
editField={[Function]}
indexPattern={
<div>
<Table
editField={[Function]}
indexPattern={
Object {
"getNonScriptedFields": [Function],
}
}
items={
Array [
Object {
"getNonScriptedFields": [Function],
}
}
items={
Array [
Object {
"displayName": "Elastic",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "Elastic",
"routes": undefined,
"searchable": true,
},
Object {
"displayName": "timestamp",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "timestamp",
"routes": undefined,
"type": "date",
},
Object {
"displayName": "conflictingField",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "conflictingField",
"routes": undefined,
"type": "conflict",
},
]
}
/>
</div>
</I18nProvider>
"displayName": "Elastic",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "Elastic",
"routes": undefined,
"searchable": true,
},
Object {
"displayName": "timestamp",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "timestamp",
"routes": undefined,
"type": "date",
},
Object {
"displayName": "conflictingField",
"excluded": false,
"format": undefined,
"indexPattern": undefined,
"info": undefined,
"name": "conflictingField",
"routes": undefined,
"type": "conflict",
},
]
}
/>
</div>
`;

View file

@ -26,8 +26,6 @@ import {
getFieldFormat
} from './lib';
import { I18nProvider } from '@kbn/i18n/react';
export class IndexedFieldsTable extends Component {
static propTypes = {
fields: PropTypes.array.isRequired,
@ -102,15 +100,13 @@ export class IndexedFieldsTable extends Component {
const fields = this.getFilteredFields(this.state, this.props);
return (
<I18nProvider>
<div>
<Table
indexPattern={indexPattern}
items={fields}
editField={field => this.props.helpers.redirectToRoute(field, 'edit')}
/>
</div>
</I18nProvider>
<div>
<Table
indexPattern={indexPattern}
items={fields}
editField={field => this.props.helpers.redirectToRoute(field, 'edit')}
/>
</div>
);
}
}

View file

@ -1,196 +1,186 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ScriptedFieldsTable should filter based on the lang filter 1`] = `
<I18nProvider>
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={
Array [
"somethingElse",
]
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={
Array [
"somethingElse",
]
}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getScriptedFields": [Function],
}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
}
items={
Array [
Object {
"getScriptedFields": [Function],
}
}
items={
Array [
Object {
"lang": "painless",
"name": "ScriptedField",
"script": "x++",
},
Object {
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
/>
</div>
</I18nProvider>
"lang": "painless",
"name": "ScriptedField",
"script": "x++",
},
Object {
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
/>
</div>
`;
exports[`ScriptedFieldsTable should filter based on the query bar 1`] = `
<I18nProvider>
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getScriptedFields": [Function],
}
}
items={
Array [
Object {
"getScriptedFields": [Function],
}
}
items={
Array [
Object {
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
/>
</div>
</I18nProvider>
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
/>
</div>
`;
exports[`ScriptedFieldsTable should hide the table if there are no scripted fields 1`] = `
<I18nProvider>
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getScriptedFields": [Function],
}
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getScriptedFields": [Function],
}
items={Array []}
/>
</div>
</I18nProvider>
}
items={Array []}
/>
</div>
`;
exports[`ScriptedFieldsTable should render normally 1`] = `
<I18nProvider>
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getScriptedFields": [Function],
}
}
items={
Array [
Object {
"getScriptedFields": [Function],
}
}
items={
Array [
Object {
"lang": "painless",
"name": "ScriptedField",
"script": "x++",
},
Object {
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
/>
</div>
</I18nProvider>
"lang": "painless",
"name": "ScriptedField",
"script": "x++",
},
Object {
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
/>
</div>
`;
exports[`ScriptedFieldsTable should show a delete modal 1`] = `
<I18nProvider>
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
<div>
<header
addScriptedFieldUrl="#"
/>
<call-outs
deprecatedLangsInUse={Array []}
painlessDocLink="painlessDocs"
/>
<eui-spacer
size="l"
/>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getScriptedFields": [Function],
}
}
items={
Array [
Object {
"getScriptedFields": [Function],
}
}
items={
Array [
Object {
"lang": "painless",
"name": "ScriptedField",
"script": "x++",
},
Object {
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
"lang": "painless",
"name": "ScriptedField",
"script": "x++",
},
Object {
"lang": "painless",
"name": "JustATest",
"script": "z++",
},
]
}
/>
<eui-overlay-mask>
<eui-confirm-modal
cancelButtonText="Cancel"
confirmButtonText="Delete"
onCancel={[Function]}
onConfirm={[Function]}
title="Delete scripted field 'ScriptedField'?"
/>
<eui-overlay-mask>
<eui-confirm-modal
cancelButtonText="Cancel"
confirmButtonText="Delete"
onCancel={[Function]}
onConfirm={[Function]}
title="Delete scripted field 'ScriptedField'?"
/>
</eui-overlay-mask>
</div>
</I18nProvider>
</eui-overlay-mask>
</div>
`;

View file

@ -20,7 +20,7 @@
import React from 'react';
import { shallowWithIntl } from 'test_utils/enzyme_helpers';
import { ScriptedFieldsTableComponent } from '../scripted_fields_table';
import { ScriptedFieldsTable } from '../scripted_fields_table';
jest.mock('@elastic/eui', () => ({
EuiTitle: 'eui-title',
@ -71,7 +71,7 @@ const indexPattern = {
describe('ScriptedFieldsTable', () => {
it('should render normally', async () => {
const component = shallowWithIntl(
<ScriptedFieldsTableComponent
<ScriptedFieldsTable
indexPattern={indexPattern}
helpers={helpers}
/>
@ -87,7 +87,7 @@ describe('ScriptedFieldsTable', () => {
it('should filter based on the query bar', async () => {
const component = shallowWithIntl(
<ScriptedFieldsTableComponent
<ScriptedFieldsTable
indexPattern={indexPattern}
helpers={helpers}
/>
@ -106,7 +106,7 @@ describe('ScriptedFieldsTable', () => {
it('should filter based on the lang filter', async () => {
const component = shallowWithIntl(
<ScriptedFieldsTableComponent
<ScriptedFieldsTable
indexPattern={{
getScriptedFields: () => ([
{ name: 'ScriptedField', lang: 'painless', script: 'x++' },
@ -131,7 +131,7 @@ describe('ScriptedFieldsTable', () => {
it('should hide the table if there are no scripted fields', async () => {
const component = shallowWithIntl(
<ScriptedFieldsTableComponent
<ScriptedFieldsTable
indexPattern={{
getScriptedFields: () => ([])
}}
@ -149,7 +149,7 @@ describe('ScriptedFieldsTable', () => {
it('should show a delete modal', async () => {
const component = shallowWithIntl(
<ScriptedFieldsTableComponent
<ScriptedFieldsTable
indexPattern={indexPattern}
helpers={helpers}
/>
@ -166,7 +166,7 @@ describe('ScriptedFieldsTable', () => {
it('should delete a field', async () => {
const removeScriptedField = jest.fn();
const component = shallowWithIntl(
<ScriptedFieldsTableComponent
<ScriptedFieldsTable
indexPattern={{
...indexPattern,
removeScriptedField,

View file

@ -28,6 +28,7 @@ import {
EuiConfirmModal,
EUI_MODAL_CONFIRM_BUTTON,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import {
Table,
@ -35,9 +36,7 @@ import {
CallOuts,
} from './components';
import { I18nProvider, injectI18n } from '@kbn/i18n/react';
export class ScriptedFieldsTableComponent extends Component {
export class ScriptedFieldsTable extends Component {
static propTypes = {
indexPattern: PropTypes.object.isRequired,
fieldFilter: PropTypes.string,
@ -143,14 +142,12 @@ export class ScriptedFieldsTableComponent extends Component {
return null;
}
const { intl } = this.props;
const title = intl.formatMessage(
{ id: 'kbn.management.editIndexPattern.scripted.deleteFieldLabel', defaultMessage: 'Delete scripted field \'{fieldName}\'?' },
{ fieldName: fieldToDelete.name });
const cancelButtonText = intl.formatMessage(
{ id: 'kbn.management.editIndexPattern.scripted.deleteField.cancelButton', defaultMessage: 'Cancel' });
const confirmButtonText = intl.formatMessage(
{ id: 'kbn.management.editIndexPattern.scripted.deleteField.deleteButton', defaultMessage: 'Delete' });
const title = i18n.translate('kbn.management.editIndexPattern.scripted.deleteFieldLabel',
{ defaultMessage: 'Delete scripted field \'{fieldName}\'?', values: { fieldName: fieldToDelete.name } });
const cancelButtonText = i18n.translate('kbn.management.editIndexPattern.scripted.deleteField.cancelButton',
{ defaultMessage: 'Cancel' });
const confirmButtonText = i18n.translate('kbn.management.editIndexPattern.scripted.deleteField.deleteButton',
{ defaultMessage: 'Delete' });
return (
<EuiOverlayMask>
@ -175,26 +172,22 @@ export class ScriptedFieldsTableComponent extends Component {
const items = this.getFilteredItems();
return (
<I18nProvider>
<div>
<Header addScriptedFieldUrl={helpers.getRouteHref(indexPattern, 'addField')} />
<div>
<Header addScriptedFieldUrl={helpers.getRouteHref(indexPattern, 'addField')} />
{this.renderCallOuts()}
{this.renderCallOuts()}
<EuiSpacer size="l" />
<EuiSpacer size="l" />
<Table
indexPattern={indexPattern}
items={items}
editField={field => this.props.helpers.redirectToRoute(field, 'edit')}
deleteField={this.startDeleteField}
/>
<Table
indexPattern={indexPattern}
items={items}
editField={field => this.props.helpers.redirectToRoute(field, 'edit')}
deleteField={this.startDeleteField}
/>
{this.renderDeleteConfirmationModal()}
</div>
</I18nProvider>
{this.renderDeleteConfirmationModal()}
</div>
);
}
}
export const ScriptedFieldsTable = injectI18n(ScriptedFieldsTableComponent);

View file

@ -28,7 +28,7 @@ import indexTemplate from './index.html';
import { SavedObjectsClientProvider } from 'ui/saved_objects';
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
@ -48,13 +48,13 @@ export function updateIndexPatternList(
}
render(
<I18nProvider>
<I18nContext>
<IndexPatternList
indexPatternCreationOptions={indexPatternCreationOptions}
defaultIndex={defaultIndex}
indexPatterns={indexPatterns}
/>
</I18nProvider>,
</I18nContext>,
node,
);
}

View file

@ -19,17 +19,15 @@
import React from 'react';
import { CreateButton } from '../create_button';
import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
import { FormattedMessage } from '@kbn/i18n/react';
export const Header = ({
indexPatternCreationOptions
}) => (
<I18nProvider>
<CreateButton options={indexPatternCreationOptions}>
<FormattedMessage
id="kbn.management.indexPatternList.header.createIndexPatternButtonLabel"
defaultMessage="Create index pattern"
/>
</CreateButton>
</I18nProvider>
<CreateButton options={indexPatternCreationOptions}>
<FormattedMessage
id="kbn.management.indexPatternList.header.createIndexPatternButtonLabel"
defaultMessage="Create index pattern"
/>
</CreateButton>
);

View file

@ -28,7 +28,7 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { ObjectsTable } from './components/objects_table';
import { getInAppUrl } from './lib/get_in_app_url';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { getIndexBreadcrumbs } from './breadcrumbs';
@ -55,7 +55,7 @@ function updateObjectsTable($scope, $injector, i18n) {
}
render(
<I18nProvider>
<I18nContext>
<ObjectsTable
savedObjectsClient={savedObjectsClient}
services={services}
@ -84,7 +84,7 @@ function updateObjectsTable($scope, $injector, i18n) {
$scope.$apply();
}}
/>
</I18nProvider>,
</I18nContext>,
node,
);
});

View file

@ -1,501 +1,497 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AdvancedSettings should render normally 1`] = `
<I18nProvider>
<div>
<EuiFlexGroup
alignItems="stretch"
<div>
<EuiFlexGroup
alignItems="stretch"
component="div"
direction="row"
gutterSize="none"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<EuiFlexItem
component="div"
direction="row"
gutterSize="none"
justifyContent="flexStart"
responsive={true}
wrap={false}
grow={true}
>
<EuiFlexItem
component="div"
grow={true}
>
<advanced_settings_page_title />
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={true}
>
<Search
categories={
Array [
"general",
"elasticsearch",
]
}
onQueryChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [],
"_indexedClauses": Object {
"field": Object {},
"is": Object {},
"term": Array [],
},
},
"syntax": Object {
"parse": [Function],
"print": [Function],
},
"text": "",
}
}
/>
</EuiFlexItem>
</EuiFlexGroup>
<advanced_settings_page_subtitle />
<EuiSpacer
size="m"
/>
<CallOuts />
<EuiSpacer
size="m"
/>
<InjectIntl(FormUI)
categories={
Array [
"general",
"elasticsearch",
]
}
categoryCounts={
Object {
"elasticsearch": 2,
"general": 11,
<advanced_settings_page_title />
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={true}
>
<Search
categories={
Array [
"general",
"elasticsearch",
]
}
onQueryChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [],
"_indexedClauses": Object {
"field": Object {},
"is": Object {},
"term": Array [],
},
},
"syntax": Object {
"parse": [Function],
"print": [Function],
},
"text": "",
}
}
/>
</EuiFlexItem>
</EuiFlexGroup>
<advanced_settings_page_subtitle />
<EuiSpacer
size="m"
/>
<CallOuts />
<EuiSpacer
size="m"
/>
<InjectIntl(FormUI)
categories={
Array [
"general",
"elasticsearch",
]
}
categoryCounts={
Object {
"elasticsearch": 2,
"general": 11,
}
clear={[Function]}
clearQuery={[Function]}
save={[Function]}
settings={
Object {
"elasticsearch": Array [
Object {
"ariaName": "Test array setting",
"category": Array [
"elasticsearch",
],
"defVal": Array [
"default_value",
],
"description": "Description for Test array setting",
"displayName": "Test array setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:array:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "array",
"value": undefined,
},
Object {
"ariaName": "Test boolean setting",
"category": Array [
"elasticsearch",
],
"defVal": true,
"description": "Description for Test boolean setting",
"displayName": "Test boolean setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:boolean:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "boolean",
"value": undefined,
},
],
"general": Array [
Object {
"ariaName": "Test custom string setting",
"category": Array [
"general",
],
"defVal": null,
"description": "Description for Test custom string setting",
"displayName": "Test custom string setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:customstring:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
},
Object {
"ariaName": "Test image setting",
"category": Array [
"general",
],
"defVal": null,
"description": "Description for Test image setting",
"displayName": "Test image setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:image:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "image",
"value": undefined,
},
Object {
"ariaName": "An overridden json",
"category": Array [
"general",
],
"defVal": "{
}
clear={[Function]}
clearQuery={[Function]}
save={[Function]}
settings={
Object {
"elasticsearch": Array [
Object {
"ariaName": "Test array setting",
"category": Array [
"elasticsearch",
],
"defVal": Array [
"default_value",
],
"description": "Description for Test array setting",
"displayName": "Test array setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:array:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "array",
"value": undefined,
},
Object {
"ariaName": "Test boolean setting",
"category": Array [
"elasticsearch",
],
"defVal": true,
"description": "Description for Test boolean setting",
"displayName": "Test boolean setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:boolean:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "boolean",
"value": undefined,
},
],
"general": Array [
Object {
"ariaName": "Test custom string setting",
"category": Array [
"general",
],
"defVal": null,
"description": "Description for Test custom string setting",
"displayName": "Test custom string setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:customstring:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
},
Object {
"ariaName": "Test image setting",
"category": Array [
"general",
],
"defVal": null,
"description": "Description for Test image setting",
"displayName": "Test image setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:image:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "image",
"value": undefined,
},
Object {
"ariaName": "An overridden json",
"category": Array [
"general",
],
"defVal": "{
\\"foo\\": \\"bar\\"
}",
"description": "Description for overridden json",
"displayName": "An overridden json",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:json",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "json",
"value": undefined,
},
Object {
"ariaName": "An overridden number",
"category": Array [
"general",
],
"defVal": 1234,
"description": "Description for overridden number",
"displayName": "An overridden number",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:number",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "number",
"value": undefined,
},
Object {
"ariaName": "Test overridden select setting",
"category": Array [
"general",
],
"defVal": "orange",
"description": "Description for overridden select setting",
"displayName": "Test overridden select setting",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:select",
"optionLabels": undefined,
"options": Array [
"apple",
"orange",
"banana",
],
"readonly": false,
"type": "select",
"value": undefined,
},
Object {
"ariaName": "An overridden string",
"category": Array [
"general",
],
"defVal": "foo",
"description": "Description for overridden string",
"displayName": "An overridden string",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:string",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
},
Object {
"ariaName": "Test json setting",
"category": Array [
"general",
],
"defVal": "{\\"foo\\": \\"bar\\"}",
"description": "Description for Test json setting",
"displayName": "Test json setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:json:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "json",
"value": undefined,
},
Object {
"ariaName": "Test markdown setting",
"category": Array [
"general",
],
"defVal": "",
"description": "Description for Test markdown setting",
"displayName": "Test markdown setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:markdown:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "markdown",
"value": undefined,
},
Object {
"ariaName": "Test number setting",
"category": Array [
"general",
],
"defVal": 5,
"description": "Description for Test number setting",
"displayName": "Test number setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:number:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "number",
"value": undefined,
},
Object {
"ariaName": "Test select setting",
"category": Array [
"general",
],
"defVal": "orange",
"description": "Description for Test select setting",
"displayName": "Test select setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:select:setting",
"optionLabels": undefined,
"options": Array [
"apple",
"orange",
"banana",
],
"readonly": false,
"type": "select",
"value": undefined,
},
Object {
"ariaName": "Test string setting",
"category": Array [
"general",
],
"defVal": null,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:string:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
},
],
}
}
showNoResultsMessage={true}
/>
<advanced_settings_page_footer
onQueryMatchChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [],
"_indexedClauses": Object {
"field": Object {},
"is": Object {},
"term": Array [],
},
"description": "Description for overridden json",
"displayName": "An overridden json",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:json",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "json",
"value": undefined,
},
"syntax": Object {
"parse": [Function],
"print": [Function],
Object {
"ariaName": "An overridden number",
"category": Array [
"general",
],
"defVal": 1234,
"description": "Description for overridden number",
"displayName": "An overridden number",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:number",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "number",
"value": undefined,
},
"text": "",
}
Object {
"ariaName": "Test overridden select setting",
"category": Array [
"general",
],
"defVal": "orange",
"description": "Description for overridden select setting",
"displayName": "Test overridden select setting",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:select",
"optionLabels": undefined,
"options": Array [
"apple",
"orange",
"banana",
],
"readonly": false,
"type": "select",
"value": undefined,
},
Object {
"ariaName": "An overridden string",
"category": Array [
"general",
],
"defVal": "foo",
"description": "Description for overridden string",
"displayName": "An overridden string",
"isCustom": undefined,
"isOverridden": true,
"name": "test:isOverridden:string",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
},
Object {
"ariaName": "Test json setting",
"category": Array [
"general",
],
"defVal": "{\\"foo\\": \\"bar\\"}",
"description": "Description for Test json setting",
"displayName": "Test json setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:json:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "json",
"value": undefined,
},
Object {
"ariaName": "Test markdown setting",
"category": Array [
"general",
],
"defVal": "",
"description": "Description for Test markdown setting",
"displayName": "Test markdown setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:markdown:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "markdown",
"value": undefined,
},
Object {
"ariaName": "Test number setting",
"category": Array [
"general",
],
"defVal": 5,
"description": "Description for Test number setting",
"displayName": "Test number setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:number:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "number",
"value": undefined,
},
Object {
"ariaName": "Test select setting",
"category": Array [
"general",
],
"defVal": "orange",
"description": "Description for Test select setting",
"displayName": "Test select setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:select:setting",
"optionLabels": undefined,
"options": Array [
"apple",
"orange",
"banana",
],
"readonly": false,
"type": "select",
"value": undefined,
},
Object {
"ariaName": "Test string setting",
"category": Array [
"general",
],
"defVal": null,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:string:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
},
],
}
/>
</div>
</I18nProvider>
}
showNoResultsMessage={true}
/>
<advanced_settings_page_footer
onQueryMatchChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [],
"_indexedClauses": Object {
"field": Object {},
"is": Object {},
"term": Array [],
},
},
"syntax": Object {
"parse": [Function],
"print": [Function],
},
"text": "",
}
}
/>
</div>
`;
exports[`AdvancedSettings should render specific setting if given setting key 1`] = `
<I18nProvider>
<div>
<EuiFlexGroup
alignItems="stretch"
<div>
<EuiFlexGroup
alignItems="stretch"
component="div"
direction="row"
gutterSize="none"
justifyContent="flexStart"
responsive={true}
wrap={false}
>
<EuiFlexItem
component="div"
direction="row"
gutterSize="none"
justifyContent="flexStart"
responsive={true}
wrap={false}
grow={true}
>
<EuiFlexItem
component="div"
grow={true}
>
<advanced_settings_page_title />
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={true}
>
<Search
categories={
Array [
"general",
"elasticsearch",
]
}
onQueryChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
"_indexedClauses": Object {
"field": Object {
"ariaName": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
},
"is": Object {},
"term": Array [],
},
},
"syntax": Object {
"parse": [Function],
"print": [Function],
},
"text": "ariaName:\\"test string setting\\"",
}
}
/>
</EuiFlexItem>
</EuiFlexGroup>
<advanced_settings_page_subtitle />
<EuiSpacer
size="m"
/>
<CallOuts />
<EuiSpacer
size="m"
/>
<InjectIntl(FormUI)
categories={
Array [
"general",
"elasticsearch",
]
}
categoryCounts={
Object {
"elasticsearch": 2,
"general": 11,
<advanced_settings_page_title />
</EuiFlexItem>
<EuiFlexItem
component="div"
grow={true}
>
<Search
categories={
Array [
"general",
"elasticsearch",
]
}
}
clear={[Function]}
clearQuery={[Function]}
save={[Function]}
settings={
Object {
"general": Array [
Object {
"ariaName": "Test string setting",
"category": Array [
"general",
onQueryChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
"defVal": null,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:string:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
"_indexedClauses": Object {
"field": Object {
"ariaName": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
},
"is": Object {},
"term": Array [],
},
},
"syntax": Object {
"parse": [Function],
"print": [Function],
},
"text": "ariaName:\\"test string setting\\"",
}
}
/>
</EuiFlexItem>
</EuiFlexGroup>
<advanced_settings_page_subtitle />
<EuiSpacer
size="m"
/>
<CallOuts />
<EuiSpacer
size="m"
/>
<InjectIntl(FormUI)
categories={
Array [
"general",
"elasticsearch",
]
}
categoryCounts={
Object {
"elasticsearch": 2,
"general": 11,
}
}
clear={[Function]}
clearQuery={[Function]}
save={[Function]}
settings={
Object {
"general": Array [
Object {
"ariaName": "Test string setting",
"category": Array [
"general",
],
"defVal": null,
"description": "Description for Test string setting",
"displayName": "Test string setting",
"isCustom": undefined,
"isOverridden": false,
"name": "test:string:setting",
"optionLabels": undefined,
"options": undefined,
"readonly": false,
"type": "string",
"value": undefined,
},
],
}
}
showNoResultsMessage={true}
/>
<advanced_settings_page_footer
onQueryMatchChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
}
}
showNoResultsMessage={true}
/>
<advanced_settings_page_footer
onQueryMatchChange={[Function]}
query={
Query {
"ast": _AST {
"_clauses": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
"_indexedClauses": Object {
"field": Object {
"ariaName": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
},
"is": Object {},
"term": Array [],
"_indexedClauses": Object {
"field": Object {
"ariaName": Array [
Object {
"field": "ariaName",
"match": "must",
"operator": "eq",
"type": "field",
"value": "test string setting",
},
],
},
"is": Object {},
"term": Array [],
},
"syntax": Object {
"parse": [Function],
"print": [Function],
},
"text": "ariaName:\\"test string setting\\"",
}
},
"syntax": Object {
"parse": [Function],
"print": [Function],
},
"text": "ariaName:\\"test string setting\\"",
}
/>
</div>
</I18nProvider>
}
/>
</div>
`;

View file

@ -42,8 +42,6 @@ import {
} from './components/default_component_registry';
import { getSettingsComponent } from './components/component_registry';
import { I18nProvider } from '@kbn/i18n/react';
export class AdvancedSettings extends Component {
static propTypes = {
config: PropTypes.object.isRequired,
@ -155,36 +153,34 @@ export class AdvancedSettings extends Component {
const PageFooter = getSettingsComponent(PAGE_FOOTER_COMPONENT);
return (
<I18nProvider>
<div>
<EuiFlexGroup gutterSize="none">
<EuiFlexItem>
<PageTitle />
</EuiFlexItem>
<EuiFlexItem>
<Search
query={query}
categories={this.categories}
onQueryChange={this.onQueryChange}
/>
</EuiFlexItem>
</EuiFlexGroup>
<PageSubtitle />
<EuiSpacer size="m" />
<CallOuts />
<EuiSpacer size="m" />
<Form
settings={filteredSettings}
categories={this.categories}
categoryCounts={this.categoryCounts}
clearQuery={this.clearQuery}
save={this.saveConfig}
clear={this.clearConfig}
showNoResultsMessage={!footerQueryMatched}
/>
<PageFooter query={query} onQueryMatchChange={this.onFooterQueryMatchChange} />
</div>
</I18nProvider>
<div>
<EuiFlexGroup gutterSize="none">
<EuiFlexItem>
<PageTitle />
</EuiFlexItem>
<EuiFlexItem>
<Search
query={query}
categories={this.categories}
onQueryChange={this.onQueryChange}
/>
</EuiFlexItem>
</EuiFlexGroup>
<PageSubtitle />
<EuiSpacer size="m" />
<CallOuts />
<EuiSpacer size="m" />
<Form
settings={filteredSettings}
categories={this.categories}
categoryCounts={this.categoryCounts}
clearQuery={this.clearQuery}
save={this.saveConfig}
clear={this.clearConfig}
showNoResultsMessage={!footerQueryMatched}
/>
<PageFooter query={query} onQueryMatchChange={this.onFooterQueryMatchChange} />
</div>
);
}
}

View file

@ -20,6 +20,7 @@
import { management } from 'ui/management';
import uiRoutes from 'ui/routes';
import { uiModules } from 'ui/modules';
import { I18nContext } from 'ui/i18n';
import indexTemplate from './index.html';
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
@ -39,10 +40,12 @@ function updateAdvancedSettings($scope, config, query) {
}
render(
<AdvancedSettings
config={config}
query={query}
/>,
<I18nContext>
<AdvancedSettings
config={config}
query={query}
/>
</I18nContext>,
node,
);
});

View file

@ -17,10 +17,10 @@
* under the License.
*/
import { I18nProvider } from '@kbn/i18n/react';
import React from 'react';
import ReactDOM from 'react-dom';
import { Embeddable } from 'ui/embeddable';
import { I18nContext } from 'ui/i18n';
import { DisabledLabVisualization } from './disabled_lab_visualization';
export class DisabledLabEmbeddable extends Embeddable {
@ -34,9 +34,9 @@ export class DisabledLabEmbeddable extends Embeddable {
if (this.metadata.title) {
this.domNode = domNode;
ReactDOM.render(
<I18nProvider>
<I18nContext>
<DisabledLabVisualization title={this.metadata.title} />
</I18nProvider>,
</I18nContext>,
domNode
);
}

View file

@ -24,17 +24,17 @@ import { uiModules } from 'ui/modules';
import { timefilter } from 'ui/timefilter';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
import chrome from 'ui/chrome';
import { wrapInI18nContext } from 'ui/i18n';
import { VisualizeListingTable } from './visualize_listing_table';
import { NewVisModal } from '../wizard/new_vis_modal';
import { VisualizeConstants } from '../visualize_constants';
import { i18n } from '@kbn/i18n';
import { injectI18nProvider } from '@kbn/i18n/react';
const app = uiModules.get('app/visualize', ['ngRoute', 'react']);
app.directive('visualizeListingTable', reactDirective => reactDirective(injectI18nProvider(VisualizeListingTable)));
app.directive('newVisModal', reactDirective => reactDirective(injectI18nProvider(NewVisModal)));
app.directive('visualizeListingTable', reactDirective => reactDirective(wrapInI18nContext(VisualizeListingTable)));
app.directive('newVisModal', reactDirective => reactDirective(wrapInI18nContext(NewVisModal)));
export function VisualizeListingController($injector, createNewVis) {
const Notifier = $injector.get('Notifier');

View file

@ -17,7 +17,6 @@
* under the License.
*/
import { I18nProvider } from '@kbn/i18n/react';
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
@ -57,18 +56,14 @@ describe('NewVisModal', () => {
it('should render as expected', () => {
const wrapper = mountWithIntl(
<I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
</I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
);
expect(wrapper).toMatchSnapshot();
});
it('should show a button for regular visualizations', () => {
const wrapper = mountWithIntl(
<I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
</I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
);
expect(wrapper.find('[data-test-subj="visType-vis"]').exists()).toBe(true);
});
@ -77,9 +72,7 @@ describe('NewVisModal', () => {
it('should open the editor for visualizations without search', () => {
window.location.assign = jest.fn();
const wrapper = mountWithIntl(
<I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
</I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
);
const visButton = wrapper.find('button[data-test-subj="visType-vis"]');
visButton.simulate('click');
@ -89,14 +82,12 @@ describe('NewVisModal', () => {
it('passes through editor params to the editor URL', () => {
window.location.assign = jest.fn();
const wrapper = mountWithIntl(
<I18nProvider>
<NewVisModal
isOpen={true}
onClose={() => null}
visTypesRegistry={visTypes}
editorParams={['foo=true', 'bar=42']}
/>
</I18nProvider>
<NewVisModal
isOpen={true}
onClose={() => null}
visTypesRegistry={visTypes}
editorParams={['foo=true', 'bar=42']}
/>
);
const visButton = wrapper.find('button[data-test-subj="visType-vis"]');
visButton.simulate('click');
@ -107,9 +98,7 @@ describe('NewVisModal', () => {
describe('filter for visualization types', () => {
it('should render as expected', () => {
const wrapper = mountWithIntl(
<I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
</I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
);
const searchBox = wrapper.find('input[data-test-subj="filterVisType"]');
searchBox.simulate('change', { target: { value: 'with' } });
@ -121,9 +110,7 @@ describe('NewVisModal', () => {
it('should not show experimental visualizations if visualize:enableLabs is false', () => {
settingsGet.mockReturnValue(false);
const wrapper = mountWithIntl(
<I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
</I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
);
expect(wrapper.find('[data-test-subj="visType-visExp"]').exists()).toBe(false);
});
@ -131,9 +118,7 @@ describe('NewVisModal', () => {
it('should show experimental visualizations if visualize:enableLabs is true', () => {
settingsGet.mockReturnValue(true);
const wrapper = mountWithIntl(
<I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
</I18nProvider>
<NewVisModal isOpen={true} onClose={() => null} visTypesRegistry={visTypes} />
);
expect(wrapper.find('[data-test-subj="visType-visExp"]').exists()).toBe(true);
});

View file

@ -20,7 +20,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { VisType } from 'ui/vis';
import { NewVisModal } from './new_vis_modal';
@ -40,14 +40,14 @@ export function showNewVisModal(
document.body.appendChild(container);
const element = (
<I18nProvider>
<I18nContext>
<NewVisModal
isOpen={true}
onClose={onClose}
visTypesRegistry={visTypeRegistry}
editorParams={editorParams}
/>
</I18nProvider>
</I18nContext>
);
ReactDOM.render(element, container);
}

View file

@ -29,7 +29,6 @@ import brushHandler from '../lib/create_brush_handler';
import { extractIndexPatterns } from '../lib/extract_index_patterns';
import { fetchFields } from '../lib/fetch_fields';
import chrome from 'ui/chrome';
import { I18nProvider } from '@kbn/i18n/react';
const IS_DARK_THEME = chrome.getUiSettingsClient().get('theme:darkMode');
@ -116,19 +115,17 @@ class VisEditor extends Component {
return null;
}
return (
<I18nProvider>
<Visualization
dateFormat={this.props.config.get('dateFormat')}
reversed={IS_DARK_THEME}
onBrush={this.onBrush}
onUiState={this.handleUiState}
uiState={this.props.vis.getUiState()}
fields={this.state.visFields}
model={this.props.vis.params}
visData={this.props.visData}
getConfig={this.getConfig}
/>
</I18nProvider>
<Visualization
dateFormat={this.props.config.get('dateFormat')}
reversed={IS_DARK_THEME}
onBrush={this.onBrush}
onUiState={this.handleUiState}
uiState={this.props.vis.getUiState()}
fields={this.state.visFields}
model={this.props.vis.params}
visData={this.props.visData}
getConfig={this.getConfig}
/>
);
}

View file

@ -19,7 +19,7 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
function ReactEditorControllerProvider(Private, config) {
class ReactEditorController {
@ -32,7 +32,7 @@ function ReactEditorControllerProvider(Private, config) {
async render(params) {
const Component = this.vis.type.editorConfig.component;
render(
<I18nProvider>
<I18nContext>
<Component
config={config}
vis={this.vis}
@ -42,7 +42,7 @@ function ReactEditorControllerProvider(Private, config) {
isEditorMode={true}
appState={params.appState}
/>
</I18nProvider>,
</I18nContext>,
this.el);
}

View file

@ -19,7 +19,7 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import StatusApp from './status_app';
@ -33,12 +33,12 @@ export function renderStatusPage(buildNum, buildSha) {
}
render(
<I18nProvider>
<I18nContext>
<StatusApp
buildNum={buildNum}
buildSha={buildSha}
/>
</I18nProvider>,
</I18nContext>,
node,
);
}

View file

@ -24,7 +24,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import React from 'react';
import { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { Label } from './label';
import { FeedbackMessage } from './feedback_message';
@ -57,7 +57,7 @@ export class TagCloudVisualization {
this._feedbackNode = document.createElement('div');
this._containerNode.appendChild(this._feedbackNode);
this._feedbackMessage = React.createRef();
render(<I18nProvider><FeedbackMessage ref={this._feedbackMessage} /></I18nProvider>, this._feedbackNode);
render(<I18nContext><FeedbackMessage ref={this._feedbackMessage} /></I18nContext>, this._feedbackNode);
this._labelNode = document.createElement('div');
this._containerNode.appendChild(this._labelNode);

View file

@ -20,8 +20,8 @@
import { uiModules } from '../../../modules';
import { Header } from './components/header';
import { wrapInI18nContext } from 'ui/i18n';
import { chromeHeaderNavControlsRegistry } from 'ui/registry/chrome_header_nav_controls';
import { injectI18nProvider } from '@kbn/i18n/react';
const module = uiModules.get('kibana');
@ -30,7 +30,7 @@ module.directive('headerGlobalNav', (reactDirective, chrome, Private) => {
const navControls = Private(chromeHeaderNavControlsRegistry);
const homeHref = chrome.addBasePath('/app/kibana#/home');
return reactDirective(injectI18nProvider(Header), [
return reactDirective(wrapInI18nContext(Header), [
// scope accepted by directive, passed in as React props
'appTitle',
'isVisible',

View file

@ -32,7 +32,7 @@ import {
banners,
} from '../../notify';
import { SubUrlRouteFilterProvider } from './sub_url_route_filter';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from '../../i18n';
export function kbnChromeProvider(chrome, internals) {
@ -86,12 +86,12 @@ export function kbnChromeProvider(chrome, internals) {
// Banners
ReactDOM.render(
<I18nProvider>
<I18nContext>
<GlobalBannerList
banners={banners.list}
subscribe={banners.onChange}
/>
</I18nProvider>,
</I18nContext>,
document.getElementById('globalBannerList')
);

View file

@ -18,12 +18,12 @@
*/
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from '../modules';
import { FilterBar } from './filter_bar';
import { injectI18nProvider } from '@kbn/i18n/react';
const app = uiModules.get('app/kibana', ['react']);
app.directive('filterBar', reactDirective => {
return reactDirective(injectI18nProvider(FilterBar));
return reactDirective(wrapInI18nContext(FilterBar));
});

View file

@ -0,0 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ui/i18n renders children and forwards properties 1`] = `
<div>
Context:
<span>
Child: some prop:100500
</span>
</div>
`;

View file

@ -0,0 +1,54 @@
/*
* 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 { render } from 'enzyme';
import PropTypes from 'prop-types';
import React from 'react';
import { __newPlatformInit__, wrapInI18nContext } from '.';
describe('ui/i18n', () => {
test('renders children and forwards properties', () => {
__newPlatformInit__(({ children }) => <div>Context: {children}</div>);
const mockPropTypes = {
stringProp: PropTypes.string.isRequired,
numberProp: PropTypes.number,
};
const WrappedComponent = wrapInI18nContext(
class extends React.PureComponent<{ [P in keyof typeof mockPropTypes]: unknown }> {
public static propTypes = mockPropTypes;
public render() {
return (
<span>
Child: {this.props.stringProp}:{this.props.numberProp}
</span>
);
}
}
);
expect(WrappedComponent.propTypes).toBe(mockPropTypes);
expect(
render(<WrappedComponent stringProp={'some prop'} numberProp={100500} />)
).toMatchSnapshot();
});
});

View file

@ -0,0 +1,57 @@
/*
* 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 React from 'react';
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
// @ts-ignore
import { uiModules } from 'ui/modules';
import { I18nStartContract } from '../../../core/public/i18n';
export let I18nContext: I18nStartContract['Context'] = null!;
export function __newPlatformInit__(context: typeof I18nContext) {
if (I18nContext) {
throw new Error('ui/i18n already initialized with new platform apis');
}
I18nContext = context;
}
export function wrapInI18nContext<P>(ComponentToWrap: React.ComponentType<P>) {
const ContextWrapper: React.SFC<P> = props => {
return (
<I18nContext>
<ComponentToWrap {...props} />
</I18nContext>
);
};
// Original propTypes from the wrapped component should be re-exposed
// since it will be used by reactDirective Angular service
// that will rely on propTypes to watch attributes with these names
ContextWrapper.propTypes = ComponentToWrap.propTypes;
return ContextWrapper;
}
uiModules
.get('i18n')
.provider('i18n', I18nProvider)
.filter('i18n', i18nFilter)
.directive('i18nId', i18nDirective);

View file

@ -19,7 +19,6 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n/react';
import { FlyoutSession, openFlyout } from 'ui/flyout';
import { Adapters } from './types';
import { InspectorPanel } from './ui/inspector_panel';
@ -73,15 +72,10 @@ function open(adapters: Adapters, options: InspectorOptions = {}): InspectorSess
if an inspector can be shown.`);
}
return openFlyout(
<I18nProvider>
<InspectorPanel views={views} adapters={adapters} title={options.title} />
</I18nProvider>,
{
'data-test-subj': 'inspectorPanel',
closeButtonAriaLabel: closeButtonLabel,
}
);
return openFlyout(<InspectorPanel views={views} adapters={adapters} title={options.title} />, {
'data-test-subj': 'inspectorPanel',
closeButtonAriaLabel: closeButtonLabel,
});
}
const Inspector = {

View file

@ -20,15 +20,15 @@
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from '../../modules';
import { QueryBar } from '../components';
import { injectI18nProvider } from '@kbn/i18n/react';
const app = uiModules.get('app/kibana', ['react']);
app.directive('queryBar', (reactDirective, localStorage) => {
return reactDirective(
injectI18nProvider(QueryBar),
wrapInI18nContext(QueryBar),
undefined,
{},
{

View file

@ -19,7 +19,7 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
export function showSaveModal(saveModal) {
const container = document.createElement('div');
@ -46,5 +46,5 @@ export function showSaveModal(saveModal) {
}
);
ReactDOM.render(<I18nProvider>{element}</I18nProvider>, container);
ReactDOM.render(<I18nContext>{element}</I18nContext>, container);
}

View file

@ -18,15 +18,15 @@
*/
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from '../../modules';
import { SearchBar } from '../components';
import { injectI18nProvider } from '@kbn/i18n/react';
const app = uiModules.get('app/kibana', ['react']);
app.directive('searchBar', (reactDirective, localStorage) => {
return reactDirective(
injectI18nProvider(SearchBar),
wrapInI18nContext(SearchBar),
undefined,
{},
{

View file

@ -25,7 +25,7 @@ import { ShareActionProvider } from './share_action';
import { EuiWrappingPopover } from '@elastic/eui';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
let isOpen = false;
@ -66,7 +66,7 @@ export function showShareContextMenu({
document.body.appendChild(container);
const element = (
<I18nProvider>
<I18nContext>
<EuiWrappingPopover
id="sharePopover"
button={anchorElement}
@ -86,7 +86,7 @@ export function showShareContextMenu({
onClose={onClose}
/>
</EuiWrappingPopover>
</I18nProvider>
</I18nContext>
);
ReactDOM.render(element, container);
}

View file

@ -22,7 +22,7 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { uiModules } from '../../../modules';
import visOptionsTemplate from './vis_options.html';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
/**
* This directive sort of "transcludes" in whatever template you pass in via the `editor` attribute.
@ -55,9 +55,9 @@ uiModules
const renderReactComponent = () => {
const Component = $scope.editor;
render(
<I18nProvider>
<I18nContext>
<Component scope={$scope} editorState={$scope.editorState} stageEditorParams={stageEditorParams} />
</I18nProvider>, $el[0]);
</I18nContext>, $el[0]);
};
// Bind the `editor` template with the scope.
if (reactOptionsComponent) {

View file

@ -20,6 +20,7 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import chrome from '../../chrome';
import { I18nContext } from '../../i18n';
import { BaseVisTypeProvider } from './base_vis_type';
export function ReactVisTypeProvider(Private) {
@ -37,13 +38,16 @@ export function ReactVisTypeProvider(Private) {
return new Promise((resolve) => {
const Component = this.vis.type.visConfig.component;
const config = chrome.getUiSettingsClient();
render(<Component
config={config}
vis={this.vis}
visData={visData}
renderComplete={resolve}
updateStatus={updateStatus}
/>, this.el);
render(
<I18nContext>
<Component
config={config}
vis={this.vis}
visData={visData}
renderComplete={resolve}
updateStatus={updateStatus}
/>
</I18nContext>, this.el);
});
}

View file

@ -26,14 +26,14 @@ import LicenseChecker from './components/app/Main/LicenseChecker';
import { history } from './components/shared/Links/url_helpers';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
chrome.setRootTemplate(template);
const store = configureStore();
initTimepicker(history, store.dispatch).then(() => {
ReactDOM.render(
<I18nProvider>
<I18nContext>
<Provider store={store}>
<Fragment>
<GlobalProgress />
@ -43,7 +43,7 @@ initTimepicker(history, store.dispatch).then(() => {
</Router>
</Fragment>
</Provider>
</I18nProvider>,
</I18nContext>,
document.getElementById('react-apm-root')
);
});

View file

@ -6,10 +6,10 @@
import * as euiVars from '@elastic/eui/dist/eui_theme_k6_light.json';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n/react';
import React from 'react';
import { HashRouter } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';
import { I18nContext } from 'ui/i18n';
import { Provider as UnstatedProvider, Subscribe } from 'unstated';
import { BASE_PATH } from '../common/constants';
import { Background } from './components/layouts/background';
@ -25,7 +25,7 @@ async function startApp(libs: FrontendLibs) {
libs.framework.renderUIAtPath(
BASE_PATH,
<ThemeProvider theme={{ eui: euiVars }}>
<I18nProvider>
<I18nContext>
<HashRouter basename="/management/beats_management">
<UnstatedProvider inject={[new BeatsContainer(libs), new TagsContainer(libs)]}>
<BreadcrumbProvider useGlobalBreadcrumbs={libs.framework.versionGreaterThen('6.7.0')}>
@ -44,7 +44,7 @@ async function startApp(libs: FrontendLibs) {
</BreadcrumbProvider>
</UnstatedProvider>
</HashRouter>
</I18nProvider>
</I18nContext>
</ThemeProvider>,
libs.framework.versionGreaterThen('6.7.0') ? 'management' : 'self'
);

View file

@ -3,7 +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.
*/
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
@ -14,13 +14,13 @@ import { ccrStore } from './store';
export const renderReact = async (elem) => {
render(
<I18nProvider>
<I18nContext>
<Provider store={ccrStore}>
<HashRouter>
<App />
</HashRouter>
</Provider>
</I18nProvider>,
</I18nContext>,
elem
);
};

View file

@ -9,7 +9,7 @@ import 'plugins/grokdebugger/services/grokdebugger';
import { GrokDebugger } from '../../components/grok_debugger';
import { render } from 'react-dom';
import React from 'react';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
const app = uiModules.get('xpack/grokdebugger');
@ -19,7 +19,7 @@ app.directive('grokdebugger', function ($injector) {
return {
restrict: 'E',
link: (scope, el) => {
render(<I18nProvider><GrokDebugger grokdebuggerService={grokdebuggerService} /></I18nProvider>, el[0]);
render(<I18nContext><GrokDebugger grokdebuggerService={grokdebuggerService} /></I18nContext>, el[0]);
}
};
});

View file

@ -12,7 +12,7 @@ import chrome from 'ui/chrome';
import { App } from './app';
import { BASE_PATH } from '../common/constants';
import { indexLifecycleManagementStore } from './store';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { setUrlService } from './services/navigation';
import routes from 'ui/routes';
@ -22,11 +22,11 @@ import { manageAngularLifecycle } from './services/manage_angular_lifecycle';
let elem;
const renderReact = async (elem) => {
render(
<I18nProvider>
<I18nContext>
<Provider store={indexLifecycleManagementStore()}>
<App />
</Provider>
</I18nProvider>,
</I18nContext>,
elem
);
};

View file

@ -9,7 +9,6 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { Provider } from 'react-redux';
import { HashRouter } from 'react-router-dom';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n/react';
import { setHttpClient } from './services/api';
import { setUrlService } from './services/navigation';
@ -17,6 +16,7 @@ import { App } from './app';
import { BASE_PATH } from '../common/constants/base_path';
import routes from 'ui/routes';
import { I18nContext } from 'ui/i18n';
import { MANAGEMENT_BREADCRUMB } from 'ui/management';
import template from './main.html';
@ -26,13 +26,13 @@ import { indexManagementStore } from './store';
let elem;
const renderReact = async (elem) => {
render(
<I18nProvider>
<I18nContext>
<Provider store={indexManagementStore()}>
<HashRouter>
<App />
</HashRouter>
</Provider>
</I18nProvider>,
</I18nContext>,
elem
);
};

View file

@ -17,7 +17,7 @@ import { ThemeProvider } from 'styled-components';
import { EuiErrorBoundary } from '@elastic/eui';
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { InfraFrontendLibs } from '../lib/lib';
import { PageRouter } from '../routes';
import { createStore } from '../store';
@ -32,7 +32,7 @@ export async function startApp(libs: InfraFrontendLibs) {
});
libs.framework.render(
<I18nProvider>
<I18nContext>
<EuiErrorBoundary>
<ConstateProvider devtools>
<ReduxStoreProvider store={store}>
@ -49,6 +49,6 @@ export async function startApp(libs: InfraFrontendLibs) {
</ReduxStoreProvider>
</ConstateProvider>
</EuiErrorBoundary>
</I18nProvider>
</I18nContext>
);
}

View file

@ -9,7 +9,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { Provider } from 'react-redux';
import { HashRouter } from 'react-router-dom';
import { setTelemetryOptInService, setTelemetryEnabled, setHttpClient, TelemetryOptInProvider } from './lib/telemetry';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import chrome from 'ui/chrome';
import App from './app';
@ -24,13 +24,13 @@ import { getDashboardBreadcrumbs, getUploadBreadcrumbs } from './breadcrumbs';
const renderReact = (elem, store) => {
render(
<I18nProvider>
<I18nContext>
<Provider store={store}>
<HashRouter>
<App />
</HashRouter>
</Provider>
</I18nProvider>,
</I18nContext>,
elem
);
};

View file

@ -9,7 +9,7 @@ import { render } from 'react-dom';
import { isEmpty } from 'lodash';
import { uiModules } from 'ui/modules';
import { Notifier, toastNotifications } from 'ui/notify';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { PipelineEditor } from '../../../../components/pipeline_editor';
import 'plugins/logstash/services/license';
import 'plugins/logstash/services/security';
@ -37,7 +37,7 @@ app.directive('pipelineEdit', function ($injector) {
: null;
render(
<I18nProvider>
<I18nContext>
<PipelineEditor
kbnUrl={kbnUrl}
close={close}
@ -51,7 +51,7 @@ app.directive('pipelineEdit', function ($injector) {
licenseService={licenseService}
notifier={new Notifier({ location: 'Logstash' })}
/>
</I18nProvider>,
</I18nContext>,
el[0]
);
},

View file

@ -8,7 +8,7 @@ import React from 'react';
import { render } from 'react-dom';
import { isEmpty } from 'lodash';
import { uiModules } from 'ui/modules';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { UpgradeFailure } from '../../../../components/upgrade_failure';
const app = uiModules.get('xpack/logstash');
@ -30,14 +30,14 @@ app.directive('upgradeFailure', $injector => {
const isManualUpgrade = !!$route.current.params.retry;
render(
<I18nProvider>
<I18nContext>
<UpgradeFailure
isNewPipeline={isNewPipeline}
isManualUpgrade={isManualUpgrade}
onRetry={onRetry}
onClose={onClose}
/>
</I18nProvider>,
</I18nContext>,
el[0]
);
},

View file

@ -8,7 +8,7 @@ import React from 'react';
import { render } from 'react-dom';
import { uiModules } from 'ui/modules';
import { toastNotifications } from 'ui/notify';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { PipelineList } from '../../../../components/pipeline_list';
import 'plugins/logstash/services/pipelines';
import 'plugins/logstash/services/license';
@ -34,7 +34,7 @@ app.directive('pipelineList', function ($injector) {
const clonePipeline = id =>
scope.$evalAsync(kbnUrl.change(`management/logstash/pipelines/pipeline/${id}/edit?clone`));
render(
<I18nProvider>
<I18nContext>
<PipelineList
clonePipeline={clonePipeline}
clusterService={clusterService}
@ -48,7 +48,7 @@ app.directive('pipelineList', function ($injector) {
pipelinesService={pipelinesService}
toastNotifications={toastNotifications}
/>
</I18nProvider>,
</I18nContext>,
el[0]
);
},

View file

@ -6,7 +6,7 @@
import chrome from 'ui/chrome';
import React from 'react';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { render, unmountComponentAtNode } from 'react-dom';
import { uiModules } from 'ui/modules';
import { timefilter } from 'ui/timefilter';
@ -142,9 +142,9 @@ app.controller('GisMapController', ($scope, $route, config, kbnUrl, localStorage
const root = document.getElementById(REACT_ANCHOR_DOM_ELEMENT_ID);
render(
<Provider store={store}>
<I18nProvider>
<I18nContext>
<GisMap/>
</I18nProvider>
</I18nContext>
</Provider>,
root
);

View file

@ -23,7 +23,7 @@ const module = uiModules.get('apps/ml');
import chrome from 'ui/chrome';
const mlAnnotationsEnabled = chrome.getInjected('mlAnnotationsEnabled', false);
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
module.directive('mlAnnotationTable', function () {
@ -41,9 +41,9 @@ module.directive('mlAnnotationTable', function () {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(AnnotationsTable, props)}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

View file

@ -7,9 +7,9 @@
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
import { timefilter } from 'ui/timefilter';
import { injectI18nProvider } from '@kbn/i18n/react';
const module = uiModules.get('apps/ml', ['react']);
import { AnomaliesTable } from './anomalies_table';
@ -18,7 +18,7 @@ module.directive('mlAnomaliesTable', function ($injector) {
const reactDirective = $injector.get('reactDirective');
return reactDirective(
injectI18nProvider(AnomaliesTable),
wrapInI18nContext(AnomaliesTable),
[
['filter', { watchDepth: 'reference' }],
['tableData', { watchDepth: 'reference' }]

View file

@ -7,13 +7,13 @@
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { stateFactoryProvider } from 'plugins/ml/factories/state_factory';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
import { SelectSeverity, mlSelectSeverityService } from './select_severity';
import { injectI18nProvider } from '@kbn/i18n/react';
module.service('mlSelectSeverityService', function (Private, i18n) {
const stateFactory = Private(stateFactoryProvider);
@ -29,7 +29,7 @@ module.service('mlSelectSeverityService', function (Private, i18n) {
const reactDirective = $injector.get('reactDirective');
return reactDirective(
injectI18nProvider(SelectSeverity),
wrapInI18nContext(SelectSeverity),
undefined,
{ restrict: 'E' },
);

View file

@ -10,7 +10,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { FieldTitleBar } from './field_title_bar';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml');
@ -33,9 +33,9 @@ module.directive('mlFieldTitleBar', function () {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(FieldTitleBar, props)}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

View file

@ -10,7 +10,7 @@ import React from 'react';
import ReactDOM from 'react-dom';
import { FieldTypeIcon } from './field_type_icon.js';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml');
@ -35,9 +35,9 @@ module.directive('mlFieldTypeIcon', function () {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(FieldTypeIcon, props)}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

View file

@ -9,16 +9,16 @@
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
import { ValidateJob } from './validate_job_view';
import { mlJobService } from 'plugins/ml/services/job_service';
import { injectI18nProvider } from '@kbn/i18n/react';
module.directive('mlValidateJob', function (reactDirective) {
return reactDirective(
injectI18nProvider(ValidateJob),
wrapInI18nContext(ValidateJob),
undefined,
{ restrict: 'E' },
{ mlJobService }

View file

@ -6,8 +6,7 @@
import 'ngreact';
import { injectI18nProvider } from '@kbn/i18n/react';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
@ -35,5 +34,5 @@ import { DatavisualizerSelector } from './datavisualizer_selector';
module.directive('datavisualizerSelector', function ($injector) {
const reactDirective = $injector.get('reactDirective');
return reactDirective(injectI18nProvider(DatavisualizerSelector), undefined, { restrict: 'E' }, { });
return reactDirective(wrapInI18nContext(DatavisualizerSelector), undefined, { restrict: 'E' }, { });
});

View file

@ -16,7 +16,7 @@ import { Explorer } from './explorer';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml');
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { mapScopeToProps } from './explorer_utils';
import { EXPLORER_ACTION } from './explorer_constants';
@ -25,7 +25,7 @@ import { mlExplorerDashboardService } from './explorer_dashboard_service';
module.directive('mlExplorerReactWrapper', function () {
function link(scope, element) {
ReactDOM.render(
<I18nProvider>{React.createElement(Explorer, mapScopeToProps(scope))}</I18nProvider>,
<I18nContext>{React.createElement(Explorer, mapScopeToProps(scope))}</I18nContext>,
element[0]
);

View file

@ -6,8 +6,8 @@
import 'ngreact';
import { injectI18nProvider } from '@kbn/i18n/react';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
@ -42,5 +42,5 @@ module.directive('fileDatavisualizerPage', function ($injector) {
const indexPatterns = $injector.get('indexPatterns');
const kibanaConfig = $injector.get('config');
return reactDirective(injectI18nProvider(FileDataVisualizerPage), undefined, { restrict: 'E' }, { indexPatterns, kibanaConfig });
return reactDirective(wrapInI18nContext(FileDataVisualizerPage), undefined, { restrict: 'E' }, { indexPatterns, kibanaConfig });
});

View file

@ -36,7 +36,7 @@ uiRoutes
});
import { JobsPage } from './jobs';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
module.directive('jobsPage', function () {
return {
@ -44,9 +44,9 @@ module.directive('jobsPage', function () {
restrict: 'E',
link: (scope, element) => {
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(JobsPage, { angularWrapperScope: scope })}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

View file

@ -8,15 +8,15 @@
import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
import { EnableModelPlotCallout } from './enable_model_plot_callout_view.js';
import { injectI18nProvider } from '@kbn/i18n/react';
module.directive('mlEnableModelPlotCallout', function (reactDirective) {
return reactDirective(
injectI18nProvider(
wrapInI18nContext(
EnableModelPlotCallout,
undefined,
{ restrict: 'E' }

View file

@ -11,7 +11,7 @@ import { BucketSpanEstimator } from './bucket_span_estimator_view';
import { EVENT_RATE_COUNT_FIELD } from 'plugins/ml/jobs/new_job/simple/components/constants/general';
import { ml } from 'plugins/ml/services/ml_api_service';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml');
@ -138,9 +138,9 @@ module.directive('mlBucketSpanEstimator', function (i18n) {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(BucketSpanEstimator, props)}
</I18nProvider>,
</I18nContext>,
$element[0]
);
}

View file

@ -11,7 +11,7 @@ import { EnableModelPlotCheckbox } from './enable_model_plot_checkbox_view.js';
import { ml } from '../../../../../services/ml_api_service';
import { checkCardinalitySuccess } from '../../../utils/new_job_utils';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml');
@ -142,9 +142,9 @@ module.directive('mlEnableModelPlotCheckbox', function (i18n) {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(EnableModelPlotCheckbox, props)}
</I18nProvider>,
</I18nContext>,
$element[0]
);
}

View file

@ -19,7 +19,7 @@ import { getCreateCalendarBreadcrumbs, getEditCalendarBreadcrumbs } from '../../
import uiRoutes from 'ui/routes';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
const template = `
<ml-nav-menu name="settings" />
@ -63,9 +63,9 @@ module.directive('mlNewCalendar', function ($route) {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(NewCalendar, props)}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

View file

@ -19,7 +19,7 @@ import { getCalendarManagementBreadcrumbs } from '../../breadcrumbs';
import uiRoutes from 'ui/routes';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
const template = `
<ml-nav-menu name="settings" />
@ -54,9 +54,9 @@ module.directive('mlCalendarsList', function () {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(CalendarsList, props)}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

View file

@ -9,7 +9,7 @@ import 'ngreact';
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
@ -62,9 +62,9 @@ module.directive('mlEditFilterList', function ($route) {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(EditFilterList, props)}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

View file

@ -9,7 +9,7 @@ import 'ngreact';
import React from 'react';
import ReactDOM from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { I18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';
const module = uiModules.get('apps/ml', ['react']);
@ -52,9 +52,9 @@ module.directive('mlFilterLists', function () {
};
ReactDOM.render(
<I18nProvider>
<I18nContext>
{React.createElement(FilterLists, props)}
</I18nProvider>,
</I18nContext>,
element[0]
);
}

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