Files
grafana/public/app/features/panel/panel_header.ts
Marcus Efraimsson 68457f5636 dashboard: copy panel to clipboard
Adds a new menu item to panels, Copy to Clipboard, that will both
copy the panel json to the clipboard and temporarily store the panel object
in the browsers window object. The temporarily stored panel object are
available in Add Panel from any dashboard for as long you don't refresh
the browser.
Fixes #10248, #1004
2017-12-22 10:24:55 +01:00

171 lines
4.8 KiB
TypeScript

///<reference path="../../headers/common.d.ts" />
import $ from 'jquery';
import { coreModule } from 'app/core/core';
var template = `
<span class="panel-title">
<span class="icon-gf panel-alert-icon"></span>
<span class="panel-title-text">{{ctrl.panel.title | interpolateTemplateVars:this}}</span>
<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">
<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>
<span class="panel-time-info" ng-show="ctrl.timeInfo"><i class="fa fa-clock-o"></i> {{ctrl.timeInfo}}</span>
</span>`;
function renderMenuItem(item, ctrl) {
let html = '';
let listItemClass = '';
if (item.divider) {
return '<li class="divider"></li>';
}
if (item.submenu) {
listItemClass = 'dropdown-submenu';
}
html += `<li class="${listItemClass}"><a `;
if (item.click) {
html += ` ng-click="${item.click}"`;
}
if (item.href) {
html += ` href="${item.href}"`;
}
if (item.directives) {
for (let directive of item.directives) {
html += ` ${directive}`;
}
}
html += `><i class="${item.icon}"></i>`;
html += `<span class="dropdown-item-text">${item.text}</span>`;
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 (let subitem of item.submenu) {
html += renderMenuItem(subitem, ctrl);
}
html += '</ul>';
}
html += `</li>`;
return html;
}
function createMenuTemplate(ctrl) {
let html = '';
for (let item of ctrl.getMenu()) {
html += renderMenuItem(item, ctrl);
}
return html;
}
/** @ngInject **/
function panelHeader($compile) {
return {
restrict: 'E',
template: template,
link: function(scope, elem, attrs) {
let menuElem = elem.find('.panel-menu');
let menuScope;
let isDragged;
elem.click(function(evt) {
const targetClass = evt.target.className;
// remove existing scope
if (menuScope) {
menuScope.$destroy();
}
menuScope = scope.$new();
let menuHtml = createMenuTemplate(scope.ctrl);
menuElem.html(menuHtml);
$compile(menuElem)(menuScope);
if (targetClass.indexOf('panel-title-text') >= 0 || targetClass.indexOf('panel-title') >= 0) {
togglePanelMenu(evt);
}
});
elem.find('.panel-menu-toggle').click(() => {
togglePanelStackPosition();
});
function togglePanelMenu(e) {
if (!isDragged) {
e.stopPropagation();
togglePanelStackPosition();
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() {
const menuOpenClass = 'dropdown-menu-open';
const panelGridClass = '.react-grid-item.panel';
let panelElem = elem
.find('[data-toggle=dropdown]')
.parentsUntil('.panel')
.parent();
let menuElem = elem.find('[data-toggle=dropdown]').parent();
panelElem = panelElem && panelElem.length ? panelElem[0] : undefined;
if (panelElem) {
panelElem = $(panelElem);
$(panelGridClass).removeClass(menuOpenClass);
let 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;
}
});
},
};
}
coreModule.directive('panelHeader', panelHeader);