Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3dcb984
security explorer
shahzad31 Nov 25, 2021
2a09b40
update
shahzad31 Nov 25, 2021
02cb107
Merge branch 'main' of github.com:elastic/kibana into security-example
shahzad31 Nov 29, 2021
15a2712
add embeddable hosts
shahzad31 Nov 29, 2021
a922a7f
add user authentications and unique ips
angorayc Nov 30, 2021
07e7a04
bar charts
angorayc Dec 1, 2021
a87f877
polish things
shahzad31 Dec 3, 2021
cf900a2
rev ind
shahzad31 Dec 3, 2021
2415486
single metric
shahzad31 Dec 3, 2021
c20103e
Merge remote-tracking branch 'upstream/main' into exploratory-view
angorayc Dec 13, 2021
3212d0c
styling
angorayc Dec 13, 2021
8240fe2
styling
angorayc Dec 14, 2021
d96f0cc
clean up
angorayc Dec 15, 2021
322f8e1
hosts page
angorayc Dec 31, 2021
ce872f7
network page
angorayc Jan 4, 2022
6392544
Merge branch 'main' of github.com:elastic/kibana into exploratory-view
shahzad31 Jan 5, 2022
5d9ffd1
push fixes
shahzad31 Jan 6, 2022
a650b6a
update events chart
shahzad31 Jan 6, 2022
e5316c4
remove status pallete
shahzad31 Jan 6, 2022
d93f9b5
Merge branch 'main' of github.com:elastic/kibana into exploratory-view
shahzad31 Jan 11, 2022
aa18365
fixes
shahzad31 Jan 11, 2022
599ee6c
update hard coded indexPatternList
angorayc Jan 12, 2022
66e9585
add extra actions
shahzad31 Jan 16, 2022
d7a6f1c
Merge branch 'lens-extra-actions' into exploratory-view
shahzad31 Jan 16, 2022
373ce46
move explore into actions
shahzad31 Jan 17, 2022
e7343a9
add dns and external alerts
angorayc Jan 24, 2022
e0dd0d1
dns chart with lens attributes
angorayc Feb 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/plugins/embeddable/public/lib/panel/embeddable_panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ interface Props {
actionPredicate?: (actionId: string) => boolean;
reportUiCounter?: UsageCollectionStart['reportUiCounter'];
showShadow?: boolean;
hasBorder?: boolean;
showBadges?: boolean;
showNotifications?: boolean;
containerContext?: EmbeddableContainerContext;
Expand Down Expand Up @@ -273,6 +274,7 @@ export class EmbeddablePanel extends React.Component<Props, State> {
role="figure"
aria-labelledby={headerId}
hasShadow={this.props.showShadow}
hasBorder={false}
>
{!this.props.hideHeader && (
<PanelHeader
Expand Down
7 changes: 4 additions & 3 deletions x-pack/examples/exploratory_view_example/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
"server": false,
"ui": true,
"requiredPlugins": [
"observability",
"cases",
"data",
"developerExamples",
"embeddable",
"developerExamples"
"observability"
],
"optionalPlugins": [],
"requiredBundles": [],
"requiredBundles": ["kibanaReact"],
"owner": {
"name": "`Synthetics team`",
"githubTeam": "uptime"
Expand Down
1 change: 1 addition & 0 deletions x-pack/examples/exploratory_view_example/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const App = (props: {
attributes={seriesList}
reportType="kpi-over-time"
title={'Monitor response duration'}
withActions={['save', 'explore']}
/>
</EuiPageContentBody>
</EuiPageContent>
Expand Down
17 changes: 12 additions & 5 deletions x-pack/examples/exploratory_view_example/public/mount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

import * as React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { CoreSetup, AppMountParameters } from 'kibana/public';
import { CoreSetup, AppMountParameters, APP_WRAPPER_CLASS } from '../../../../src/core/public';
import { StartDependencies } from './plugin';

import {
KibanaContextProvider,
RedirectAppLinks,
} from '../../../../src/plugins/kibana_react/public';
export const mount =
(coreSetup: CoreSetup<StartDependencies>) =>
async ({ element }: AppMountParameters) => {
Expand All @@ -26,9 +29,13 @@ export const mount =
const i18nCore = core.i18n;

const reactElement = (
<i18nCore.Context>
<App {...deps} defaultIndexPattern={defaultIndexPattern} />
</i18nCore.Context>
<KibanaContextProvider services={{ ...coreSetup, ...core, ...plugins }}>
<i18nCore.Context>
<RedirectAppLinks application={core.application} className={APP_WRAPPER_CLASS}>
<App {...deps} defaultIndexPattern={defaultIndexPattern} />
</RedirectAppLinks>
</i18nCore.Context>
</KibanaContextProvider>
);
render(reactElement, element);
return () => unmountComponentAtNode(element);
Expand Down
23 changes: 17 additions & 6 deletions x-pack/plugins/lens/public/embeddable/embeddable_component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import React, { FC, useEffect } from 'react';
import type { CoreStart, ThemeServiceStart } from 'kibana/public';
import type { UiActionsStart } from 'src/plugins/ui_actions/public';
import type { Action, UiActionsStart } from 'src/plugins/ui_actions/public';
import type { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { EuiLoadingChart } from '@elastic/eui';
import {
Expand Down Expand Up @@ -52,7 +52,7 @@ export type TypedLensByValueInput = Omit<LensByValueInput, 'attributes'> & {
};

export type EmbeddableComponentProps = (TypedLensByValueInput | LensByReferenceInput) & {
withActions?: boolean;
withActions?: boolean | Action[];
};

interface PluginsStartDependencies {
Expand All @@ -67,7 +67,7 @@ export function getEmbeddableComponent(core: CoreStart, plugins: PluginsStartDep
const factory = embeddableStart.getEmbeddableFactory('lens')!;
const input = { ...props };
const [embeddable, loading, error] = useEmbeddableFactory({ factory, input });
const hasActions = props.withActions === true;
const hasActions = Boolean(props.withActions);
const theme = core.theme;

if (loading) {
Expand All @@ -83,6 +83,7 @@ export function getEmbeddableComponent(core: CoreStart, plugins: PluginsStartDep
actionPredicate={() => hasActions}
input={input}
theme={theme}
extraActions={Array.isArray(props.withActions) ? props.withActions : []}
/>
);
}
Expand All @@ -98,6 +99,9 @@ interface EmbeddablePanelWrapperProps {
actionPredicate: (id: string) => boolean;
input: EmbeddableComponentProps;
theme: ThemeServiceStart;
hideHeader?: boolean;
showShadow?: boolean;
extraActions: Action[];
}

const EmbeddablePanelWrapper: FC<EmbeddablePanelWrapperProps> = ({
Expand All @@ -107,22 +111,29 @@ const EmbeddablePanelWrapper: FC<EmbeddablePanelWrapperProps> = ({
inspector,
input,
theme,
extraActions,
hideHeader = false,
showShadow = false,
}) => {
useEffect(() => {
embeddable.updateInput(input);
}, [embeddable, input]);

return (
<EmbeddablePanel
hideHeader={false}
hideHeader={hideHeader}
embeddable={embeddable as IEmbeddable<EmbeddableInput, EmbeddableOutput>}
getActions={uiActions.getTriggerCompatibleActions}
getActions={async (triggerId, context) => {
const actions = await uiActions.getTriggerCompatibleActions(triggerId, context);
return [...extraActions, ...actions];
}}
inspector={inspector}
actionPredicate={actionPredicate}
showShadow={false}
showShadow={showShadow}
showBadges={false}
showNotifications={false}
theme={theme}
hasBorder={false}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function SeriesDatePicker({ series, seriesId }: Props) {
const { setSeries, reportType, allSeries } = useSeriesStorage();

function onTimeChange({ start, end }: { start: string; end: string }) {
onRefreshTimeRange();
onRefreshTimeRange?.();
if (reportType === ReportTypes.KPI) {
allSeries.forEach((currSeries, seriesIndex) => {
setSeries(seriesIndex, { ...currSeries, time: { from: start, to: end } });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {
PERCENTILE_RANKS,
ReportTypes,
} from './constants';
import { ColumnFilter, SeriesConfig, UrlFilter, URLReportDefinition } from '../types';
import { ColumnFilter, ParamFilter, SeriesConfig, UrlFilter, URLReportDefinition } from '../types';
import { PersistableFilter } from '../../../../../../lens/common';
import { parseRelativeDate } from '../components/date_range_picker';
import { getDistributionInPercentageColumn } from './lens_columns/overall_column';
Expand All @@ -63,6 +63,8 @@ function buildNumberColumn(sourceField: string) {
export const parseCustomFieldName = (seriesConfig: SeriesConfig, selectedMetricField?: string) => {
let columnType;
let columnFilters;
let columnFilter;
let paramFilters;
let timeScale;
let columnLabel;

Expand All @@ -75,12 +77,22 @@ export const parseCustomFieldName = (seriesConfig: SeriesConfig, selectedMetricF
);
columnType = currField?.columnType;
columnFilters = currField?.columnFilters;
columnFilter = currField?.columnFilter;
timeScale = currField?.timeScale;
columnLabel = currField?.label;
paramFilters = currField?.paramFilters;
}
}

return { fieldName: selectedMetricField!, columnType, columnFilters, timeScale, columnLabel };
return {
fieldName: selectedMetricField!,
columnType,
columnFilters,
paramFilters,
timeScale,
columnLabel,
columnFilter,
};
};

export interface LayerConfig {
Expand All @@ -103,12 +115,14 @@ export class LensAttributes {
layerConfigs: LayerConfig[];
isMultiSeries: boolean;
globalFilter?: { query: string; language: string };
reportType: string;

constructor(layerConfigs: LayerConfig[]) {
constructor(layerConfigs: LayerConfig[], reportType: string) {
this.layers = {};
this.reportType = reportType;

layerConfigs.forEach(({ seriesConfig, operationType }) => {
if (operationType) {
if (operationType && reportType !== 'singleMetric') {
seriesConfig.yAxisColumns.forEach((yAxisColumn) => {
if (typeof yAxisColumn.operationType !== undefined) {
yAxisColumn.operationType =
Expand All @@ -121,7 +135,11 @@ export class LensAttributes {
this.layerConfigs = layerConfigs;
this.isMultiSeries = layerConfigs.length > 1;
this.globalFilter = this.getGlobalFilter(this.isMultiSeries);
this.layers = this.getLayers();
if (reportType === 'singleMetric') {
this.layers = this.getSingleMetricLayer();
} else {
this.layers = this.getLayers();
}
this.visualization = this.getXyState();
}

Expand Down Expand Up @@ -208,6 +226,19 @@ export class LensAttributes {
});
}

getFiltersColumn({ label, paramFilters }: { paramFilters: ParamFilter[]; label?: string }) {
return {
label: label ?? 'Filters',
dataType: 'string',
operationType: 'filters',
scale: 'ordinal',
isBucketed: true,
params: {
filters: paramFilters,
},
};
}

getNumberColumn({
seriesConfig,
label,
Expand Down Expand Up @@ -389,6 +420,10 @@ export class LensAttributes {
getXAxis(layerConfig: LayerConfig, layerId: string) {
const { xAxisColumn } = layerConfig.seriesConfig;

if (!xAxisColumn.sourceField) {
return xAxisColumn;
}

if (xAxisColumn?.sourceField === USE_BREAK_DOWN_COLUMN) {
return this.getBreakdownColumn({
layerId,
Expand All @@ -398,10 +433,17 @@ export class LensAttributes {
});
}

if (xAxisColumn.sourceField === REPORT_METRIC_FIELD) {
const { paramFilters } = this.getFieldMeta(xAxisColumn.sourceField, layerConfig);
if (paramFilters) {
return this.getFiltersColumn({ paramFilters });
}
}

return this.getColumnBasedOnType({
layerConfig,
label: xAxisColumn.label,
sourceField: xAxisColumn.sourceField!,
sourceField: xAxisColumn.sourceField,
});
}

Expand Down Expand Up @@ -485,12 +527,18 @@ export class LensAttributes {

getFieldMeta(sourceField: string, layerConfig: LayerConfig) {
if (sourceField === REPORT_METRIC_FIELD) {
const { fieldName, columnType, columnLabel, columnFilters, timeScale } = parseCustomFieldName(
layerConfig.seriesConfig,
layerConfig.selectedMetricField
);
const { fieldName, columnType, columnLabel, columnFilters, timeScale, paramFilters } =
parseCustomFieldName(layerConfig.seriesConfig, layerConfig.selectedMetricField);
const fieldMeta = layerConfig.indexPattern.getFieldByName(fieldName!);
return { fieldMeta, fieldName, columnType, columnLabel, columnFilters, timeScale };
return {
fieldMeta,
fieldName,
columnType,
columnLabel,
columnFilters,
timeScale,
paramFilters,
};
} else {
const fieldMeta = layerConfig.indexPattern.getFieldByName(sourceField);

Expand Down Expand Up @@ -732,7 +780,52 @@ export class LensAttributes {
return layers;
}

getSingleMetricLayer() {
const layerConfig = this.layerConfigs[0];
const { columnFilter } = parseCustomFieldName(
layerConfig.seriesConfig,
layerConfig.selectedMetricField
);

const getSourceField = () => {
if (
layerConfig.selectedMetricField.startsWith('Records') ||
layerConfig.selectedMetricField.startsWith('records')
) {
return 'Records';
}
return layerConfig.selectedMetricField;
};

return {
layer0: {
columns: {
'layer-0-column-1': {
label: '',
dataType: 'number',
operationType: layerConfig.operationType,
scale: 'ratio',
sourceField: getSourceField(),
isBucketed: false,
filter: columnFilter,
},
},
columnOrder: ['layer-0-column-1'],
incompleteColumns: {},
},
};
}

getXyState(): XYState {
if (this.reportType === 'singleMetric') {
return {
accessor: 'layer-0-column-1',
layerId: 'layer0',
layerType: 'data',
layers: [],
};
}

return {
legend: { isVisible: true, showSingleSeries: true, position: 'right' },
valueLabels: 'hide',
Expand Down Expand Up @@ -793,7 +886,7 @@ export class LensAttributes {
return {
title: 'Prefilled from exploratory view app',
description: String(refresh),
visualizationType: 'lnsXY',
visualizationType: this.reportType === 'singleMetric' ? 'lnsMetric' : 'lnsXY',
references: [
...uniqueIndexPatternsIds.map((patternId) => ({
id: patternId!,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,21 @@ export function convertToShortUrl(series: SeriesUrl) {

export function createExploratoryViewUrl(
{ reportType, allSeries }: { reportType: ReportViewType; allSeries: AllSeries },
baseHref = ''
baseHref = '',
appId = 'observability',
onlyPath?: boolean
) {
const allShortSeries: AllShortSeries = allSeries.map((series) => convertToShortUrl(series));

if (onlyPath) {
return `/exploratory-view/#?reportType=${reportType}&sr=${rison.encode(
allShortSeries as unknown as RisonValue
)}`;
}

return (
baseHref +
`/app/observability/exploratory-view/#?reportType=${reportType}&sr=${rison.encode(
`/app/${appId}/exploratory-view/#?reportType=${reportType}&sr=${rison.encode(
allShortSeries as unknown as RisonValue
)}`
);
Expand Down
Loading