Enabling the timeRangeSelector inside a React visualization (plugin)

Hi,

I would like to show the default visualization timefilter (the timeRangeSelector specifically) inside my own visualization. (I thought it was displayed by default in any case)

My visualization is itself just a simple display table. I am using ReactJS for rendering (and developing a Kibana 7.x plugin). I have not been able to see how I can enable the timeRangeSelector.
I have seen many examples for Angular (inside other plugins source code or the Kibana source itself). But I am however unable to control the timefilter from inside my plugin.

My code (generated at first using the kibana-plugin-generator) is structured as follows:

/* index.js /
export default function (kibana) {
return new kibana.Plugin({...
uiExports: {
app: {
main: 'plugins/myPlugin/app'
}, ...
/
app.js /
function RootController($scope, $element, $http) {
const domNode = $element[0];
render(, domNode);
...
/
main.js */
export class Main extends React.Component {
render() { return ( ...);

I was unable to find if there is a plugin option (in the current dev docs) that I can add in the app UiExports or how I could "manually" render it in my <EuiPage> content.

Can anyone point out some documentation or code examples?

Thank you in advance,
Andrei.

Hi,

@timroes or @ppisljar can help you.

Also please check if any of the resources in this post help you? Kibana Plugin visualization problem

Thanks,
Bhavya

Hi,

the current timepicker is still written in Angular (see #15212 for ticket to move it to React). Thus you cannot embed it into a non Angular plugin, since it's an angular directive, that needs all dependencies injected correctly. But since the global timepicker has no links to visualizations anymore (finally!), you can just pick yourself any other timepicker you would like until we moved the Kibana one to React. You need to pass in the timerange a visualization should show, anyway specifically into the visualize loader as a parameter timeRange. It doesn't matter what timepicker you use to get that information from. Of course another time picker would still lack all the quick options, but you should be able to quickly implement that, it will just need to set the timeRange in the visualize loader to ES datemath strings, like: { from: 'now-7d', to: 'now' }.

One other possibility would be, include that timepicker directive outside of your React code using the actual Angular wrapper, that you use to mount the react component to also render the timepicker, and somehow pass the values from it into your react code, but to be honest, that doesn't sound much simpler than using a different timepicker :slight_smile:

We are already actively looking into building the new time picker component in our EUI framework, but we are still needing to fix a lot of accessibility issues on the used libraries before we can integrate that into Kibana.

Hope that answer could help you a bit moving forward.

Cheers,
Tim

1 Like

Hi,

Thank you @bhavyarm and @timroes for your replies. Now I understand my problem better :slight_smile: .

Regarding the indicated approaches, I would (at this point) go for including another datepicker there, not combining Angular and React code. I see from #15212 that there is, more or less, something already done in Kibana. I am not sure if I can use it, but I would have another look.

The visualization loader you mentioned, I assume is this one (and the timeRange is one of the accepted parameters)?
Will this loader be called even if I use a React visualization (component), specified in the app object of the uiExports?

I apologize for asking things that might be simple for experienced plugin developers.

Best regards,
Andrei.

1 Like

Hi,

the issue you refer to is our still open progress to replace the current date picker by a React version, but that's not done yet.

The visualize loader you pointed out is the correct one. It is vanilla JS and totally framework agnostic. You just need to pass it in the saved visualization id (or saved object), and a DOM node that we should render into. For most of the visualizations to work, you will nevertheless need to include some uiExports imports into your code, see e.g. this sample plugin.

That way you instruct the optimizer to bundle all that relevant parts into your application bundle, otherwise that code would be missing and you might get some weird errors trying to load a visualization.

Cheers,
Tim

Hi Tim,

Thank you for your help!

I will move forward trying to use a datepicker range, from the EUI framework you pointed out. I trust that usage of components is an already available workaround. And then I can hopefully use that timeRange with the visualization loader, as you suggested.

I will mark your first reply as the one that got me unstuck; but the entire discussion helped me.

Best regards,
Andrei

Hi @timroes,

Just a quick question, regarding the usage of the visualize loader you pointed out.
I have tried to use code as documented, inside of the RootController that I use with ui/chrome. But I am getting some Angular related errors (Uncaught (in promise) Error: [$injector:unpr] Unknown provider: savedVisualizationsProvider <- savedVisualizations).

Can you please point out if there is any documentation, or code examples, of the loader used in/with React codebase? I have looked in the Kibana, Eui sources and other example plugins (from other threads), but was unable to find such a sample.

Sorry for the trouble,
Andrei

I think the main issue when you are getting some unknown provider is, that your application bundle will usually miss the related Angular files (no matter if you are using Angular yourself or not).

Which files Kibana should bundle for your plugin is controlled by a couple of import 'uiExport/*'; statements in your application entry file - if you are developing against 6.x or master - or earlier to that, a uiExports.app.uses statement.

See e.g. the Kibana main application file: https://github.com/elastic/kibana/blob/master/src/core_plugins/kibana/public/kibana.js#L28:L42 for an example of those imports.

In case you are developing against 6.x or master could you show your main application file and check if you have any of those imports, if you are developing for 6.3.0 or earlier, could you paste your index.js from you plugin?

Cheers,
Tim

Hi Tim,

I am developing against Kibana 7.0.a1 (so the master).

I tried a list of imports, as showed in your indicated url. Still I have "missing provider" errors.

My main app file is as follows (the troublesome code is marked with a FIXME):

import React from 'react';
import chrome from 'ui/chrome';
import { uiModules } from 'ui/modules';
import { render, unmountComponentAtNode } from 'react-dom';

import 'ui/autoload/styles';
import './less/main.less';
import { Main } from './components/main';

import 'uiExports/home';
import 'uiExports/visTypes';
import 'uiExports/visResponseHandlers';
import 'uiExports/visRequestHandlers';
import 'uiExports/visEditorTypes';
import 'uiExports/visualize';
import 'uiExports/savedObjectTypes';
import 'uiExports/fieldFormats';
import 'uiExports/fieldFormatEditors';
import 'uiExports/navbarExtensions';
import 'uiExports/dashboardPanelActions';
import 'uiExports/managementSections';
import 'uiExports/devTools';
import 'uiExports/docViews';
import 'uiExports/embeddableFactories';
import 'uiExports/inspectorViews';
import { getVisualizeLoader } from 'ui/visualize/loader';

const app = uiModules.get("apps/myPlugin");

app.config($locationProvider => {
$locationProvider.html5Mode({
enabled: false,
requireBase: false,
rewriteLinks: false,
});
});

app.config(stateManagementConfigProvider => {
stateManagementConfigProvider.disable();
});

function RootController($scope, $element, $http) {
const domNode = $element[0];

// FIXME: Troublesome code
// $scope.visualizationList = null;
// $scope.selectedVisualization = null;
// $scope.savedVisualizationsProvider = null;
// $scope.savedVisualizations = null;
//
// let visualizeLoader = null;
// getVisualizeLoader().then(loader => {
// debugger;
// visualizeLoader = loader;
// loader.getVisualizationList().then(list => {
// $scope.visualizationList = list;
// });
// });

render(, domNode);

$scope.$on('$destroy', () => {
unmountComponentAtNode(domNode);
});
}
chrome.setRootController("myPlugin", RootController);

Again, many thanks for the help.

Best regards,
Andrei

Could you please share which providers currently error. Also in the error message, there is usually a link to the Angular docs explaining this error, which would contain more information about where this injection happened, could you please provide that too (if unsure what I am asking for, also post a screenshot of the error on the console :D)

Cheers,
Tim

Hi Tim,

My current error is Uncaught (in promise) Error: [$injector:unpr] Unknown provider: regionmapsConfigProvider <- regionmapsConfig <- SavedVis <- savedVisualizations

And the link to the explanation is:

AngularJS

Best regards,
Andrei

Hi Andrei,

that's luckily now a new error, which is actually an issue, if you are not properly injecting the kibana variables into your application (and thus region map cannot find it's configuration).

Check this post for more information and the solution how to fix that!

Cheers,
Tim

Hi Tim,

Great, it works with the fix from the post; no more errors.
Sorry, I did not see the post earlier today.
Thank you for your time!

Best regards,
Andrei

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.