Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Canvas] Misc NP Stuff #63703

Merged
merged 5 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import React from 'react';
import ReactDOM from 'react-dom';
import { I18nContext } from 'ui/i18n';
import { CoreStart } from '../../../../../../../src/core/public';
import { StartDeps } from '../../plugin';
import {
Expand All @@ -30,6 +29,8 @@ const embeddablesRegistry: {
} = {};

const renderEmbeddableFactory = (core: CoreStart, plugins: StartDeps) => {
const I18nContext = core.i18n.Context;

return (embeddableObject: IEmbeddable, domNode: HTMLElement) => {
return (
<div
Expand Down
5 changes: 5 additions & 0 deletions x-pack/legacy/plugins/canvas/public/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { VALUE_CLICK_TRIGGER, ActionByType } from '../../../../../src/plugins/ui
/* eslint-disable */
import { ACTION_VALUE_CLICK } from '../../../../../src/plugins/data/public/actions/value_click_action';
/* eslint-enable */
import { init as initStatsReporter } from './lib/ui_metric';

import { CapabilitiesStrings } from '../i18n';
const { ReadOnlyBadge: strings } = CapabilitiesStrings;
Expand Down Expand Up @@ -121,6 +122,10 @@ export const initializeCanvas = async (
startPlugins.uiActions.attachAction(VALUE_CLICK_TRIGGER, emptyAction);
}

if (setupPlugins.usageCollection) {
initStatsReporter(setupPlugins.usageCollection.reportUiStats);
}

return canvasStore;
};

Expand Down
15 changes: 11 additions & 4 deletions x-pack/legacy/plugins/canvas/public/functions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ExpressionsSetup } from 'src/plugins/expressions/public';
import { asset } from './asset';
import { filtersFunctionFactory } from './filters';
import { timelion } from './timelion';
import { timelionFunctionFactory } from './timelion';
import { toFunctionFactory } from './to';
import { CanvasSetupDeps, CoreSetup } from '../plugin';

export interface InitializeArguments {
typesRegistry: ExpressionsSetup['__LEGACY']['types'];
prependBasePath: CoreSetup['http']['basePath']['prepend'];
typesRegistry: CanvasSetupDeps['expressions']['__LEGACY']['types'];
calculateBounds: CanvasSetupDeps['data']['query']['timefilter']['timefilter']['calculateBounds'];
}

export function initFunctions(initialize: InitializeArguments) {
return [asset, filtersFunctionFactory(initialize), timelion, toFunctionFactory(initialize)];
return [
asset,
filtersFunctionFactory(initialize),
timelionFunctionFactory(initialize),
toFunctionFactory(initialize),
];
}
177 changes: 94 additions & 83 deletions x-pack/legacy/plugins/canvas/public/functions/timelion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@

import { flatten } from 'lodash';
import moment from 'moment-timezone';
import chrome from 'ui/chrome';
import { npStart } from 'ui/new_platform';
import { TimeRange } from 'src/plugins/data/common';
import { ExpressionFunctionDefinition, DatatableRow } from 'src/plugins/expressions/public';
import { fetch } from '../../common/lib/fetch';
// @ts-ignore untyped local
import { buildBoolArray } from '../../server/lib/build_bool_array';
import { Datatable, Filter } from '../../types';
import { getFunctionHelp } from '../../i18n';
import { InitializeArguments } from './';

interface Arguments {
query: string;
Expand All @@ -30,110 +29,122 @@ interface Arguments {
* @param timeRange time range to parse
* @param timeZone time zone to do the parsing in
*/
function parseDateMath(timeRange: TimeRange, timeZone: string) {
function parseDateMath(
timeRange: TimeRange,
timeZone: string,
calculateBounds: InitializeArguments['calculateBounds']
) {
// the datemath plugin always parses dates by using the current default moment time zone.
// to use the configured time zone, we are switching just for the bounds calculation.
const defaultTimezone = moment().zoneName();
moment.tz.setDefault(timeZone);

const parsedRange = npStart.plugins.data.query.timefilter.timefilter.calculateBounds(timeRange);
const parsedRange = calculateBounds(timeRange);

// reset default moment timezone
moment.tz.setDefault(defaultTimezone);

return parsedRange;
}

export function timelion(): ExpressionFunctionDefinition<
type TimelionFunction = ExpressionFunctionDefinition<
'timelion',
Filter,
Arguments,
Promise<Datatable>
> {
const { help, args: argHelp } = getFunctionHelp().timelion;
>;

return {
name: 'timelion',
type: 'datatable',
inputTypes: ['filter'],
help,
args: {
query: {
types: ['string'],
aliases: ['_', 'q'],
help: argHelp.query,
default: '".es(*)"',
},
interval: {
types: ['string'],
help: argHelp.interval,
default: 'auto',
},
from: {
types: ['string'],
help: argHelp.from,
default: 'now-1y',
},
to: {
types: ['string'],
help: argHelp.to,
default: 'now',
},
timezone: {
types: ['string'],
help: argHelp.timezone,
default: 'UTC',
export function timelionFunctionFactory(initialize: InitializeArguments): () => TimelionFunction {
return () => {
const { help, args: argHelp } = getFunctionHelp().timelion;

return {
name: 'timelion',
type: 'datatable',
inputTypes: ['filter'],
help,
args: {
query: {
types: ['string'],
aliases: ['_', 'q'],
help: argHelp.query,
default: '".es(*)"',
},
interval: {
types: ['string'],
help: argHelp.interval,
default: 'auto',
},
from: {
types: ['string'],
help: argHelp.from,
default: 'now-1y',
},
to: {
types: ['string'],
help: argHelp.to,
default: 'now',
},
timezone: {
types: ['string'],
help: argHelp.timezone,
default: 'UTC',
},
},
},
fn: (input, args): Promise<Datatable> => {
// Timelion requires a time range. Use the time range from the timefilter element in the
// workpad, if it exists. Otherwise fall back on the function args.
const timeFilter = input.and.find(and => and.type === 'time');
const range = timeFilter
? { min: timeFilter.from, max: timeFilter.to }
: parseDateMath({ from: args.from, to: args.to }, args.timezone);
fn: (input, args): Promise<Datatable> => {
// Timelion requires a time range. Use the time range from the timefilter element in the
// workpad, if it exists. Otherwise fall back on the function args.
const timeFilter = input.and.find(and => and.type === 'time');
const range = timeFilter
? { min: timeFilter.from, max: timeFilter.to }
: parseDateMath(
{ from: args.from, to: args.to },
args.timezone,
initialize.calculateBounds
);

const body = {
extended: {
es: {
filter: {
bool: {
must: buildBoolArray(input.and),
const body = {
extended: {
es: {
filter: {
bool: {
must: buildBoolArray(input.and),
},
},
},
},
},
sheet: [args.query],
time: {
from: range.min,
to: range.max,
interval: args.interval,
timezone: args.timezone,
},
};
sheet: [args.query],
time: {
from: range.min,
to: range.max,
interval: args.interval,
timezone: args.timezone,
},
};

return fetch(chrome.addBasePath(`/api/timelion/run`), {
method: 'POST',
responseType: 'json',
data: body,
}).then(resp => {
const seriesList = resp.data.sheet[0].list;
const rows = flatten(
seriesList.map((series: { data: any[]; label: string }) =>
series.data.map(row => ({ '@timestamp': row[0], value: row[1], label: series.label }))
)
) as DatatableRow[];
return fetch(initialize.prependBasePath(`/api/timelion/run`), {
method: 'POST',
responseType: 'json',
data: body,
}).then(resp => {
const seriesList = resp.data.sheet[0].list;
const rows = flatten(
seriesList.map((series: { data: any[]; label: string }) =>
series.data.map(row => ({ '@timestamp': row[0], value: row[1], label: series.label }))
)
) as DatatableRow[];

return {
type: 'datatable',
columns: [
{ name: '@timestamp', type: 'date' },
{ name: 'value', type: 'number' },
{ name: 'label', type: 'string' },
],
rows,
};
});
},
return {
type: 'datatable',
columns: [
{ name: '@timestamp', type: 'date' },
{ name: 'value', type: 'number' },
{ name: 'label', type: 'string' },
],
rows,
};
});
},
};
};
}
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/canvas/public/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ const shimCoreStart = {
};

const shimSetupPlugins: CanvasSetupDeps = {
data: npSetup.plugins.data,
expressions: npSetup.plugins.expressions,
home: npSetup.plugins.home,
usageCollection: npSetup.plugins.usageCollection,
};
const shimStartPlugins: CanvasStartDeps = {
...npStart.plugins,
Expand Down
21 changes: 16 additions & 5 deletions x-pack/legacy/plugins/canvas/public/lib/ui_metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/

import {
createUiStatsReporter,
METRIC_TYPE,
} from '../../../../../../src/legacy/core_plugins/ui_metric/public';
import { UiStatsMetricType, METRIC_TYPE } from '@kbn/analytics';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/public';

export const trackCanvasUiMetric = createUiStatsReporter('canvas');
export { METRIC_TYPE };

export let reportUiStats: UsageCollectionSetup['reportUiStats'] | undefined;

export function init(_reportUiStats: UsageCollectionSetup['reportUiStats']): void {
reportUiStats = _reportUiStats;
}

export function trackCanvasUiMetric(metricType: UiStatsMetricType, name: string | string[]) {
if (!reportUiStats) {
return;
}

reportUiStats('canvas', metricType, name);
}
15 changes: 13 additions & 2 deletions x-pack/legacy/plugins/canvas/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import { HomePublicPluginSetup } from '../../../../../src/plugins/home/public';
import { initLoadingIndicator } from './lib/loading_indicator';
import { featureCatalogueEntry } from './feature_catalogue_entry';
import { ExpressionsSetup, ExpressionsStart } from '../../../../../src/plugins/expressions/public';
import { DataPublicPluginSetup } from '../../../../../src/plugins/data/public';
import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public';
import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public';
import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public';
// @ts-ignore untyped local
import { argTypeSpecs } from './expression_types/arg_types';
Expand All @@ -20,22 +22,25 @@ import { legacyRegistries } from './legacy_plugin_support';
import { getPluginApi, CanvasApi } from './plugin_api';
import { initFunctions } from './functions';
import { CanvasSrcPlugin } from '../canvas_plugin_src/plugin';
export { CoreStart };
export { CoreStart, CoreSetup };

/**
* These are the private interfaces for the services your plugin depends on.
* @internal
*/
// This interface will be built out as we require other plugins for setup
export interface CanvasSetupDeps {
data: DataPublicPluginSetup;
expressions: ExpressionsSetup;
home: HomePublicPluginSetup;
usageCollection?: UsageCollectionSetup;
}

export interface CanvasStartDeps {
embeddable: EmbeddableStart;
expressions: ExpressionsStart;
inspector: InspectorStart;

uiActions: UiActionsStart;
__LEGACY: {
absoluteToParsedUrl: (url: string, basePath: string) => any;
Expand Down Expand Up @@ -94,7 +99,13 @@ export class CanvasPlugin
canvasApi.addTypes(legacyRegistries.types.getOriginalFns());

// Register core canvas stuff
canvasApi.addFunctions(initFunctions({ typesRegistry: plugins.expressions.__LEGACY.types }));
canvasApi.addFunctions(
initFunctions({
calculateBounds: plugins.data.query.timefilter.timefilter.calculateBounds,
prependBasePath: core.http.basePath.prepend,
typesRegistry: plugins.expressions.__LEGACY.types,
})
);
canvasApi.addArgumentUIs(argTypeSpecs);
canvasApi.addTransitions(transitions);

Expand Down