mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Timelion: Move datemath parsing to the client (#47813)
This commit is contained in:
parent
65ab1dd403
commit
6c5c6ef5b3
9 changed files with 30 additions and 135 deletions
|
@ -1,7 +1,6 @@
|
|||
.kuiLocalTitle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: ($localNavSideSpacing * 1.5) $localNavSideSpacing;
|
||||
font-size: $kuiFontSize;
|
||||
font-weight: bold;
|
||||
|
|
|
@ -407,9 +407,15 @@ app.controller('timelion', function (
|
|||
$scope.state.save();
|
||||
$scope.running = true;
|
||||
|
||||
// parse the time range client side to make sure it behaves like other charts
|
||||
const timeRangeBounds = timefilter.getBounds();
|
||||
|
||||
const httpResult = $http.post('../api/timelion/run', {
|
||||
sheet: $scope.state.sheet,
|
||||
time: _.extend(timefilter.getTime(), {
|
||||
time: _.extend({
|
||||
from: timeRangeBounds.min,
|
||||
to: timeRangeBounds.max,
|
||||
}, {
|
||||
interval: $scope.state.interval,
|
||||
timezone: timezone
|
||||
}),
|
||||
|
|
|
@ -21,11 +21,13 @@ import { PluginInitializerContext } from 'kibana/public';
|
|||
import { npSetup, npStart } from 'ui/new_platform';
|
||||
import { plugin } from '.';
|
||||
import { setup as visualizations } from '../../visualizations/public/np_ready/public/legacy';
|
||||
import { setup as data } from '../../data/public/legacy';
|
||||
import { TimelionPluginSetupDependencies } from './plugin';
|
||||
import { LegacyDependenciesPlugin } from './shim';
|
||||
|
||||
const setupPlugins: Readonly<TimelionPluginSetupDependencies> = {
|
||||
visualizations,
|
||||
data,
|
||||
expressions: npSetup.plugins.expressions,
|
||||
|
||||
// Temporary solution
|
||||
|
|
|
@ -29,6 +29,8 @@ import { VisualizationsSetup } from '../../visualizations/public/np_ready/public
|
|||
import { getTimelionVisualizationConfig } from './timelion_vis_fn';
|
||||
import { getTimelionVisualization } from './vis';
|
||||
import { getTimeChart } from './panels/timechart/timechart';
|
||||
import { DataSetup } from '../../data/public';
|
||||
import { TimefilterSetup } from '../../data/public/timefilter';
|
||||
import { Panel } from './panels/panel';
|
||||
import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim';
|
||||
|
||||
|
@ -37,12 +39,14 @@ export interface TimelionVisualizationDependencies extends LegacyDependenciesPlu
|
|||
uiSettings: UiSettingsClientContract;
|
||||
http: HttpSetup;
|
||||
timelionPanels: Map<string, Panel>;
|
||||
timefilter: TimefilterSetup;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export interface TimelionPluginSetupDependencies {
|
||||
expressions: ReturnType<ExpressionsPlugin['setup']>;
|
||||
visualizations: VisualizationsSetup;
|
||||
data: DataSetup;
|
||||
|
||||
// Temporary solution
|
||||
__LEGACY: LegacyDependenciesPlugin;
|
||||
|
@ -58,13 +62,14 @@ export class TimelionPlugin implements Plugin<Promise<void>, void> {
|
|||
|
||||
public async setup(
|
||||
core: CoreSetup,
|
||||
{ __LEGACY, expressions, visualizations }: TimelionPluginSetupDependencies
|
||||
{ __LEGACY, expressions, visualizations, data }: TimelionPluginSetupDependencies
|
||||
) {
|
||||
const timelionPanels: Map<string, Panel> = new Map();
|
||||
|
||||
const dependencies: TimelionVisualizationDependencies = {
|
||||
uiSettings: core.uiSettings,
|
||||
http: core.http,
|
||||
timefilter: data.timefilter,
|
||||
timelionPanels,
|
||||
...(await __LEGACY.setup(core, timelionPanels)),
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ export interface TimelionSuccessResponse {
|
|||
}
|
||||
|
||||
export function getTimelionRequestHandler(dependencies: TimelionVisualizationDependencies) {
|
||||
const { uiSettings, http } = dependencies;
|
||||
const { uiSettings, http, timefilter } = dependencies;
|
||||
const timezone = timezoneProvider(uiSettings)();
|
||||
|
||||
return async function({
|
||||
|
@ -77,6 +77,9 @@ export function getTimelionRequestHandler(dependencies: TimelionVisualizationDep
|
|||
|
||||
const esQueryConfigs = getEsQueryConfig(uiSettings);
|
||||
|
||||
// parse the time range client side to make sure it behaves like other charts
|
||||
const timeRangeBounds = timefilter.timefilter.calculateBounds(timeRange);
|
||||
|
||||
try {
|
||||
return await http.post('../api/timelion/run', {
|
||||
body: JSON.stringify({
|
||||
|
@ -86,7 +89,12 @@ export function getTimelionRequestHandler(dependencies: TimelionVisualizationDep
|
|||
filter: buildEsQuery(undefined, query, filters, esQueryConfigs),
|
||||
},
|
||||
},
|
||||
time: { ...timeRange, interval: visParams.interval, timezone },
|
||||
time: {
|
||||
from: timeRangeBounds.min,
|
||||
to: timeRangeBounds.max,
|
||||
interval: visParams.interval,
|
||||
timezone,
|
||||
},
|
||||
}),
|
||||
});
|
||||
} catch (e) {
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
import _ from 'lodash';
|
||||
import Bluebird from 'bluebird';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import moment from 'moment';
|
||||
|
||||
import parseSheet from './lib/parse_sheet.js';
|
||||
import parseDateMath from '../lib/date_math.js';
|
||||
import repositionArguments from './lib/reposition_arguments.js';
|
||||
import indexArguments from './lib/index_arguments.js';
|
||||
import validateTime from './lib/validate_time.js';
|
||||
|
@ -191,8 +191,8 @@ export default function chainRunner(tlConfig) {
|
|||
validateTime(request.time, tlConfig);
|
||||
|
||||
tlConfig.time = request.time;
|
||||
tlConfig.time.to = parseDateMath(request.time.to, true).valueOf();
|
||||
tlConfig.time.from = parseDateMath(request.time.from).valueOf();
|
||||
tlConfig.time.to = moment(request.time.to).valueOf();
|
||||
tlConfig.time.from = moment(request.time.from).valueOf();
|
||||
tlConfig.time.interval = calculateInterval(
|
||||
tlConfig.time.from,
|
||||
tlConfig.time.to,
|
||||
|
|
|
@ -18,12 +18,12 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import moment from 'moment';
|
||||
|
||||
import parseDateMath from '../../lib/date_math.js';
|
||||
import toMS from '../../lib/to_milliseconds.js';
|
||||
|
||||
export default function validateTime(time, tlConfig) {
|
||||
const span = parseDateMath(time.to, true) - parseDateMath(time.from);
|
||||
const span = moment.duration(moment(time.to).diff(moment(time.from))).asMilliseconds();
|
||||
const interval = toMS(time.interval);
|
||||
const bucketCount = span / interval;
|
||||
const maxBuckets = tlConfig.settings['timelion:max_buckets'];
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import moment from 'moment';
|
||||
|
||||
const units = ['y', 'M', 'w', 'd', 'h', 'm', 's'];
|
||||
|
||||
/* This is a simplified version of elasticsearch's date parser */
|
||||
export default function parse(text, roundUp) {
|
||||
if (!text) {
|
||||
return undefined;
|
||||
}
|
||||
if (moment.isMoment(text)) {
|
||||
return text;
|
||||
}
|
||||
if (_.isDate(text)) {
|
||||
return moment(text);
|
||||
}
|
||||
|
||||
let time;
|
||||
let mathString = '';
|
||||
let index;
|
||||
let parseString;
|
||||
|
||||
if (text.substring(0, 3) === 'now') {
|
||||
time = moment();
|
||||
mathString = text.substring('now'.length);
|
||||
} else {
|
||||
index = text.indexOf('||');
|
||||
if (index === -1) {
|
||||
parseString = text;
|
||||
mathString = ''; // nothing else
|
||||
} else {
|
||||
parseString = text.substring(0, index);
|
||||
mathString = text.substring(index + 2);
|
||||
}
|
||||
// We're going to just require ISO8601 timestamps, k?
|
||||
time = moment(parseString);
|
||||
}
|
||||
|
||||
if (!mathString.length) {
|
||||
return time;
|
||||
}
|
||||
|
||||
return parseDateMath(mathString, time, roundUp);
|
||||
}
|
||||
|
||||
function parseDateMath(mathString, time, roundUp) {
|
||||
const dateTime = time;
|
||||
|
||||
for (let i = 0; i < mathString.length;) {
|
||||
const c = mathString.charAt(i++);
|
||||
let type;
|
||||
let num;
|
||||
|
||||
if (c === '/') {
|
||||
type = 0;
|
||||
} else if (c === '+') {
|
||||
type = 1;
|
||||
} else if (c === '-') {
|
||||
type = 2;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (isNaN(mathString.charAt(i))) {
|
||||
num = 1;
|
||||
} else if (mathString.length === 2) {
|
||||
num = mathString.charAt(i);
|
||||
} else {
|
||||
const numFrom = i;
|
||||
while (!isNaN(mathString.charAt(i))) {
|
||||
i++;
|
||||
if (i > 10) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
num = parseInt(mathString.substring(numFrom, i), 10);
|
||||
}
|
||||
|
||||
if (type === 0) {
|
||||
// rounding is only allowed on whole, single, units (eg M or 1M, not 0.5M or 2M)
|
||||
if (num !== 1) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
const unit = mathString.charAt(i++);
|
||||
|
||||
if (!_.contains(units, unit)) {
|
||||
return undefined;
|
||||
} else {
|
||||
if (type === 0) {
|
||||
if (roundUp) {
|
||||
dateTime.endOf(unit);
|
||||
} else {
|
||||
dateTime.startOf(unit);
|
||||
}
|
||||
} else if (type === 1) {
|
||||
dateTime.add(num, unit);
|
||||
} else if (type === 2) {
|
||||
dateTime.subtract(num, unit);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dateTime;
|
||||
}
|
|
@ -23,8 +23,6 @@ import fetch from 'node-fetch';
|
|||
import moment from 'moment';
|
||||
fetch.Promise = require('bluebird');
|
||||
|
||||
//var parseDateMath = require('../utils/date_math.js');
|
||||
|
||||
import Datasource from '../lib/classes/datasource';
|
||||
|
||||
export default new Datasource ('quandl', {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue