Skip to content

Commit

Permalink
Merge branch 'main' into guided_onboarding/8.6_landing_page
Browse files Browse the repository at this point in the history
  • Loading branch information
yuliacech authored Oct 20, 2022
2 parents f340248 + 3799ed3 commit bbaeb90
Show file tree
Hide file tree
Showing 124 changed files with 2,039 additions and 1,450 deletions.
1 change: 1 addition & 0 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ enabled:
- x-pack/test/functional/apps/lens/group1/config.ts
- x-pack/test/functional/apps/lens/group2/config.ts
- x-pack/test/functional/apps/lens/group3/config.ts
- x-pack/test/functional/apps/lens/open_in_lens/config.ts
- x-pack/test/functional/apps/license_management/config.ts
- x-pack/test/functional/apps/logstash/config.ts
- x-pack/test/functional/apps/management/config.ts
Expand Down
10 changes: 7 additions & 3 deletions .buildkite/pipeline-utils/ci-stats/pick_test_group_run_order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,15 @@ function getRunGroups(bk: BuildkiteClient, allTypes: RunGroup[], typeName: strin
if (tooLongs.length > 0) {
bk.setAnnotation(
`test-group-too-long:${typeName}`,
'error',
'warning',
[
tooLongs.length === 1
? `The following "${typeName}" config has a duration that exceeds the maximum amount of time desired for a single CI job. Please split it up.`
: `The following "${typeName}" configs have durations that exceed the maximum amount of time desired for a single CI job. Please split them up.`,
? `The following "${typeName}" config has a duration that exceeds the maximum amount of time desired for a single CI job. ` +
`This is not an error, and if you don't own this config then you can ignore this warning. ` +
`If you own this config please split it up ASAP and ask Operations if you have questions about how to do that.`
: `The following "${typeName}" configs have durations that exceed the maximum amount of time desired for a single CI job. ` +
`This is not an error, and if you don't own any of these configs then you can ignore this warning.` +
`If you own any of these configs please split them up ASAP and ask Operations if you have questions about how to do that.`,
'',
...tooLongs.map(({ config, durationMin }) => ` - ${config}: ${durationMin} minutes`),
].join('\n')
Expand Down
16 changes: 12 additions & 4 deletions docs/settings/reporting-settings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ security is enabled, <<xpack-security-encryptionKey, `xpack.security.encryptionK
Specifies the {time-units}[time] that the reporting poller waits between polling the index for any pending Reporting jobs. Can be specified as number of milliseconds. Defaults to `3s`.

[[xpack-reporting-q-timeout]] `xpack.reporting.queue.timeout` {ess-icon}::
{time-units}[How long] each worker has to produce a report. If your machine is slow or under heavy load, you might need to increase this timeout. If a Reporting job execution goes over this time limit, the job is marked as a failure and no download will be available. Can be specified as number of milliseconds. Defaults to `2m`.
{time-units}[How long] each worker has to produce a report. If your machine is slow or under heavy load, you
might need to increase this timeout. If a Reporting job execution goes over this time limit, the job is marked
as a failure and no download will be available. Can be specified as number of milliseconds. Defaults to `4m`.

[float]
[[reporting-capture-settings]]
Expand All @@ -92,13 +94,19 @@ Specifies the {time-units}[time] that the reporting poller waits between polling
Reporting uses an internal "screenshotting" plugin to capture screenshots from {kib}. The following settings control the capturing process.

`xpack.screenshotting.capture.timeouts.openUrl` {ess-icon}::
Specify the {time-units}[time] to allow the Reporting browser to wait for the "Loading..." screen to dismiss and find the initial data for the page. If the time is exceeded, a screenshot is captured showing the current page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `1m`.
Specify the {time-units}[time] to allow the Reporting browser to wait for the "Loading..." screen to dismiss
and find the initial data for the page. If the time is exceeded, a screenshot is captured showing the current
page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `1m`.

`xpack.screenshotting.capture.timeouts.waitForElements` {ess-icon}::
Specify the {time-units}[time] to allow the Reporting browser to wait for all visualization panels to load on the page. If the time is exceeded, a screenshot is captured showing the current page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `30s`.
Specify the {time-units}[time] to allow the Reporting browser to wait for all visualization panels to load on
the page. If the time is exceeded, a screenshot is captured showing the current page, and the download link
shows a warning message. Can be specified as number of milliseconds. Defaults to `1m`.

`xpack.screenshotting.capture.timeouts.renderComplete` {ess-icon}::
Specify the {time-units}[time] to allow the Reporting browser to wait for all visualizations to fetch and render the data. If the time is exceeded, a screenshot is captured showing the current page, and the download link shows a warning message. Can be specified as number of milliseconds. Defaults to `30s`.
Specify the {time-units}[time] to allow the Reporting browser to wait for all visualizations to fetch and
render the data. If the time is exceeded, a screenshot is captured showing the current page, and the download
link shows a warning message. Can be specified as number of milliseconds. Defaults to `2m`.

NOTE: If any timeouts from `xpack.screenshotting.capture.timeouts.*` settings occur when
running a report job, Reporting will log the error and try to continue
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@
"prop-types": "^15.8.1",
"proxy-from-env": "1.0.0",
"puid": "1.0.7",
"puppeteer": "^10.2.0",
"puppeteer": "18.1.0",
"query-string": "^6.13.2",
"rbush": "^3.0.1",
"re-resizable": "^6.1.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import uuid from 'uuid';
import useLifecycles from 'react-use/lib/useLifecycles';
import React, { useEffect, useMemo, useRef, useState } from 'react';

import { IEmbeddable } from '@kbn/embeddable-plugin/public';

import { pluginServices } from '../services';
import { getDefaultControlGroupInput } from '../../common';
import { ControlGroupInput, ControlGroupOutput, CONTROL_GROUP_TYPE } from './types';
import { ControlGroupContainer } from './embeddable/control_group_container';

export interface ControlGroupRendererProps {
input?: Partial<Pick<ControlGroupInput, 'viewMode' | 'executionContext'>>;
onEmbeddableLoad: (controlGroupContainer: ControlGroupContainer) => void;
}

export const ControlGroupRenderer = ({ input, onEmbeddableLoad }: ControlGroupRendererProps) => {
const controlsRoot = useRef(null);
const [controlGroupContainer, setControlGroupContainer] = useState<ControlGroupContainer>();

const id = useMemo(() => uuid.v4(), []);

/**
* Use Lifecycles to load initial control group container
*/
useLifecycles(
() => {
const { embeddable } = pluginServices.getServices();

(async () => {
const container = (await embeddable
.getEmbeddableFactory<
ControlGroupInput,
ControlGroupOutput,
IEmbeddable<ControlGroupInput, ControlGroupOutput>
>(CONTROL_GROUP_TYPE)
?.create({ id, ...getDefaultControlGroupInput(), ...input })) as ControlGroupContainer;

if (controlsRoot.current) {
container.render(controlsRoot.current);
}
setControlGroupContainer(container);
onEmbeddableLoad(container);
})();
},
() => {
controlGroupContainer?.destroy();
}
);

/**
* Update embeddable input when props input changes
*/
useEffect(() => {
let updateCanceled = false;
(async () => {
// check if applying input from props would result in any changes to the embeddable input
const isInputEqual = await controlGroupContainer?.getExplicitInputIsEqual({
...controlGroupContainer?.getInput(),
...input,
});
if (!controlGroupContainer || isInputEqual || updateCanceled) return;
controlGroupContainer.updateInput({ ...input });
})();

return () => {
updateCanceled = true;
};
}, [controlGroupContainer, input]);

return <div ref={controlsRoot} />;
};

// required for dynamic import using React.lazy()
// eslint-disable-next-line import/no-default-export
export default ControlGroupRenderer;
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
import { i18n } from '@kbn/i18n';

export const ControlGroupStrings = {
getEmbeddableTitle: () =>
i18n.translate('controls.controlGroup.title', {
defaultMessage: 'Control group',
}),
getControlButtonTitle: () =>
i18n.translate('controls.controlGroup.toolbarButtonTitle', {
defaultMessage: 'Controls',
Expand Down
55 changes: 10 additions & 45 deletions src/plugins/controls/public/control_group/editor/control_editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* Side Public License, v 1.
*/

import React, { useEffect, useMemo, useState } from 'react';
import React, { useEffect, useState } from 'react';
import useMount from 'react-use/lib/useMount';

import {
Expand All @@ -36,7 +36,6 @@ import {
EuiTextColor,
} from '@elastic/eui';
import { DataViewListItem, DataView, DataViewField } from '@kbn/data-views-plugin/common';
import { IFieldSubTypeMulti } from '@kbn/es-query';
import {
LazyDataViewPicker,
LazyFieldPicker,
Expand All @@ -53,6 +52,7 @@ import {
} from '../../types';
import { CONTROL_WIDTH_OPTIONS } from './editor_constants';
import { pluginServices } from '../../services';
import { loadFieldRegistryFromDataViewId } from './data_control_editor_tools';
interface EditControlProps {
embeddable?: ControlEmbeddable<DataControlInput>;
isCreate: boolean;
Expand Down Expand Up @@ -97,7 +97,7 @@ export const ControlEditor = ({
}: EditControlProps) => {
const {
dataViews: { getIdsWithTitle, getDefaultId, get },
controls: { getControlTypes, getControlFactory },
controls: { getControlFactory },
} = pluginServices.getServices();
const [state, setState] = useState<ControlEditorState>({
dataViewListItems: [],
Expand All @@ -112,49 +112,14 @@ export const ControlEditor = ({
embeddable ? embeddable.getInput().fieldName : undefined
);

const doubleLinkFields = (dataView: DataView) => {
// double link the parent-child relationship specifically for case-sensitivity support for options lists
const fieldRegistry: DataControlFieldRegistry = {};

for (const field of dataView.fields.getAll()) {
if (!fieldRegistry[field.name]) {
fieldRegistry[field.name] = { field, compatibleControlTypes: [] };
}
const parentFieldName = (field.subType as IFieldSubTypeMulti)?.multi?.parent;
if (parentFieldName) {
fieldRegistry[field.name].parentFieldName = parentFieldName;

const parentField = dataView.getFieldByName(parentFieldName);
if (!fieldRegistry[parentFieldName] && parentField) {
fieldRegistry[parentFieldName] = { field: parentField, compatibleControlTypes: [] };
}
fieldRegistry[parentFieldName].childFieldName = field.name;
}
}
return fieldRegistry;
};

const fieldRegistry = useMemo(() => {
if (!state.selectedDataView) return;
const newFieldRegistry: DataControlFieldRegistry = doubleLinkFields(state.selectedDataView);

const controlFactories = getControlTypes().map(
(controlType) => getControlFactory(controlType) as IEditableControlFactory
);
state.selectedDataView.fields.map((dataViewField) => {
for (const factory of controlFactories) {
if (factory.isFieldCompatible) {
factory.isFieldCompatible(newFieldRegistry[dataViewField.name]);
}
}

if (newFieldRegistry[dataViewField.name]?.compatibleControlTypes.length === 0) {
delete newFieldRegistry[dataViewField.name];
const [fieldRegistry, setFieldRegistry] = useState<DataControlFieldRegistry>();
useEffect(() => {
(async () => {
if (state.selectedDataView?.id) {
setFieldRegistry(await loadFieldRegistryFromDataViewId(state.selectedDataView.id));
}
});

return newFieldRegistry;
}, [state.selectedDataView, getControlFactory, getControlTypes]);
})();
}, [state.selectedDataView]);

useMount(() => {
let mounted = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { IFieldSubTypeMulti } from '@kbn/es-query';
import { DataView } from '@kbn/data-views-plugin/common';

import { pluginServices } from '../../services';
import { DataControlFieldRegistry, IEditableControlFactory } from '../../types';

const dataControlFieldRegistryCache: { [key: string]: DataControlFieldRegistry } = {};

const doubleLinkFields = (dataView: DataView) => {
// double link the parent-child relationship specifically for case-sensitivity support for options lists
const fieldRegistry: DataControlFieldRegistry = {};

for (const field of dataView.fields.getAll()) {
if (!fieldRegistry[field.name]) {
fieldRegistry[field.name] = { field, compatibleControlTypes: [] };
}
const parentFieldName = (field.subType as IFieldSubTypeMulti)?.multi?.parent;
if (parentFieldName) {
fieldRegistry[field.name].parentFieldName = parentFieldName;

const parentField = dataView.getFieldByName(parentFieldName);
if (!fieldRegistry[parentFieldName] && parentField) {
fieldRegistry[parentFieldName] = { field: parentField, compatibleControlTypes: [] };
}
fieldRegistry[parentFieldName].childFieldName = field.name;
}
}
return fieldRegistry;
};

export const loadFieldRegistryFromDataViewId = async (
dataViewId: string
): Promise<DataControlFieldRegistry> => {
if (dataControlFieldRegistryCache[dataViewId]) {
return dataControlFieldRegistryCache[dataViewId];
}
const {
dataViews,
controls: { getControlTypes, getControlFactory },
} = pluginServices.getServices();
const dataView = await dataViews.get(dataViewId);

const newFieldRegistry: DataControlFieldRegistry = doubleLinkFields(dataView);

const controlFactories = getControlTypes().map(
(controlType) => getControlFactory(controlType) as IEditableControlFactory
);
dataView.fields.map((dataViewField) => {
for (const factory of controlFactories) {
if (factory.isFieldCompatible) {
factory.isFieldCompatible(newFieldRegistry[dataViewField.name]);
}
}

if (newFieldRegistry[dataViewField.name]?.compatibleControlTypes.length === 0) {
delete newFieldRegistry[dataViewField.name];
}
});
dataControlFieldRegistryCache[dataViewId] = newFieldRegistry;

return newFieldRegistry;
};
Loading

0 comments on commit bbaeb90

Please sign in to comment.