diff --git a/public/app/features/alerting/AlertTabCtrl.ts b/public/app/features/alerting/AlertTabCtrl.ts index ef68ddcf4a5..5a8abee00d7 100644 --- a/public/app/features/alerting/AlertTabCtrl.ts +++ b/public/app/features/alerting/AlertTabCtrl.ts @@ -1,4 +1,5 @@ import _ from 'lodash'; +import coreModule from 'app/core/core_module'; import { ThresholdMapper } from './state/ThresholdMapper'; import { QueryPart } from 'app/core/components/query_part/query_part'; import alertDef from './state/alertDef'; @@ -430,3 +431,5 @@ export function alertTab() { controller: AlertTabCtrl, }; } + +coreModule.directive('alertTab', alertTab); diff --git a/public/app/features/dashboard/dashgrid/AlertTab.tsx b/public/app/features/dashboard/dashgrid/AlertTab.tsx new file mode 100644 index 00000000000..bf691782e92 --- /dev/null +++ b/public/app/features/dashboard/dashgrid/AlertTab.tsx @@ -0,0 +1,72 @@ +import React, { PureComponent } from 'react'; + +import { getAngularLoader, AngularComponent } from 'app/core/services/AngularLoader'; +import { EditorTabBody } from './EditorTabBody'; +import 'app/features/alerting/AlertTabCtrl'; + +interface Props { + angularPanel?: AngularComponent; +} + +export class AlertTab extends PureComponent { + element: any; + component: AngularComponent; + + constructor(props) { + super(props); + } + + componentDidMount() { + if (this.shouldLoadAlertTab()) { + this.loadAlertTab(); + } + } + + componentDidUpdate(prevProps: Props) { + if (this.shouldLoadAlertTab()) { + this.loadAlertTab(); + } + } + + shouldLoadAlertTab() { + return this.props.angularPanel && this.element; + } + + componentWillUnmount() { + if (this.component) { + this.component.destroy(); + } + } + + loadAlertTab() { + const { angularPanel } = this.props; + + const scope = angularPanel.getScope(); + + // When full page reloading in edit mode the angular panel has on fully compiled & instantiated yet + if (!scope.$$childHead) { + setTimeout(() => { + this.forceUpdate(); + }); + return; + } + + const panelCtrl = scope.$$childHead.ctrl; + const loader = getAngularLoader(); + const template = ''; + + const scopeProps = { + ctrl: panelCtrl, + }; + + this.component = loader.load(this.element, scopeProps, template); + } + + render() { + return ( + +
(this.element = element)} /> + + ); + } +} diff --git a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx index 84db3a2cf99..6df8a8bc0aa 100644 --- a/public/app/features/dashboard/dashgrid/DashboardGrid.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardGrid.tsx @@ -176,10 +176,9 @@ export class DashboardGrid extends React.Component { renderPanels() { const panelElements = []; - console.log('render panels'); for (const panel of this.props.dashboard.panels) { - const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen }); + const panelClasses = classNames({ 'react-grid-item--fullscreen': panel.fullscreen }); panelElements.push(
{ } render() { - const { panel, dashboard } = this.props; + const { panel, dashboard, isFullscreen, isEditing } = this.props; const { plugin, angularPanel } = this.state; if (this.isSpecial()) { @@ -148,8 +149,12 @@ export class DashboardPanel extends PureComponent { return null; } - const containerClass = this.props.isEditing ? 'panel-editor-container' : 'panel-height-helper'; - const panelWrapperClass = this.props.isEditing ? 'panel-editor-container__panel' : 'panel-height-helper'; + const containerClass = classNames({ 'panel-editor-container': isEditing, 'panel-height-helper': !isEditing }); + const panelWrapperClass = classNames({ + 'panel-wrapper': true, + 'panel-wrapper--edit': isEditing, + 'panel-wrapper--view': isFullscreen && !isEditing, + }); return (
diff --git a/public/app/features/dashboard/dashgrid/GeneralTab.tsx b/public/app/features/dashboard/dashgrid/GeneralTab.tsx index 830421a6cc6..0b600e08d83 100644 --- a/public/app/features/dashboard/dashgrid/GeneralTab.tsx +++ b/public/app/features/dashboard/dashgrid/GeneralTab.tsx @@ -51,7 +51,7 @@ export class GeneralTab extends PureComponent { return ( -
(this.element = element)} style={{ width: '100%' }} /> +
(this.element = element)} /> ); } diff --git a/public/app/features/dashboard/dashgrid/PanelEditor.tsx b/public/app/features/dashboard/dashgrid/PanelEditor.tsx index 24e67538504..019982707a1 100644 --- a/public/app/features/dashboard/dashgrid/PanelEditor.tsx +++ b/public/app/features/dashboard/dashgrid/PanelEditor.tsx @@ -4,7 +4,9 @@ import classNames from 'classnames'; import { QueriesTab } from './QueriesTab'; import { VisualizationTab } from './VisualizationTab'; import { GeneralTab } from './GeneralTab'; +import { AlertTab } from './AlertTab'; +import config from 'app/core/config'; import { store } from 'app/store/store'; import { updateLocation } from 'app/core/actions'; import { AngularComponent } from 'app/core/services/AngularLoader'; @@ -28,16 +30,8 @@ interface PanelEditorTab { } export class PanelEditor extends PureComponent { - tabs: PanelEditorTab[]; - constructor(props) { super(props); - - this.tabs = [ - { id: 'general', text: 'General', icon: 'gicon gicon-preferences' }, - { id: 'queries', text: 'Queries', icon: 'fa fa-database' }, - { id: 'visualization', text: 'Visualization', icon: 'fa fa-line-chart' }, - ]; } onChangeTab = (tab: PanelEditorTab) => { @@ -50,19 +44,48 @@ export class PanelEditor extends PureComponent { this.forceUpdate(); }; - onClose = () => { - store.dispatch( - updateLocation({ - query: { tab: null, fullscreen: null, edit: null }, - partial: true, - }) - ); - }; + renderCurrentTab(activeTab: string) { + const { panel, dashboard, onTypeChanged, plugin, angularPanel } = this.props; + + switch (activeTab) { + case 'general': + return ; + case 'queries': + return ; + case 'alert': + return ; + case 'visualization': + return ( + + ); + default: + return null; + } + } render() { - const { panel, dashboard, onTypeChanged, plugin, angularPanel } = this.props; - const { location } = store.getState(); - const activeTab = location.query.tab || 'queries'; + const { plugin } = this.props; + const activeTab = store.getState().location.query.tab || 'queries'; + + const tabs = [ + { id: 'general', text: 'General', icon: 'gicon gicon-preferences' }, + { id: 'queries', text: 'Queries', icon: 'fa fa-database' }, + { id: 'visualization', text: 'Visualization', icon: 'fa fa-line-chart' }, + ]; + + if (config.alertingEnabled && plugin.id === 'graph') { + tabs.push({ + id: 'alert', + text: 'Alert', + icon: 'gicon gicon-alert', + }); + } return (
@@ -74,27 +97,12 @@ export class PanelEditor extends PureComponent {
    - {this.tabs.map(tab => { + {tabs.map(tab => { return ; })}
- -
- - {activeTab === 'general' && } - {activeTab === 'queries' && } - {activeTab === 'visualization' && ( - - )} + {this.renderCurrentTab(activeTab)}
); } diff --git a/public/app/plugins/panel/graph/module.ts b/public/app/plugins/panel/graph/module.ts index 37b805f2f40..24c8825e883 100644 --- a/public/app/plugins/panel/graph/module.ts +++ b/public/app/plugins/panel/graph/module.ts @@ -138,11 +138,6 @@ class GraphCtrl extends MetricsPanelCtrl { this.addEditorTab('Display options', 'public/app/plugins/panel/graph/tab_display.html'); this.addEditorTab('Axes', axesEditorComponent); this.addEditorTab('Legend', 'public/app/plugins/panel/graph/tab_legend.html'); - - // if (config.alertingEnabled) { - // this.addEditorTab('Alert', alertTab, 5); - // } - this.subTabIndex = 0; } diff --git a/public/sass/components/_dashboard_grid.scss b/public/sass/components/_dashboard_grid.scss index 5f142dfd02f..1370bd96709 100644 --- a/public/sass/components/_dashboard_grid.scss +++ b/public/sass/components/_dashboard_grid.scss @@ -9,18 +9,14 @@ .react-grid-item { display: none !important; transition-property: none !important; - } - .panel--fullscreen { - display: block !important; - position: unset !important; - width: 100% !important; - height: 100% !important; - transform: translate(0px, 0px) !important; - } - - .panel { - margin: 0 !important; + &--fullscreen { + display: block !important; + position: unset !important; + width: 100% !important; + height: 100% !important; + transform: translate(0px, 0px) !important; + } } // Disable grid interaction indicators in fullscreen panels @@ -83,10 +79,10 @@ } // Disable animation on initial rendering and enable it when component has been mounted. -.react-grid-item.cssTransforms.panel { +.react-grid-item.cssTransforms { transition-property: none; } -.animated .react-grid-item.cssTransforms.panel { +.animated .react-grid-item.cssTransforms { transition-property: transform; } diff --git a/public/sass/components/_navbar.scss b/public/sass/components/_navbar.scss index dcf3b1f0aa9..84416c75c7d 100644 --- a/public/sass/components/_navbar.scss +++ b/public/sass/components/_navbar.scss @@ -50,6 +50,10 @@ .navbar-page-btn .fa-caret-down { display: none; } + + .navbar-buttons--close { + display: flex; + } } .navbar-page-btn { diff --git a/public/sass/components/_panel_editor.scss b/public/sass/components/_panel_editor.scss index 05608fd38ec..0baaaa3ea88 100644 --- a/public/sass/components/_panel_editor.scss +++ b/public/sass/components/_panel_editor.scss @@ -4,8 +4,21 @@ height: 100%; } -.panel-editor-container__panel { - flex: 1 1 0; +.panel-wrapper { + height: 100%; + + &--edit { + flex: 1 1 0; + height: unset; + margin: 0 $dashboard-padding; + } + + &--view { + flex: 1 1 0; + height: 80%; + margin: 0 $dashboard-padding; + padding-top: $dashboard-padding; + } } .panel-editor-container__editor {