From 68457f56360542988f91f73e37c43c76987d1e26 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Thu, 21 Dec 2017 18:10:24 +0100 Subject: [PATCH 1/2] 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 --- public/app/features/dashboard/all.ts | 1 + .../app/features/dashboard/dashboard_ctrl.ts | 7 ++- .../dashboard/dashgrid/AddPanelPanel.tsx | 51 +++++++++++++++---- .../dashboard/dashgrid/PanelContainer.ts | 1 + .../features/dashboard/panel_clipboard_srv.ts | 21 ++++++++ public/app/features/panel/panel_ctrl.ts | 20 ++++++++ public/app/features/panel/panel_header.ts | 6 +++ public/sass/base/font-awesome/_larger.scss | 2 +- public/sass/components/_panel_add_panel.scss | 4 ++ 9 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 public/app/features/dashboard/panel_clipboard_srv.ts diff --git a/public/app/features/dashboard/all.ts b/public/app/features/dashboard/all.ts index a3535c8fb35..267de52c609 100644 --- a/public/app/features/dashboard/all.ts +++ b/public/app/features/dashboard/all.ts @@ -27,6 +27,7 @@ import './acl/acl'; import './folder_picker/folder_picker'; import './move_to_folder_modal/move_to_folder'; import './settings/settings'; +import './panel_clipboard_srv'; import coreModule from 'app/core/core_module'; import { DashboardListCtrl } from './dashboard_list_ctrl'; diff --git a/public/app/features/dashboard/dashboard_ctrl.ts b/public/app/features/dashboard/dashboard_ctrl.ts index 8b1c69ef7fe..3012f86fe31 100644 --- a/public/app/features/dashboard/dashboard_ctrl.ts +++ b/public/app/features/dashboard/dashboard_ctrl.ts @@ -22,7 +22,8 @@ export class DashboardCtrl implements PanelContainer { private unsavedChangesSrv, private dashboardViewStateSrv, public playlistSrv, - private panelLoader + private panelLoader, + private panelClipboardSrv ) { // temp hack due to way dashboards are loaded // can't use controllerAs on route yet @@ -122,6 +123,10 @@ export class DashboardCtrl implements PanelContainer { return this.panelLoader; } + getClipboardPanel() { + return this.panelClipboardSrv.getPanel(); + } + timezoneChanged() { this.$rootScope.$broadcast('refresh'); } diff --git a/public/app/features/dashboard/dashgrid/AddPanelPanel.tsx b/public/app/features/dashboard/dashgrid/AddPanelPanel.tsx index 75c8cbf36bc..78def4d47bc 100644 --- a/public/app/features/dashboard/dashgrid/AddPanelPanel.tsx +++ b/public/app/features/dashboard/dashgrid/AddPanelPanel.tsx @@ -2,8 +2,8 @@ import React from 'react'; import _ from 'lodash'; import config from 'app/core/config'; -import {PanelModel} from '../panel_model'; -import {PanelContainer} from './PanelContainer'; +import { PanelModel } from '../panel_model'; +import { PanelContainer } from './PanelContainer'; import ScrollBar from 'app/core/components/ScrollBar/ScrollBar'; export interface AddPanelPanelProps { @@ -14,6 +14,7 @@ export interface AddPanelPanelProps { export interface AddPanelPanelState { filter: string; panelPlugins: any[]; + clipboardPanel: any; } export class AddPanelPanel extends React.Component { @@ -22,45 +23,77 @@ export class AddPanelPanel extends React.Component item) .value(); // add special row type - panels.push({id: 'row', name: 'Row', sort: 8, info: {logos: {small: 'public/img/icn-row.svg'}}}); + panels.push({ id: 'row', name: 'Row', sort: 8, info: { logos: { small: 'public/img/icn-row.svg' } } }); // add sort by sort property return _.sortBy(panels, 'sort'); } + getClipboardPanel() { + return this.props.getPanelContainer().getClipboardPanel(); + } + onPanelSelected(panelPluginInfo) { const panelContainer = this.props.getPanelContainer(); const dashboard = panelContainer.getDashboard(); - const {gridPos} = this.props.panel; + const { gridPos } = this.props.panel; var newPanel: any = { type: panelPluginInfo.id, title: 'Panel Title', - gridPos: {x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h} + gridPos: { x: gridPos.x, y: gridPos.y, w: gridPos.w, h: gridPos.h }, }; if (panelPluginInfo.id === 'row') { newPanel.title = 'Row title'; - newPanel.gridPos = {x: 0, y: 0}; + newPanel.gridPos = { x: 0, y: 0 }; } dashboard.addPanel(newPanel); dashboard.removePanel(this.props.panel); } + onClipboardPanelSelected(panel) { + const panelContainer = this.props.getPanelContainer(); + const dashboard = panelContainer.getDashboard(); + + const { gridPos } = this.props.panel; + panel.gridPos.x = gridPos.x; + panel.gridPos.y = gridPos.y; + + dashboard.addPanel(panel); + dashboard.removePanel(this.props.panel); + } + + renderClipboardPanel(copiedPanel) { + const panel = copiedPanel.panel; + const title = `Paste copied panel '${panel.title}' from '${copiedPanel.dashboard}'`; + + return ( +
this.onClipboardPanelSelected(panel)} title={title}> +
+ +
+
Paste copied panel
+
+ ); + } + renderPanelItem(panel) { return (
this.onPanelSelected(panel)} title={panel.name}> @@ -75,11 +108,12 @@ export class AddPanelPanel extends React.Component
- + New Panel Select a visualization
+ {this.state.clipboardPanel && this.renderClipboardPanel(this.state.clipboardPanel)} {this.state.panelPlugins.map(this.renderPanelItem.bind(this))}
@@ -87,4 +121,3 @@ export class AddPanelPanel extends React.Component { diff --git a/public/app/features/panel/panel_header.ts b/public/app/features/panel/panel_header.ts index ca6ed68b648..de8c93d5038 100644 --- a/public/app/features/panel/panel_header.ts +++ b/public/app/features/panel/panel_header.ts @@ -51,6 +51,12 @@ function renderMenuItem(item, ctrl) { html += ` href="${item.href}"`; } + if (item.directives) { + for (let directive of item.directives) { + html += ` ${directive}`; + } + } + html += `>`; html += `${item.text}`; diff --git a/public/sass/base/font-awesome/_larger.scss b/public/sass/base/font-awesome/_larger.scss index 1efeef30392..5d7bebcda14 100644 --- a/public/sass/base/font-awesome/_larger.scss +++ b/public/sass/base/font-awesome/_larger.scss @@ -8,7 +8,7 @@ vertical-align: -15%; } .#{$fa-css-prefix}-2x { - font-size: 2em; + font-size: 2em !important; } .#{$fa-css-prefix}-3x { font-size: 3em; diff --git a/public/sass/components/_panel_add_panel.scss b/public/sass/components/_panel_add_panel.scss index a6b5aebd107..548d677ef47 100644 --- a/public/sass/components/_panel_add_panel.scss +++ b/public/sass/components/_panel_add_panel.scss @@ -65,3 +65,7 @@ .add-panel__item-img { height: calc(100% - 15px); } + +.add-panel__item-icon { + padding: 2px; +} From 281e519fab16a66da50b09ba48954995d5e234eb Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 22 Dec 2017 10:26:01 +0100 Subject: [PATCH 2/2] fix: remove unused code --- public/app/features/panel/panel_ctrl.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts index 47d48af0fa2..1cf4681515c 100644 --- a/public/app/features/panel/panel_ctrl.ts +++ b/public/app/features/panel/panel_ctrl.ts @@ -271,7 +271,6 @@ export class PanelCtrl { let editScope = this.$scope.$root.$new(); editScope.object = this.panel.getSaveModel(); editScope.updateHandler = this.replacePanel.bind(this); - editScope.enableCopy = true; this.publishAppEvent('show-modal', { src: 'public/app/partials/edit_json.html',