Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
911646f9
Commit
911646f9
authored
Nov 15, 2018
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
poc: handling panel edit mode in react even for angular panels poc
parent
487fd12d
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
105 additions
and
86 deletions
+105
-86
public/app/core/services/AngularLoader.ts
+4
-0
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
+41
-36
public/app/features/dashboard/dashgrid/PanelEditor.tsx
+10
-2
public/app/features/dashboard/dashgrid/VisualizationTab.tsx
+36
-1
public/app/features/panel/panel_directive.ts
+14
-46
public/app/features/panel/panel_editor_tab.ts
+0
-1
No files found.
public/app/core/services/AngularLoader.ts
View file @
911646f9
...
@@ -5,6 +5,7 @@ import _ from 'lodash';
...
@@ -5,6 +5,7 @@ import _ from 'lodash';
export
interface
AngularComponent
{
export
interface
AngularComponent
{
destroy
();
destroy
();
digest
();
digest
();
getScope
();
}
}
export
class
AngularLoader
{
export
class
AngularLoader
{
...
@@ -28,6 +29,9 @@ export class AngularLoader {
...
@@ -28,6 +29,9 @@ export class AngularLoader {
digest
:
()
=>
{
digest
:
()
=>
{
scope
.
$digest
();
scope
.
$digest
();
},
},
getScope
:
()
=>
{
return
scope
;
},
};
};
}
}
}
}
...
...
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
View file @
911646f9
...
@@ -23,11 +23,11 @@ export interface Props {
...
@@ -23,11 +23,11 @@ export interface Props {
export
interface
State
{
export
interface
State
{
plugin
:
PanelPlugin
;
plugin
:
PanelPlugin
;
angularPanel
:
AngularComponent
;
}
}
export
class
DashboardPanel
extends
PureComponent
<
Props
,
State
>
{
export
class
DashboardPanel
extends
PureComponent
<
Props
,
State
>
{
element
:
any
;
element
:
HTMLElement
;
angularPanel
:
AngularComponent
;
specialPanels
=
{};
specialPanels
=
{};
constructor
(
props
)
{
constructor
(
props
)
{
...
@@ -35,6 +35,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
...
@@ -35,6 +35,7 @@ export class DashboardPanel extends PureComponent<Props, State> {
this
.
state
=
{
this
.
state
=
{
plugin
:
null
,
plugin
:
null
,
angularPanel
:
null
,
};
};
this
.
specialPanels
[
'row'
]
=
this
.
renderRow
.
bind
(
this
);
this
.
specialPanels
[
'row'
]
=
this
.
renderRow
.
bind
(
this
);
...
@@ -96,25 +97,30 @@ export class DashboardPanel extends PureComponent<Props, State> {
...
@@ -96,25 +97,30 @@ export class DashboardPanel extends PureComponent<Props, State> {
this
.
loadPlugin
();
this
.
loadPlugin
();
// handle angular plugin loading
// handle angular plugin loading
if
(
!
this
.
element
||
this
.
angularPanel
)
{
if
(
!
this
.
element
||
this
.
state
.
angularPanel
)
{
return
;
return
;
}
}
const
loader
=
getAngularLoader
();
const
loader
=
getAngularLoader
();
const
template
=
'<plugin-component type="panel" class="panel-height-helper"></plugin-component>'
;
const
template
=
'<plugin-component type="panel" class="panel-height-helper"></plugin-component>'
;
const
scopeProps
=
{
panel
:
this
.
props
.
panel
,
dashboard
:
this
.
props
.
dashboard
};
const
scopeProps
=
{
panel
:
this
.
props
.
panel
,
dashboard
:
this
.
props
.
dashboard
};
this
.
angularPanel
=
loader
.
load
(
this
.
element
,
scopeProps
,
template
);
const
angularPanel
=
loader
.
load
(
this
.
element
,
scopeProps
,
template
);
this
.
setState
({
angularPanel
});
}
}
cleanUpAngularPanel
()
{
cleanUpAngularPanel
(
unmounted
?:
boolean
)
{
if
(
this
.
angularPanel
)
{
if
(
this
.
state
.
angularPanel
)
{
this
.
angularPanel
.
destroy
();
this
.
state
.
angularPanel
.
destroy
();
this
.
angularPanel
=
null
;
if
(
!
unmounted
)
{
this
.
setState
({
angularPanel
:
null
});
}
}
}
}
}
componentWillUnmount
()
{
componentWillUnmount
()
{
this
.
cleanUpAngularPanel
();
this
.
cleanUpAngularPanel
(
true
);
}
}
onMouseEnter
=
()
=>
{
onMouseEnter
=
()
=>
{
...
@@ -129,25 +135,16 @@ export class DashboardPanel extends PureComponent<Props, State> {
...
@@ -129,25 +135,16 @@ export class DashboardPanel extends PureComponent<Props, State> {
const
{
dashboard
,
panel
}
=
this
.
props
;
const
{
dashboard
,
panel
}
=
this
.
props
;
const
{
plugin
}
=
this
.
state
;
const
{
plugin
}
=
this
.
state
;
const
containerClass
=
this
.
props
.
isEditing
?
'panel-editor-container'
:
'panel-height-helper'
;
return
<
PanelChrome
component=
{
plugin
.
exports
.
Panel
}
panel=
{
panel
}
dashboard=
{
dashboard
}
/>;
const
panelWrapperClass
=
this
.
props
.
isEditing
?
'panel-editor-container__panel'
:
'panel-height-helper'
;
}
// this might look strange with these classes that change when edit, but
// I want to try to keep markup (parents) for panel the same in edit mode to avoide unmount / new mount of panel
renderAngularPanel
()
{
return
(
return
<
div
ref=
{
element
=>
(
this
.
element
=
element
)
}
className=
"panel-height-helper"
/>;
<
div
className=
{
containerClass
}
>
<
div
className=
{
panelWrapperClass
}
onMouseEnter=
{
this
.
onMouseEnter
}
onMouseLeave=
{
this
.
onMouseLeave
}
>
<
PanelChrome
component=
{
plugin
.
exports
.
Panel
}
panel=
{
panel
}
dashboard=
{
dashboard
}
/>
</
div
>
{
panel
.
isEditing
&&
(
<
PanelEditor
panel=
{
panel
}
plugin=
{
plugin
}
dashboard=
{
dashboard
}
onTypeChanged=
{
this
.
onPluginTypeChanged
}
/>
)
}
</
div
>
);
}
}
render
()
{
render
()
{
const
{
panel
}
=
this
.
props
;
const
{
panel
,
dashboard
}
=
this
.
props
;
const
{
plugin
}
=
this
.
state
;
const
{
plugin
,
angularPanel
}
=
this
.
state
;
if
(
this
.
isSpecial
())
{
if
(
this
.
isSpecial
())
{
return
this
.
specialPanels
[
panel
.
type
]();
return
this
.
specialPanels
[
panel
.
type
]();
...
@@ -158,19 +155,27 @@ export class DashboardPanel extends PureComponent<Props, State> {
...
@@ -158,19 +155,27 @@ export class DashboardPanel extends PureComponent<Props, State> {
return
null
;
return
null
;
}
}
// if exporting PanelComponent it must be a react panel
console
.
log
(
'DashboardPanel.render()'
);
if
(
plugin
.
exports
.
Panel
)
{
return
this
.
renderReactPanel
()
;
const
containerClass
=
this
.
props
.
isEditing
?
'panel-editor-container'
:
'panel-height-helper'
;
}
const
panelWrapperClass
=
this
.
props
.
isEditing
?
'panel-editor-container__panel'
:
'panel-height-helper'
;
// legacy angular rendering
return
(
return
(
<
div
<
div
className=
{
containerClass
}
>
ref=
{
element
=>
(
this
.
element
=
element
)
}
<
div
className=
{
panelWrapperClass
}
onMouseEnter=
{
this
.
onMouseEnter
}
onMouseLeave=
{
this
.
onMouseLeave
}
>
className=
"panel-height-helper"
{
plugin
.
exports
.
Panel
&&
this
.
renderReactPanel
()
}
onMouseEnter=
{
this
.
onMouseEnter
}
{
plugin
.
exports
.
PanelCtrl
&&
this
.
renderAngularPanel
()
}
onMouseLeave=
{
this
.
onMouseLeave
}
</
div
>
/>
{
panel
.
isEditing
&&
(
<
PanelEditor
panel=
{
panel
}
plugin=
{
plugin
}
dashboard=
{
dashboard
}
angularPanel=
{
angularPanel
}
onTypeChanged=
{
this
.
onPluginTypeChanged
}
/>
)
}
</
div
>
);
);
}
}
}
}
public/app/features/dashboard/dashgrid/PanelEditor.tsx
View file @
911646f9
...
@@ -7,6 +7,7 @@ import { GeneralTab } from './GeneralTab';
...
@@ -7,6 +7,7 @@ import { GeneralTab } from './GeneralTab';
import
{
store
}
from
'app/store/store'
;
import
{
store
}
from
'app/store/store'
;
import
{
updateLocation
}
from
'app/core/actions'
;
import
{
updateLocation
}
from
'app/core/actions'
;
import
{
AngularComponent
}
from
'app/core/services/AngularLoader'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
...
@@ -16,6 +17,7 @@ interface PanelEditorProps {
...
@@ -16,6 +17,7 @@ interface PanelEditorProps {
panel
:
PanelModel
;
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
dashboard
:
DashboardModel
;
plugin
:
PanelPlugin
;
plugin
:
PanelPlugin
;
angularPanel
?:
AngularComponent
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
}
}
...
@@ -58,7 +60,7 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
...
@@ -58,7 +60,7 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
};
};
render
()
{
render
()
{
const
{
panel
,
dashboard
,
onTypeChanged
,
plugin
}
=
this
.
props
;
const
{
panel
,
dashboard
,
onTypeChanged
,
plugin
,
angularPanel
}
=
this
.
props
;
const
{
location
}
=
store
.
getState
();
const
{
location
}
=
store
.
getState
();
const
activeTab
=
location
.
query
.
tab
||
'queries'
;
const
activeTab
=
location
.
query
.
tab
||
'queries'
;
...
@@ -85,7 +87,13 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
...
@@ -85,7 +87,13 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
{
activeTab
===
'general'
&&
<
GeneralTab
panel=
{
panel
}
/>
}
{
activeTab
===
'general'
&&
<
GeneralTab
panel=
{
panel
}
/>
}
{
activeTab
===
'queries'
&&
<
QueriesTab
panel=
{
panel
}
dashboard=
{
dashboard
}
/>
}
{
activeTab
===
'queries'
&&
<
QueriesTab
panel=
{
panel
}
dashboard=
{
dashboard
}
/>
}
{
activeTab
===
'visualization'
&&
(
{
activeTab
===
'visualization'
&&
(
<
VisualizationTab
panel=
{
panel
}
dashboard=
{
dashboard
}
plugin=
{
plugin
}
onTypeChanged=
{
onTypeChanged
}
/>
<
VisualizationTab
panel=
{
panel
}
dashboard=
{
dashboard
}
plugin=
{
plugin
}
onTypeChanged=
{
onTypeChanged
}
angularPanel=
{
angularPanel
}
/>
)
}
)
}
</
div
>
</
div
>
);
);
...
...
public/app/features/dashboard/dashgrid/VisualizationTab.tsx
View file @
911646f9
// Libraries
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
// Utils & Services
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/AngularLoader'
;
// Components
import
{
EditorTabBody
}
from
'./EditorTabBody'
;
import
{
EditorTabBody
}
from
'./EditorTabBody'
;
import
{
VizTypePicker
}
from
'./VizTypePicker'
;
import
{
VizTypePicker
}
from
'./VizTypePicker'
;
// Types
import
{
PanelModel
}
from
'../panel_model'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
PanelPlugin
}
from
'app/types/plugins'
;
import
{
PanelPlugin
}
from
'app/types/plugins'
;
...
@@ -11,18 +17,26 @@ interface Props {
...
@@ -11,18 +17,26 @@ interface Props {
panel
:
PanelModel
;
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
dashboard
:
DashboardModel
;
plugin
:
PanelPlugin
;
plugin
:
PanelPlugin
;
angularPanel
?:
AngularComponent
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
}
}
export
class
VisualizationTab
extends
PureComponent
<
Props
>
{
export
class
VisualizationTab
extends
PureComponent
<
Props
>
{
element
:
HTMLElement
;
angularOptions
:
AngularComponent
;
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
);
super
(
props
);
}
}
renderPanelOptions
()
{
renderPanelOptions
()
{
const
{
plugin
,
panel
}
=
this
.
props
;
const
{
plugin
,
panel
,
angularPanel
}
=
this
.
props
;
const
{
PanelOptions
}
=
plugin
.
exports
;
const
{
PanelOptions
}
=
plugin
.
exports
;
if
(
angularPanel
)
{
return
<
div
ref=
{
element
=>
(
this
.
element
=
element
)
}
/>;
}
if
(
PanelOptions
)
{
if
(
PanelOptions
)
{
return
<
PanelOptions
options=
{
panel
.
getOptions
()
}
onChange=
{
this
.
onPanelOptionsChanged
}
/>;
return
<
PanelOptions
options=
{
panel
.
getOptions
()
}
onChange=
{
this
.
onPanelOptionsChanged
}
/>;
}
else
{
}
else
{
...
@@ -30,6 +44,27 @@ export class VisualizationTab extends PureComponent<Props> {
...
@@ -30,6 +44,27 @@ export class VisualizationTab extends PureComponent<Props> {
}
}
}
}
componentDidMount
()
{
const
{
angularPanel
}
=
this
.
props
;
if
(
angularPanel
)
{
const
scope
=
angularPanel
.
getScope
();
const
panelCtrl
=
scope
.
$$childHead
.
ctrl
;
const
loader
=
getAngularLoader
();
const
template
=
'<panel-editor-tab editor-tab="tab" ctrl="ctrl"></panel-editor-tab>'
;
const
scopeProps
=
{
ctrl
:
panelCtrl
,
tab
:
panelCtrl
.
editorTabs
[
2
]
};
this
.
angularOptions
=
loader
.
load
(
this
.
element
,
scopeProps
,
template
);
}
}
componentWillUnmount
()
{
if
(
this
.
angularOptions
)
{
this
.
angularOptions
.
destroy
();
}
}
onPanelOptionsChanged
=
(
options
:
any
)
=>
{
onPanelOptionsChanged
=
(
options
:
any
)
=>
{
this
.
props
.
panel
.
updateOptions
(
options
);
this
.
props
.
panel
.
updateOptions
(
options
);
this
.
forceUpdate
();
this
.
forceUpdate
();
...
...
public/app/features/panel/panel_directive.ts
View file @
911646f9
...
@@ -6,54 +6,22 @@ import baron from 'baron';
...
@@ -6,54 +6,22 @@ import baron from 'baron';
const
module
=
angular
.
module
(
'grafana.directives'
);
const
module
=
angular
.
module
(
'grafana.directives'
);
const
panelTemplate
=
`
const
panelTemplate
=
`
<div ng-class="{'panel-editor-container': ctrl.panel.isEditing, 'panel-height-helper': !ctrl.panel.isEditing}">
<div class="panel-container">
<div ng-class="{'panel-editor-container__panel': ctrl.panel.isEditing, 'panel-height-helper': !ctrl.panel.isEditing}">
<div class="panel-header" ng-class="{'grid-drag-handle': !ctrl.panel.fullscreen}">
<div class="panel-container">
<span class="panel-info-corner">
<div class="panel-header" ng-class="{'grid-drag-handle': !ctrl.panel.fullscreen}">
<i class="fa"></i>
<span class="panel-info-corner">
<span class="panel-info-corner-inner"></span>
<i class="fa"></i>
</span>
<span class="panel-info-corner-inner"></span>
</span>
<span class="panel-loading" ng-show="ctrl.loading">
<i class="fa fa-spinner fa-spin"></i>
<span class="panel-loading" ng-show="ctrl.loading">
</span>
<i class="fa fa-spinner fa-spin"></i>
</span>
<panel-header class="panel-title-container" panel-ctrl="ctrl"></panel-header>
<panel-header class="panel-title-container" panel-ctrl="ctrl"></panel-header>
</div>
<div class="panel-content">
<ng-transclude class="panel-height-helper"></ng-transclude>
</div>
</div>
</div>
</div>
<div ng-if="ctrl.panel.isEditing" ng-class="{'panel-editor-container__editor': ctrl.panel.isEditing,
<div class="panel-content">
'panel-height-helper': !ctrl.panel.isEditing}">
<ng-transclude class="panel-height-helper"></ng-transclude>
<div class="tabbed-view tabbed-view--new">
<div class="tabbed-view-header">
<h3 class="tabbed-view-panel-title">
{{ctrl.pluginName}}
</h3>
<ul class="gf-tabs">
<li class="gf-tabs-item" ng-repeat="tab in ::ctrl.editorTabs">
<a class="gf-tabs-link" ng-click="ctrl.changeTab($index)" ng-class="{active: ctrl.editorTabIndex === $index}">
{{::tab.title}}
</a>
</li>
</ul>
<button class="panel-editor-tabs__close" ng-click="ctrl.exitFullscreen();">
<i class="fa fa-reply"></i>
</button>
</div>
<div class="tabbed-view-body">
<div ng-repeat="tab in ctrl.editorTabs" ng-if="ctrl.editorTabIndex === $index" class="panel-height-helper">
<panel-editor-tab editor-tab="tab" ctrl="ctrl" index="$index"></panel-editor-tab>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
...
public/app/features/panel/panel_editor_tab.ts
View file @
911646f9
...
@@ -9,7 +9,6 @@ function panelEditorTab(dynamicDirectiveSrv) {
...
@@ -9,7 +9,6 @@ function panelEditorTab(dynamicDirectiveSrv) {
scope
:
{
scope
:
{
ctrl
:
'='
,
ctrl
:
'='
,
editorTab
:
'='
,
editorTab
:
'='
,
index
:
'='
,
},
},
directive
:
scope
=>
{
directive
:
scope
=>
{
const
pluginId
=
scope
.
ctrl
.
pluginId
;
const
pluginId
=
scope
.
ctrl
.
pluginId
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment