can navigate Autoplay Settings 2`] = `
data-focus-lock-disabled="disabled"
>
can navigate Toolbar Settings, closes when activated 1`] =
data-focus-lock-disabled="disabled"
>
can navigate Toolbar Settings, closes when activated 1`] =
`;
-exports[`
can navigate Toolbar Settings, closes when activated 2`] = `"
"`;
+exports[`
can navigate Toolbar Settings, closes when activated 2`] = `"
"`;
-exports[`
can navigate Toolbar Settings, closes when activated 3`] = `"
"`;
+exports[`
can navigate Toolbar Settings, closes when activated 3`] = `"
"`;
diff --git a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx
index 78fefead027e5..5ebb30d79e046 100644
--- a/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx
+++ b/x-pack/legacy/plugins/canvas/shareable_runtime/components/footer/settings/__tests__/settings.test.tsx
@@ -18,6 +18,11 @@ import { Settings } from '../settings';
jest.mock('../../../../supported_renderers');
jest.mock(`@elastic/eui/lib/components/form/form_row/make_id`, () => () => `generated-id`);
+jest.mock('@elastic/eui/lib/services/accessibility', () => {
+ return {
+ htmlIdGenerator: () => () => `generated-id`,
+ };
+});
jest.mock('@elastic/eui/lib/components/portal/portal', () => {
// eslint-disable-next-line no-shadow
const React = require.requireActual('react');
diff --git a/x-pack/legacy/plugins/graph/public/angular/templates/index.html b/x-pack/legacy/plugins/graph/public/angular/templates/index.html
index 686f0f590a19c..b3f5bce7ea6ec 100644
--- a/x-pack/legacy/plugins/graph/public/angular/templates/index.html
+++ b/x-pack/legacy/plugins/graph/public/angular/templates/index.html
@@ -61,7 +61,7 @@
initial-query="initialQuery"
plugin-data-start="pluginDataStart"
core-start="coreStart"
- store="store"
+ storage="storage"
no-index-patterns="noIndexPatterns"
>
diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js
index 41e5819bcbf37..ab83815457981 100644
--- a/x-pack/legacy/plugins/graph/public/app.js
+++ b/x-pack/legacy/plugins/graph/public/app.js
@@ -100,7 +100,7 @@ export function initGraphApp(angularModule, deps) {
app.directive('graphApp', function (reactDirective) {
return reactDirective(GraphApp, [
- ['store', { watchDepth: 'reference' }],
+ ['storage', { watchDepth: 'reference' }],
['isInitialized', { watchDepth: 'reference' }],
['currentIndexPattern', { watchDepth: 'reference' }],
['indexPatternProvider', { watchDepth: 'reference' }],
@@ -310,7 +310,7 @@ export function initGraphApp(angularModule, deps) {
// register things on scope passed down to react components
$scope.pluginDataStart = npData;
- $scope.store = new Storage(window.localStorage);
+ $scope.storage = new Storage(window.localStorage);
$scope.coreStart = coreStart;
$scope.loading = false;
$scope.reduxStore = store;
diff --git a/x-pack/legacy/plugins/graph/public/components/app.tsx b/x-pack/legacy/plugins/graph/public/components/app.tsx
index aa2221441793f..5ff7fc2e5da93 100644
--- a/x-pack/legacy/plugins/graph/public/components/app.tsx
+++ b/x-pack/legacy/plugins/graph/public/components/app.tsx
@@ -10,8 +10,8 @@ import { DataPublicPluginStart } from 'src/plugins/data/public';
import { Provider } from 'react-redux';
import React, { useState } from 'react';
import { I18nProvider } from '@kbn/i18n/react';
-import { Storage } from 'ui/storage';
import { CoreStart } from 'kibana/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { FieldManager } from './field_manager';
import { SearchBarProps, SearchBar } from './search_bar';
import { GraphStore } from '../state_management';
@@ -23,7 +23,7 @@ export interface GraphAppProps extends SearchBarProps {
coreStart: CoreStart;
// This is not named dataStart because of Angular treating data- prefix differently
pluginDataStart: DataPublicPluginStart;
- store: Storage;
+ storage: IStorageWrapper;
reduxStore: GraphStore;
isInitialized: boolean;
noIndexPatterns: boolean;
@@ -34,7 +34,7 @@ export function GraphApp(props: GraphAppProps) {
const {
coreStart,
pluginDataStart,
- store,
+ storage,
reduxStore,
noIndexPatterns,
...searchBarProps
@@ -45,7 +45,7 @@ export function GraphApp(props: GraphAppProps) {
{},
},
};
diff --git a/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx b/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx
index b321ea3a0d8ed..f7ae04ef9dbcc 100644
--- a/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx
+++ b/x-pack/legacy/plugins/graph/public/components/settings/blacklist_form.tsx
@@ -39,7 +39,7 @@ export function BlacklistForm({
}}
+ values={{ stopSign: }}
/>
}
/>
diff --git a/x-pack/legacy/plugins/graph/public/index.ts b/x-pack/legacy/plugins/graph/public/index.ts
index 0249ca74035d6..5e500367ccdc5 100644
--- a/x-pack/legacy/plugins/graph/public/index.ts
+++ b/x-pack/legacy/plugins/graph/public/index.ts
@@ -14,11 +14,11 @@ import chrome from 'ui/chrome';
import { IPrivate } from 'ui/private';
// @ts-ignore
import { xpackInfo } from 'plugins/xpack_main/services/xpack_info';
-import { Storage } from 'ui/storage';
// @ts-ignore
import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_registry';
import { npSetup, npStart } from 'ui/new_platform';
+import { Storage } from '../../../../../src/plugins/kibana_utils/public';
import { start as data } from '../../../../../src/legacy/core_plugins/data/public/legacy';
import { GraphPlugin } from './plugin';
diff --git a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js
index e96fc79967316..31d8337857911 100644
--- a/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js
+++ b/x-pack/legacy/plugins/index_lifecycle_management/__jest__/components/policy_table.test.js
@@ -111,7 +111,7 @@ describe('policy table', () => {
});
test('should show more when per page value is increased', () => {
const rendered = mountWithIntl(component);
- const perPageButton = rendered.find('#customizablePagination').find('button');
+ const perPageButton = rendered.find('EuiTablePagination EuiPopover').find('button');
perPageButton.simulate('click');
rendered.update();
const fiftyButton = rendered.find('.euiContextMenuItem').at(1);
diff --git a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js
index d6a53eefcdc95..278ec918100d9 100644
--- a/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js
+++ b/x-pack/legacy/plugins/index_management/__jest__/components/index_table.test.js
@@ -155,7 +155,7 @@ describe('index table', () => {
});
test('should show more when per page value is increased', () => {
const rendered = mountWithIntl(component);
- const perPageButton = rendered.find('#customizablePagination').find('button');
+ const perPageButton = rendered.find('EuiTablePagination EuiPopover').find('button');
perPageButton.simulate('click');
rendered.update();
const fiftyButton = rendered.find('.euiContextMenuItem').at(1);
diff --git a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx
index d1ed816bebd45..3a1dcbc7e762d 100644
--- a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx
+++ b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_aliases.tsx
@@ -34,6 +34,6 @@ export const TabAliases: React.FunctionComponent = ({ templateDetails })
}
iconType="pin"
data-test-subj="noAliasesCallout"
- >
+ />
);
};
diff --git a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx
index 91f84a5ecf726..9439b0e31ae84 100644
--- a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx
+++ b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_mappings.tsx
@@ -34,6 +34,6 @@ export const TabMappings: React.FunctionComponent = ({ templateDetails })
}
iconType="pin"
data-test-subj="noMappingsCallout"
- >
+ />
);
};
diff --git a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx
index 6a83b714519d7..0370a89850721 100644
--- a/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx
+++ b/x-pack/legacy/plugins/index_management/public/sections/home/template_list/template_details/tabs/tab_settings.tsx
@@ -34,6 +34,6 @@ export const TabSettings: React.FunctionComponent = ({ templateDetails })
}
iconType="pin"
data-test-subj="noSettingsCallout"
- >
+ />
);
};
diff --git a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
index ca67aec9642ac..d7c9876a07a8d 100644
--- a/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/autocomplete_field/suggestion_item.tsx
@@ -11,36 +11,30 @@ import React from 'react';
import { AutocompleteSuggestion } from '../../../../../../../src/plugins/data/public';
import euiStyled from '../../../../../common/eui_styled_components';
-interface SuggestionItemProps {
+interface Props {
isSelected?: boolean;
onClick?: React.MouseEventHandler;
onMouseEnter?: React.MouseEventHandler;
suggestion: AutocompleteSuggestion;
}
-export class SuggestionItem extends React.Component {
- public static defaultProps: Partial = {
- isSelected: false,
- };
+export const SuggestionItem: React.SFC = props => {
+ const { isSelected, onClick, onMouseEnter, suggestion } = props;
- public render() {
- const { isSelected, onClick, onMouseEnter, suggestion } = this.props;
+ return (
+
+
+
+
+ {suggestion.text}
+ {suggestion.description}
+
+ );
+};
- return (
-
-
-
-
- {suggestion.text}
- {suggestion.description}
-
- );
- }
-}
+SuggestionItem.defaultProps = {
+ isSelected: false,
+};
const SuggestionItemContainer = euiStyled.div<{
isSelected?: boolean;
diff --git a/x-pack/legacy/plugins/infra/public/components/loading_overlay_wrapper.tsx b/x-pack/legacy/plugins/infra/public/components/loading_overlay_wrapper.tsx
new file mode 100644
index 0000000000000..0f70c40059c93
--- /dev/null
+++ b/x-pack/legacy/plugins/infra/public/components/loading_overlay_wrapper.tsx
@@ -0,0 +1,45 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { EuiLoadingSpinner } from '@elastic/eui';
+import { transparentize } from 'polished';
+import React from 'react';
+
+import { euiStyled } from '../../../../common/eui_styled_components';
+
+export const LoadingOverlayWrapper: React.FC<
+ React.HTMLAttributes & {
+ isLoading: boolean;
+ loadingChildren?: React.ReactNode;
+ }
+> = ({ children, isLoading, loadingChildren, ...rest }) => {
+ return (
+
+ {children}
+ {isLoading ? {loadingChildren} : null}
+
+ );
+};
+
+const Overlay: React.FC = ({ children }) => (
+ {children ? children : }
+);
+
+const RelativeDiv = euiStyled.div`
+ position: relative;
+`;
+
+const OverlayDiv = euiStyled.div`
+ align-items: center;
+ background-color: ${props => transparentize(0.3, props.theme.eui.euiColorEmptyShade)};
+ display: flex;
+ height: 100%;
+ justify-content: center;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 100%;
+`;
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx
index 218b42b48c9b9..752a0d6e27a7f 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/loading_item_view.tsx
@@ -114,29 +114,28 @@ interface ProgressEntryProps {
isLoading: boolean;
}
-class ProgressEntry extends React.PureComponent {
- public render() {
- const { alignment, children, className, color, isLoading } = this.props;
- // NOTE: styled-components seems to make all props in EuiProgress required, so this
- // style attribute hacking replaces styled-components here for now until that can be fixed
- // see: https://github.com/elastic/eui/issues/1655
- const alignmentStyle =
- alignment === 'top' ? { top: 0, bottom: 'initial' } : { top: 'initial', bottom: 0 };
+const ProgressEntry: React.SFC = props => {
+ const { alignment, children, className, color, isLoading } = props;
- return (
-
-
- {children}
-
- );
- }
-}
+ // NOTE: styled-components seems to make all props in EuiProgress required, so this
+ // style attribute hacking replaces styled-components here for now until that can be fixed
+ // see: https://github.com/elastic/eui/issues/1655
+ const alignmentStyle =
+ alignment === 'top' ? { top: 0, bottom: 'initial' } : { top: 'initial', bottom: 0 };
+
+ return (
+
+
+ {children}
+
+ );
+};
const ProgressEntryWrapper = euiStyled.div`
align-items: center;
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx
index d439308194d18..fc3c8b3bf2b31 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/scrollable_log_text_stream_view.tsx
@@ -102,6 +102,14 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
targetId: null,
items: [],
};
+ } else if (
+ hasItems &&
+ (nextItems.length !== prevState.items.length || nextItems[0] !== prevState.items[0])
+ ) {
+ return {
+ ...prevState,
+ items: nextItems,
+ };
}
return null;
@@ -180,6 +188,7 @@ export class ScrollableLogTextStreamView extends React.PureComponent<
hideScrollbar={true}
data-test-subj={'logStream'}
isLocked={scrollLock.isEnabled}
+ entriesCount={items.length}
>
{registerChild => (
<>
diff --git a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx
index 7ff4a2cacee09..dd368ef4d8f92 100644
--- a/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx
+++ b/x-pack/legacy/plugins/infra/public/components/logging/log_text_stream/vertical_scroll_panel.tsx
@@ -30,6 +30,7 @@ interface VerticalScrollPanelProps {
hideScrollbar?: boolean;
'data-test-subj'?: string;
isLocked: boolean;
+ entriesCount: number;
}
interface VerticalScrollPanelSnapshot {
@@ -226,7 +227,7 @@ export class VerticalScrollPanel extends React.PureComponent<
if (
prevProps.height !== this.props.height ||
prevProps.target !== this.props.target ||
- React.Children.count(prevProps.children) !== React.Children.count(this.props.children)
+ prevProps.entriesCount !== this.props.entriesCount
) {
this.handleUpdatedChildren(snapshot.scrollTarget, snapshot.scrollOffset);
}
diff --git a/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx b/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx
index abb3aa6b26b15..1318e9ca6c2c5 100644
--- a/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/link_to/link_to.tsx
@@ -16,27 +16,21 @@ interface LinkToPageProps {
match: RouteMatch<{}>;
}
-export class LinkToPage extends React.Component {
- public render() {
- const { match } = this.props;
-
- return (
-
-
-
-
-
-
-
- );
- }
-}
+export const LinkToPage: React.SFC = props => (
+
+
+
+
+
+
+
+);
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
index ffc48a0af9de9..e740689da50f6 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/page_results_content.tsx
@@ -6,23 +6,23 @@
import datemath from '@elastic/datemath';
import {
+ EuiBadge,
EuiFlexGroup,
EuiFlexItem,
EuiPage,
EuiPanel,
EuiSuperDatePicker,
- EuiBadge,
EuiText,
} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
import numeral from '@elastic/numeral';
import { FormattedMessage } from '@kbn/i18n/react';
import moment from 'moment';
import React, { useCallback, useContext, useMemo, useState } from 'react';
+
import euiStyled from '../../../../../../common/eui_styled_components';
import { TimeRange } from '../../../../common/http_api/shared/time_range';
import { bucketSpan } from '../../../../common/log_analysis';
-import { LoadingPage } from '../../../components/loading_page';
+import { LoadingOverlayWrapper } from '../../../components/loading_overlay_wrapper';
import {
LogAnalysisJobs,
StringTimeRange,
@@ -162,89 +162,77 @@ export const AnalysisResultsContent = ({
);
return (
- <>
- {isLoading && !logEntryRate ? (
-
- ) : (
- <>
-
-
+
+
+
+
+
-
-
-
- {!isLoading && logEntryRate ? (
-
-
-
- {numeral(logEntryRate.totalNumberOfLogEntries).format('0.00a')}
-
-
- ),
- startTime: (
- {moment(queryTimeRange.value.startTime).format(dateFormat)}
- ),
- endTime: (
- {moment(queryTimeRange.value.endTime).format(dateFormat)}
- ),
- }}
- />
-
- ) : null}
-
-
-
+
+
+
+ {numeral(logEntryRate.totalNumberOfLogEntries).format('0.00a')}
+
+
+ ),
+ startTime: (
+ {moment(queryTimeRange.value.startTime).format(dateFormat)}
+ ),
+ endTime: {moment(queryTimeRange.value.endTime).format(dateFormat)},
+ }}
/>
-
-
-
-
-
-
- {isFirstUse && !hasResults ? : null}
-
-
+
+
+ ) : null}
-
-
-
+
-
- >
- )}
- >
+
+
+
+
+ {isFirstUse && !hasResults ? : null}
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
index 5aa5891d7981d..c340de4ad3848 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/anomalies/index.tsx
@@ -8,10 +8,10 @@ import {
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
- EuiLoadingChart,
EuiSpacer,
EuiStat,
EuiTitle,
+ EuiLoadingSpinner,
} from '@elastic/eui';
import numeral from '@elastic/numeral';
import { i18n } from '@kbn/i18n';
@@ -31,6 +31,7 @@ import { AnomaliesChart } from './chart';
import { AnomaliesTable } from './table';
import { LogAnalysisJobProblemIndicator } from '../../../../../components/logging/log_analysis_job_status';
import { AnalyzeInMlButton } from '../analyze_in_ml_button';
+import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper';
export const AnomaliesResults: React.FunctionComponent<{
isLoading: boolean;
@@ -53,15 +54,6 @@ export const AnomaliesResults: React.FunctionComponent<{
viewSetupForUpdate,
jobId,
}) => {
- const title = i18n.translate('xpack.infra.logs.analysis.anomaliesSectionTitle', {
- defaultMessage: 'Anomalies',
- });
-
- const loadingAriaLabel = i18n.translate(
- 'xpack.infra.logs.analysis.anomaliesSectionLoadingAriaLabel',
- { defaultMessage: 'Loading anomalies' }
- );
-
const hasAnomalies = useMemo(() => {
return results && results.histogramBuckets
? results.histogramBuckets.some(bucket => {
@@ -117,90 +109,91 @@ export const AnomaliesResults: React.FunctionComponent<{
onRecreateMlJobForUpdate={viewSetupForUpdate}
/>
- {isLoading ? (
-
-
-
-
-
- ) : !results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
-
- {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataTitle', {
- defaultMessage: 'There is no data to display.',
- })}
-
- }
- titleSize="m"
- body={
-
- {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataBody', {
- defaultMessage: 'You may want to adjust your time range.',
- })}
-
- }
- />
- ) : !hasAnomalies ? (
-
- {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoAnomaliesTitle', {
- defaultMessage: 'No anomalies were detected.',
- })}
-
- }
- titleSize="m"
- />
- ) : (
- <>
-
-
-
-
-
-
-
-
-
-
- }>
+ {!results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
+
+ {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataTitle', {
+ defaultMessage: 'There is no data to display.',
+ })}
+
+ }
+ titleSize="m"
+ body={
+
+ {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoDataBody', {
+ defaultMessage: 'You may want to adjust your time range.',
+ })}
+
+ }
+ />
+ ) : !hasAnomalies ? (
+
+ {i18n.translate('xpack.infra.logs.analysis.anomalySectionNoAnomaliesTitle', {
+ defaultMessage: 'No anomalies were detected.',
+ })}
+
+ }
+ titleSize="m"
/>
- >
- )}
+ ) : (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+ )}
+
>
);
};
+const title = i18n.translate('xpack.infra.logs.analysis.anomaliesSectionTitle', {
+ defaultMessage: 'Anomalies',
+});
+
interface ParsedAnnotationDetails {
anomalyScoresByPartition: Array<{ partitionId: string; maximumAnomalyScore: number }>;
}
@@ -211,6 +204,7 @@ const overallAnomalyScoreLabel = i18n.translate(
defaultMessage: 'Max anomaly scores:',
}
);
+
const AnnotationTooltip: React.FunctionComponent<{ details: string }> = ({ details }) => {
const parsedDetails: ParsedAnnotationDetails = JSON.parse(details);
return (
@@ -237,7 +231,7 @@ const AnnotationTooltip: React.FunctionComponent<{ details: string }> = ({ detai
const renderAnnotationTooltip = (details?: string) => {
// Note: Seems to be necessary to get things typed correctly all the way through to elastic-charts components
if (!details) {
- return ;
+ return ;
}
return ;
};
@@ -245,3 +239,10 @@ const renderAnnotationTooltip = (details?: string) => {
const TooltipWrapper = euiStyled('div')`
white-space: nowrap;
`;
+
+const loadingAriaLabel = i18n.translate(
+ 'xpack.infra.logs.analysis.anomaliesSectionLoadingAriaLabel',
+ { defaultMessage: 'Loading anomalies' }
+);
+
+const LoadingOverlayContent = () => ;
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx
index d4ddd14bfaa28..682eb23fa4774 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/sections/log_rate/index.tsx
@@ -4,15 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import {
- EuiEmptyPrompt,
- EuiFlexGroup,
- EuiFlexItem,
- EuiLoadingChart,
- EuiSpacer,
- EuiTitle,
- EuiText,
-} from '@elastic/eui';
+import { EuiEmptyPrompt, EuiLoadingSpinner, EuiSpacer, EuiTitle, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useMemo } from 'react';
@@ -20,6 +12,7 @@ import { GetLogEntryRateSuccessResponsePayload } from '../../../../../../common/
import { TimeRange } from '../../../../../../common/http_api/shared/time_range';
import { LogEntryRateBarChart } from './bar_chart';
import { getLogEntryRatePartitionedSeries } from '../helpers/data_formatters';
+import { LoadingOverlayWrapper } from '../../../../../components/loading_overlay_wrapper';
export const LogRateResults = ({
isLoading,
@@ -32,15 +25,6 @@ export const LogRateResults = ({
setTimeRange: (timeRange: TimeRange) => void;
timeRange: TimeRange;
}) => {
- const title = i18n.translate('xpack.infra.logs.analysis.logRateSectionTitle', {
- defaultMessage: 'Log entries',
- });
-
- const loadingAriaLabel = i18n.translate(
- 'xpack.infra.logs.analysis.logRateSectionLoadingAriaLabel',
- { defaultMessage: 'Loading log rate results' }
- );
-
const logEntryRateSeries = useMemo(
() => (results && results.histogramBuckets ? getLogEntryRatePartitionedSeries(results) : []),
[results]
@@ -51,57 +35,61 @@ export const LogRateResults = ({
{title}
- {isLoading ? (
- <>
-
-
-
-
-
-
- >
- ) : !results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
- <>
-
-
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataTitle', {
- defaultMessage: 'There is no data to display.',
- })}
-
- }
- titleSize="m"
- body={
+ }>
+ {!results || (results && results.histogramBuckets && !results.histogramBuckets.length) ? (
+ <>
+
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataTitle', {
+ defaultMessage: 'There is no data to display.',
+ })}
+
+ }
+ titleSize="m"
+ body={
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataBody', {
+ defaultMessage: 'You may want to adjust your time range.',
+ })}
+
+ }
+ />
+ >
+ ) : (
+ <>
+
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionNoDataBody', {
- defaultMessage: 'You may want to adjust your time range.',
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanLabel', {
+ defaultMessage: 'Bucket span: ',
+ })}
+
+ {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanValue', {
+ defaultMessage: '15 minutes',
})}
- }
- />
- >
- ) : (
- <>
-
-
-
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanLabel', {
- defaultMessage: 'Bucket span: ',
- })}
-
- {i18n.translate('xpack.infra.logs.analysis.logRateSectionBucketSpanValue', {
- defaultMessage: '15 minutes',
- })}
-
-
-
- >
- )}
+
+
+ >
+ )}
+
>
);
};
+
+const title = i18n.translate('xpack.infra.logs.analysis.logRateSectionTitle', {
+ defaultMessage: 'Log entries',
+});
+
+const loadingAriaLabel = i18n.translate(
+ 'xpack.infra.logs.analysis.logRateSectionLoadingAriaLabel',
+ { defaultMessage: 'Loading log rate results' }
+);
+
+const LoadingOverlayContent = () => ;
diff --git a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx
index e966336567e59..17f1aa48c87a2 100644
--- a/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx
+++ b/x-pack/legacy/plugins/infra/public/pages/logs/analysis/setup/initial_configuration_step/analysis_setup_timerange_form.tsx
@@ -4,18 +4,20 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { useMemo } from 'react';
-import moment, { Moment } from 'moment';
-
-import { i18n } from '@kbn/i18n';
import {
- EuiDescribedFormGroup,
- EuiFormRow,
EuiDatePicker,
+ EuiDatePickerProps,
+ EuiDescribedFormGroup,
EuiFlexGroup,
EuiFormControlLayout,
+ EuiFormRow,
} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import moment, { Moment } from 'moment';
+import React, { useMemo } from 'react';
+
+import { euiStyled } from '../../../../../../../../common/eui_styled_components';
const startTimeLabel = i18n.translate('xpack.infra.analysisSetup.startTimeLabel', {
defaultMessage: 'Start time',
@@ -84,7 +86,7 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
setStartTime(undefined) } : undefined}
>
- setStartTime(selectedDateToParam(date))}
@@ -105,7 +107,7 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
setEndTime(undefined) } : undefined}
>
- setEndTime(selectedDateToParam(date))}
@@ -129,3 +131,18 @@ export const AnalysisSetupTimerangeForm: React.FunctionComponent<{
);
};
+
+const FixedDatePicker = euiStyled(
+ ({
+ className,
+ inputClassName,
+ ...datePickerProps
+ }: {
+ className?: string;
+ inputClassName?: string;
+ } & EuiDatePickerProps) => (
+
+ )
+)`
+ z-index: 3 !important;
+`;
diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx
index 87f0872c52343..a1710d67b31db 100644
--- a/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.test.tsx
@@ -10,7 +10,7 @@ import { act } from 'react-dom/test-utils';
import { buildExistsFilter } from '@kbn/es-query';
import { App } from './app';
import { EditorFrameInstance } from '../types';
-import { Storage } from 'ui/storage';
+import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { Document, SavedObjectStore } from '../persistence';
import { mount } from 'enzyme';
@@ -80,7 +80,7 @@ describe('Lens App', () => {
data: typeof dataStartMock;
core: typeof core;
dataShim: DataStart;
- store: Storage;
+ storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
redirectTo: (id?: string) => void;
@@ -97,6 +97,11 @@ describe('Lens App', () => {
},
},
},
+ data: {
+ query: {
+ filterManager: createMockFilterManager(),
+ },
+ },
dataShim: {
indexPatterns: {
indexPatterns: {
@@ -106,11 +111,8 @@ describe('Lens App', () => {
},
},
timefilter: { history: {} },
- filter: {
- filterManager: createMockFilterManager(),
- },
},
- store: {
+ storage: {
get: jest.fn(),
},
docStorage: {
@@ -123,7 +125,7 @@ describe('Lens App', () => {
data: typeof dataStartMock;
core: typeof core;
dataShim: DataStart;
- store: Storage;
+ storage: Storage;
docId?: string;
docStorage: SavedObjectStore;
redirectTo: (id?: string) => void;
@@ -592,7 +594,7 @@ describe('Lens App', () => {
const instance = mount();
- args.dataShim.filter.filterManager.setFilters([
+ args.data.query.filterManager.setFilters([
buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
]);
@@ -723,7 +725,7 @@ describe('Lens App', () => {
query: { query: 'new', language: 'lucene' },
});
- args.dataShim.filter.filterManager.setFilters([
+ args.data.query.filterManager.setFilters([
buildExistsFilter({ name: 'myfield' }, { id: 'index1' }),
]);
instance.update();
diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx
index bd75198714dc3..a95e0450f614c 100644
--- a/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx
+++ b/x-pack/legacy/plugins/lens/public/app_plugin/app.tsx
@@ -8,7 +8,6 @@ import _ from 'lodash';
import React, { useState, useEffect, useCallback } from 'react';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
-import { Storage } from 'ui/storage';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { SavedObjectSaveModal } from 'ui/saved_objects/components/saved_object_save_modal';
import { CoreStart, NotificationsStart } from 'src/core/public';
@@ -20,6 +19,7 @@ import {
Query,
} from 'src/legacy/core_plugins/data/public';
import { Filter } from '@kbn/es-query';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { start as navigation } from '../../../../../../src/legacy/core_plugins/navigation/public/legacy';
import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public';
import { Document, SavedObjectStore } from '../persistence';
@@ -49,7 +49,7 @@ export function App({
data,
dataShim,
core,
- store,
+ storage,
docId,
docStorage,
redirectTo,
@@ -58,14 +58,14 @@ export function App({
data: DataPublicPluginStart;
core: CoreStart;
dataShim: DataStart;
- store: Storage;
+ storage: IStorageWrapper;
docId?: string;
docStorage: SavedObjectStore;
redirectTo: (id?: string) => void;
}) {
const timeDefaults = core.uiSettings.get('timepicker:timeDefaults');
const language =
- store.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage');
+ storage.get('kibana.userQueryLanguage') || core.uiSettings.get('search:queryLanguage');
const [state, setState] = useState({
isLoading: !!docId,
@@ -82,10 +82,9 @@ export function App({
const { lastKnownDoc } = state;
useEffect(() => {
- const subscription = dataShim.filter.filterManager.getUpdates$().subscribe({
+ const subscription = data.query.filterManager.getUpdates$().subscribe({
next: () => {
- setState(s => ({ ...s, filters: dataShim.filter.filterManager.getFilters() }));
-
+ setState(s => ({ ...s, filters: data.query.filterManager.getFilters() }));
trackUiEvent('app_filters_updated');
},
});
@@ -171,7 +170,7 @@ export function App({
services={{
appName: 'lens',
data,
- store,
+ storage,
...core,
}}
>
@@ -227,9 +226,7 @@ export function App({
setState(s => ({ ...s, savedQuery }));
}}
onSavedQueryUpdated={savedQuery => {
- dataShim.filter.filterManager.setFilters(
- savedQuery.attributes.filters || state.filters
- );
+ data.query.filterManager.setFilters(savedQuery.attributes.filters || state.filters);
setState(s => ({
...s,
savedQuery: { ...savedQuery }, // Shallow query for reference issues
@@ -242,7 +239,7 @@ export function App({
}));
}}
onClearSavedQuery={() => {
- dataShim.filter.filterManager.removeAll();
+ data.query.filterManager.removeAll();
setState(s => ({
...s,
savedQuery: undefined,
@@ -250,7 +247,7 @@ export function App({
query: {
query: '',
language:
- store.get('kibana.userQueryLanguage') ||
+ storage.get('kibana.userQueryLanguage') ||
core.uiSettings.get('search:queryLanguage'),
},
}));
diff --git a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx
index b7960b23651c6..56c19ea2bb9f2 100644
--- a/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx
+++ b/x-pack/legacy/plugins/lens/public/app_plugin/plugin.tsx
@@ -8,12 +8,12 @@ import React from 'react';
import { I18nProvider, FormattedMessage } from '@kbn/i18n/react';
import { HashRouter, Switch, Route, RouteComponentProps } from 'react-router-dom';
import chrome from 'ui/chrome';
-import { Storage } from 'ui/storage';
import { CoreSetup, CoreStart } from 'src/core/public';
import { npSetup, npStart } from 'ui/new_platform';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { DataStart } from '../../../../../../src/legacy/core_plugins/data/public';
import { start as dataShimStart } from '../../../../../../src/legacy/core_plugins/data/public/legacy';
+import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { editorFrameSetup, editorFrameStart, editorFrameStop } from '../editor_frame_plugin';
import { indexPatternDatasourceSetup, indexPatternDatasourceStop } from '../indexpattern_plugin';
import { SavedObjectIndexStore } from '../persistence';
@@ -84,7 +84,7 @@ export class AppPlugin {
data={data}
dataShim={dataShim}
editorFrame={this.instance!}
- store={new Storage(localStorage)}
+ storage={new Storage(localStorage)}
docId={routeProps.match.params.id}
docStorage={store}
redirectTo={id => {
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
index fb3f8774be92a..79c4cc8d4529c 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.test.tsx
@@ -807,30 +807,38 @@ describe('editor_frame', () => {
await waitForPromises();
expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith(
- datasource1State,
- expect.anything(),
- 'first'
+ expect.objectContaining({
+ state: datasource1State,
+ setState: expect.anything(),
+ layerId: 'first',
+ })
);
expect(mockDatasource2.getPublicAPI).toHaveBeenCalledWith(
- datasource2State,
- expect.anything(),
- 'second'
+ expect.objectContaining({
+ state: datasource2State,
+ setState: expect.anything(),
+ layerId: 'second',
+ })
);
expect(mockDatasource2.getPublicAPI).toHaveBeenCalledWith(
- datasource2State,
- expect.anything(),
- 'third'
+ expect.objectContaining({
+ state: datasource2State,
+ setState: expect.anything(),
+ layerId: 'third',
+ })
);
});
it('should give access to the datasource state in the datasource factory function', async () => {
const datasourceState = {};
+ const dateRange = { fromDate: 'now-1w', toDate: 'now' };
mockDatasource.initialize.mockResolvedValue(datasourceState);
mockDatasource.getLayers.mockReturnValue(['first']);
mount(
{
await waitForPromises();
- expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith(
- datasourceState,
- expect.any(Function),
- 'first'
- );
+ expect(mockDatasource.getPublicAPI).toHaveBeenCalledWith({
+ dateRange,
+ state: datasourceState,
+ setState: expect.any(Function),
+ layerId: 'first',
+ });
});
it('should re-create the public api after state has been set', async () => {
@@ -872,15 +881,17 @@ describe('editor_frame', () => {
await waitForPromises();
const updatedState = {};
- const setDatasourceState = mockDatasource.getPublicAPI.mock.calls[0][1];
+ const setDatasourceState = mockDatasource.getPublicAPI.mock.calls[0][0].setState;
act(() => {
setDatasourceState(updatedState);
});
expect(mockDatasource.getPublicAPI).toHaveBeenLastCalledWith(
- updatedState,
- expect.any(Function),
- 'first'
+ expect.objectContaining({
+ state: updatedState,
+ setState: expect.any(Function),
+ layerId: 'first',
+ })
);
});
});
@@ -1509,7 +1520,7 @@ describe('editor_frame', () => {
query: { query: '', language: 'lucene' },
filters: [],
},
- title: 'New visualization',
+ title: '',
type: 'lens',
visualizationType: 'testVis',
},
@@ -1528,7 +1539,7 @@ describe('editor_frame', () => {
query: { query: '', language: 'lucene' },
filters: [],
},
- title: 'New visualization',
+ title: '',
type: 'lens',
visualizationType: 'testVis',
},
@@ -1585,7 +1596,7 @@ describe('editor_frame', () => {
query: { query: 'new query', language: 'lucene' },
filters: [],
},
- title: 'New visualization',
+ title: '',
type: 'lens',
visualizationType: 'testVis',
},
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
index 04c0b22c378d7..8e89d8edc9f23 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/editor_frame.tsx
@@ -89,9 +89,9 @@ export function EditorFrame(props: EditorFrameProps) {
const layers = datasource.getLayers(datasourceState);
layers.forEach(layer => {
- const publicAPI = props.datasourceMap[id].getPublicAPI(
- datasourceState,
- (newState: unknown) => {
+ const publicAPI = props.datasourceMap[id].getPublicAPI({
+ state: datasourceState,
+ setState: (newState: unknown) => {
dispatch({
type: 'UPDATE_DATASOURCE_STATE',
datasourceId: id,
@@ -99,8 +99,9 @@ export function EditorFrame(props: EditorFrameProps) {
clearStagedPreview: true,
});
},
- layer
- );
+ layerId: layer,
+ dateRange: props.dateRange,
+ });
datasourceLayers[layer] = publicAPI;
});
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
index 5104ace7c79a3..78a9a13f48d6a 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/state_management.ts
@@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { i18n } from '@kbn/i18n';
import { EditorFrameProps } from '../editor_frame';
import { Document } from '../../persistence/saved_object_store';
@@ -113,7 +112,7 @@ export const getInitialState = (props: EditorFrameProps): EditorFrameState => {
}
return {
- title: i18n.translate('xpack.lens.chartTitle', { defaultMessage: 'New visualization' }),
+ title: '',
datasourceStates,
activeDatasourceId: getInitialDatasourceId(props),
visualization: {
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
index 6aee215d11591..e29ac84486d0b 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/suggestion_panel.tsx
@@ -367,7 +367,12 @@ function getPreviewExpression(
const changedLayers = datasource.getLayers(visualizableState.datasourceState);
changedLayers.forEach(layerId => {
if (updatedLayerApis[layerId]) {
- updatedLayerApis[layerId] = datasource.getPublicAPI(datasourceState, () => {}, layerId);
+ updatedLayerApis[layerId] = datasource.getPublicAPI({
+ layerId,
+ dateRange: frame.dateRange,
+ state: datasourceState,
+ setState: () => {},
+ });
}
});
}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx
index 18d5feac4edbe..cc91510146f35 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/editor_frame/workspace_panel_wrapper.tsx
@@ -15,9 +15,11 @@ interface Props {
export function WorkspacePanelWrapper({ children, title }: Props) {
return (
-
- {title}
-
+ {title && (
+
+ {title}
+
+ )}
{children}
diff --git a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx
index f349585ce88a4..c3e91c9debcd0 100644
--- a/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx
+++ b/x-pack/legacy/plugins/lens/public/editor_frame_plugin/mocks.tsx
@@ -53,7 +53,7 @@ export function createMockDatasource(): DatasourceMock {
getDatasourceSuggestionsForField: jest.fn((_state, item) => []),
getDatasourceSuggestionsFromCurrentState: jest.fn(_state => []),
getPersistableState: jest.fn(),
- getPublicAPI: jest.fn((_state, _setState, _layerId) => publicAPIMock),
+ getPublicAPI: jest.fn().mockReturnValue(publicAPIMock),
initialize: jest.fn((_state?) => Promise.resolve()),
renderDataPanel: jest.fn(),
toExpression: jest.fn((_frame, _state) => null),
diff --git a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx
index 3865f08862e1c..74de7fe5c4fdc 100644
--- a/x-pack/legacy/plugins/lens/public/help_menu_util.tsx
+++ b/x-pack/legacy/plugins/lens/public/help_menu_util.tsx
@@ -47,7 +47,7 @@ function HelpMenu() {
-
+
{i18n.translate('xpack.lens.helpMenu.feedbackLinkText', {
defaultMessage: 'Provide feedback for the Lens application',
})}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts
index 359c6d7c35c3a..566e5bece096d 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/auto_date.ts
@@ -10,25 +10,38 @@ import {
ExpressionFunction,
KibanaContext,
} from '../../../../../../src/plugins/expressions/common';
+import { DateRange } from '../../common';
interface LensAutoDateProps {
aggConfigs: string;
}
-export function getAutoInterval(ctx?: KibanaContext | null) {
- if (!ctx || !ctx.timeRange) {
- return;
+export function autoIntervalFromDateRange(dateRange?: DateRange, defaultValue: string = '1h') {
+ if (!dateRange) {
+ return defaultValue;
}
- const { timeRange } = ctx;
const buckets = new TimeBuckets();
buckets.setInterval('auto');
buckets.setBounds({
- min: dateMath.parse(timeRange.from),
- max: dateMath.parse(timeRange.to, { roundUp: true }),
+ min: dateMath.parse(dateRange.fromDate),
+ max: dateMath.parse(dateRange.toDate, { roundUp: true }),
});
- return buckets.getInterval();
+ return buckets.getInterval().expression;
+}
+
+function autoIntervalFromContext(ctx?: KibanaContext | null) {
+ if (!ctx || !ctx.timeRange) {
+ return;
+ }
+
+ const { timeRange } = ctx;
+
+ return autoIntervalFromDateRange({
+ fromDate: timeRange.from,
+ toDate: timeRange.to,
+ });
}
/**
@@ -56,7 +69,7 @@ export const autoDate: ExpressionFunction<
},
},
fn(ctx: KibanaContext, args: LensAutoDateProps) {
- const interval = getAutoInterval(ctx);
+ const interval = autoIntervalFromContext(ctx);
if (!interval) {
return args.aggConfigs;
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
index 35bb3d2de0192..bd6dd6dca0c5b 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/datapanel.tsx
@@ -320,7 +320,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
className="euiFieldText euiFieldText--fullWidth lnsInnerIndexPatternDataPanel__textField"
data-test-subj="lnsIndexPatternFieldSearch"
placeholder={i18n.translate('xpack.lens.indexPatterns.filterByNameLabel', {
- defaultMessage: 'Search for fields',
+ defaultMessage: 'Search field names',
description:
'Search the list of fields in the index pattern for the provided text',
})}
@@ -339,7 +339,7 @@ export const InnerIndexPatternDataPanel = function InnerIndexPatternDataPanel({
id="dataPanelTypeFilter"
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
- anchorPosition="downLeft"
+ anchorPosition="rightDown"
display="block"
isOpen={localState.isTypeFilterOpen}
closePopover={() => setLocalState(() => ({ ...localState, isTypeFilterOpen: false }))}
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx
index 49a04e59b7cc9..81e0a214f93e3 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.test.tsx
@@ -18,7 +18,7 @@ import {
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { IndexPatternPrivateState } from '../types';
jest.mock('ui/new_platform');
@@ -129,11 +129,12 @@ describe('IndexPatternDimensionPanel', () => {
dragDropContext,
state,
setState,
+ dateRange: { fromDate: 'now-1d', toDate: 'now' },
columnId: 'col1',
layerId: 'first',
uniqueLabel: 'stuff',
filterOperations: () => true,
- storage: {} as Storage,
+ storage: {} as IStorageWrapper,
uiSettings: {} as UiSettingsClientContract,
savedObjectsClient: {} as SavedObjectsClientContract,
http: {} as HttpServiceBase,
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx
index c0c774a225642..fd4acef41f0bf 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/dimension_panel.tsx
@@ -7,13 +7,13 @@
import _ from 'lodash';
import React, { memo, useMemo } from 'react';
import { EuiButtonIcon } from '@elastic/eui';
-import { Storage } from 'ui/storage';
import { i18n } from '@kbn/i18n';
import {
UiSettingsClientContract,
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { DatasourceDimensionPanelProps, StateSetter } from '../../types';
import { IndexPatternColumn, OperationType } from '../indexpattern';
import { getAvailableOperationsByMetadata, buildColumn, changeField } from '../operations';
@@ -23,17 +23,19 @@ import { changeColumn, deleteColumn } from '../state_helpers';
import { isDraggedField, hasField } from '../utils';
import { IndexPatternPrivateState, IndexPatternField } from '../types';
import { trackUiEvent } from '../../lens_ui_telemetry';
+import { DateRange } from '../../../common';
export type IndexPatternDimensionPanelProps = DatasourceDimensionPanelProps & {
state: IndexPatternPrivateState;
setState: StateSetter;
dragDropContext: DragContextState;
uiSettings: UiSettingsClientContract;
- storage: Storage;
+ storage: IStorageWrapper;
savedObjectsClient: SavedObjectsClientContract;
layerId: string;
http: HttpServiceBase;
uniqueLabel: string;
+ dateRange: DateRange;
};
export interface OperationFieldSupportMatrix {
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx
index b9baa489f3382..ce30e1195f4ca 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/dimension_panel/popover_editor.tsx
@@ -354,7 +354,7 @@ export function PopoverEditor(props: PopoverEditorProps) {
defaultMessage: 'To use this function, select a field.',
})}
iconType="sortUp"
- >
+ />
)}
{!incompatibleSelectedOperationType && ParamEditor && (
<>
@@ -368,6 +368,7 @@ export function PopoverEditor(props: PopoverEditorProps) {
savedObjectsClient={props.savedObjectsClient}
layerId={layerId}
http={props.http}
+ dateRange={props.dateRange}
/>
>
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts
index b4f01078f1f78..9fb7be01642e5 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.test.ts
@@ -5,7 +5,7 @@
*/
import chromeMock from 'ui/chrome';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { SavedObjectsClientContract } from 'kibana/public';
import { getIndexPatternDatasource, IndexPatternColumn, uniqueLabels } from './indexpattern';
import { DatasourcePublicAPI, Operation, Datasource } from '../types';
@@ -143,7 +143,7 @@ describe('IndexPattern Data Source', () => {
beforeEach(() => {
indexPatternDatasource = getIndexPatternDatasource({
chrome: chromeMock,
- storage: {} as Storage,
+ storage: {} as IStorageWrapper,
core: coreMock.createStart(),
savedObjectsClient: {} as SavedObjectsClientContract,
data: pluginsMock.createStart().data,
@@ -414,7 +414,15 @@ describe('IndexPattern Data Source', () => {
beforeEach(async () => {
const initialState = stateFromPersistedState(persistedState);
- publicAPI = indexPatternDatasource.getPublicAPI(initialState, () => {}, 'first');
+ publicAPI = indexPatternDatasource.getPublicAPI({
+ state: initialState,
+ setState: () => {},
+ layerId: 'first',
+ dateRange: {
+ fromDate: 'now-30d',
+ toDate: 'now',
+ },
+ });
});
describe('getTableSpec', () => {
@@ -453,8 +461,8 @@ describe('IndexPattern Data Source', () => {
suggestedPriority: 2,
},
};
- const api = indexPatternDatasource.getPublicAPI(
- {
+ const api = indexPatternDatasource.getPublicAPI({
+ state: {
...initialState,
layers: {
first: {
@@ -465,8 +473,12 @@ describe('IndexPattern Data Source', () => {
},
},
setState,
- 'first'
- );
+ layerId: 'first',
+ dateRange: {
+ fromDate: 'now-1y',
+ toDate: 'now',
+ },
+ });
api.removeColumnInTableSpec('b');
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
index 359eb687b5741..bde5ce01aecda 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/indexpattern.tsx
@@ -9,13 +9,14 @@ import React from 'react';
import { render } from 'react-dom';
import { I18nProvider } from '@kbn/i18n/react';
import { CoreStart, SavedObjectsClientContract } from 'src/core/public';
-import { Storage } from 'ui/storage';
import { i18n } from '@kbn/i18n';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import {
DatasourceDimensionPanelProps,
DatasourceDataPanelProps,
Operation,
DatasourceLayerPanelProps,
+ PublicAPIProps,
} from '../types';
import { loadInitialState, changeIndexPattern, changeLayerIndexPattern } from './loader';
import { toExpression } from './to_expression';
@@ -104,7 +105,7 @@ export function getIndexPatternDatasource({
// Core start is being required here because it contains the savedObject client
// In the new platform, this plugin wouldn't be initialized until after setup
core: CoreStart;
- storage: Storage;
+ storage: IStorageWrapper;
savedObjectsClient: SavedObjectsClientContract;
data: ReturnType;
}) {
@@ -196,11 +197,12 @@ export function getIndexPatternDatasource({
);
},
- getPublicAPI(
- state: IndexPatternPrivateState,
- setState: StateSetter,
- layerId: string
- ) {
+ getPublicAPI({
+ state,
+ setState,
+ layerId,
+ dateRange,
+ }: PublicAPIProps) {
const columnLabelMap = uniqueLabels(state.layers);
return {
@@ -221,7 +223,7 @@ export function getIndexPatternDatasource({
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx
index f984597a8eb4b..d19493d579b64 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.test.tsx
@@ -8,17 +8,37 @@ import React from 'react';
import { DateHistogramIndexPatternColumn } from './date_histogram';
import { dateHistogramOperation } from '.';
import { shallow } from 'enzyme';
-import { EuiRange, EuiSwitch } from '@elastic/eui';
+import { EuiSwitch } from '@elastic/eui';
import {
UiSettingsClientContract,
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { createMockedIndexPattern } from '../../mocks';
import { IndexPatternPrivateState } from '../../types';
jest.mock('ui/new_platform');
+jest.mock('ui/chrome', () => ({
+ getUiSettingsClient: () => ({
+ get(path: string) {
+ if (path === 'histogram:maxBars') {
+ return 10;
+ }
+ },
+ }),
+}));
+
+const defaultOptions = {
+ storage: {} as IStorageWrapper,
+ uiSettings: {} as UiSettingsClientContract,
+ savedObjectsClient: {} as SavedObjectsClientContract,
+ dateRange: {
+ fromDate: 'now-1y',
+ toDate: 'now',
+ },
+ http: {} as HttpServiceBase,
+};
describe('date_histogram', () => {
let state: IndexPatternPrivateState;
@@ -72,7 +92,7 @@ describe('date_histogram', () => {
// Private
operationType: 'date_histogram',
params: {
- interval: 'w',
+ interval: '42w',
},
sourceField: 'timestamp',
},
@@ -118,6 +138,27 @@ describe('date_histogram', () => {
};
});
+ function stateWithInterval(interval: string) {
+ return ({
+ ...state,
+ layers: {
+ ...state.layers,
+ first: {
+ ...state.layers.first,
+ columns: {
+ ...state.layers.first.columns,
+ col1: {
+ ...state.layers.first.columns.col1,
+ params: {
+ interval,
+ },
+ },
+ },
+ },
+ },
+ } as unknown) as IndexPatternPrivateState;
+ }
+
describe('buildColumn', () => {
it('should create column object with auto interval for primary time field', () => {
const column = dateHistogramOperation.buildColumn({
@@ -188,7 +229,7 @@ describe('date_histogram', () => {
expect(esAggsConfig).toEqual(
expect.objectContaining({
params: expect.objectContaining({
- interval: 'w',
+ interval: '42w',
field: 'timestamp',
}),
})
@@ -217,7 +258,7 @@ describe('date_histogram', () => {
expect(column.label).toContain('start_date');
});
- it('should change interval from auto when switching to a non primary time field', () => {
+ it('should not change interval from auto when switching to a non primary time field', () => {
const oldColumn: DateHistogramIndexPatternColumn = {
operationType: 'date_histogram',
sourceField: 'timestamp',
@@ -233,7 +274,7 @@ describe('date_histogram', () => {
const column = dateHistogramOperation.onFieldChange(oldColumn, indexPattern, newDateField);
expect(column).toHaveProperty('sourceField', 'start_date');
- expect(column).toHaveProperty('params.interval', 'd');
+ expect(column).toHaveProperty('params.interval', 'auto');
expect(column.label).toContain('start_date');
});
});
@@ -281,7 +322,7 @@ describe('date_histogram', () => {
);
});
- it('should remove time zone param and normalize interval param', () => {
+ it('should retain interval', () => {
const transferedColumn = dateHistogramOperation.transfer!(
{
dataType: 'date',
@@ -309,7 +350,7 @@ describe('date_histogram', () => {
expect(transferedColumn).toEqual(
expect.objectContaining({
params: {
- interval: 'M',
+ interval: '20s',
timeZone: undefined,
},
})
@@ -322,55 +363,49 @@ describe('date_histogram', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
- expect(instance.find(EuiRange).prop('value')).toEqual(1);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual(42);
+ expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('w');
});
it('should render current value for other index pattern', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
- expect(instance.find(EuiRange).prop('value')).toEqual(2);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').prop('value')).toEqual('');
+ expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('value')).toEqual('d');
});
- it('should render disabled switch and no time intervals control for auto interval', () => {
+ it('should render disabled switch and no time interval control for auto interval', () => {
const instance = shallow(
);
- expect(instance.find(EuiRange).exists()).toBe(false);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy();
+ expect(instance.find('[data-test-subj="lensDateHistogramUnit"]').exists()).toBeFalsy();
expect(instance.find(EuiSwitch).prop('checked')).toBe(false);
});
@@ -378,15 +413,12 @@ describe('date_histogram', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
instance.find(EuiSwitch).prop('onChange')!({
@@ -394,57 +426,124 @@ describe('date_histogram', () => {
} as React.ChangeEvent
);
expect(setStateSpy).toHaveBeenCalled();
const newState = setStateSpy.mock.calls[0][0];
- expect(newState).toHaveProperty('layers.third.columns.col1.params.interval', 'd');
+ expect(newState).toHaveProperty('layers.third.columns.col1.params.interval', '30d');
});
- it('should update state with the interval value', () => {
+ it('should force calendar values to 1', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
+ instance.find('[data-test-subj="lensDateHistogramValue"]').prop('onChange')!({
+ target: {
+ value: '2',
+ },
+ } as React.ChangeEvent);
+ expect(setStateSpy).toHaveBeenCalledWith(stateWithInterval('1w'));
+ });
- instance.find(EuiRange).prop('onChange')!(
- {
- target: {
- value: '2',
- },
- } as React.ChangeEvent,
- true
+ it('should display error if an invalid interval is specified', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('4quid');
+ const instance = shallow(
+
);
- expect(setStateSpy).toHaveBeenCalledWith({
- ...state,
- layers: {
- ...state.layers,
- first: {
- ...state.layers.first,
- columns: {
- ...state.layers.first.columns,
- col1: {
- ...state.layers.first.columns.col1,
- params: {
- interval: 'd',
- },
- },
- },
- },
+ expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy();
+ });
+
+ it('should not display error if interval value is blank', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('d');
+ const instance = shallow(
+
+ );
+ expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeFalsy();
+ });
+
+ it('should display error if interval value is 0', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('0d');
+ const instance = shallow(
+
+ );
+ expect(instance.find('[data-test-subj="lensDateHistogramError"]').exists()).toBeTruthy();
+ });
+
+ it('should update the unit', () => {
+ const setStateSpy = jest.fn();
+ const instance = shallow(
+
+ );
+ instance.find('[data-test-subj="lensDateHistogramUnit"]').prop('onChange')!({
+ target: {
+ value: 'd',
},
- });
+ } as React.ChangeEvent);
+ expect(setStateSpy).toHaveBeenCalledWith(stateWithInterval('42d'));
+ });
+
+ it('should update the value', () => {
+ const setStateSpy = jest.fn();
+ const testState = stateWithInterval('42d');
+
+ const instance = shallow(
+
+ );
+ instance.find('[data-test-subj="lensDateHistogramValue"]').prop('onChange')!({
+ target: {
+ value: '9',
+ },
+ } as React.ChangeEvent);
+ expect(setStateSpy).toHaveBeenCalledWith(stateWithInterval('9d'));
});
it('should not render options if they are restricted', () => {
const setStateSpy = jest.fn();
const instance = shallow(
{
columnId="col1"
layerId="first"
currentColumn={state.layers.first.columns.col1 as DateHistogramIndexPatternColumn}
- storage={{} as Storage}
- uiSettings={{} as UiSettingsClientContract}
- savedObjectsClient={{} as SavedObjectsClientContract}
- http={{} as HttpServiceBase}
/>
);
- expect(instance.find(EuiRange)).toHaveLength(0);
+ expect(instance.find('[data-test-subj="lensDateHistogramValue"]').exists()).toBeFalsy();
});
});
});
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
index e5c00542df7d3..017dccab64607 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/date_histogram.tsx
@@ -7,31 +7,29 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiForm, EuiFormRow, EuiRange, EuiSwitch } from '@elastic/eui';
+
+// TODO: make this new-platform compatible
+import { isValidInterval } from 'ui/agg_types/utils';
+
+import {
+ EuiForm,
+ EuiFormRow,
+ EuiSwitch,
+ EuiFieldNumber,
+ EuiSelect,
+ EuiFlexItem,
+ EuiFlexGroup,
+ EuiTextColor,
+ EuiSpacer,
+} from '@elastic/eui';
import { updateColumnParam } from '../../state_helpers';
import { OperationDefinition } from '.';
import { FieldBasedIndexPatternColumn } from './column_types';
-import { IndexPattern } from '../../types';
-
-type PropType = C extends React.ComponentType ? P : unknown;
+import { autoIntervalFromDateRange } from '../../auto_date';
+import { AggregationRestrictions } from '../../types';
const autoInterval = 'auto';
-const supportedIntervals = ['M', 'w', 'd', 'h', 'm'];
-const defaultCustomInterval = supportedIntervals[2];
-
-// Add ticks to EuiRange component props
-const FixedEuiRange = (EuiRange as unknown) as React.ComponentType<
- PropType & {
- ticks?: Array<{
- label: string;
- value: number;
- }>;
- }
->;
-
-function supportsAutoInterval(fieldName: string, indexPattern: IndexPattern): boolean {
- return indexPattern.timeFieldName ? indexPattern.timeFieldName === fieldName : false;
-}
+const calendarOnlyIntervals = new Set(['w', 'M', 'q', 'y']);
export interface DateHistogramIndexPatternColumn extends FieldBasedIndexPatternColumn {
operationType: 'date_histogram';
@@ -59,12 +57,11 @@ export const dateHistogramOperation: OperationDefinition {
return {
...oldColumn,
label: field.name,
sourceField: field.name,
- params: {
- ...oldColumn.params,
- // If we have an "auto" interval but the field we're switching to doesn't support auto intervals
- // we use the default custom interval instead
- interval:
- oldColumn.params.interval === 'auto' && !supportsAutoInterval(field.name, indexPattern)
- ? defaultCustomInterval
- : oldColumn.params.interval,
- },
};
},
toEsAggsConfig: (column, columnId) => ({
@@ -157,7 +135,7 @@ export const dateHistogramOperation: OperationDefinition {
+ paramEditor: ({ state, setState, currentColumn: currentColumn, layerId, dateRange }) => {
const field =
currentColumn &&
state.indexPatterns[state.layers[layerId].indexPatternId].fields.find(
@@ -166,20 +144,35 @@ export const dateHistogramOperation: OperationDefinition) {
- const interval = ev.target.checked ? defaultCustomInterval : autoInterval;
+ const value = ev.target.checked ? autoIntervalFromDateRange(dateRange) : autoInterval;
+ setState(updateColumnParam({ state, layerId, currentColumn, paramName: 'interval', value }));
+ }
+
+ const setInterval = (newInterval: typeof interval) => {
+ const isCalendarInterval = calendarOnlyIntervals.has(newInterval.unit);
+ const value = `${isCalendarInterval ? '1' : newInterval.value}${newInterval.unit || 'd'}`;
+
setState(
- updateColumnParam({ state, layerId, currentColumn, paramName: 'interval', value: interval })
+ updateColumnParam({
+ state,
+ layerId,
+ currentColumn,
+ value,
+ paramName: 'interval',
+ })
);
- }
+ };
return (
@@ -187,7 +180,7 @@ export const dateHistogramOperation: OperationDefinition
{intervalIsRestricted ? (
@@ -209,33 +202,101 @@ export const dateHistogramOperation: OperationDefinition
) : (
- ({
- label: interval,
- value: index,
- }))}
- onChange={(
- e: React.ChangeEvent | React.MouseEvent
- ) =>
- setState(
- updateColumnParam({
- state,
- layerId,
- currentColumn,
- paramName: 'interval',
- value: numericToInterval(Number((e.target as HTMLInputElement).value)),
- })
- )
- }
- aria-label={i18n.translate('xpack.lens.indexPattern.dateHistogram.interval', {
- defaultMessage: 'Time intervals',
- })}
- />
+ <>
+
+
+ {
+ setInterval({
+ ...interval,
+ value: e.target.value,
+ });
+ }}
+ />
+
+
+ {
+ setInterval({
+ ...interval,
+ unit: e.target.value,
+ });
+ }}
+ isInvalid={!isValid}
+ options={[
+ {
+ value: 'ms',
+ text: i18n.translate(
+ 'xpack.lens.indexPattern.dateHistogram.milliseconds',
+ {
+ defaultMessage: 'milliseconds',
+ }
+ ),
+ },
+ {
+ value: 's',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.seconds', {
+ defaultMessage: 'seconds',
+ }),
+ },
+ {
+ value: 'm',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.minutes', {
+ defaultMessage: 'minutes',
+ }),
+ },
+ {
+ value: 'h',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.hours', {
+ defaultMessage: 'hours',
+ }),
+ },
+ {
+ value: 'd',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.days', {
+ defaultMessage: 'days',
+ }),
+ },
+ {
+ value: 'w',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.week', {
+ defaultMessage: 'week',
+ }),
+ },
+ {
+ value: 'M',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.month', {
+ defaultMessage: 'month',
+ }),
+ },
+ // Quarterly intervals appear to be unsupported by esaggs
+ {
+ value: 'y',
+ text: i18n.translate('xpack.lens.indexPattern.dateHistogram.year', {
+ defaultMessage: 'year',
+ }),
+ },
+ ]}
+ />
+
+
+ {!isValid && (
+ <>
+
+
+ {i18n.translate('xpack.lens.indexPattern.invalidInterval', {
+ defaultMessage: 'Invalid interval value',
+ })}
+
+ >
+ )}
+ >
)}
)}
@@ -243,3 +304,26 @@ export const dateHistogramOperation: OperationDefinition {
columnId: string;
layerId: string;
uiSettings: UiSettingsClientContract;
- storage: Storage;
+ storage: IStorageWrapper;
savedObjectsClient: SavedObjectsClientContract;
http: HttpServiceBase;
+ dateRange: DateRange;
}
interface BaseOperationDefinitionProps {
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
index df5bfac6d03a4..9fba3e205dd45 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/operations/definitions/terms.test.tsx
@@ -12,7 +12,7 @@ import {
SavedObjectsClientContract,
HttpServiceBase,
} from 'src/core/public';
-import { Storage } from 'ui/storage';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { createMockedIndexPattern } from '../../mocks';
import { TermsIndexPatternColumn } from './terms';
import { termsOperation } from '.';
@@ -20,6 +20,14 @@ import { IndexPatternPrivateState } from '../../types';
jest.mock('ui/new_platform');
+const defaultProps = {
+ storage: {} as IStorageWrapper,
+ uiSettings: {} as UiSettingsClientContract,
+ savedObjectsClient: {} as SavedObjectsClientContract,
+ dateRange: { fromDate: 'now-1d', toDate: 'now' },
+ http: {} as HttpServiceBase,
+};
+
describe('terms', () => {
let state: IndexPatternPrivateState;
const InlineOptions = termsOperation.paramEditor!;
@@ -324,15 +332,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -350,15 +355,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -398,15 +400,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -422,15 +421,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -467,15 +463,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
@@ -486,15 +479,12 @@ describe('terms', () => {
const setStateSpy = jest.fn();
const instance = shallow(
);
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx
index 9c4835437546e..4dde289259c41 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/plugin.tsx
@@ -8,8 +8,8 @@ import { Registry } from '@kbn/interpreter/target/common';
import { CoreSetup } from 'src/core/public';
// The following dependencies on ui/* and src/legacy/core_plugins must be mocked when testing
import chrome, { Chrome } from 'ui/chrome';
-import { Storage } from 'ui/storage';
import { npSetup, npStart } from 'ui/new_platform';
+import { Storage } from '../../../../../../src/plugins/kibana_utils/public';
import { ExpressionFunction } from '../../../../../../src/legacy/core_plugins/interpreter/public';
import { functionsRegistry } from '../../../../../../src/legacy/core_plugins/interpreter/public/registries';
import { getIndexPatternDatasource } from './indexpattern';
diff --git a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
index 3bf3be41f4c89..9ed5083633314 100644
--- a/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
+++ b/x-pack/legacy/plugins/lens/public/indexpattern_plugin/types.ts
@@ -20,25 +20,27 @@ export interface IndexPattern {
>;
}
+export type AggregationRestrictions = Partial<
+ Record<
+ string,
+ {
+ agg: string;
+ interval?: number;
+ fixed_interval?: string;
+ calendar_interval?: string;
+ delay?: string;
+ time_zone?: string;
+ }
+ >
+>;
+
export interface IndexPatternField {
name: string;
type: string;
esTypes?: string[];
aggregatable: boolean;
searchable: boolean;
- aggregationRestrictions?: Partial<
- Record<
- string,
- {
- agg: string;
- interval?: number;
- fixed_interval?: string;
- calendar_interval?: string;
- delay?: string;
- time_zone?: string;
- }
- >
- >;
+ aggregationRestrictions?: AggregationRestrictions;
}
export interface IndexPatternLayer {
diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts
index 6e860c594f4a5..15d36a7c31169 100644
--- a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts
+++ b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.test.ts
@@ -11,9 +11,9 @@ import {
trackUiEvent,
trackSuggestionEvent,
} from './factory';
-import { Storage } from 'src/legacy/core_plugins/data/public/types';
import { coreMock } from 'src/core/public/mocks';
import { HttpServiceBase } from 'kibana/public';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
jest.useFakeTimers();
@@ -30,7 +30,7 @@ const createMockStorage = () => {
};
describe('Lens UI telemetry', () => {
- let storage: jest.Mocked;
+ let storage: jest.Mocked;
let http: jest.Mocked;
let dateSpy: jest.SpyInstance;
diff --git a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts
index 673910deae339..1a8ec604eda54 100644
--- a/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts
+++ b/x-pack/legacy/plugins/lens/public/lens_ui_telemetry/factory.ts
@@ -7,7 +7,7 @@
import moment from 'moment';
import { HttpServiceBase } from 'src/core/public';
-import { Storage } from 'src/legacy/core_plugins/data/public/types';
+import { IStorageWrapper } from 'src/plugins/kibana_utils/public';
import { BASE_API_URL } from '../../common';
const STORAGE_KEY = 'lens-ui-telemetry';
@@ -43,11 +43,11 @@ export class LensReportManager {
private events: Record> = {};
private suggestionEvents: Record> = {};
- private storage: Storage;
+ private storage: IStorageWrapper;
private http: HttpServiceBase;
private timer: ReturnType;
- constructor({ storage, http }: { storage: Storage; http: HttpServiceBase }) {
+ constructor({ storage, http }: { storage: IStorageWrapper; http: HttpServiceBase }) {
this.storage = storage;
this.http = http;
diff --git a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts
index 8c0b9cb25300d..562d0f0ef6135 100644
--- a/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts
+++ b/x-pack/legacy/plugins/lens/public/register_vis_type_alias.ts
@@ -20,7 +20,7 @@ visualizations.types.registerAlias({
}),
},
title: i18n.translate('xpack.lens.visTypeAlias.title', {
- defaultMessage: 'Lens Visualizations',
+ defaultMessage: 'Lens',
}),
description: i18n.translate('xpack.lens.visTypeAlias.description', {
defaultMessage: `Lens is a simpler way to create basic visualizations`,
diff --git a/x-pack/legacy/plugins/lens/public/types.ts b/x-pack/legacy/plugins/lens/public/types.ts
index 1efa123f4f0a3..93b8f93cbd2ff 100644
--- a/x-pack/legacy/plugins/lens/public/types.ts
+++ b/x-pack/legacy/plugins/lens/public/types.ts
@@ -13,19 +13,24 @@ import { SavedQuery } from 'src/legacy/core_plugins/data/public';
import { KibanaDatatable } from '../../../../../src/legacy/core_plugins/interpreter/common';
import { DragContextState } from './drag_drop';
import { Document } from './persistence';
+import { DateRange } from '../common';
// eslint-disable-next-line
export interface EditorFrameOptions {}
export type ErrorCallback = (e: { message: string }) => void;
+export interface PublicAPIProps {
+ state: T;
+ setState: StateSetter;
+ layerId: string;
+ dateRange: DateRange;
+}
+
export interface EditorFrameProps {
onError: ErrorCallback;
doc?: Document;
- dateRange: {
- fromDate: string;
- toDate: string;
- };
+ dateRange: DateRange;
query: Query;
filters: Filter[];
savedQuery?: SavedQuery;
@@ -138,7 +143,7 @@ export interface Datasource {
getDatasourceSuggestionsForField: (state: T, field: unknown) => Array>;
getDatasourceSuggestionsFromCurrentState: (state: T) => Array>;
- getPublicAPI: (state: T, setState: StateSetter, layerId: string) => DatasourcePublicAPI;
+ getPublicAPI: (props: PublicAPIProps) => DatasourcePublicAPI;
}
/**
@@ -171,7 +176,7 @@ export interface DatasourceDataPanelProps {
setState: StateSetter;
core: Pick;
query: Query;
- dateRange: FramePublicAPI['dateRange'];
+ dateRange: DateRange;
filters: Filter[];
}
@@ -296,10 +301,7 @@ export interface VisualizationSuggestion {
export interface FramePublicAPI {
datasourceLayers: Record;
- dateRange: {
- fromDate: string;
- toDate: string;
- };
+ dateRange: DateRange;
query: Query;
filters: Filter[];
diff --git a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
index 41b5d5a70ae67..9d5e91c2d5f16 100644
--- a/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
+++ b/x-pack/legacy/plugins/license_management/__jest__/__snapshots__/upload_license.test.js.snap
@@ -330,7 +330,11 @@ exports[`UploadLicense should display a modal when license requires acknowledgem
as="div"
autoFocus={true}
disabled={false}
- lockProps={Object {}}
+ lockProps={
+ Object {
+ "style": undefined,
+ }
+ }
noFocusGuards={false}
persistentFocus={false}
returnFocus={true}
diff --git a/x-pack/legacy/plugins/maps/index.js b/x-pack/legacy/plugins/maps/index.js
index 3bb9d48741ab9..a8cc328e532e5 100644
--- a/x-pack/legacy/plugins/maps/index.js
+++ b/x-pack/legacy/plugins/maps/index.js
@@ -43,6 +43,7 @@ export function maps(kibana) {
const mapConfig = serverConfig.get('map');
return {
+ showMapVisualizationTypes: serverConfig.get('xpack.maps.showMapVisualizationTypes'),
showMapsInspectorAdapter: serverConfig.get('xpack.maps.showMapsInspectorAdapter'),
preserveDrawingBuffer: serverConfig.get('xpack.maps.preserveDrawingBuffer'),
isEmsEnabled: mapConfig.includeElasticMapsService,
@@ -92,6 +93,7 @@ export function maps(kibana) {
config(Joi) {
return Joi.object({
enabled: Joi.boolean().default(true),
+ showMapVisualizationTypes: Joi.boolean().default(false),
showMapsInspectorAdapter: Joi.boolean().default(false), // flag used in functional testing
preserveDrawingBuffer: Joi.boolean().default(false), // flag used in functional testing
}).default();
diff --git a/x-pack/legacy/plugins/maps/public/angular/map_controller.js b/x-pack/legacy/plugins/maps/public/angular/map_controller.js
index d8f957bd38199..cef2a70a6d03d 100644
--- a/x-pack/legacy/plugins/maps/public/angular/map_controller.js
+++ b/x-pack/legacy/plugins/maps/public/angular/map_controller.js
@@ -7,6 +7,7 @@
import _ from 'lodash';
import chrome from 'ui/chrome';
import 'ui/directives/listen';
+import 'ui/directives/storage';
import React from 'react';
import { I18nProvider } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
@@ -54,6 +55,7 @@ import {
} from '../../common/constants';
import { FilterStateStore } from '@kbn/es-query';
import { start as data } from '../../../../../../src/legacy/core_plugins/data/public/legacy';
+import { npStart } from 'ui/new_platform';
const { savedQueryService } = data.search.services;
@@ -62,7 +64,7 @@ const REACT_ANCHOR_DOM_ELEMENT_ID = 'react-maps-root';
const app = uiModules.get(MAP_APP_PATH, []);
app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppState, globalState) => {
-
+ const { filterManager } = npStart.plugins.data.query;
const savedMap = $route.current.locals.map;
let unsubscribe;
let initialLayerListConfig;
@@ -98,7 +100,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
$scope.$evalAsync(() => {
// appState
$state.query = $scope.query;
- $state.filters = data.filter.filterManager.getAppFilters();
+ $state.filters = filterManager.getAppFilters();
$state.save();
// globalState
@@ -107,7 +109,7 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
pause: $scope.refreshConfig.isPaused,
value: $scope.refreshConfig.interval,
};
- globalState.filters = data.filter.filterManager.getGlobalFilters();
+ globalState.filters = filterManager.getGlobalFilters();
globalState.save();
});
}
@@ -198,8 +200,8 @@ app.controller('GisMapController', ($scope, $route, kbnUrl, localStorage, AppSta
/* End of Saved Queries */
async function onQueryChange({ filters, query, time }) {
if (filters) {
- await data.filter.filterManager.setFilters(filters); // Maps and merges filters
- $scope.filters = data.filter.filterManager.getFilters();
+ filterManager.setFilters(filters); // Maps and merges filters
+ $scope.filters = filterManager.getFilters();
}
if (query) {
$scope.query = query;
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap
index c3d4ff673e3d5..4377fa4725483 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/__snapshots__/view.test.js.snap
@@ -6,7 +6,7 @@ exports[`LayerPanel is rendered 1`] = `
Object {
"appName": "maps",
"data": undefined,
- "store": Storage {
+ "storage": Storage {
"clear": [Function],
"get": [Function],
"remove": [Function],
diff --git a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js
index 28afabc40bd75..78cb8aa827e35 100644
--- a/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js
+++ b/x-pack/legacy/plugins/maps/public/connected_components/layer_panel/view.js
@@ -30,8 +30,8 @@ import {
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { KibanaContextProvider } from '../../../../../../../src/plugins/kibana_react/public';
+import { Storage } from '../../../../../../../src/plugins/kibana_utils/public';
-import { Storage } from 'ui/storage';
const localStorage = new Storage(window.localStorage);
// This import will eventually become a dependency injected by the fully deangularized NP plugin.
@@ -154,7 +154,7 @@ export class LayerPanel extends React.Component {
= memo(({ score, multiBucketImp
+ />
{severity}
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js b/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js
index 28c616d3e74a6..5e9cd19ab388a 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/file_based/components/about_panel/welcome_content.js
@@ -133,7 +133,7 @@ export function WelcomeContent() {
values={{
githubLink: (
GitHub
diff --git a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
index c8295a1e3d8db..fca2508cb5d14 100644
--- a/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
+++ b/x-pack/legacy/plugins/ml/public/datavisualizer/index_based/components/actions_panel/actions_panel.tsx
@@ -64,7 +64,7 @@ export const ActionsPanel: FC = ({ indexPattern }) => {
-
+
diff --git a/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js b/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
index 133adea7cff6e..0c356959cd2af 100644
--- a/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
+++ b/x-pack/legacy/plugins/ml/public/jobs/jobs_list/components/start_datafeed_modal/start_datafeed_modal.js
@@ -136,6 +136,7 @@ export class StartDatafeedModal extends Component {
onClose={this.closeModal}
style={{ width: '850px' }}
maxWidth={false}
+ data-test-subj="mlStartDatafeedModal"
>