mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
* Typescript visualize_embeddable file * Remove left over comment
This commit is contained in:
parent
eda90761c8
commit
b82bf8272a
10 changed files with 143 additions and 85 deletions
|
@ -19,6 +19,7 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import { ContainerState, EmbeddableMetadata, Filters, Query, TimeRange } from 'ui/embeddable';
|
||||
import { EmbeddableCustomization } from 'ui/embeddable/types';
|
||||
import { DashboardViewMode } from '../dashboard_view_mode';
|
||||
import {
|
||||
DashboardMetadata,
|
||||
|
@ -42,8 +43,10 @@ export const getEmbeddables = (dashboard: DashboardState): EmbeddablesMap => das
|
|||
|
||||
// TODO: rename panel.embeddableConfig to embeddableCustomization. Because it's on the panel that's stored on a
|
||||
// dashboard, renaming this will require a migration step.
|
||||
export const getEmbeddableCustomization = (dashboard: DashboardState, panelId: PanelId): object =>
|
||||
getPanel(dashboard, panelId).embeddableConfig;
|
||||
export const getEmbeddableCustomization = (
|
||||
dashboard: DashboardState,
|
||||
panelId: PanelId
|
||||
): EmbeddableCustomization => getPanel(dashboard, panelId).embeddableConfig;
|
||||
|
||||
export const getEmbeddable = (dashboard: DashboardState, panelId: PanelId): EmbeddableReduxState =>
|
||||
dashboard.embeddables[panelId];
|
||||
|
|
|
@ -17,42 +17,71 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { PersistedState } from 'ui/persisted_state';
|
||||
import { Embeddable } from 'ui/embeddable';
|
||||
import _ from 'lodash';
|
||||
import { ContainerState, Embeddable } from 'ui/embeddable';
|
||||
import { OnEmbeddableStateChanged } from 'ui/embeddable/embeddable_factory';
|
||||
import { Filters, Query, TimeRange } from 'ui/embeddable/types';
|
||||
import { PersistedState } from 'ui/persisted_state';
|
||||
import { VisualizeLoader } from 'ui/visualize/loader';
|
||||
import { EmbeddedVisualizeHandler } from 'ui/visualize/loader/embedded_visualize_handler';
|
||||
import {
|
||||
VisSavedObject,
|
||||
VisualizeLoaderParams,
|
||||
VisualizeUpdateParams,
|
||||
} from 'ui/visualize/loader/types';
|
||||
|
||||
export class VisualizeEmbeddable extends Embeddable {
|
||||
constructor({ onEmbeddableStateChanged, savedVisualization, editUrl, loader }) {
|
||||
export interface VisualizeEmbeddableConfiguration {
|
||||
onEmbeddableStateChanged: OnEmbeddableStateChanged;
|
||||
savedVisualization: VisSavedObject;
|
||||
editUrl?: string;
|
||||
loader: VisualizeLoader;
|
||||
}
|
||||
|
||||
export class VisualizeEmbeddable extends Embeddable {
|
||||
private onEmbeddableStateChanged: OnEmbeddableStateChanged;
|
||||
private savedVisualization: VisSavedObject;
|
||||
private loader: VisualizeLoader;
|
||||
private uiState: PersistedState;
|
||||
private handler?: EmbeddedVisualizeHandler;
|
||||
private customization?: object;
|
||||
private panelTitle?: string;
|
||||
private timeRange?: TimeRange;
|
||||
private query?: Query;
|
||||
private filters?: Filters;
|
||||
|
||||
constructor({
|
||||
onEmbeddableStateChanged,
|
||||
savedVisualization,
|
||||
editUrl,
|
||||
loader,
|
||||
}: VisualizeEmbeddableConfiguration) {
|
||||
super({
|
||||
metadata: {
|
||||
title: savedVisualization.title,
|
||||
editUrl,
|
||||
indexPattern: savedVisualization.vis.indexPattern
|
||||
}
|
||||
indexPattern: savedVisualization.vis.indexPattern,
|
||||
},
|
||||
});
|
||||
this._onEmbeddableStateChanged = onEmbeddableStateChanged;
|
||||
this.onEmbeddableStateChanged = onEmbeddableStateChanged;
|
||||
this.savedVisualization = savedVisualization;
|
||||
this.loader = loader;
|
||||
|
||||
const parsedUiState = savedVisualization.uiStateJSON ? JSON.parse(savedVisualization.uiStateJSON) : {};
|
||||
const parsedUiState = savedVisualization.uiStateJSON
|
||||
? JSON.parse(savedVisualization.uiStateJSON)
|
||||
: {};
|
||||
this.uiState = new PersistedState(parsedUiState);
|
||||
|
||||
this.uiState.on('change', this._uiStateChangeHandler);
|
||||
this.uiState.on('change', this.uiStateChangeHandler);
|
||||
}
|
||||
|
||||
_uiStateChangeHandler = () => {
|
||||
this.customization = this.uiState.toJSON();
|
||||
this._onEmbeddableStateChanged(this.getEmbeddableState());
|
||||
};
|
||||
|
||||
getInspectorAdapters() {
|
||||
public getInspectorAdapters() {
|
||||
if (!this.handler) {
|
||||
return undefined;
|
||||
}
|
||||
return this.handler.inspectorAdapters;
|
||||
}
|
||||
|
||||
getEmbeddableState() {
|
||||
public getEmbeddableState() {
|
||||
return {
|
||||
customization: this.customization,
|
||||
};
|
||||
|
@ -62,41 +91,27 @@ export class VisualizeEmbeddable extends Embeddable {
|
|||
* Transfers all changes in the containerState.embeddableCustomization into
|
||||
* the uiState of this visualization.
|
||||
*/
|
||||
transferCustomizationsToUiState(containerState) {
|
||||
public transferCustomizationsToUiState(containerState: ContainerState) {
|
||||
// Check for changes that need to be forwarded to the uiState
|
||||
// Since the vis has an own listener on the uiState we don't need to
|
||||
// pass anything from here to the handler.update method
|
||||
const customization = containerState.embeddableCustomization;
|
||||
if (!_.isEqual(this.customization, customization)) {
|
||||
if (customization && !_.isEqual(this.customization, customization)) {
|
||||
// Turn this off or the uiStateChangeHandler will fire for every modification.
|
||||
this.uiState.off('change', this._uiStateChangeHandler);
|
||||
this.uiState.off('change', this.uiStateChangeHandler);
|
||||
this.uiState.clearAllKeys();
|
||||
Object.getOwnPropertyNames(customization).forEach(key => {
|
||||
this.uiState.set(key, customization[key]);
|
||||
});
|
||||
this.customization = customization;
|
||||
this.uiState.on('change', this._uiStateChangeHandler);
|
||||
this.uiState.on('change', this.uiStateChangeHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the panel title for this panel from the container state.
|
||||
* This will either return the overwritten panel title or the visualization title.
|
||||
*/
|
||||
getPanelTitle(containerState) {
|
||||
let derivedPanelTitle = '';
|
||||
if (!containerState.hidePanelTitles) {
|
||||
derivedPanelTitle = containerState.customTitle !== undefined ?
|
||||
containerState.customTitle :
|
||||
this.savedVisualization.title;
|
||||
}
|
||||
return derivedPanelTitle;
|
||||
}
|
||||
|
||||
onContainerStateChanged(containerState) {
|
||||
public onContainerStateChanged(containerState: ContainerState) {
|
||||
this.transferCustomizationsToUiState(containerState);
|
||||
|
||||
const updatedParams = {};
|
||||
const updatedParams: VisualizeUpdateParams = {};
|
||||
|
||||
// Check if timerange has changed
|
||||
if (containerState.timeRange !== this.timeRange) {
|
||||
|
@ -134,7 +149,7 @@ export class VisualizeEmbeddable extends Embeddable {
|
|||
* @param {Element} domNode
|
||||
* @param {ContainerState} containerState
|
||||
*/
|
||||
render(domNode, containerState) {
|
||||
public render(domNode: HTMLElement, containerState: ContainerState) {
|
||||
this.panelTitle = this.getPanelTitle(containerState);
|
||||
this.timeRange = containerState.timeRange;
|
||||
this.query = containerState.query;
|
||||
|
@ -142,7 +157,15 @@ export class VisualizeEmbeddable extends Embeddable {
|
|||
|
||||
this.transferCustomizationsToUiState(containerState);
|
||||
|
||||
const handlerParams = {
|
||||
const dataAttrs: { [key: string]: string } = {
|
||||
'shared-item': '',
|
||||
title: this.panelTitle,
|
||||
};
|
||||
if (this.savedVisualization.description) {
|
||||
dataAttrs.description = this.savedVisualization.description;
|
||||
}
|
||||
|
||||
const handlerParams: VisualizeLoaderParams = {
|
||||
uiState: this.uiState,
|
||||
// Append visualization to container instead of replacing its content
|
||||
append: true,
|
||||
|
@ -150,28 +173,42 @@ export class VisualizeEmbeddable extends Embeddable {
|
|||
query: containerState.query,
|
||||
filters: containerState.filters,
|
||||
cssClass: `panel-content panel-content--fullWidth`,
|
||||
// The chrome is permanently hidden in "embed mode" in which case we don't want to show the spy pane, since
|
||||
// we deem that situation to be more public facing and want to hide more detailed information.
|
||||
dataAttrs: {
|
||||
'shared-item': '',
|
||||
title: this.panelTitle,
|
||||
description: this.savedVisualization.description,
|
||||
}
|
||||
dataAttrs,
|
||||
};
|
||||
|
||||
this.handler = this.loader.embedVisualizationWithSavedObject(
|
||||
domNode,
|
||||
this.savedVisualization,
|
||||
handlerParams,
|
||||
handlerParams
|
||||
);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.uiState.off('change', this._uiStateChangeHandler);
|
||||
public destroy() {
|
||||
this.uiState.off('change', this.uiStateChangeHandler);
|
||||
this.savedVisualization.destroy();
|
||||
if (this.handler) {
|
||||
this.handler.destroy();
|
||||
this.handler.getElement().remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the panel title for this panel from the container state.
|
||||
* This will either return the overwritten panel title or the visualization title.
|
||||
*/
|
||||
private getPanelTitle(containerState: ContainerState) {
|
||||
let derivedPanelTitle = '';
|
||||
if (!containerState.hidePanelTitles) {
|
||||
derivedPanelTitle =
|
||||
containerState.customTitle !== undefined
|
||||
? containerState.customTitle
|
||||
: this.savedVisualization.title;
|
||||
}
|
||||
return derivedPanelTitle;
|
||||
}
|
||||
|
||||
private uiStateChangeHandler = () => {
|
||||
this.customization = this.uiState.toJSON();
|
||||
this.onEmbeddableStateChanged(this.getEmbeddableState());
|
||||
};
|
||||
}
|
|
@ -18,8 +18,8 @@
|
|||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import { Embeddable, EmbeddableFactory } from 'ui/embeddable';
|
||||
import { getVisualizeLoader } from 'ui/visualize/loader';
|
||||
import { EmbeddableFactory, Embeddable } from 'ui/embeddable';
|
||||
import { VisualizeEmbeddable } from './visualize_embeddable';
|
||||
|
||||
import labDisabledTemplate from './visualize_lab_disabled.html';
|
||||
|
@ -48,30 +48,29 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory {
|
|||
const visId = panelMetadata.id;
|
||||
const editUrl = this.getEditPath(visId);
|
||||
|
||||
const waitFor = [ getVisualizeLoader(), this.savedVisualizations.get(visId) ];
|
||||
return Promise.all(waitFor)
|
||||
.then(([loader, savedObject]) => {
|
||||
const isLabsEnabled = this._config.get('visualize:enableLabs');
|
||||
const waitFor = [getVisualizeLoader(), this.savedVisualizations.get(visId)];
|
||||
return Promise.all(waitFor).then(([loader, savedObject]) => {
|
||||
const isLabsEnabled = this._config.get('visualize:enableLabs');
|
||||
|
||||
if (!isLabsEnabled && savedObject.vis.type.stage === 'experimental') {
|
||||
return new Embeddable({
|
||||
metadata: {
|
||||
title: savedObject.title,
|
||||
},
|
||||
render: (domNode) => {
|
||||
const template = $(labDisabledTemplate);
|
||||
template.find('.visDisabledLabVisualization__title').text(savedObject.title);
|
||||
$(domNode).html(template);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return new VisualizeEmbeddable({
|
||||
onEmbeddableStateChanged,
|
||||
savedVisualization: savedObject,
|
||||
editUrl,
|
||||
loader,
|
||||
});
|
||||
}
|
||||
});
|
||||
if (!isLabsEnabled && savedObject.vis.type.stage === 'experimental') {
|
||||
return new Embeddable({
|
||||
metadata: {
|
||||
title: savedObject.title,
|
||||
},
|
||||
render: domNode => {
|
||||
const template = $(labDisabledTemplate);
|
||||
template.find('.visDisabledLabVisualization__title').text(savedObject.title);
|
||||
$(domNode).html(template);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return new VisualizeEmbeddable({
|
||||
onEmbeddableStateChanged,
|
||||
savedVisualization: savedObject,
|
||||
editUrl,
|
||||
loader,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
import { Embeddable } from './embeddable';
|
||||
import { EmbeddableState } from './types';
|
||||
|
||||
export type OnEmbeddableStateChanged = (embeddableStateChanges: EmbeddableState) => void;
|
||||
|
||||
/**
|
||||
* The EmbeddableFactory creates and initializes an embeddable instance
|
||||
*/
|
||||
|
@ -35,6 +37,6 @@ export abstract class EmbeddableFactory {
|
|||
*/
|
||||
public abstract create(
|
||||
containerMetadata: { id: string },
|
||||
onEmbeddableStateChanged: (embeddableStateChanges: EmbeddableState) => void
|
||||
onEmbeddableStateChanged: OnEmbeddableStateChanged
|
||||
): Promise<Embeddable>;
|
||||
}
|
||||
|
|
|
@ -22,9 +22,13 @@ export interface TimeRange {
|
|||
from: string;
|
||||
}
|
||||
|
||||
export interface FilterMeta {
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
// TODO: Filter object representation needs to be fleshed out.
|
||||
export interface Filter {
|
||||
meta: object;
|
||||
meta: FilterMeta;
|
||||
query: object;
|
||||
}
|
||||
|
||||
|
@ -39,6 +43,9 @@ export interface Query {
|
|||
language: QueryLanguageType;
|
||||
query: string;
|
||||
}
|
||||
export interface EmbeddableCustomization {
|
||||
[key: string]: object | string;
|
||||
}
|
||||
|
||||
export interface ContainerState {
|
||||
// 'view' or 'edit'. Should probably be an enum but I'm undecided where to define it, here or in dashboard code.
|
||||
|
@ -51,7 +58,7 @@ export interface ContainerState {
|
|||
query: Query;
|
||||
|
||||
// The shape will be up to the embeddable type.
|
||||
embeddableCustomization?: object;
|
||||
embeddableCustomization?: EmbeddableCustomization;
|
||||
|
||||
/**
|
||||
* Whether or not panel titles are hidden. It is not the embeddable's responsibility to hide the title (the container
|
||||
|
@ -77,9 +84,9 @@ export interface EmbeddableState {
|
|||
* Any customization data that should be stored at the panel level. For
|
||||
* example, pie slice colors, or custom per panel sort order or columns.
|
||||
*/
|
||||
customization: object;
|
||||
customization?: object;
|
||||
/**
|
||||
* A possible filter the embeddable wishes dashboard to apply.
|
||||
*/
|
||||
stagedFilter: object;
|
||||
stagedFilter?: object;
|
||||
}
|
||||
|
|
|
@ -18,5 +18,12 @@
|
|||
*/
|
||||
|
||||
// It's currenty hard to properly type PersistedState, since it dynamically
|
||||
// inherits the class passed into the constructor.
|
||||
export type PersistedState = any;
|
||||
// inherits the class passed into the constructor. These typings are really pretty bad
|
||||
// but needed in the short term to make incremental progress elsewhere. Can't even
|
||||
// just use `any` since then typescript complains about using PersistedState as a
|
||||
// constructor.
|
||||
export class PersistedState {
|
||||
constructor(value?: any, path?: any, EmitterClass?: any);
|
||||
// method you want typed so far
|
||||
[prop: string]: any;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ export interface RequestHandlerParams {
|
|||
filters?: Filters;
|
||||
forceFetch: boolean;
|
||||
queryFilter: QueryFilter;
|
||||
uiState: PersistedState;
|
||||
uiState?: PersistedState;
|
||||
partialRows?: boolean;
|
||||
inspectorAdapters?: Adapters;
|
||||
isHierarchical?: boolean;
|
||||
|
|
|
@ -58,6 +58,7 @@ export class EmbeddedVisualizeHandler {
|
|||
* @ignore
|
||||
*/
|
||||
public readonly data$: Rx.Observable<any>;
|
||||
public readonly inspectorAdapters: Adapters = {};
|
||||
private vis: Vis;
|
||||
private loaded: boolean = false;
|
||||
private destroyed: boolean = false;
|
||||
|
@ -81,7 +82,6 @@ export class EmbeddedVisualizeHandler {
|
|||
private uiState: PersistedState;
|
||||
private dataLoader: VisualizeDataLoader;
|
||||
private dataSubject: Rx.Subject<any>;
|
||||
private readonly inspectorAdapters: Adapters = {};
|
||||
private actions: any = {};
|
||||
private events$: Rx.Observable<any>;
|
||||
private autoFetch: boolean;
|
||||
|
|
|
@ -52,6 +52,9 @@ export interface VisSavedObject {
|
|||
vis: Vis;
|
||||
description?: string;
|
||||
searchSource: SearchSource;
|
||||
title: string;
|
||||
uiStateJSON?: string;
|
||||
destroy: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -29,7 +29,7 @@ import { IPrivate } from '../../private';
|
|||
import { EmbeddedVisualizeHandler } from './embedded_visualize_handler';
|
||||
import { VisSavedObject, VisualizeLoaderParams } from './types';
|
||||
|
||||
class VisualizeLoader {
|
||||
export class VisualizeLoader {
|
||||
constructor(private readonly savedVisualizations: any, private readonly Private: IPrivate) {}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue