源码解析 - dashboard解析
plugins/kibana/public/dashboard/index.js
结构跟 visualize 类似,设置两个调用 savedDashboards.get()
方法的 routes,提供一个叫 dashboard-app 的 directive。
savedDashboards 由 plugins/kibana/public/dashboard/services/saved_dashboard.js
提供,调用 es.search 获取数据,生成 savedDashboard 对象,这个对象同样也是继承 savedObject,主要内容是 panelsJSON
数组字段。实现如下:
module.factory('SavedDashboard', function (courier) {
_.class(SavedDashboard).inherits(courier.SavedObject);
function SavedDashboard(id) {
SavedDashboard.Super.call(this, {
type: SavedDashboard.type,
mapping: SavedDashboard.mapping,
searchSource: SavedDashboard.searchsource,
id: id,
defaults: {
title: 'New Dashboard',
hits: 0,
description: '',
panelsJSON: '[]',
optionsJSON: angular.toJson({
darkTheme: config.get('dashboard:defaultDarkTheme')
}),
uiStateJSON: '{}',
version: 1,
timeRestore: false,
timeTo: undefined,
timeFrom: undefined,
refreshInterval: undefined
},
clearSavedIndexPattern: true
});
}
可以注意到,这个 panelsJSON 是一个字符串,这跟之前 kbnIndex 提到的是一致的。
dashboard-app 中,最重要的功能,是监听搜索框和过滤条件的变更,我们可以看到 init 函数中有下面这段:
function updateQueryOnRootSource() {
var filters = queryFilter.getFilters();
if ($state.query) {
dash.searchSource.set('filter', _.union(filters, [{
query: $state.query
}]));
} else {
dash.searchSource.set('filter', filters);
}
}
$scope.$listen(queryFilter, 'update', function () {
updateQueryOnRootSource();
$state.save();
});
在 index.html 里,实际承载面板的,是下面这行:
<dashboard-grid></dashboard-grid>
这也是一个 angular directive,通过加载 plugins/kibana/public/dashboard/directives/grid.js
引入的。其中添加面板相关的代码有两部分:
$scope.$watchCollection('state.panels', function (panels) {
const currentPanels = gridster.$widgets.toArray().map(function (el) {
return getPanelFor(el);
});
const removed = _.difference(currentPanels, panels);
const added = _.difference(panels, currentPanels);
if (added.length) added.forEach(addPanel);
...
这段用来监听 $state.panels
数组,一旦有新增面板,调用 addPanel
函数。同理也有删除面板的,这里就不重复贴了。
而 addPanel 函数的实现大致如下:
var addPanel = function (panel) {
_.defaults(panel, {
size_x: 3,
size_y: 2
});
...
panel.$scope = $scope.$new();
panel.$scope.panel = panel;
panel.$el = $compile('<li><dashboard-panel></li>')(panel.$scope);
gridster.add_widget(panel.$el, panel.size_x, panel.size_y, panel.col, panel.row);
...
};
这里即验证了之前 kbnIndex 小节中讲的 gridster 默认大小,又引入了一个新的 directive,叫 dashboard-panel。
dashboard-panel 在 plugins/kibana/public/dashboard/components/panel/panel.js
中实现,其中使用了 plugins/kibana/public/dashboard/components/panel/panel.html
页面。页面最后是这么一段:
<visualize ng-switch-when="visualization"
vis="savedObj.vis"
search-source="savedObj.searchSource"
class="panel-content">
</visualize>
<doc-table ng-switch-when="search"
search-source="savedObj.searchSource"
sorting="panel.sort"
columns="panel.columns"
class="panel-content"
filter="filter">
</doc-table>
这里使用的 savedObj 对象,来自 plugins/kibana/public/dashboard/components/panel/lib/load_panel.js
获取的 savedSearch 或者 savedVisualization。获得的对象,以 savedVisualization 为例:
define(function (require) {
return function visualizationLoader(savedVisualizations, Private) { // Inject services here
return function (panel, $scope) {
return savedVisualizations.get(panel.id)
.then(function (savedVis) {
savedVis.vis.listeners.click = filterBarClickHandler($scope.state);
savedVis.vis.listeners.brush = brushEvent;
return {
savedObj: savedVis,
panel: panel,
editUrl: savedVisualizations.urlFor(panel.id)
};
});
};
};
});
而 visualize 和 doc-table 两个 directive。这两个正是之前在 visualize 和 discover 插件解析里提到过的,在 components/
底下实现。