[Canvas] Misc NP Stuff (#63703)
* Timelion function -> np * embeddable renderer -> np i18n context * ui_metric -> np * Fix timelion issue Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
103a3cd11c
commit
dfddcdd903
8 changed files with 143 additions and 99 deletions
|
@ -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 {
|
||||
|
@ -30,6 +29,8 @@ const embeddablesRegistry: {
|
|||
} = {};
|
||||
|
||||
const renderEmbeddableFactory = (core: CoreStart, plugins: StartDeps) => {
|
||||
const I18nContext = core.i18n.Context;
|
||||
|
||||
return (embeddableObject: IEmbeddable, domNode: HTMLElement) => {
|
||||
return (
|
||||
<div
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { timelion } from '../../../public/functions/timelion';
|
||||
import { timelionFunctionFactory } from '../../../public/functions/timelion';
|
||||
import { FunctionHelp } from '../function_help';
|
||||
import { FunctionFactory } from '../../../types';
|
||||
import { ELASTICSEARCH, DATEMATH, MOMENTJS_TIMEZONE_URL } from '../../constants';
|
||||
|
||||
export const help: FunctionHelp<FunctionFactory<typeof timelion>> = {
|
||||
export const help: FunctionHelp<FunctionFactory<ReturnType<typeof timelionFunctionFactory>>> = {
|
||||
help: i18n.translate('xpack.canvas.functions.timelionHelpText', {
|
||||
defaultMessage: 'Use Timelion to extract one or more timeseries from many sources.',
|
||||
}),
|
||||
|
|
|
@ -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;
|
||||
|
@ -121,6 +122,10 @@ export const initializeCanvas = async (
|
|||
startPlugins.uiActions.attachAction(VALUE_CLICK_TRIGGER, emptyAction);
|
||||
}
|
||||
|
||||
if (setupPlugins.usageCollection) {
|
||||
initStatsReporter(setupPlugins.usageCollection.reportUiStats);
|
||||
}
|
||||
|
||||
return canvasStore;
|
||||
};
|
||||
|
||||
|
|
|
@ -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'];
|
||||
timefilter: CanvasSetupDeps['data']['query']['timefilter']['timefilter'];
|
||||
}
|
||||
|
||||
export function initFunctions(initialize: InitializeArguments) {
|
||||
return [asset, filtersFunctionFactory(initialize), timelion, toFunctionFactory(initialize)];
|
||||
return [
|
||||
asset,
|
||||
filtersFunctionFactory(initialize),
|
||||
timelionFunctionFactory(initialize),
|
||||
toFunctionFactory(initialize),
|
||||
];
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
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';
|
||||
|
@ -15,6 +13,7 @@ import { fetch } from '../../common/lib/fetch';
|
|||
import { buildBoolArray } from '../../server/lib/build_bool_array';
|
||||
import { Datatable, Filter } from '../../types';
|
||||
import { getFunctionHelp } from '../../i18n';
|
||||
import { InitializeArguments } from './';
|
||||
|
||||
interface Arguments {
|
||||
query: string;
|
||||
|
@ -30,13 +29,17 @@ 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,
|
||||
timefilter: InitializeArguments['timefilter']
|
||||
) {
|
||||
// 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 = timefilter.calculateBounds(timeRange);
|
||||
|
||||
// reset default moment timezone
|
||||
moment.tz.setDefault(defaultTimezone);
|
||||
|
@ -44,96 +47,100 @@ function parseDateMath(timeRange: TimeRange, timeZone: string) {
|
|||
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',
|
||||
},
|
||||
},
|
||||
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);
|
||||
export function timelionFunctionFactory(initialize: InitializeArguments): () => TimelionFunction {
|
||||
return () => {
|
||||
const { help, args: argHelp } = getFunctionHelp().timelion;
|
||||
|
||||
const body = {
|
||||
extended: {
|
||||
es: {
|
||||
filter: {
|
||||
bool: {
|
||||
must: buildBoolArray(input.and),
|
||||
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, initialize.timefilter);
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
|
||||
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 {
|
||||
type: 'datatable',
|
||||
columns: [
|
||||
{ name: '@timestamp', type: 'date' },
|
||||
{ name: 'value', type: 'number' },
|
||||
{ name: 'label', type: 'string' },
|
||||
],
|
||||
rows,
|
||||
sheet: [args.query],
|
||||
time: {
|
||||
from: range.min,
|
||||
to: range.max,
|
||||
interval: args.interval,
|
||||
timezone: args.timezone,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
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,
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
@ -20,7 +22,7 @@ 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.
|
||||
|
@ -28,14 +30,17 @@ export { CoreStart };
|
|||
*/
|
||||
// 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;
|
||||
|
@ -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({
|
||||
timefilter: plugins.data.query.timefilter.timefilter,
|
||||
prependBasePath: core.http.basePath.prepend,
|
||||
typesRegistry: plugins.expressions.__LEGACY.types,
|
||||
})
|
||||
);
|
||||
canvasApi.addArgumentUIs(argTypeSpecs);
|
||||
canvasApi.addTransitions(transitions);
|
||||
|
||||
|
|
Loading…
Reference in a new issue