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
e052e165
Commit
e052e165
authored
Jul 09, 2018
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'react-panels' of github.com:grafana/grafana into react-panels
parents
4fd21070
51f8d3ca
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
471 additions
and
102 deletions
+471
-102
public/app/core/config.ts
+12
-1
public/app/features/dashboard/dashgrid/DashboardGrid.tsx
+1
-1
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
+15
-12
public/app/features/dashboard/dashgrid/DataPanel.tsx
+85
-0
public/app/features/dashboard/dashgrid/PanelChrome.tsx
+30
-16
public/app/features/dashboard/dashgrid/PanelEditor.tsx
+67
-32
public/app/features/dashboard/dashgrid/PanelHeader.tsx
+8
-5
public/app/features/dashboard/dashgrid/QueriesTab.tsx
+49
-0
public/app/features/dashboard/dashgrid/VizTypePicker.tsx
+61
-0
public/app/features/dashboard/dashnav/dashnav.ts
+2
-0
public/app/features/dashboard/specs/AddPanelPanel.jest.tsx
+15
-0
public/app/features/panel/panel_directive.ts
+1
-1
public/app/features/plugins/plugin_component.ts
+1
-2
public/app/features/plugins/plugin_loader.ts
+12
-1
public/app/plugins/panel/text2/module.tsx
+11
-3
public/app/stores/ViewStore/ViewStore.ts
+4
-2
public/sass/_grafana.scss
+1
-0
public/sass/components/_panel_add_panel.scss
+0
-4
public/sass/components/_tabbed_view.scss
+9
-19
public/sass/components/_viz_editor.scss
+78
-0
public/sass/pages/_dashboard.scss
+9
-3
No files found.
public/app/core/config.ts
View file @
e052e165
...
...
@@ -7,9 +7,20 @@ export interface BuildInfo {
env
:
string
;
}
export
interface
PanelPlugin
{
id
:
string
;
name
:
string
;
meta
:
any
;
hideFromList
:
boolean
;
module
:
string
;
baseUrl
:
string
;
info
:
any
;
sort
:
number
;
}
export
class
Settings
{
datasources
:
any
;
panels
:
any
;
panels
:
PanelPlugin
[]
;
appSubUrl
:
string
;
window_title_prefix
:
string
;
buildInfo
:
BuildInfo
;
...
...
public/app/features/dashboard/dashgrid/DashboardGrid.tsx
View file @
e052e165
...
...
@@ -139,7 +139,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
}
onViewModeChanged
(
payload
)
{
this
.
setState
({
animated
:
payload
.
fullscreen
});
this
.
setState
({
animated
:
!
payload
.
fullscreen
});
}
updateGridPos
(
item
,
layout
)
{
...
...
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
View file @
e052e165
...
...
@@ -5,24 +5,27 @@ import { DashboardModel } from '../dashboard_model';
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/angular_loader'
;
import
{
DashboardRow
}
from
'./DashboardRow'
;
import
{
AddPanelPanel
}
from
'./AddPanelPanel'
;
import
{
importPluginModule
}
from
'app/features/plugins/plugin_loader'
;
import
{
importPluginModule
,
PluginExports
}
from
'app/features/plugins/plugin_loader'
;
import
{
PanelChrome
}
from
'./PanelChrome'
;
export
interface
DashboardPanel
Props
{
export
interface
Props
{
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
}
export
class
DashboardPanel
extends
React
.
Component
<
DashboardPanelProps
,
any
>
{
export
interface
State
{
pluginExports
:
PluginExports
;
}
export
class
DashboardPanel
extends
React
.
Component
<
Props
,
State
>
{
element
:
any
;
angularPanel
:
AngularComponent
;
pluginInfo
:
any
;
pluginExports
:
any
;
specialPanels
=
{};
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{};
this
.
state
=
{
pluginExports
:
null
};
this
.
specialPanels
[
'row'
]
=
this
.
renderRow
.
bind
(
this
);
this
.
specialPanels
[
'add-panel'
]
=
this
.
renderAddPanel
.
bind
(
this
);
...
...
@@ -32,8 +35,7 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
// load panel plugin
importPluginModule
(
this
.
pluginInfo
.
module
).
then
(
pluginExports
=>
{
this
.
pluginExports
=
pluginExports
;
this
.
forceUpdate
();
this
.
setState
({
pluginExports
:
pluginExports
});
});
}
}
...
...
@@ -51,8 +53,7 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
}
componentDidUpdate
()
{
// skip loading angular component if we have no element
// or we have already loaded it
// skip loading angular component if we have no element or we have already loaded it
if
(
!
this
.
element
||
this
.
angularPanel
)
{
return
;
}
...
...
@@ -70,18 +71,20 @@ export class DashboardPanel extends React.Component<DashboardPanelProps, any> {
}
render
()
{
const
{
pluginExports
}
=
this
.
state
;
if
(
this
.
isSpecial
())
{
return
this
.
specialPanels
[
this
.
props
.
panel
.
type
]();
}
if
(
!
this
.
pluginExports
)
{
if
(
!
pluginExports
)
{
return
null
;
}
if
(
this
.
pluginExports
.
PanelComponent
)
{
if
(
pluginExports
.
PanelComponent
)
{
return
(
<
PanelChrome
component=
{
this
.
pluginExports
.
PanelComponent
}
component=
{
pluginExports
.
PanelComponent
}
panel=
{
this
.
props
.
panel
}
dashboard=
{
this
.
props
.
dashboard
}
/>
...
...
public/app/features/dashboard/dashgrid/DataPanel.tsx
0 → 100644
View file @
e052e165
import
React
,
{
Component
,
ComponentClass
}
from
'react'
;
export
interface
OuterProps
{
type
:
string
;
queries
:
any
[];
isVisible
:
boolean
;
}
export
interface
PanelProps
extends
OuterProps
{
data
:
any
[];
}
export
interface
DataPanel
extends
ComponentClass
<
OuterProps
>
{
}
interface
State
{
isLoading
:
boolean
;
data
:
any
[];
}
export
const
DataPanelWrapper
=
(
ComposedComponent
:
ComponentClass
<
PanelProps
>
)
=>
{
class
Wrapper
extends
Component
<
OuterProps
,
State
>
{
public
static
defaultProps
=
{
isVisible
:
true
,
};
constructor
(
props
:
OuterProps
)
{
super
(
props
);
this
.
state
=
{
isLoading
:
false
,
data
:
[],
};
}
public
componentDidMount
()
{
console
.
log
(
'data panel mount'
);
this
.
issueQueries
();
}
public
issueQueries
=
async
()
=>
{
const
{
isVisible
}
=
this
.
props
;
if
(
!
isVisible
)
{
return
;
}
this
.
setState
({
isLoading
:
true
});
await
new
Promise
(
resolve
=>
{
setTimeout
(()
=>
{
this
.
setState
({
isLoading
:
false
,
data
:
[{
value
:
10
}]
});
},
500
);
});
};
public
render
()
{
const
{
data
,
isLoading
}
=
this
.
state
;
console
.
log
(
'data panel render'
);
if
(
!
data
.
length
)
{
return
(
<
div
className=
"no-data"
>
<
p
>
No Data
</
p
>
</
div
>
);
}
if
(
isLoading
)
{
return
(
<
div
className=
"loading"
>
<
p
>
Loading
</
p
>
</
div
>
);
}
return
<
ComposedComponent
{
...
this
.
props
}
data=
{
data
}
/>;
}
}
return
Wrapper
;
};
public/app/features/dashboard/dashgrid/PanelChrome.tsx
View file @
e052e165
import
React
from
'react'
;
import
React
,
{
ComponentClass
}
from
'react'
;
import
$
from
'jquery'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
GRID_CELL_HEIGHT
,
GRID_CELL_VMARGIN
}
from
'app/core/constants'
;
import
{
PanelHeader
}
from
'./PanelHeader'
;
import
{
PanelEditor
}
from
'./PanelEditor'
;
import
{
DataPanel
,
PanelProps
,
DataPanelWrapper
}
from
'./DataPanel'
;
const
TITLE_HEIGHT
=
27
;
const
PANEL_BORDER
=
2
;
export
interface
P
anelChromeP
rops
{
export
interface
Props
{
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
component
:
any
;
component
:
ComponentClass
<
PanelProps
>
;
}
export
class
PanelChrome
extends
React
.
Component
<
PanelChromeProps
,
any
>
{
interface
State
{
height
:
number
;
}
export
class
PanelChrome
extends
React
.
Component
<
Props
,
State
>
{
panelComponent
:
DataPanel
;
constructor
(
props
)
{
super
(
props
);
this
.
props
.
panel
.
events
.
on
(
'panel-size-changed'
,
this
.
triggerForceUpdate
.
bind
(
this
));
}
this
.
state
=
{
height
:
this
.
getPanelHeight
(),
};
triggerForceUpdate
()
{
this
.
forceUpdate
(
);
this
.
panelComponent
=
DataPanelWrapper
(
this
.
props
.
component
);
this
.
props
.
panel
.
events
.
on
(
'panel-size-changed'
,
this
.
onPanelSizeChanged
);
}
render
()
{
let
panelContentStyle
=
{
onPanelSizeChanged
=
()
=>
{
this
.
setState
(
{
height
:
this
.
getPanelHeight
(),
};
});
};
let
PanelComponent
=
this
.
props
.
component
;
componentDidMount
()
{
console
.
log
(
'panel chrome mounted'
);
}
render
()
{
let
PanelComponent
=
this
.
panelComponent
;
return
(
<
div
className=
"panel-
height-help
er"
>
<
div
className=
"panel-
editor-contain
er"
>
<
div
className=
"panel-container"
>
<
PanelHeader
panel=
{
this
.
props
.
panel
}
dashboard=
{
this
.
props
.
dashboard
}
/>
<
div
className=
"panel-content"
style=
{
panelContentStyle
}
>
{
<
PanelComponent
/>
}
<
div
className=
"panel-content"
style=
{
{
height
:
this
.
state
.
height
}
}
>
{
<
PanelComponent
type=
{
'test'
}
queries=
{
[]
}
isVisible=
{
true
}
/>
}
</
div
>
</
div
>
{
this
.
props
.
panel
.
isEditing
&&
<
PanelEditor
panel=
{
this
.
props
.
panel
}
dashboard=
{
this
.
props
.
dashboard
}
/>
}
...
...
@@ -59,6 +73,6 @@ export class PanelChrome extends React.Component<PanelChromeProps, any> {
height
=
panel
.
gridPos
.
h
*
GRID_CELL_HEIGHT
+
(
panel
.
gridPos
.
h
-
1
)
*
GRID_CELL_VMARGIN
;
}
return
height
-
PANEL_BORDER
+
TITLE_HEIGHT
;
return
height
-
(
PANEL_BORDER
+
TITLE_HEIGHT
)
;
}
}
public/app/features/dashboard/dashgrid/PanelEditor.tsx
View file @
e052e165
import
React
from
'react'
;
import
classNames
from
'classnames'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/angular_loader'
;
import
{
store
}
from
'app/stores/store'
;
import
{
observer
}
from
'mobx-react'
;
import
{
QueriesTab
}
from
'./QueriesTab'
;
import
{
PanelPlugin
}
from
'app/core/config'
;
import
{
VizTypePicker
}
from
'./VizTypePicker'
;
interface
PanelEditorProps
{
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
}
interface
PanelEditorTab
{
id
:
string
;
text
:
string
;
icon
:
string
;
}
@
observer
export
class
PanelEditor
extends
React
.
Component
<
PanelEditorProps
,
any
>
{
queryElement
:
any
;
queryComp
:
AngularComponent
;
tabs
:
any
[];
tabs
:
PanelEditorTab
[];
constructor
(
props
)
{
super
(
props
);
...
...
@@ -22,40 +32,42 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> {
];
}
componentDidMount
()
{
if
(
!
this
.
queryElement
)
{
return
;
}
let
loader
=
getAngularLoader
();
var
template
=
'<metrics-tab />'
;
let
scopeProps
=
{
ctrl
:
{
panel
:
this
.
props
.
panel
,
dashboard
:
this
.
props
.
dashboard
,
panelCtrl
:
{
panel
:
this
.
props
.
panel
,
dashboard
:
this
.
props
.
dashboard
,
},
},
};
this
.
queryComp
=
loader
.
load
(
this
.
queryElement
,
scopeProps
,
template
);
renderQueriesTab
()
{
return
<
QueriesTab
panel=
{
this
.
props
.
panel
}
dashboard=
{
this
.
props
.
dashboard
}
/>;
}
renderVizTab
()
{
return
(
<
div
className=
"viz-editor"
>
<
div
className=
"viz-editor-col1"
>
<
VizTypePicker
currentType=
{
this
.
props
.
panel
.
type
}
onTypeChanged=
{
this
.
onVizTypeChanged
}
/>
</
div
>
<
div
className=
"viz-editor-col2"
>
<
h5
className=
"page-heading"
>
Options
</
h5
>
</
div
>
</
div
>
);
}
onChangeTab
=
tabName
=>
{};
onVizTypeChanged
=
(
plugin
:
PanelPlugin
)
=>
{
this
.
props
.
panel
.
type
=
plugin
.
id
;
this
.
forceUpdate
();
};
onChangeTab
=
(
tab
:
PanelEditorTab
)
=>
{
store
.
view
.
updateQuery
({
tab
:
tab
.
id
},
false
);
};
render
()
{
const
activeTab
:
string
=
store
.
view
.
query
.
get
(
'tab'
)
||
'queries'
;
return
(
<
div
className=
"tabbed-view tabbed-view--
panel-edit-
new"
>
<
div
className=
"tabbed-view tabbed-view--new"
>
<
div
className=
"tabbed-view-header"
>
<
ul
className=
"gf-tabs"
>
<
li
className=
"gf-tabs-item"
>
<
a
className=
"gf-tabs-link active"
>
Queries
</
a
>
</
li
>
<
li
className=
"gf-tabs-item"
>
<
a
className=
"gf-tabs-link"
>
Visualization
</
a
>
</
li
>
{
this
.
tabs
.
map
(
tab
=>
{
return
<
TabItem
tab=
{
tab
}
activeTab=
{
activeTab
}
onClick=
{
this
.
onChangeTab
}
key=
{
tab
.
id
}
/>;
})
}
</
ul
>
<
button
className=
"tabbed-view-close-btn"
ng
-
click=
"ctrl.exitFullscreen();"
>
...
...
@@ -64,9 +76,32 @@ export class PanelEditor extends React.Component<PanelEditorProps, any> {
</
div
>
<
div
className=
"tabbed-view-body"
>
<
div
ref=
{
element
=>
(
this
.
queryElement
=
element
)
}
className=
"panel-height-helper"
/>
{
activeTab
===
'queries'
&&
this
.
renderQueriesTab
()
}
{
activeTab
===
'viz'
&&
this
.
renderVizTab
()
}
</
div
>
</
div
>
);
}
}
interface
TabItemParams
{
tab
:
PanelEditorTab
;
activeTab
:
string
;
onClick
:
(
tab
:
PanelEditorTab
)
=>
void
;
}
function
TabItem
({
tab
,
activeTab
,
onClick
}:
TabItemParams
)
{
const
tabClasses
=
classNames
({
'gf-tabs-link'
:
true
,
active
:
activeTab
===
tab
.
id
,
});
return
(
<
li
className=
"gf-tabs-item"
key=
{
tab
.
id
}
>
<
a
className=
{
tabClasses
}
onClick=
{
()
=>
onClick
(
tab
)
}
>
<
i
className=
{
tab
.
icon
}
/>
{
tab
.
text
}
</
a
>
</
li
>
);
}
public/app/features/dashboard/dashgrid/PanelHeader.tsx
View file @
e052e165
...
...
@@ -11,11 +11,14 @@ interface PanelHeaderProps {
export
class
PanelHeader
extends
React
.
Component
<
PanelHeaderProps
,
any
>
{
onEditPanel
=
()
=>
{
store
.
view
.
updateQuery
({
panelId
:
this
.
props
.
panel
.
id
,
edit
:
true
,
fullscreen
:
true
,
});
store
.
view
.
updateQuery
(
{
panelId
:
this
.
props
.
panel
.
id
,
edit
:
true
,
fullscreen
:
true
,
},
false
);
};
render
()
{
...
...
public/app/features/dashboard/dashgrid/QueriesTab.tsx
0 → 100644
View file @
e052e165
import
React
from
'react'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/angular_loader'
;
interface
Props
{
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
}
export
class
QueriesTab
extends
React
.
Component
<
Props
,
any
>
{
element
:
any
;
component
:
AngularComponent
;
constructor
(
props
)
{
super
(
props
);
}
componentDidMount
()
{
if
(
!
this
.
element
)
{
return
;
}
let
loader
=
getAngularLoader
();
var
template
=
'<metrics-tab />'
;
let
scopeProps
=
{
ctrl
:
{
panel
:
this
.
props
.
panel
,
dashboard
:
this
.
props
.
dashboard
,
panelCtrl
:
{
panel
:
this
.
props
.
panel
,
dashboard
:
this
.
props
.
dashboard
,
},
},
};
this
.
component
=
loader
.
load
(
this
.
element
,
scopeProps
,
template
);
}
componentWillUnmount
()
{
if
(
this
.
component
)
{
this
.
component
.
destroy
();
}
}
render
()
{
return
<
div
ref=
{
element
=>
(
this
.
element
=
element
)
}
className=
"panel-height-helper"
/>;
}
}
public/app/features/dashboard/dashgrid/VizTypePicker.tsx
0 → 100644
View file @
e052e165
import
React
,
{
PureComponent
}
from
'react'
;
import
classNames
from
'classnames'
;
import
config
,
{
PanelPlugin
}
from
'app/core/config'
;
import
_
from
'lodash'
;
interface
Props
{
currentType
:
string
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
}
interface
State
{
pluginList
:
PanelPlugin
[];
}
export
class
VizTypePicker
extends
PureComponent
<
Props
,
State
>
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
pluginList
:
this
.
getPanelPlugins
(
''
),
};
}
getPanelPlugins
(
filter
)
{
let
panels
=
_
.
chain
(
config
.
panels
)
.
filter
({
hideFromList
:
false
})
.
map
(
item
=>
item
)
.
value
();
// add sort by sort property
return
_
.
sortBy
(
panels
,
'sort'
);
}
renderVizPlugin
=
(
plugin
,
index
)
=>
{
const
cssClass
=
classNames
({
'viz-picker__item'
:
true
,
'viz-picker__item--selected'
:
plugin
.
id
===
this
.
props
.
currentType
,
});
return
(
<
div
key=
{
index
}
className=
{
cssClass
}
onClick=
{
()
=>
this
.
props
.
onTypeChanged
(
plugin
)
}
title=
{
plugin
.
name
}
>
<
img
className=
"viz-picker__item-img"
src=
{
plugin
.
info
.
logos
.
small
}
/>
<
div
className=
"viz-picker__item-name"
>
{
plugin
.
name
}
</
div
>
</
div
>
);
};
render
()
{
return
(
<
div
className=
"viz-picker"
>
<
div
className=
"gf-form gf-form--grow"
>
<
label
className=
"gf-form--has-input-icon gf-form--grow"
>
<
input
type=
"text"
className=
"gf-form-input"
placeholder=
"Search type"
/>
<
i
className=
"gf-form-input-icon fa fa-search"
/>
</
label
>
</
div
>
<
div
className=
"viz-picker-list"
>
{
this
.
state
.
pluginList
.
map
(
this
.
renderVizPlugin
)
}
</
div
>
</
div
>
);
}
}
public/app/features/dashboard/dashnav/dashnav.ts
View file @
e052e165
...
...
@@ -38,6 +38,8 @@ export class DashNavCtrl {
}
else
if
(
search
.
fullscreen
)
{
delete
search
.
fullscreen
;
delete
search
.
edit
;
delete
search
.
tab
;
delete
search
.
panelId
;
}
this
.
$location
.
search
(
search
);
}
...
...
public/app/features/dashboard/specs/AddPanelPanel.jest.tsx
View file @
e052e165
...
...
@@ -23,6 +23,9 @@ describe('AddPanelPanel', () => {
hideFromList
:
false
,
name
:
'Singlestat'
,
sort
:
2
,
module
:
''
,
baseUrl
:
''
,
meta
:
{},
info
:
{
logos
:
{
small
:
''
,
...
...
@@ -34,6 +37,9 @@ describe('AddPanelPanel', () => {
hideFromList
:
true
,
name
:
'Hidden'
,
sort
:
100
,
meta
:
{},
module
:
''
,
baseUrl
:
''
,
info
:
{
logos
:
{
small
:
''
,
...
...
@@ -45,6 +51,9 @@ describe('AddPanelPanel', () => {
hideFromList
:
false
,
name
:
'Graph'
,
sort
:
1
,
meta
:
{},
module
:
''
,
baseUrl
:
''
,
info
:
{
logos
:
{
small
:
''
,
...
...
@@ -56,6 +65,9 @@ describe('AddPanelPanel', () => {
hideFromList
:
false
,
name
:
'Zabbix'
,
sort
:
100
,
meta
:
{},
module
:
''
,
baseUrl
:
''
,
info
:
{
logos
:
{
small
:
''
,
...
...
@@ -67,6 +79,9 @@ describe('AddPanelPanel', () => {
hideFromList
:
false
,
name
:
'Piechart'
,
sort
:
100
,
meta
:
{},
module
:
''
,
baseUrl
:
''
,
info
:
{
logos
:
{
small
:
''
,
...
...
public/app/features/panel/panel_directive.ts
View file @
e052e165
...
...
@@ -26,7 +26,7 @@ var panelTemplate = `
</div>
<div class="panel-full-edit" ng-if="ctrl.panel.isEditing">
<div class="tabbed-view
tabbed-view--panel-edit
">
<div class="tabbed-view">
<div class="tabbed-view-header">
<h3 class="tabbed-view-panel-title">
{{ctrl.pluginName}}
...
...
public/app/features/plugins/plugin_component.ts
View file @
e052e165
...
...
@@ -95,7 +95,7 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
PanelCtrl
.
templatePromise
=
getTemplate
(
PanelCtrl
).
then
(
template
=>
{
PanelCtrl
.
templateUrl
=
null
;
PanelCtrl
.
template
=
`<grafana-panel ctrl="ctrl" class="panel-
height-help
er">
${
template
}
</grafana-panel>`
;
PanelCtrl
.
template
=
`<grafana-panel ctrl="ctrl" class="panel-
editor-contain
er">
${
template
}
</grafana-panel>`
;
return
componentInfo
;
});
...
...
@@ -110,7 +110,6 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $
let
datasource
=
scope
.
target
.
datasource
||
scope
.
ctrl
.
panel
.
datasource
;
return
datasourceSrv
.
get
(
datasource
).
then
(
ds
=>
{
scope
.
datasource
=
ds
;
console
.
log
(
'scope'
,
scope
);
return
importPluginModule
(
ds
.
meta
.
module
).
then
(
dsModule
=>
{
return
{
...
...
public/app/features/plugins/plugin_loader.ts
View file @
e052e165
...
...
@@ -138,11 +138,22 @@ const flotDeps = [
'jquery.flot.stackpercent'
,
'jquery.flot.events'
,
];
for
(
let
flotDep
of
flotDeps
)
{
exposeToPlugin
(
flotDep
,
{
fakeDep
:
1
});
}
export
function
importPluginModule
(
path
:
string
):
Promise
<
any
>
{
export
interface
PluginExports
{
PanelCtrl
?;
any
;
PanelComponent
?:
any
;
Datasource
?:
any
;
QueryCtrl
?:
any
;
ConfigCtrl
?:
any
;
AnnotationsQueryCtrl
?:
any
;
}
export
function
importPluginModule
(
path
:
string
):
Promise
<
PluginExports
>
{
let
builtIn
=
builtInPlugins
[
path
];
if
(
builtIn
)
{
return
Promise
.
resolve
(
builtIn
);
...
...
public/app/plugins/panel/text2/module.tsx
View file @
e052e165
import
React
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
{
PanelProps
}
from
'app/features/dashboard/dashgrid/DataPanel'
;
export
class
ReactTestPanel
extends
React
.
Component
<
any
,
any
>
{
export
class
ReactTestPanel
extends
PureComponent
<
PanelProps
>
{
constructor
(
props
)
{
super
(
props
);
}
render
()
{
return
<
h2
>
I am a react panel, haha!
</
h2
>;
const
{
data
}
=
this
.
props
;
let
value
=
0
;
if
(
data
.
length
)
{
value
=
data
[
0
].
value
;
}
return
<
h2
>
I am a react value:
{
value
}
</
h2
>;
}
}
...
...
public/app/stores/ViewStore/ViewStore.ts
View file @
e052e165
...
...
@@ -23,8 +23,10 @@ export const ViewStore = types
}))
.
actions
(
self
=>
{
// querystring only
function
updateQuery
(
query
:
any
)
{
self
.
query
.
clear
();
function
updateQuery
(
query
:
any
,
clear
=
true
)
{
if
(
clear
)
{
self
.
query
.
clear
();
}
for
(
let
key
of
Object
.
keys
(
query
))
{
if
(
query
[
key
])
{
self
.
query
.
set
(
key
,
query
[
key
]);
...
...
public/sass/_grafana.scss
View file @
e052e165
...
...
@@ -93,6 +93,7 @@
@import
'components/form_select_box'
;
@import
'components/user-picker'
;
@import
'components/description-picker'
;
@import
'components/viz_editor'
;
// PAGES
@import
'pages/login'
;
...
...
public/sass/components/_panel_add_panel.scss
View file @
e052e165
...
...
@@ -85,10 +85,6 @@
height
:
calc
(
100%
-
15px
);
}
.add-panel__item-icon
{
padding
:
2px
;
}
.add-panel__searchbar
{
width
:
100%
;
margin-bottom
:
10px
;
...
...
public/sass/components/_tabbed_view.scss
View file @
e052e165
.tabbed-view
{
padding
:
$spacer
*
3
;
margin-bottom
:
$dashboard-padding
;
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
&
.tabbed-view--panel-edit
{
padding
:
0
;
.tabbed-view-header
{
padding
:
0px
25px
;
background
:
none
;
}
}
&
.tabbed-view--panel-edit-new
{
&
.tabbed-view--new
{
padding
:
10px
0
0
0
;
.tabbed-view-header
{
padding
:
0px
;
background
:
none
;
}
height
:
100%
;
}
}
.tabbed-view-header
{
background
:
$page-header-bg
;
box-shadow
:
$page-header-shadow
;
border-bottom
:
1px
solid
$page-header-border-color
;
@include
clearfix
();
...
...
@@ -57,7 +44,10 @@
}
.tabbed-view-body
{
padding
:
$spacer
*
2
$spacer
;
padding
:
$spacer
*
2
$spacer
$spacer
$spacer
;
display
:
flex
;
flex-direction
:
column
;
flex
:
1
;
&
--small
{
min-height
:
0px
;
...
...
public/sass/components/_viz_editor.scss
0 → 100644
View file @
e052e165
.viz-editor
{
display
:
flex
;
height
:
100%
;
}
.viz-editor-col1
{
width
:
210px
;
height
:
100%
;
margin-right
:
40px
;
}
.viz-editor-col2
{
flex-grow
:
1
;
}
.viz-picker
{
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
}
.viz-picker-list
{
padding-top
:
$spacer
;
display
:
flex
;
flex-direction
:
column
;
overflow
:
hidden
;
flex-grow
:
1
;
}
.viz-picker__item
{
background
:
$card-background
;
box-shadow
:
$card-shadow
;
border-radius
:
3px
;
padding
:
$spacer
;
width
:
100%
;
height
:
60px
;
text-align
:
center
;
margin-bottom
:
6px
;
cursor
:
pointer
;
display
:
flex
;
flex-shrink
:
0
;
border
:
1px
solid
transparent
;
&
:hover
{
background
:
$card-background-hover
;
}
&
--selected
{
border
:
1px
solid
$orange
;
.viz-picker__item-name
{
color
:
$text-color
;
}
.viz-picker__item-img
{
filter
:
saturate
(
100%
);
}
}
}
.viz-picker__item-name
{
text-overflow
:
ellipsis
;
overflow
:
hidden
;
white-space
:
nowrap
;
font-size
:
$font-size-h5
;
display
:
flex
;
flex-direction
:
column
;
align-self
:
center
;
padding-left
:
$spacer
;
font-size
:
$font-size-md
;
color
:
$text-muted
;
}
.viz-picker__item-img
{
height
:
100%
;
filter
:
saturate
(
30%
);
}
public/sass/pages/_dashboard.scss
View file @
e052e165
.dashboard-container
{
padding
:
$dashboard-padding
;
width
:
100%
;
min-height
:
100%
;
height
:
100%
;
box-sizing
:
border-box
;
}
.template-variable
{
...
...
@@ -28,12 +29,17 @@ div.flot-text {
height
:
100%
;
}
.panel-editor-container
{
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
}
.panel-container
{
background-color
:
$panel-bg
;
border
:
$panel-border
;
position
:
relative
;
border-radius
:
3px
;
height
:
100%
;
&
.panel-transparent
{
background-color
:
transparent
;
...
...
@@ -233,5 +239,5 @@ div.flot-text {
}
.panel-full-edit
{
margin
:
$dashboard-padding
(
-
$dashboard-padding
)
0
(
-
$dashboard-padding
)
;
padding-top
:
$dashboard-padding
;
}
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