Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/6.x' into upgrade-checkup-reindex
Browse files Browse the repository at this point in the history
  • Loading branch information
joshdover committed Jan 28, 2019
2 parents 574ed90 + 979ae76 commit f4342df
Show file tree
Hide file tree
Showing 51 changed files with 737 additions and 437 deletions.
6 changes: 3 additions & 3 deletions docs/CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,6 @@ Canvas::
* Adds persistent grouping and ungrouping {pull}25854[#25854]
Geo::
* Improves message for maximum zoom level {pull}26267[#26267]
Kibana App::
* Moves Canvas interpreter to OSS {pull}25711[#25711]
* Adds `en` as a valid locale to the settings {pull}25948[#25948]
Machine Learning::
* Adds checkbox to enable model plot in Advanced job wizard {pull}25468[#25468]
* Adds auditbeat process data recognizer modules {pull}25716[#25716]
Expand All @@ -157,6 +154,8 @@ Operations::
* Creates vendor DLL for the client modules {pull}22618[#22618]
Platform::
* Migrates to new design system for breadcrumbs {pull}25914[#25914]
* Moves Canvas interpreter to OSS {pull}25711[#25711]
* Adds `en` as a valid locale to the settings {pull}25948[#25948]
Reporting::
* Add png output to reports {pull}24759[#24759]
Security::
Expand Down Expand Up @@ -363,6 +362,7 @@ Visualizations::
* Enables visualisations in a dashboard to be opened in a new tab {pull}25233[#25233]
* Fixes other bucket option to correctly apply without having to change other settings {pull}26874[#26874]
* Stops using schemas in aggconfigs to output dsl {pull}26010[#26010].
* Fixes Timelion props function {pull}28834[#28834]



Expand Down
1 change: 1 addition & 0 deletions packages/kbn-i18n/src/angular/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,6 @@ export class I18nProvider implements angular.IServiceProvider {
public getFormats = i18n.getFormats;
public getRegisteredLocales = i18n.getRegisteredLocales;
public init = i18n.init;
public load = i18n.load;
public $get = () => i18n.translate;
}
44 changes: 44 additions & 0 deletions packages/kbn-i18n/src/core/i18n.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe('I18n engine', () => {
afterEach(() => {
// isolate modules for every test so that local module state doesn't conflict between tests
jest.resetModules();
jest.clearAllMocks();
});

describe('addMessages', () => {
Expand Down Expand Up @@ -882,4 +883,47 @@ describe('I18n engine', () => {
expect(message).toMatchSnapshot();
});
});

describe('load', () => {
let mockFetch: jest.Mock<unknown>;
beforeEach(() => {
mockFetch = jest.spyOn(global as any, 'fetch').mockImplementation();
});

test('fails if server returns >= 300 status code', async () => {
mockFetch.mockResolvedValue({ status: 301 });

await expect(i18n.load('some-url')).rejects.toMatchInlineSnapshot(
`[Error: Translations request failed with status code: 301]`
);

mockFetch.mockResolvedValue({ status: 404 });

await expect(i18n.load('some-url')).rejects.toMatchInlineSnapshot(
`[Error: Translations request failed with status code: 404]`
);
});

test('initializes engine with received translations', async () => {
const translations = {
locale: 'en-XA',
formats: {
number: { currency: { style: 'currency' } },
},
messages: { 'common.ui.someLabel': 'some label' },
};

mockFetch.mockResolvedValue({
status: 200,
json: jest.fn().mockResolvedValue(translations),
});

await expect(i18n.load('some-url')).resolves.toBeUndefined();

expect(mockFetch).toHaveBeenCalledTimes(1);
expect(mockFetch).toHaveBeenCalledWith('some-url');

expect(i18n.getTranslation()).toEqual(translations);
});
});
});
14 changes: 14 additions & 0 deletions packages/kbn-i18n/src/core/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,17 @@ export function init(newTranslation?: Translation) {
setFormats(newTranslation.formats);
}
}

/**
* Loads JSON with translations from the specified URL and initializes i18n engine with them.
* @param translationsUrl URL pointing to the JSON bundle with translations.
*/
export async function load(translationsUrl: string) {
const response = await fetch(translationsUrl);

if (response.status >= 300) {
throw new Error(`Translations request failed with status code: ${response.status}`);
}

init(await response.json());
}
6 changes: 5 additions & 1 deletion src/core/public/core_system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ describe('#start()', () => {
rootDomElement,
});

core.start();
return core.start();
}

it('clears the children of the rootDomElement and appends container for legacyPlatform and notifications', () => {
Expand Down Expand Up @@ -353,6 +353,10 @@ describe('#start()', () => {
expect(mockInstance.start).toHaveBeenCalledTimes(1);
expect(mockInstance.start).toHaveBeenCalledWith();
});

it('returns start contract', () => {
expect(startCore()).toEqual({ fatalErrors: mockFatalErrorsStartContract });
});
});

describe('LegacyPlatform targetDomElement', () => {
Expand Down
2 changes: 2 additions & 0 deletions src/core/public/core_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ export class CoreSystem {
uiSettings,
chrome,
});

return { fatalErrors };
} catch (error) {
this.fatalErrors.add(error);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ class RequestSelector extends Component {
{ selectedRequest.status === RequestStatus.PENDING &&
<EuiLoadingSpinner
size="m"
aria-label={this.props.intl.formatMessage({
id: 'inspectorViews.requests.requestInProgressAriaLabel',
aria-label={i18n.translate('inspectorViews.requests.requestInProgressAriaLabel', {
defaultMessage: 'Request in progress'
})}
/>
Expand Down
3 changes: 3 additions & 0 deletions src/legacy/core_plugins/interpreter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export default function (kibana) {
id: 'interpreter',
require: ['kibana', 'elasticsearch'],
publicDir: resolve(__dirname, 'public'),
uiExports: {
injectDefaultVars: server => ({ serverBasePath: server.config().get('server.basePath') }),
},
init,
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/legacy/core_plugins/interpreter/public/interpreter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import chrome from 'ui/chrome';
import { functionsRegistry } from './functions_registry';
import { typesRegistry } from './types_registry';

const basePath = chrome.getBasePath();
const basePath = chrome.getInjected('serverBasePath');

const types = {
browserFunctions: functionsRegistry,
Expand Down
13 changes: 4 additions & 9 deletions src/server/i18n/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,11 @@ export async function i18nMixin(kbnServer, server, config) {
]);

const translationPaths = [].concat(...groupedEntries);

i18nLoader.registerTranslationFiles(translationPaths);

const pureTranslations = await i18nLoader.getTranslationsByLocale(locale);
const translations = Object.freeze({
const translations = await i18nLoader.getTranslationsByLocale(locale);
i18n.init(Object.freeze({
locale,
...pureTranslations,
});

i18n.init(translations);

server.decorate('server', 'getUiTranslations', () => translations);
...translations,
}));
}
2 changes: 1 addition & 1 deletion src/server/kbn_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default class KbnServer {
// writes pid file
pidMixin,

// scan translations dirs, register locale files, initialize i18n engine and define `server.getUiTranslations`
// scan translations dirs, register locale files and initialize i18n engine.
i18nMixin,

// find plugins and set this.plugins and this.pluginSpecs
Expand Down
8 changes: 4 additions & 4 deletions src/ui/public/styles/_legacy/_base.scss
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Forms

// Angular form states
.ng-dirty, .ng-touched {
input.ng-invalid#{&},
textarea.ng-invalid#{&},
select.ng-invalid#{&} {
input.ng-invalid,
textarea.ng-invalid,
select.ng-invalid {
&.ng-dirty, &.ng-touched {
border-color: $euiColorDanger !important;
}
}
Expand Down
25 changes: 17 additions & 8 deletions src/ui/ui_bundles/app_entry_template.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,22 @@ import { i18n } from '@kbn/i18n';
import { CoreSystem } from '__kibanaCore__'
const injectedMetadata = JSON.parse(document.querySelector('kbn-injected-metadata').getAttribute('data'));
i18n.init(injectedMetadata.legacyMetadata.translations);
new CoreSystem({
injectedMetadata,
rootDomElement: document.body,
requireLegacyFiles: () => {
${bundle.getRequires().join('\n ')}
}
}).start()
i18n.load(injectedMetadata.i18n.translationsUrl)
.catch(e => e)
.then((i18nError) => {
const coreSystem = new CoreSystem({
injectedMetadata,
rootDomElement: document.body,
requireLegacyFiles: () => {
${bundle.getRequires().join('\n ')}
}
});
const coreStartContract = coreSystem.start();
if (i18nError) {
coreStartContract.fatalErrors.add(i18nError);
}
});
`;
2 changes: 0 additions & 2 deletions src/ui/ui_exports/ui_export_defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ export const UI_EXPORT_DEFAULTS = {
'moment-timezone$': resolve(ROOT, 'webpackShims/moment-timezone')
},

translationPaths: [],

styleSheetPaths: [],

appExtensions: {
Expand Down
35 changes: 33 additions & 2 deletions src/ui/ui_render/ui_render_mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

import { createHash } from 'crypto';
import { props, reduce as reduceAsync } from 'bluebird';
import Boom from 'boom';
import { resolve } from 'path';
Expand Down Expand Up @@ -54,6 +55,35 @@ export function uiRenderMixin(kbnServer, server, config) {
// expose built css
server.exposeStaticDir('/built_assets/css/{path*}', fromRoot('built_assets/css'));

const translationsCache = { translations: null, hash: null };
server.route({
path: '/translations/{locale}.json',
method: 'GET',
config: { auth: false },
handler(request, h) {
// Kibana server loads translations only for a single locale
// that is specified in `i18n.locale` config value.
const { locale } = request.params;
if (i18n.getLocale() !== locale.toLowerCase()) {
throw Boom.notFound(`Unknown locale: ${locale}`);
}

// Stringifying thousands of labels and calculating hash on the resulting
// string can be expensive so it makes sense to do it once and cache.
if (translationsCache.translations == null) {
translationsCache.translations = JSON.stringify(i18n.getTranslation());
translationsCache.hash = createHash('sha1')
.update(translationsCache.translations)
.digest('hex');
}

return h.response(translationsCache.translations)
.header('cache-control', 'must-revalidate')
.header('content-type', 'application/json')
.etag(translationsCache.hash);
}
});

server.route({
path: '/bundles/app/{id}/bootstrap.js',
method: 'GET',
Expand Down Expand Up @@ -144,7 +174,6 @@ export function uiRenderMixin(kbnServer, server, config) {

async function renderApp({ app, h, includeUserProvidedConfig = true, injectedVarsOverrides = {} }) {
const request = h.request;
const translations = await server.getUiTranslations();
const basePath = request.getBasePath();

return h.view('ui_app', {
Expand All @@ -157,6 +186,9 @@ export function uiRenderMixin(kbnServer, server, config) {
version: kbnServer.version,
buildNumber: config.get('pkg.buildNum'),
basePath,
i18n: {
translationsUrl: `${basePath}/translations/${i18n.getLocale()}.json`,
},
vars: await replaceInjectedVars(
request,
mergeVariables(
Expand All @@ -168,7 +200,6 @@ export function uiRenderMixin(kbnServer, server, config) {

legacyMetadata: await getLegacyKibanaPayload({
app,
translations,
request,
includeUserProvidedConfig,
injectedVarsOverrides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,23 @@ describe('pie', () => {

describe('data', () => {
const result = fn(testPie).value.data;
it('is sorted by the series labels', () => {
expect(result.every((val, i) => (!!i ? val.label >= result[i - 1].label : true))).to.be(true);
});

it('has one series per unique label', () => {
const uniqueLabels = testPie.rows
.reduce(
(unique, series) =>
!unique.includes(series.color) ? unique.concat([series.color]) : unique,
[]
)
.sort();
const uniqueLabels = testPie.rows.reduce(
(unique, series) =>
!unique.includes(series.color) ? unique.concat([series.color]) : unique,
[]
);

expect(result).to.have.length(uniqueLabels.length);
expect(result.every((series, i) => series.label === uniqueLabels[i])).to.be(true);
});

it('populates the data of the plot with points from the pointseries', () => {
expect(result[0].data).to.eql([536]);
expect(result[1].data).to.eql([202]);
expect(result[2].data).to.eql([67]);
expect(result[3].data).to.eql([311]);
expect(result[0].data).to.eql([202]);
expect(result[1].data).to.eql([67]);
expect(result[2].data).to.eql([311]);
expect(result[3].data).to.eql([536]);
expect(result[4].data).to.eql([288]);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

import keyBy from 'lodash.keyby';
import { get, map, groupBy, sortBy } from 'lodash';
import { get, map, groupBy } from 'lodash';
import { getColorsFromPalette } from '../../../common/lib/get_colors_from_palette';
import { getLegendConfig } from '../../../common/lib/get_legend_config';

Expand Down Expand Up @@ -67,10 +67,9 @@ export const pie = () => ({
},
},
fn: (context, args) => {
const rows = sortBy(context.rows, ['color', 'size']);
const seriesStyles = keyBy(args.seriesStyle || [], 'label') || {};

const data = map(groupBy(rows, 'color'), (series, label) => {
const data = map(groupBy(context.rows, 'color'), (series, label) => {
const item = {
label: label,
data: series.map(point => point.size || 1),
Expand All @@ -91,7 +90,7 @@ export const pie = () => ({
as: 'pie',
value: {
font: args.font,
data: sortBy(data, 'label'),
data,
options: {
canvas: false,
colors: getColorsFromPalette(args.palette, data.length),
Expand Down
Loading

0 comments on commit f4342df

Please sign in to comment.