Files
grafana/public/app/features/panel/panel_header.ts

163 lines
4.7 KiB
TypeScript
Raw Normal View History

2017-12-20 12:33:33 +01:00
import $ from 'jquery';
import { coreModule } from 'app/core/core';
2017-04-11 10:05:30 +02:00
2018-08-26 20:19:23 +02:00
const template = `
2017-08-09 15:33:19 +02:00
<span class="panel-title">
2017-04-11 10:05:30 +02:00
<span class="icon-gf panel-alert-icon"></span>
2017-08-09 15:33:19 +02:00
<span class="panel-title-text">{{ctrl.panel.title | interpolateTemplateVars:this}}</span>
2017-04-11 10:05:30 +02:00
<span class="panel-menu-container dropdown">
<span class="fa fa-caret-down panel-menu-toggle" data-toggle="dropdown"></span>
<ul class="dropdown-menu dropdown-menu--menu panel-menu" role="menu">
2017-04-11 10:05:30 +02:00
<li>
<a ng-click="ctrl.addDataQuery(datasource);">
<i class="fa fa-cog"></i> Edit <span class="dropdown-menu-item-shortcut">e</span>
</a>
</li>
<li class="dropdown-submenu">
<a ng-click="ctrl.addDataQuery(datasource);"><i class="fa fa-cube"></i> Actions</a>
<ul class="dropdown-menu panel-menu">
<li><a ng-click="ctrl.addDataQuery(datasource);"><i class="fa fa-flash"></i> Add Annotation</a></li>
<li><a ng-click="ctrl.addDataQuery(datasource);"><i class="fa fa-bullseye"></i> Toggle Legend</a></li>
<li><a ng-click="ctrl.addDataQuery(datasource);"><i class="fa fa-download"></i> Export to CSV</a></li>
<li><a ng-click="ctrl.addDataQuery(datasource);"><i class="fa fa-eye"></i> View JSON</a></li>
</ul>
</li>
<li><a ng-click="ctrl.addDataQuery(datasource);"><i class="fa fa-trash"></i> Remove</a></li>
</ul>
</span>
2018-06-08 15:49:30 +02:00
<span class="panel-time-info" ng-if="ctrl.timeInfo"><i class="fa fa-clock-o"></i> {{ctrl.timeInfo}}</span>
2017-04-11 10:05:30 +02:00
</span>`;
2017-08-02 09:22:22 +02:00
function renderMenuItem(item, ctrl) {
2017-12-20 12:33:33 +01:00
let html = '';
let listItemClass = '';
2017-08-02 09:22:22 +02:00
2017-08-03 13:26:30 +02:00
if (item.divider) {
return '<li class="divider"></li>';
}
2017-08-02 09:22:22 +02:00
if (item.submenu) {
2017-12-20 12:33:33 +01:00
listItemClass = 'dropdown-submenu';
2017-08-02 09:22:22 +02:00
}
html += `<li class="${listItemClass}"><a `;
if (item.click) {
html += ` ng-click="${item.click}"`;
}
if (item.href) {
html += ` href="${item.href}"`;
}
2017-08-02 09:22:22 +02:00
html += `><i class="${item.icon}"></i>`;
html += `<span class="dropdown-item-text">${item.text}</span>`;
2017-08-02 09:22:22 +02:00
if (item.shortcut) {
html += `<span class="dropdown-menu-item-shortcut">${item.shortcut}</span>`;
}
html += `</a>`;
if (item.submenu) {
html += '<ul class="dropdown-menu dropdown-menu--menu panel-menu">';
for (const subitem of item.submenu) {
2017-08-02 09:22:22 +02:00
html += renderMenuItem(subitem, ctrl);
}
2017-12-20 12:33:33 +01:00
html += '</ul>';
2017-08-02 09:22:22 +02:00
}
html += `</li>`;
return html;
}
function createMenuTemplate(ctrl) {
2017-12-20 12:33:33 +01:00
let html = '';
2017-08-02 09:22:22 +02:00
for (const item of ctrl.getMenu()) {
2017-08-02 09:22:22 +02:00
html += renderMenuItem(item, ctrl);
}
return html;
}
/** @ngInject */
2017-08-02 09:22:22 +02:00
function panelHeader($compile) {
2017-04-11 10:05:30 +02:00
return {
2017-12-20 12:33:33 +01:00
restrict: 'E',
2017-04-11 10:05:30 +02:00
template: template,
link: function(scope, elem, attrs) {
const menuElem = elem.find('.panel-menu');
2017-08-02 09:22:22 +02:00
let menuScope;
let isDragged;
2017-08-02 09:22:22 +02:00
elem.click(function(evt) {
const targetClass = evt.target.className;
2017-08-02 09:22:22 +02:00
// remove existing scope
if (menuScope) {
menuScope.$destroy();
}
menuScope = scope.$new();
const menuHtml = createMenuTemplate(scope.ctrl);
2017-08-02 09:22:22 +02:00
menuElem.html(menuHtml);
$compile(menuElem)(menuScope);
if (targetClass.indexOf('panel-title-text') >= 0 || targetClass.indexOf('panel-title') >= 0) {
togglePanelMenu(evt);
}
});
2017-12-20 12:33:33 +01:00
elem.find('.panel-menu-toggle').click(() => {
togglePanelStackPosition();
});
function togglePanelMenu(e) {
if (!isDragged) {
e.stopPropagation();
togglePanelStackPosition();
2017-12-20 12:33:33 +01:00
elem.find('[data-toggle=dropdown]').dropdown('toggle');
}
}
/**
* Hack for adding special class 'dropdown-menu-open' to the panel.
* This class sets z-index for panel and prevents menu overlapping.
*/
function togglePanelStackPosition() {
2017-12-20 12:33:33 +01:00
const menuOpenClass = 'dropdown-menu-open';
const panelGridClass = '.react-grid-item.panel';
let panelElem = elem
2017-12-20 12:33:33 +01:00
.find('[data-toggle=dropdown]')
.parentsUntil('.panel')
.parent();
const menuElem = elem.find('[data-toggle=dropdown]').parent();
panelElem = panelElem && panelElem.length ? panelElem[0] : undefined;
if (panelElem) {
panelElem = $(panelElem);
$(panelGridClass).removeClass(menuOpenClass);
const state = !menuElem.hasClass('open');
panelElem.toggleClass(menuOpenClass, state);
}
}
let mouseX, mouseY;
elem.mousedown(e => {
mouseX = e.pageX;
mouseY = e.pageY;
});
elem.mouseup(e => {
if (mouseX === e.pageX && mouseY === e.pageY) {
isDragged = false;
} else {
isDragged = true;
}
});
2017-12-20 12:33:33 +01:00
},
2017-04-11 10:05:30 +02:00
};
}
2017-12-20 12:33:33 +01:00
coreModule.directive('panelHeader', panelHeader);