Skip to content

Commit

Permalink
Revert "Refactor and improve Visualize Loader (#15157) (#15359)"
Browse files Browse the repository at this point in the history
This reverts commit bead358.

This backport was botched, so a bunch of inline diffs were committed.
  • Loading branch information
epixa committed Dec 2, 2017
1 parent bead358 commit fa3c2d5
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 543 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[[development-embedding-visualizations]]
=== Embedding Visualizations

<<<<<<< HEAD
There are two different angular directives you can use to insert a visualization in your page.
To display an already saved visualization, use the `<visualize>` directive.
To reuse an existing Visualization implementation for a more custom purpose, use the `<visualization>` directive instead.
Expand All @@ -21,15 +20,8 @@ two methods:
- `uiState`: uiState to pass to `<visualize>` directive
- `appState`: appState to pass to `<visualize>` directive
- `showSpyPanel`: showSpyPanel property to pass to `<visualize>` directive
=======
There are two different methods you can use to insert a visualization in your page.
>>>>>>> e5d2ff821... Refactor and improve Visualize Loader (#15157)

To display an already saved visualization, use the `VisualizeLoader`.
To reuse an existing visualization implementation for a more custom purpose,
use the Angular `<visualization>` directive instead.

<<<<<<< HEAD
==== `<visualize>` directive
The `<visualize>` directive takes care of loading data, parsing data, rendering the editor
(if the Visualization is in edit mode) and rendering the visualization.
Expand All @@ -41,82 +33,58 @@ If that is not the case, take a look at using `<visualization>` directive.
The simplest way is to just pass `saved-id` to `<visualize>`:

`<visualize saved-id="'447d2930-9eb2-11e7-a956-5558df96e706'"></visualize>`
=======
==== VisualizeLoader
>>>>>>> e5d2ff821... Refactor and improve Visualize Loader (#15157)

The `VisualizeLoader` class is the easiest way to embed a visualization into your plugin.
It will take care of loading the data and rendering the visualization.
For the above to work with time based visualizations time picker must be present (enabled) on the page. For scenarios
where timepicker is not available time range can be passed in as additional parameter:

<<<<<<< HEAD
`<visualize saved-id="'447d2930-9eb2-11e7-a956-5558df96e706'"
time-range="{ max: '2017-09-21T21:59:59.999Z', min: '2017-09-18T22:00:00.000Z' }"></visualize>`
=======
To get an instance of the loader, do the following:
>>>>>>> e5d2ff821... Refactor and improve Visualize Loader (#15157)

["source","js"]
-----------
import { getVisualizeLoader } from 'ui/visualize/loader';
Once <visualize> is done rendering the element will emit `renderComplete` event.

getVisualizeLoader().then((loader) => {
// You now have access to the loader
});
-----------
When more control is required over the visualization you may prefer to load the saved object yourself and then pass it
to `<visualize>`

The loader exposes the following methods:
`<visualize saved-obj='savedVis' app-state='appState' ui-state='uiState' editor-mode='false'></visualize>` where

- `getVisualizationList()`: which returns promise which gets resolved with a list of saved visualizations
- `embedVisualizationWithId(container, savedId, params)`: which embeds visualization by id
- `embedVisualizationWithSavedObject(container, savedObject, params)`: which embeds visualization from saved object
`savedVis` is an instance of savedVisualization object, which can be retrieved using `savedVisualizations` service
which is explained later in this documentation.

Depending on which embed method you are using, you either pass in the id of the
saved object for the visualization, or a `savedObject`, that you can retrieve via
the `savedVisualizations` Angular service by its id. The `savedObject` give you access
to the filter and query logic and allows you to attach listeners to the visualizations.
For a more complex use-case you usually want to use that method.
`appState` is an instance of `AppState`. <visualize> is expecting two keys defined on AppState:

`container` should be a DOM element (jQuery wrapped or regular DOM element) into which the visualization should be embedded
`params` is a parameter object specifying several parameters, that influence rendering.
- `filters` which is an instance of searchSource filter object and
- `query` which is an instance of searchSource query object

You will find a detailed description of all the parameters in the inline docs
in the {repo}blob/{branch}/src/ui/public/visualize/loader/loader.js[loader source code].
If `appState` is not provided, `<visualize>` will not monitor the `AppState`.

<<<<<<< HEAD
`uiState` should be an instance of `PersistedState`. if not provided visualize will generate one,
but you will have no access to it. It is used to store viewer specific information like whether the legend is toggled on or off.
=======
Both methods return an `EmbeddedVisualizeHandler`, that gives you some access
to the visualization. The `embedVisualizationWithSavedObject` method will return
the handler immediately from the method call, whereas the `embedVisualizationWithId`
will return a promise, that resolves with the handler, as soon as the `id` could be
found. It will reject, if the `id` is invalid.
>>>>>>> e5d2ff821... Refactor and improve Visualize Loader (#15157)

The returned `EmbeddedVisualizeHandler` itself has the following methods and properties:

- `destroy()`: destroys the underlying Angualr scope of the visualization
- `getElement()`: a reference to the jQuery wrapped DOM element, that renders the visualization
- `whenFirstRenderComplete()`: will return a promise, that resolves as soon as the visualization has
finished rendering for the first time
- `addRenderCompleteListener(listener)`: will register a listener to be called whenever
a rendering of this visualization finished (not just the first one)
- `removeRenderCompleteListener(listener)`: removes an event listener from the handler again

You can find the detailed `EmbeddedVisualizeHandler` documentation in its
{repo}blob/{branch}/src/ui/public/visualize/loader/embedded_visualize_handler.js[source code].

<<<<<<< HEAD

`editor-mode` defines if <visualize> should render in editor or in view mode.

*code example: Showing a saved visualization, without linking to querybar or filterbar.*
["source","html"]
-----------
<div ng-controller="KbnTestController" class="test_vis">
<visualize saved-obj='savedVis'></visualize>
</div>
-----------
["source","js"]
-----------
import { uiModules } from 'ui/modules';
uiModules.get('kibana')
.controller('KbnTestController', function ($scope, AppState, savedVisualizations) {
const visId = 'enter_your_vis_id';
savedVisualizations.get(visId).then(savedVis => $scope.savedObj = savedVis);
});
-----------

When <visualize> is ready it will emit `ready:vis` event on the root scope.
When <visualize> is done rendering it will emit `renderComplete` event on the element.
=======
We recommend *not* to use the internal `<visualize>` Angular directive directly.
>>>>>>> e5d2ff821... Refactor and improve Visualize Loader (#15157)

==== `<visualization>` directive
The `<visualization>` directive takes a visualization configuration and data.
It should be used, if you don't want to render a saved visualization, but specify
the config and data directly.

`<visualization vis='vis' vis-data='visData' ui-state='uiState' ></visualization>` where

Expand Down
4 changes: 2 additions & 2 deletions src/test_utils/public/stub_get_active_injector.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import sinon from 'sinon';
* This method setups the stub for chrome.dangerouslyGetActiveInjector. You must call it in
* a place where beforeEach is allowed to be called (read: inside your describe)
* method. You must call this AFTER you've called `ngMock.module` to setup the modules,
* but BEFORE you first execute code, that uses chrome.dangerouslyGetActiveInjector.
* but BEFORE you first execute code, that uses chrome.getActiveInjector.
*/
export function setupInjectorStub() {
beforeEach(ngMock.inject(($injector) => {
Expand All @@ -30,7 +30,7 @@ export function setupInjectorStub() {
*/
export function teardownInjectorStub() {
afterEach(() => {
chrome.dangerouslyGetActiveInjector.restore();
chrome.getActiveInjector.restore();
});
}

Expand Down
75 changes: 75 additions & 0 deletions src/ui/public/visualize/loader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import $ from 'jquery';
import uiRoutes from 'ui/routes';
import 'ui/visualize';

const VisualizeLoaderProvider = ($compile, $rootScope, savedVisualizations) => {
const renderVis = (el, savedObj, params) => {
const scope = $rootScope.$new();
scope.savedObj = savedObj;
scope.appState = params.appState;
scope.uiState = params.uiState;
scope.timeRange = params.timeRange;
scope.showSpyPanel = params.showSpyPanel;
scope.editorMode = params.editorMode;

const container = el instanceof $ ? el : $(el);

container.html('');
const visEl = $('<visualize saved-obj="savedObj" app-state="appState" ui-state="uiState" ' +
'time-range="timeRange" editor-mode="editorMode" show-spy-panel="showSpyPanel"></visualize>');
const visHtml = $compile(visEl)(scope);
container.html(visHtml);

const handler = { destroy: scope.$destroy };

return new Promise((resolve) => {
visEl.on('renderComplete', () => {
resolve(handler);
});
});

};

return {
embedVisualizationWithId: async (el, savedVisualizationId, params) => {
return new Promise((resolve) => {
savedVisualizations.get(savedVisualizationId).then(savedObj => {
renderVis(el, savedObj, params).then(handler => {
resolve(handler);
});
});
});
},
embedVisualizationWithSavedObject: (el, savedObj, params) => {
return renderVis(el, savedObj, params);
},
getVisualizationList: () => {
return savedVisualizations.find().then(result => result.hits);
},
};
};


let visualizeLoader = null;
let pendingPromise = null;
let pendingResolve = null;
uiRoutes.addSetupWork(function (Private) {
visualizeLoader = Private(VisualizeLoaderProvider);

if (pendingResolve) {
pendingResolve(visualizeLoader);
}
});

async function getVisualizeLoader() {
if (!pendingResolve) {
pendingPromise = new Promise((resolve)=> {
pendingResolve = resolve;
if (visualizeLoader) resolve(visualizeLoader);
});
}
return pendingPromise;
}


export { getVisualizeLoader, VisualizeLoaderProvider };

0 comments on commit fa3c2d5

Please sign in to comment.