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
727efa5a
Commit
727efa5a
authored
Nov 12, 2018
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'pane-edit-ux-tabs' into develop
parents
e0feb726
a0620ac8
Show whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
841 additions
and
301 deletions
+841
-301
public/app/core/components/Animations/FadeIn.tsx
+37
-0
public/app/core/components/Animations/SlideDown.tsx
+1
-1
public/app/core/components/CustomScrollbar/CustomScrollbar.tsx
+1
-1
public/app/core/directives/dash_class.ts
+6
-3
public/app/core/reducers/location.ts
+1
-0
public/app/features/dashboard/dashgrid/DashboardGrid.tsx
+7
-1
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
+33
-34
public/app/features/dashboard/dashgrid/DataSourcePicker.tsx
+88
-0
public/app/features/dashboard/dashgrid/EditorTabBody.tsx
+96
-0
public/app/features/dashboard/dashgrid/PanelEditor.tsx
+30
-48
public/app/features/dashboard/dashgrid/QueriesTab.tsx
+24
-4
public/app/features/dashboard/dashgrid/VisualizationTab.tsx
+57
-0
public/app/features/dashboard/dashgrid/VizTypePicker.tsx
+40
-17
public/app/features/panel/panel_directive.ts
+2
-2
public/app/features/plugins/datasource_srv.ts
+3
-6
public/app/plugins/panel/graph2/module.tsx
+16
-1
public/app/types/datasources.ts
+7
-0
public/app/types/index.ts
+2
-1
public/sass/_grafana.scss
+2
-1
public/sass/_variables.dark.scss
+8
-2
public/sass/_variables.light.scss
+6
-0
public/sass/components/_buttons.scss
+1
-1
public/sass/components/_dashboard_grid.scss
+5
-1
public/sass/components/_gf-form.scss
+21
-1
public/sass/components/_navbar.scss
+2
-6
public/sass/components/_panel_editor.scss
+208
-0
public/sass/components/_scrollbar.scss
+71
-71
public/sass/components/_submenu.scss
+1
-2
public/sass/components/_tabbed_view.scss
+4
-2
public/sass/components/_tabs.scss
+1
-0
public/sass/components/_timepicker.scss
+1
-0
public/sass/components/_toolbar.scss
+59
-0
public/sass/components/_viz_editor.scss
+0
-81
public/sass/pages/_dashboard.scss
+0
-14
No files found.
public/app/core/components/Animations/FadeIn.tsx
0 → 100644
View file @
727efa5a
import
React
,
{
SFC
}
from
'react'
;
import
Transition
from
'react-transition-group/Transition'
;
interface
Props
{
duration
:
number
;
children
:
JSX
.
Element
;
in
:
boolean
;
}
export
const
FadeIn
:
SFC
<
Props
>
=
props
=>
{
const
defaultStyle
=
{
transition
:
`opacity
${
props
.
duration
}
ms linear`
,
opacity
:
0
,
};
const
transitionStyles
=
{
exited
:
{
opacity
:
0
,
display
:
'none'
},
entering
:
{
opacity
:
0
},
entered
:
{
opacity
:
1
},
exiting
:
{
opacity
:
0
},
};
return
(
<
Transition
in=
{
props
.
in
}
timeout=
{
props
.
duration
}
>
{
state
=>
(
<
div
style=
{
{
...
defaultStyle
,
...
transitionStyles
[
state
],
}
}
>
{
props
.
children
}
</
div
>
)
}
</
Transition
>
);
};
public/app/core/components/Animations/SlideDown.tsx
View file @
727efa5a
...
@@ -23,7 +23,7 @@ export default ({ children, in: inProp, maxHeight = defaultMaxHeight, style = de
...
@@ -23,7 +23,7 @@ export default ({ children, in: inProp, maxHeight = defaultMaxHeight, style = de
const
transitionStyles
=
{
const
transitionStyles
=
{
exited
:
{
maxHeight
:
0
},
exited
:
{
maxHeight
:
0
},
entering
:
{
maxHeight
:
maxHeight
},
entering
:
{
maxHeight
:
maxHeight
},
entered
:
{
maxHeight
:
maxHeight
,
overflow
:
'visible'
},
entered
:
{
maxHeight
:
'unset'
,
overflow
:
'visible'
},
exiting
:
{
maxHeight
:
0
},
exiting
:
{
maxHeight
:
0
},
};
};
...
...
public/app/core/components/CustomScrollbar/CustomScrollbar.tsx
View file @
727efa5a
...
@@ -15,7 +15,7 @@ interface Props {
...
@@ -15,7 +15,7 @@ interface Props {
class
CustomScrollbar
extends
PureComponent
<
Props
>
{
class
CustomScrollbar
extends
PureComponent
<
Props
>
{
static
defaultProps
:
Partial
<
Props
>
=
{
static
defaultProps
:
Partial
<
Props
>
=
{
customClassName
:
'custom-scrollbars'
,
customClassName
:
'custom-scrollbars'
,
autoHide
:
tru
e
,
autoHide
:
fals
e
,
autoHideTimeout
:
200
,
autoHideTimeout
:
200
,
autoHideDuration
:
200
,
autoHideDuration
:
200
,
hideTracksWhenNotNeeded
:
false
,
hideTracksWhenNotNeeded
:
false
,
...
...
public/app/core/directives/dash_class.ts
View file @
727efa5a
import
$
from
'jquery'
;
import
_
from
'lodash'
;
import
_
from
'lodash'
;
import
coreModule
from
'../core_module'
;
import
coreModule
from
'../core_module'
;
...
@@ -5,18 +6,20 @@ import coreModule from '../core_module';
...
@@ -5,18 +6,20 @@ import coreModule from '../core_module';
function
dashClass
(
$timeout
)
{
function
dashClass
(
$timeout
)
{
return
{
return
{
link
:
(
$scope
,
elem
)
=>
{
link
:
(
$scope
,
elem
)
=>
{
const
body
=
$
(
'body'
);
$scope
.
ctrl
.
dashboard
.
events
.
on
(
'view-mode-changed'
,
panel
=>
{
$scope
.
ctrl
.
dashboard
.
events
.
on
(
'view-mode-changed'
,
panel
=>
{
console
.
log
(
'view-mode-changed'
,
panel
.
fullscreen
);
console
.
log
(
'view-mode-changed'
,
panel
.
fullscreen
);
if
(
panel
.
fullscreen
)
{
if
(
panel
.
fullscreen
)
{
elem
.
addClass
(
'panel-in-fullscreen'
);
body
.
addClass
(
'panel-in-fullscreen'
);
}
else
{
}
else
{
$timeout
(()
=>
{
$timeout
(()
=>
{
elem
.
removeClass
(
'panel-in-fullscreen'
);
body
.
removeClass
(
'panel-in-fullscreen'
);
});
});
}
}
});
});
elem
.
toggleClass
(
'panel-in-fullscreen'
,
$scope
.
ctrl
.
dashboard
.
meta
.
fullscreen
===
true
);
body
.
toggleClass
(
'panel-in-fullscreen'
,
$scope
.
ctrl
.
dashboard
.
meta
.
fullscreen
===
true
);
$scope
.
$watch
(
'ctrl.dashboardViewState.state.editview'
,
newValue
=>
{
$scope
.
$watch
(
'ctrl.dashboardViewState.state.editview'
,
newValue
=>
{
if
(
newValue
)
{
if
(
newValue
)
{
...
...
public/app/core/reducers/location.ts
View file @
727efa5a
...
@@ -18,6 +18,7 @@ export const locationReducer = (state = initialState, action: Action): LocationS
...
@@ -18,6 +18,7 @@ export const locationReducer = (state = initialState, action: Action): LocationS
if
(
action
.
payload
.
partial
)
{
if
(
action
.
payload
.
partial
)
{
query
=
_
.
defaults
(
query
,
state
.
query
);
query
=
_
.
defaults
(
query
,
state
.
query
);
query
=
_
.
omitBy
(
query
,
_
.
isNull
);
}
}
return
{
return
{
...
...
public/app/features/dashboard/dashgrid/DashboardGrid.tsx
View file @
727efa5a
...
@@ -8,6 +8,7 @@ import classNames from 'classnames';
...
@@ -8,6 +8,7 @@ import classNames from 'classnames';
import
sizeMe
from
'react-sizeme'
;
import
sizeMe
from
'react-sizeme'
;
let
lastGridWidth
=
1200
;
let
lastGridWidth
=
1200
;
let
ignoreNextWidthChange
=
false
;
function
GridWrapper
({
function
GridWrapper
({
size
,
size
,
...
@@ -24,8 +25,12 @@ function GridWrapper({
...
@@ -24,8 +25,12 @@ function GridWrapper({
isFullscreen
,
isFullscreen
,
})
{
})
{
const
width
=
size
.
width
>
0
?
size
.
width
:
lastGridWidth
;
const
width
=
size
.
width
>
0
?
size
.
width
:
lastGridWidth
;
// logic to ignore width changes (optimization)
if
(
width
!==
lastGridWidth
)
{
if
(
width
!==
lastGridWidth
)
{
if
(
!
isFullscreen
&&
Math
.
abs
(
width
-
lastGridWidth
)
>
8
)
{
if
(
ignoreNextWidthChange
)
{
ignoreNextWidthChange
=
false
;
}
else
if
(
!
isFullscreen
&&
Math
.
abs
(
width
-
lastGridWidth
)
>
8
)
{
onWidthChange
();
onWidthChange
();
lastGridWidth
=
width
;
lastGridWidth
=
width
;
}
}
...
@@ -138,6 +143,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
...
@@ -138,6 +143,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
}
}
onViewModeChanged
(
payload
)
{
onViewModeChanged
(
payload
)
{
ignoreNextWidthChange
=
true
;
this
.
setState
({
animated
:
!
payload
.
fullscreen
});
this
.
setState
({
animated
:
!
payload
.
fullscreen
});
}
}
...
...
public/app/features/dashboard/dashgrid/DashboardPanel.tsx
View file @
727efa5a
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
config
from
'app/core/config'
;
import
config
from
'app/core/config'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/AngularLoader'
;
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/AngularLoader'
;
import
{
DashboardRow
}
from
'./DashboardRow'
;
import
{
AddPanelPanel
}
from
'./AddPanelPanel'
;
import
{
importPluginModule
}
from
'app/features/plugins/plugin_loader'
;
import
{
importPluginModule
}
from
'app/features/plugins/plugin_loader'
;
import
{
PluginExports
,
PanelPlugin
}
from
'app/types/plugins'
;
import
{
AddPanelPanel
}
from
'./AddPanelPanel'
;
import
{
DashboardRow
}
from
'./DashboardRow'
;
import
{
PanelPlugin
}
from
'app/types/plugins'
;
import
{
PanelChrome
}
from
'./PanelChrome'
;
import
{
PanelChrome
}
from
'./PanelChrome'
;
import
{
PanelEditor
}
from
'./PanelEditor'
;
import
{
PanelEditor
}
from
'./PanelEditor'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
export
interface
Props
{
export
interface
Props
{
panel
:
PanelModel
;
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
dashboard
:
DashboardModel
;
...
@@ -18,20 +21,19 @@ export interface Props {
...
@@ -18,20 +21,19 @@ export interface Props {
}
}
export
interface
State
{
export
interface
State
{
plugin
Exports
:
PluginExports
;
plugin
:
PanelPlugin
;
}
}
export
class
DashboardPanel
extends
PureComponent
<
Props
,
State
>
{
export
class
DashboardPanel
extends
PureComponent
<
Props
,
State
>
{
element
:
any
;
element
:
any
;
angularPanel
:
AngularComponent
;
angularPanel
:
AngularComponent
;
pluginInfo
:
any
;
specialPanels
=
{};
specialPanels
=
{};
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
);
super
(
props
);
this
.
state
=
{
this
.
state
=
{
plugin
Exports
:
null
,
plugin
:
null
,
};
};
this
.
specialPanels
[
'row'
]
=
this
.
renderRow
.
bind
(
this
);
this
.
specialPanels
[
'row'
]
=
this
.
renderRow
.
bind
(
this
);
...
@@ -64,20 +66,22 @@ export class DashboardPanel extends PureComponent<Props, State> {
...
@@ -64,20 +66,22 @@ export class DashboardPanel extends PureComponent<Props, State> {
return
;
return
;
}
}
const
{
panel
}
=
this
.
props
;
// handle plugin loading & changing of plugin type
// handle plugin loading & changing of plugin type
if
(
!
this
.
pluginInfo
||
this
.
pluginInfo
.
id
!==
this
.
props
.
panel
.
type
)
{
if
(
!
this
.
state
.
plugin
||
this
.
state
.
plugin
.
id
!==
panel
.
type
)
{
this
.
pluginInfo
=
config
.
panels
[
this
.
props
.
panel
.
type
];
const
plugin
=
config
.
panels
[
panel
.
type
];
if
(
this
.
pluginInfo
.
exports
)
{
if
(
plugin
.
exports
)
{
this
.
cleanUpAngularPanel
();
this
.
cleanUpAngularPanel
();
this
.
setState
({
plugin
Exports
:
this
.
pluginInfo
.
exports
});
this
.
setState
({
plugin
:
plugin
});
}
else
{
}
else
{
importPluginModule
(
this
.
pluginInfo
.
module
).
then
(
pluginExports
=>
{
importPluginModule
(
plugin
.
module
).
then
(
pluginExports
=>
{
this
.
cleanUpAngularPanel
();
this
.
cleanUpAngularPanel
();
// cache plugin exports (saves a promise async cycle next time)
// cache plugin exports (saves a promise async cycle next time)
this
.
pluginInfo
.
exports
=
pluginExports
;
plugin
.
exports
=
pluginExports
;
// update panel state
// update panel state
this
.
setState
({
plugin
Exports
:
pluginExports
});
this
.
setState
({
plugin
:
plugin
});
});
});
}
}
}
}
...
@@ -113,7 +117,9 @@ export class DashboardPanel extends PureComponent<Props, State> {
...
@@ -113,7 +117,9 @@ export class DashboardPanel extends PureComponent<Props, State> {
}
}
renderReactPanel
()
{
renderReactPanel
()
{
const
{
pluginExports
}
=
this
.
state
;
const
{
dashboard
,
panel
}
=
this
.
props
;
const
{
plugin
}
=
this
.
state
;
const
containerClass
=
this
.
props
.
isEditing
?
'panel-editor-container'
:
'panel-height-helper'
;
const
containerClass
=
this
.
props
.
isEditing
?
'panel-editor-container'
:
'panel-height-helper'
;
const
panelWrapperClass
=
this
.
props
.
isEditing
?
'panel-editor-container__panel'
:
'panel-height-helper'
;
const
panelWrapperClass
=
this
.
props
.
isEditing
?
'panel-editor-container__panel'
:
'panel-height-helper'
;
// this might look strange with these classes that change when edit, but
// this might look strange with these classes that change when edit, but
...
@@ -121,37 +127,30 @@ export class DashboardPanel extends PureComponent<Props, State> {
...
@@ -121,37 +127,30 @@ export class DashboardPanel extends PureComponent<Props, State> {
return
(
return
(
<
div
className=
{
containerClass
}
>
<
div
className=
{
containerClass
}
>
<
div
className=
{
panelWrapperClass
}
>
<
div
className=
{
panelWrapperClass
}
>
<
PanelChrome
<
PanelChrome
component=
{
plugin
.
exports
.
PanelComponent
}
panel=
{
panel
}
dashboard=
{
dashboard
}
/>
component=
{
pluginExports
.
PanelComponent
}
panel=
{
this
.
props
.
panel
}
dashboard=
{
this
.
props
.
dashboard
}
/>
</
div
>
{
this
.
props
.
panel
.
isEditing
&&
(
<
div
className=
"panel-editor-container__editor"
>
<
PanelEditor
panel=
{
this
.
props
.
panel
}
panelType=
{
this
.
props
.
panel
.
type
}
dashboard=
{
this
.
props
.
dashboard
}
onTypeChanged=
{
this
.
onPluginTypeChanged
}
pluginExports=
{
pluginExports
}
/>
</
div
>
</
div
>
{
panel
.
isEditing
&&
(
<
PanelEditor
panel=
{
panel
}
plugin=
{
plugin
}
dashboard=
{
dashboard
}
onTypeChanged=
{
this
.
onPluginTypeChanged
}
/>
)
}
)
}
</
div
>
</
div
>
);
);
}
}
render
()
{
render
()
{
const
{
panel
}
=
this
.
props
;
const
{
plugin
}
=
this
.
state
;
if
(
this
.
isSpecial
())
{
if
(
this
.
isSpecial
())
{
return
this
.
specialPanels
[
this
.
props
.
panel
.
type
]();
return
this
.
specialPanels
[
panel
.
type
]();
}
}
if
(
!
this
.
state
.
pluginExports
)
{
// if we have not loaded plugin exports yet, wait
if
(
!
plugin
||
!
plugin
.
exports
)
{
return
null
;
return
null
;
}
}
if
(
this
.
state
.
pluginExports
.
PanelComponent
)
{
// if exporting PanelComponent it must be a react panel
if
(
plugin
.
exports
.
PanelComponent
)
{
return
this
.
renderReactPanel
();
return
this
.
renderReactPanel
();
}
}
...
...
public/app/features/dashboard/dashgrid/DataSourcePicker.tsx
0 → 100644
View file @
727efa5a
import
React
,
{
PureComponent
}
from
'react'
;
import
classNames
from
'classnames'
;
import
_
from
'lodash'
;
import
{
getDatasourceSrv
}
from
'app/features/plugins/datasource_srv'
;
import
{
DataSourceSelectItem
}
from
'app/types'
;
interface
Props
{}
interface
State
{
datasources
:
DataSourceSelectItem
[];
searchQuery
:
string
;
}
export
class
DataSourcePicker
extends
PureComponent
<
Props
,
State
>
{
searchInput
:
HTMLElement
;
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
datasources
:
getDatasourceSrv
().
getMetricSources
(),
searchQuery
:
''
,
};
}
getDataSources
()
{
const
{
datasources
,
searchQuery
}
=
this
.
state
;
const
regex
=
new
RegExp
(
searchQuery
,
'i'
);
const
filtered
=
datasources
.
filter
(
item
=>
{
return
regex
.
test
(
item
.
name
)
||
regex
.
test
(
item
.
meta
.
name
);
});
return
_
.
sortBy
(
filtered
,
'sort'
);
}
renderDataSource
=
(
ds
:
DataSourceSelectItem
,
index
)
=>
{
const
cssClass
=
classNames
({
'ds-picker-list__item'
:
true
,
});
return
(
<
div
key=
{
index
}
className=
{
cssClass
}
title=
{
ds
.
name
}
>
<
img
className=
"ds-picker-list__img"
src=
{
ds
.
meta
.
info
.
logos
.
small
}
/>
<
div
className=
"ds-picker-list__name"
>
{
ds
.
name
}
</
div
>
</
div
>
);
};
componentDidMount
()
{
setTimeout
(()
=>
{
this
.
searchInput
.
focus
();
},
300
);
}
renderFilters
()
{
return
(
<>
<
label
className=
"gf-form--has-input-icon"
>
<
input
type=
"text"
className=
"gf-form-input width-13"
placeholder=
""
ref=
{
elem
=>
(
this
.
searchInput
=
elem
)
}
/>
<
i
className=
"gf-form-input-icon fa fa-search"
/>
</
label
>
<
div
className=
"p-l-1"
>
<
button
className=
"btn toggle-btn gf-form-btn active"
>
All
</
button
>
<
button
className=
"btn toggle-btn gf-form-btn"
>
Favorites
</
button
>
</
div
>
</>
);
}
render
()
{
return
(
<>
<
div
className=
"cta-form__bar"
>
{
this
.
renderFilters
()
}
<
div
className=
"gf-form--grow"
/>
</
div
>
<
div
className=
"ds-picker-list"
>
{
this
.
getDataSources
().
map
(
this
.
renderDataSource
)
}
</
div
>
</>
);
}
}
public/app/features/dashboard/dashgrid/EditorTabBody.tsx
0 → 100644
View file @
727efa5a
import
React
,
{
PureComponent
}
from
'react'
;
import
CustomScrollbar
from
'app/core/components/CustomScrollbar/CustomScrollbar'
;
import
{
FadeIn
}
from
'app/core/components/Animations/FadeIn'
;
interface
Props
{
children
:
JSX
.
Element
;
main
:
EditorToolBarView
;
toolbarItems
:
EditorToolBarView
[];
}
export
interface
EditorToolBarView
{
title
:
string
;
imgSrc
?:
string
;
icon
?:
string
;
render
:
()
=>
JSX
.
Element
;
}
interface
State
{
openView
?:
EditorToolBarView
;
}
export
class
EditorTabBody
extends
PureComponent
<
Props
,
State
>
{
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
openView
:
null
,
};
}
onToggleToolBarView
=
(
item
:
EditorToolBarView
)
=>
{
this
.
setState
({
openView
:
item
===
this
.
state
.
openView
?
null
:
item
,
});
};
onCloseOpenView
=
()
=>
{
this
.
setState
({
openView
:
null
});
};
renderMainSelection
(
view
:
EditorToolBarView
)
{
return
(
<
div
className=
"toolbar__main"
onClick=
{
()
=>
this
.
onToggleToolBarView
(
view
)
}
key=
{
view
.
title
}
>
<
img
className=
"toolbar__main-image"
src=
{
view
.
imgSrc
}
/>
<
div
className=
"toolbar__main-name"
>
{
view
.
title
}
</
div
>
<
i
className=
"fa fa-caret-down"
/>
</
div
>
);
}
renderButton
(
view
:
EditorToolBarView
)
{
return
(
<
div
className=
"nav-buttons"
key=
{
view
.
title
}
>
<
button
className=
"btn navbar-button"
onClick=
{
()
=>
this
.
onToggleToolBarView
(
view
)
}
>
{
view
.
icon
&&
<
i
className=
{
view
.
icon
}
/>
}
{
view
.
title
}
</
button
>
</
div
>
);
}
renderOpenView
(
view
:
EditorToolBarView
)
{
return
(
<
div
className=
"toolbar-subview"
>
<
button
className=
"toolbar-subview__close"
onClick=
{
this
.
onCloseOpenView
}
>
<
i
className=
"fa fa-chevron-up"
/>
</
button
>
{
view
.
render
()
}
</
div
>
);
}
render
()
{
const
{
children
,
toolbarItems
,
main
}
=
this
.
props
;
const
{
openView
}
=
this
.
state
;
return
(
<>
<
div
className=
"toolbar"
>
{
this
.
renderMainSelection
(
main
)
}
<
div
className=
"gf-form--grow"
/>
{
toolbarItems
.
map
(
item
=>
this
.
renderButton
(
item
))
}
</
div
>
<
div
className=
"panel-editor__scroll"
>
<
CustomScrollbar
>
<
div
className=
"panel-editor__content"
>
<
FadeIn
in=
{
openView
!==
null
}
duration=
{
200
}
>
{
openView
&&
this
.
renderOpenView
(
openView
)
}
</
FadeIn
>
{
children
}
</
div
>
</
CustomScrollbar
>
</
div
>
</>
);
}
}
public/app/features/dashboard/dashgrid/PanelEditor.tsx
View file @
727efa5a
...
@@ -2,20 +2,19 @@ import React, { PureComponent } from 'react';
...
@@ -2,20 +2,19 @@ import React, { PureComponent } from 'react';
import
classNames
from
'classnames'
;
import
classNames
from
'classnames'
;
import
{
QueriesTab
}
from
'./QueriesTab'
;
import
{
QueriesTab
}
from
'./QueriesTab'
;
import
{
Vi
zTypePicker
}
from
'./VizTypePicker
'
;
import
{
Vi
sualizationTab
}
from
'./VisualizationTab
'
;
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
{
PanelModel
}
from
'../panel_model'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
PanelPlugin
,
PluginExports
}
from
'app/types/plugins'
;
import
{
PanelPlugin
}
from
'app/types/plugins'
;
interface
PanelEditorProps
{
interface
PanelEditorProps
{
panel
:
PanelModel
;
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
dashboard
:
DashboardModel
;
panelType
:
string
;
plugin
:
PanelPlugin
;
pluginExports
:
PluginExports
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
}
}
...
@@ -34,43 +33,10 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
...
@@ -34,43 +33,10 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
this
.
tabs
=
[
this
.
tabs
=
[
{
id
:
'queries'
,
text
:
'Queries'
,
icon
:
'fa fa-database'
},
{
id
:
'queries'
,
text
:
'Queries'
,
icon
:
'fa fa-database'
},
{
id
:
'visualization'
,
text
:
'Visualization'
,
icon
:
'fa fa-line-chart'
},
{
id
:
'visualization'
,
text
:
'Visualization'
,
icon
:
'fa fa-line-chart'
},
{
id
:
'alert'
,
text
:
'Alert'
,
icon
:
'gicon gicon-alert'
},
];
];
}
}
renderQueriesTab
()
{
return
<
QueriesTab
panel=
{
this
.
props
.
panel
}
dashboard=
{
this
.
props
.
dashboard
}
/>;
}
renderPanelOptions
()
{
const
{
pluginExports
,
panel
}
=
this
.
props
;
if
(
pluginExports
.
PanelOptionsComponent
)
{
const
OptionsComponent
=
pluginExports
.
PanelOptionsComponent
;
return
<
OptionsComponent
options=
{
panel
.
getOptions
()
}
onChange=
{
this
.
onPanelOptionsChanged
}
/>;
}
else
{
return
<
p
>
Visualization has no options
</
p
>;
}
}
onPanelOptionsChanged
=
(
options
:
any
)
=>
{
this
.
props
.
panel
.
updateOptions
(
options
);
this
.
forceUpdate
();
};
renderVizTab
()
{
return
(
<
div
className=
"viz-editor"
>
<
div
className=
"viz-editor-col1"
>
<
VizTypePicker
currentType=
{
this
.
props
.
panel
.
type
}
onTypeChanged=
{
this
.
props
.
onTypeChanged
}
/>
</
div
>
<
div
className=
"viz-editor-col2"
>
<
h5
className=
"page-heading"
>
Options
</
h5
>
{
this
.
renderPanelOptions
()
}
</
div
>
</
div
>
);
}
onChangeTab
=
(
tab
:
PanelEditorTab
)
=>
{
onChangeTab
=
(
tab
:
PanelEditorTab
)
=>
{
store
.
dispatch
(
store
.
dispatch
(
updateLocation
({
updateLocation
({
...
@@ -81,28 +47,44 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
...
@@ -81,28 +47,44 @@ export class PanelEditor extends PureComponent<PanelEditorProps> {
this
.
forceUpdate
();
this
.
forceUpdate
();
};
};
onClose
=
()
=>
{
store
.
dispatch
(
updateLocation
({
query
:
{
tab
:
null
,
fullscreen
:
null
,
edit
:
null
},
partial
:
true
,
})
);
};
render
()
{
render
()
{
const
{
panel
,
dashboard
,
onTypeChanged
,
plugin
}
=
this
.
props
;
const
{
location
}
=
store
.
getState
();
const
{
location
}
=
store
.
getState
();
const
activeTab
=
location
.
query
.
tab
||
'queries'
;
const
activeTab
=
location
.
query
.
tab
||
'queries'
;
return
(
return
(
<
div
className=
"tabbed-view tabbed-view--new"
>
<
div
className=
"panel-editor-container__editor"
>
<
div
className=
"tabbed-view-header"
>
<
div
className=
"panel-editor-resizer"
>
<
div
className=
"panel-editor-resizer__handle"
>
<
div
className=
"panel-editor-resizer__handle-dots"
/>
</
div
>
</
div
>
<
div
className=
"panel-editor-tabs"
>
<
ul
className=
"gf-tabs"
>
<
ul
className=
"gf-tabs"
>
{
this
.
tabs
.
map
(
tab
=>
{
{
this
.
tabs
.
map
(
tab
=>
{
return
<
TabItem
tab=
{
tab
}
activeTab=
{
activeTab
}
onClick=
{
this
.
onChangeTab
}
key=
{
tab
.
id
}
/>;
return
<
TabItem
tab=
{
tab
}
activeTab=
{
activeTab
}
onClick=
{
this
.
onChangeTab
}
key=
{
tab
.
id
}
/>;
})
}
})
}
</
ul
>
</
ul
>
<
button
className=
"
tabbed-view-close-btn"
ng
-
click=
"ctrl.exitFullscreen();"
>
<
button
className=
"
panel-editor-tabs__close"
onClick=
{
this
.
onClose
}
>
<
i
className=
"fa fa-re
move
"
/>
<
i
className=
"fa fa-re
ply
"
/>
</
button
>
</
button
>
</
div
>
</
div
>
<
div
className=
"tabbed-view-body"
>
{
activeTab
===
'queries'
&&
<
QueriesTab
panel=
{
panel
}
dashboard=
{
dashboard
}
/>
}
{
activeTab
===
'queries'
&&
this
.
renderQueriesTab
()
}
{
activeTab
===
'visualization'
&&
(
{
activeTab
===
'visualization'
&&
this
.
renderVizTab
()
}
<
VisualizationTab
panel=
{
panel
}
dashboard=
{
dashboard
}
plugin=
{
plugin
}
onTypeChanged=
{
onTypeChanged
}
/>
</
div
>
)
}
</
div
>
</
div
>
);
);
}
}
...
@@ -121,8 +103,8 @@ function TabItem({ tab, activeTab, onClick }: TabItemParams) {
...
@@ -121,8 +103,8 @@ function TabItem({ tab, activeTab, onClick }: TabItemParams) {
});
});
return
(
return
(
<
li
className=
"gf-tabs-item"
key=
{
tab
.
id
}
>
<
li
className=
"gf-tabs-item"
onClick=
{
()
=>
onClick
(
tab
)
}
>
<
a
className=
{
tabClasses
}
onClick=
{
()
=>
onClick
(
tab
)
}
>
<
a
className=
{
tabClasses
}
>
<
i
className=
{
tab
.
icon
}
/>
{
tab
.
text
}
<
i
className=
{
tab
.
icon
}
/>
{
tab
.
text
}
</
a
>
</
a
>
</
li
>
</
li
>
...
...
public/app/features/dashboard/dashgrid/QueriesTab.tsx
View file @
727efa5a
// Libraries
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
// Services & utils
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/AngularLoader'
;
import
{
getAngularLoader
,
AngularComponent
}
from
'app/core/services/AngularLoader'
;
import
{
EditorTabBody
}
from
'./EditorTabBody'
;
import
{
DataSourcePicker
}
from
'./DataSourcePicker'
;
// Types
import
{
PanelModel
}
from
'../panel_model'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
...
@@ -48,6 +47,27 @@ export class QueriesTab extends PureComponent<Props> {
...
@@ -48,6 +47,27 @@ export class QueriesTab extends PureComponent<Props> {
}
}
render
()
{
render
()
{
return
<
div
ref=
{
element
=>
(
this
.
element
=
element
)
}
className=
"panel-height-helper"
/>;
const
currentDataSource
=
{
title
:
'ProductionDB'
,
imgSrc
:
'public/app/plugins/datasource/prometheus/img/prometheus_logo.svg'
,
render
:
()
=>
<
DataSourcePicker
/>,
};
const
queryInspector
=
{
title
:
'Query Inspector'
,
render
:
()
=>
<
h2
>
hello
</
h2
>,
};
const
dsHelp
=
{
title
:
''
,
icon
:
'fa fa-question'
,
render
:
()
=>
<
h2
>
hello
</
h2
>,
};
return
(
<
EditorTabBody
main=
{
currentDataSource
}
toolbarItems=
{
[
queryInspector
,
dsHelp
]
}
>
<
div
ref=
{
element
=>
(
this
.
element
=
element
)
}
style=
{
{
width
:
'100%'
}
}
/>
</
EditorTabBody
>
);
}
}
}
}
public/app/features/dashboard/dashgrid/VisualizationTab.tsx
0 → 100644
View file @
727efa5a
import
React
,
{
PureComponent
}
from
'react'
;
import
{
EditorTabBody
}
from
'./EditorTabBody'
;
import
{
VizTypePicker
}
from
'./VizTypePicker'
;
import
{
PanelModel
}
from
'../panel_model'
;
import
{
DashboardModel
}
from
'../dashboard_model'
;
import
{
PanelPlugin
}
from
'app/types/plugins'
;
interface
Props
{
panel
:
PanelModel
;
dashboard
:
DashboardModel
;
plugin
:
PanelPlugin
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
}
export
class
VisualizationTab
extends
PureComponent
<
Props
>
{
constructor
(
props
)
{
super
(
props
);
}
renderPanelOptions
()
{
const
{
plugin
,
panel
}
=
this
.
props
;
const
{
PanelOptionsComponent
}
=
plugin
.
exports
;
if
(
PanelOptionsComponent
)
{
return
<
PanelOptionsComponent
options=
{
panel
.
getOptions
()
}
onChange=
{
this
.
onPanelOptionsChanged
}
/>;
}
else
{
return
<
p
>
Visualization has no options
</
p
>;
}
}
onPanelOptionsChanged
=
(
options
:
any
)
=>
{
this
.
props
.
panel
.
updateOptions
(
options
);
this
.
forceUpdate
();
};
render
()
{
const
{
plugin
}
=
this
.
props
;
const
panelSelection
=
{
title
:
plugin
.
name
,
imgSrc
:
plugin
.
info
.
logos
.
small
,
render
:
()
=>
{
// the needs to be scoped inside this closure
const
{
plugin
,
onTypeChanged
}
=
this
.
props
;
return
<
VizTypePicker
current=
{
plugin
}
onTypeChanged=
{
onTypeChanged
}
/>;
},
};
return
(
<
EditorTabBody
main=
{
panelSelection
}
toolbarItems=
{
[]
}
>
{
this
.
renderPanelOptions
()
}
</
EditorTabBody
>
);
}
}
public/app/features/dashboard/dashgrid/VizTypePicker.tsx
View file @
727efa5a
import
React
,
{
PureComponent
}
from
'react'
;
import
React
,
{
PureComponent
}
from
'react'
;
import
classNames
from
'classnames'
;
import
classNames
from
'classnames'
;
import
_
from
'lodash'
;
import
config
from
'app/core/config'
;
import
config
from
'app/core/config'
;
import
{
PanelPlugin
}
from
'app/types/plugins'
;
import
{
PanelPlugin
}
from
'app/types/plugins'
;
import
CustomScrollbar
from
'app/core/components/CustomScrollbar/CustomScrollbar'
;
import
_
from
'lodash'
;
interface
Props
{
interface
Props
{
current
Type
:
string
;
current
:
PanelPlugin
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
onTypeChanged
:
(
newType
:
PanelPlugin
)
=>
void
;
}
}
...
@@ -15,6 +15,8 @@ interface State {
...
@@ -15,6 +15,8 @@ interface State {
}
}
export
class
VizTypePicker
extends
PureComponent
<
Props
,
State
>
{
export
class
VizTypePicker
extends
PureComponent
<
Props
,
State
>
{
searchInput
:
HTMLElement
;
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
);
super
(
props
);
...
@@ -36,34 +38,55 @@ export class VizTypePicker extends PureComponent<Props, State> {
...
@@ -36,34 +38,55 @@ export class VizTypePicker extends PureComponent<Props, State> {
renderVizPlugin
=
(
plugin
,
index
)
=>
{
renderVizPlugin
=
(
plugin
,
index
)
=>
{
const
cssClass
=
classNames
({
const
cssClass
=
classNames
({
'viz-picker__item'
:
true
,
'viz-picker__item'
:
true
,
'viz-picker__item--selected'
:
plugin
.
id
===
this
.
props
.
current
Type
,
'viz-picker__item--selected'
:
plugin
.
id
===
this
.
props
.
current
.
id
,
});
});
return
(
return
(
<
div
key=
{
index
}
className=
{
cssClass
}
onClick=
{
()
=>
this
.
props
.
onTypeChanged
(
plugin
)
}
title=
{
plugin
.
name
}
>
<
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
className=
"viz-picker__item-name"
>
{
plugin
.
name
}
</
div
>
<
img
className=
"viz-picker__item-img"
src=
{
plugin
.
info
.
logos
.
small
}
/>
</
div
>
</
div
>
);
);
};
};
render
()
{
componentDidMount
()
{
setTimeout
(()
=>
{
this
.
searchInput
.
focus
();
},
300
);
}
renderFilters
()
{
return
(
return
(
<
div
className=
"viz-picker"
>
<>
<
div
className=
"viz-picker__search"
>
<
label
className=
"gf-form--has-input-icon"
>
<
div
className=
"gf-form gf-form--grow"
>
<
input
<
label
className=
"gf-form--has-input-icon gf-form--grow"
>
type=
"text"
<
input
type=
"text"
className=
"gf-form-input"
placeholder=
"Search type"
/>
className=
"gf-form-input width-13"
placeholder=
""
ref=
{
elem
=>
(
this
.
searchInput
=
elem
)
}
/>
<
i
className=
"gf-form-input-icon fa fa-search"
/>
<
i
className=
"gf-form-input-icon fa fa-search"
/>
</
label
>
</
label
>
<
div
className=
"p-l-1"
>
<
button
className=
"btn toggle-btn gf-form-btn active"
>
Basic Types
</
button
>
<
button
className=
"btn toggle-btn gf-form-btn"
>
Master Types
</
button
>
</
div
>
</
div
>
</>
);
}
render
()
{
const
{
pluginList
}
=
this
.
state
;
return
(
<>
<
div
className=
"cta-form__bar"
>
{
this
.
renderFilters
()
}
<
div
className=
"gf-form--grow"
/>
</
div
>
</
div
>
<
div
className=
"viz-picker__items"
>
<
CustomScrollbar
>
<
div
className=
"viz-picker"
>
{
pluginList
.
map
(
this
.
renderVizPlugin
)
}
</
div
>
<
div
className=
"scroll-margin-helper"
>
{
this
.
state
.
pluginList
.
map
(
this
.
renderVizPlugin
)
}
</
div
>
</>
</
CustomScrollbar
>
</
div
>
</
div
>
);
);
}
}
}
}
public/app/features/panel/panel_directive.ts
View file @
727efa5a
...
@@ -44,8 +44,8 @@ const panelTemplate = `
...
@@ -44,8 +44,8 @@ const panelTemplate = `
</li>
</li>
</ul>
</ul>
<button class="
tabbed-view-close-btn
" ng-click="ctrl.exitFullscreen();">
<button class="
panel-editor-tabs__close
" ng-click="ctrl.exitFullscreen();">
<i class="fa fa-re
move
"></i>
<i class="fa fa-re
ply
"></i>
</button>
</button>
</div>
</div>
...
...
public/app/features/plugins/datasource_srv.ts
View file @
727efa5a
// Libraries
import
_
from
'lodash'
;
import
_
from
'lodash'
;
import
coreModule
from
'app/core/core_module'
;
import
coreModule
from
'app/core/core_module'
;
// Utils
import
config
from
'app/core/config'
;
import
config
from
'app/core/config'
;
import
{
importPluginModule
}
from
'./plugin_loader'
;
import
{
importPluginModule
}
from
'./plugin_loader'
;
// Types
import
{
DataSourceApi
}
from
'app/types/series'
;
import
{
DataSourceApi
}
from
'app/types/series'
;
import
{
DataSource
}
from
'app/types'
;
import
{
DataSource
,
DataSourceSelectItem
}
from
'app/types'
;
export
class
DatasourceSrv
{
export
class
DatasourceSrv
{
datasources
:
{
[
name
:
string
]:
DataSource
};
datasources
:
{
[
name
:
string
]:
DataSource
};
...
@@ -102,8 +99,8 @@ export class DatasourceSrv {
...
@@ -102,8 +99,8 @@ export class DatasourceSrv {
return
_
.
sortBy
(
es
,
[
'name'
]);
return
_
.
sortBy
(
es
,
[
'name'
]);
}
}
getMetricSources
(
options
)
{
getMetricSources
(
options
?
)
{
const
metricSources
=
[];
const
metricSources
:
DataSourceSelectItem
[]
=
[];
_
.
each
(
config
.
datasources
,
(
value
,
key
)
=>
{
_
.
each
(
config
.
datasources
,
(
value
,
key
)
=>
{
if
(
value
.
meta
&&
value
.
meta
.
metrics
)
{
if
(
value
.
meta
&&
value
.
meta
.
metrics
)
{
...
...
public/app/plugins/panel/graph2/module.tsx
View file @
727efa5a
...
@@ -61,12 +61,27 @@ export class GraphOptions extends PureComponent<PanelOptionsProps<Options>> {
...
@@ -61,12 +61,27 @@ export class GraphOptions extends PureComponent<PanelOptionsProps<Options>> {
return
(
return
(
<
div
>
<
div
>
<
div
className=
"form-option-box"
>
<
div
className=
"form-option-box__header"
>
Display Options
</
div
>
<
div
className=
"section gf-form-group"
>
<
div
className=
"section gf-form-group"
>
<
h5
className=
"page
-heading"
>
Draw Modes
</
h5
>
<
h5
className=
"section
-heading"
>
Draw Modes
</
h5
>
<
Switch
label=
"Lines"
labelClass=
"width-5"
checked=
{
showLines
}
onChange=
{
this
.
onToggleLines
}
/>
<
Switch
label=
"Lines"
labelClass=
"width-5"
checked=
{
showLines
}
onChange=
{
this
.
onToggleLines
}
/>
<
Switch
label=
"Bars"
labelClass=
"width-5"
checked=
{
showBars
}
onChange=
{
this
.
onToggleBars
}
/>
<
Switch
label=
"Bars"
labelClass=
"width-5"
checked=
{
showBars
}
onChange=
{
this
.
onToggleBars
}
/>
<
Switch
label=
"Points"
labelClass=
"width-5"
checked=
{
showPoints
}
onChange=
{
this
.
onTogglePoints
}
/>
<
Switch
label=
"Points"
labelClass=
"width-5"
checked=
{
showPoints
}
onChange=
{
this
.
onTogglePoints
}
/>
</
div
>
</
div
>
<
div
className=
"section gf-form-group"
>
<
h5
className=
"section-heading"
>
Test Options
</
h5
>
<
Switch
label=
"Lines"
labelClass=
"width-5"
checked=
{
showLines
}
onChange=
{
this
.
onToggleLines
}
/>
<
Switch
label=
"Bars"
labelClass=
"width-5"
checked=
{
showBars
}
onChange=
{
this
.
onToggleBars
}
/>
<
Switch
label=
"Points"
labelClass=
"width-5"
checked=
{
showPoints
}
onChange=
{
this
.
onTogglePoints
}
/>
</
div
>
</
div
>
<
div
className=
"form-option-box"
>
<
div
className=
"form-option-box__header"
>
Axes
</
div
>
</
div
>
<
div
className=
"form-option-box"
>
<
div
className=
"form-option-box__header"
>
Thresholds
</
div
>
</
div
>
</
div
>
</
div
>
);
);
}
}
...
...
public/app/types/datasources.ts
View file @
727efa5a
...
@@ -25,6 +25,13 @@ export interface DataSource {
...
@@ -25,6 +25,13 @@ export interface DataSource {
testDatasource
?:
()
=>
Promise
<
any
>
;
testDatasource
?:
()
=>
Promise
<
any
>
;
}
}
export
interface
DataSourceSelectItem
{
name
:
string
;
value
:
string
|
null
;
meta
:
PluginMeta
;
sort
:
string
;
}
export
interface
DataSourcesState
{
export
interface
DataSourcesState
{
dataSources
:
DataSource
[];
dataSources
:
DataSource
[];
searchQuery
:
string
;
searchQuery
:
string
;
...
...
public/app/types/index.ts
View file @
727efa5a
...
@@ -7,7 +7,7 @@ import { DashboardState } from './dashboard';
...
@@ -7,7 +7,7 @@ import { DashboardState } from './dashboard';
import
{
DashboardAcl
,
OrgRole
,
PermissionLevel
}
from
'./acl'
;
import
{
DashboardAcl
,
OrgRole
,
PermissionLevel
}
from
'./acl'
;
import
{
ApiKey
,
ApiKeysState
,
NewApiKey
}
from
'./apiKeys'
;
import
{
ApiKey
,
ApiKeysState
,
NewApiKey
}
from
'./apiKeys'
;
import
{
Invitee
,
OrgUser
,
User
,
UsersState
,
UserState
}
from
'./user'
;
import
{
Invitee
,
OrgUser
,
User
,
UsersState
,
UserState
}
from
'./user'
;
import
{
DataSource
,
DataSourcesState
}
from
'./datasources'
;
import
{
DataSource
,
DataSource
SelectItem
,
DataSource
sState
}
from
'./datasources'
;
import
{
import
{
TimeRange
,
TimeRange
,
LoadingState
,
LoadingState
,
...
@@ -55,6 +55,7 @@ export {
...
@@ -55,6 +55,7 @@ export {
OrgRole
,
OrgRole
,
PermissionLevel
,
PermissionLevel
,
DataSource
,
DataSource
,
DataSourceSelectItem
,
PluginMeta
,
PluginMeta
,
ApiKey
,
ApiKey
,
ApiKeysState
,
ApiKeysState
,
...
...
public/sass/_grafana.scss
View file @
727efa5a
...
@@ -97,7 +97,8 @@
...
@@ -97,7 +97,8 @@
@import
'components/form_select_box'
;
@import
'components/form_select_box'
;
@import
'components/user-picker'
;
@import
'components/user-picker'
;
@import
'components/description-picker'
;
@import
'components/description-picker'
;
@import
'components/viz_editor'
;
@import
'components/panel_editor'
;
@import
'components/toolbar'
;
@import
'components/delete_button'
;
@import
'components/delete_button'
;
@import
'components/add_data_source.scss'
;
@import
'components/add_data_source.scss'
;
@import
'components/page_loader'
;
@import
'components/page_loader'
;
...
...
public/sass/_variables.dark.scss
View file @
727efa5a
...
@@ -77,6 +77,7 @@ $brand-gradient: linear-gradient(
...
@@ -77,6 +77,7 @@ $brand-gradient: linear-gradient(
rgba
(
255
,
68
,
0
,
0
.7
)
99%
,
rgba
(
255
,
68
,
0
,
0
.7
)
99%
,
rgba
(
255
,
68
,
0
,
0
.7
)
100%
rgba
(
255
,
68
,
0
,
0
.7
)
100%
);
);
$page-gradient
:
linear-gradient
(
180deg
,
#222426
10px
,
rgb
(
22
,
23
,
25
)
100px
);
$page-gradient
:
linear-gradient
(
180deg
,
#222426
10px
,
rgb
(
22
,
23
,
25
)
100px
);
// Links
// Links
...
@@ -110,7 +111,6 @@ $divider-border-color: #555;
...
@@ -110,7 +111,6 @@ $divider-border-color: #555;
// Graphite Target Editor
// Graphite Target Editor
$tight-form-bg
:
$dark-3
;
$tight-form-bg
:
$dark-3
;
$tight-form-func-bg
:
#333334
;
$tight-form-func-bg
:
#333334
;
$tight-form-func-highlight-bg
:
#444445
;
$tight-form-func-highlight-bg
:
#444445
;
...
@@ -128,6 +128,7 @@ $list-item-bg: $card-background;
...
@@ -128,6 +128,7 @@ $list-item-bg: $card-background;
$list-item-hover-bg
:
lighten
(
$gray-blue
,
2%
);
$list-item-hover-bg
:
lighten
(
$gray-blue
,
2%
);
$list-item-link-color
:
$text-color
;
$list-item-link-color
:
$text-color
;
$list-item-shadow
:
$card-shadow
;
$list-item-shadow
:
$card-shadow
;
$empty-list-cta-bg
:
$gray-blue
;
$empty-list-cta-bg
:
$gray-blue
;
// Scrollbars
// Scrollbars
...
@@ -152,8 +153,8 @@ $table-bg-hover: $dark-3;
...
@@ -152,8 +153,8 @@ $table-bg-hover: $dark-3;
$btn-primary-bg
:
#ff6600
;
$btn-primary-bg
:
#ff6600
;
$btn-primary-bg-hl
:
#bc3e06
;
$btn-primary-bg-hl
:
#bc3e06
;
$btn-secondary-bg
:
$blue-dark
;
$btn-secondary-bg-hl
:
lighten
(
$blue-dark
,
5%
);
$btn-secondary-bg-hl
:
lighten
(
$blue-dark
,
5%
);
$btn-secondary-bg
:
$blue-dark
;
$btn-success-bg
:
$green
;
$btn-success-bg
:
$green
;
$btn-success-bg-hl
:
darken
(
$green
,
6%
);
$btn-success-bg-hl
:
darken
(
$green
,
6%
);
...
@@ -266,6 +267,11 @@ $menu-dropdown-shadow: 5px 5px 20px -5px $black;
...
@@ -266,6 +267,11 @@ $menu-dropdown-shadow: 5px 5px 20px -5px $black;
// -------------------------
// -------------------------
$tab-border-color
:
$dark-4
;
$tab-border-color
:
$dark-4
;
// Toolbar
$toolbar-bg
:
$page-header-bg
;
$toolbar-shadow
:
0
0
20px
black
;
$toolbar-tab-bg
:
$gray-blue
;
// Pagination
// Pagination
// -------------------------
// -------------------------
...
...
public/sass/_variables.light.scss
View file @
727efa5a
...
@@ -31,6 +31,7 @@ $white: #fff;
...
@@ -31,6 +31,7 @@ $white: #fff;
// Accent colors
// Accent colors
// -------------------------
// -------------------------
$blue
:
#0083b3
;
$blue
:
#0083b3
;
$blue-dark
:
#005f81
;
$blue-light
:
#00a8e6
;
$blue-light
:
#00a8e6
;
$green
:
#3aa655
;
$green
:
#3aa655
;
$red
:
#d44939
;
$red
:
#d44939
;
...
@@ -213,6 +214,11 @@ $menu-dropdown-shadow: 5px 5px 10px -5px $gray-1;
...
@@ -213,6 +214,11 @@ $menu-dropdown-shadow: 5px 5px 10px -5px $gray-1;
// -------------------------
// -------------------------
$tab-border-color
:
$gray-5
;
$tab-border-color
:
$gray-5
;
// Toolbar
$toolbar-bg
:
linear-gradient
(
90deg
,
#ffffff
,
#e6eef9
);
$toolbar-shadow
:
1px
1px
3px
#c7d0d8
;
$toolbar-tab-bg
:
$white
;
// search
// search
$search-shadow
:
0
5px
30px
0
$gray-4
;
$search-shadow
:
0
5px
30px
0
$gray-4
;
$search-filter-box-bg
:
$gray-7
;
$search-filter-box-bg
:
$gray-7
;
...
...
public/sass/components/_buttons.scss
View file @
727efa5a
...
@@ -120,8 +120,8 @@
...
@@ -120,8 +120,8 @@
// Info appears as a neutral blue
// Info appears as a neutral blue
.btn-secondary
{
.btn-secondary
{
@include
buttonBackground
(
$btn-secondary-bg
,
$btn-secondary-bg-hl
);
@include
buttonBackground
(
$btn-secondary-bg
,
$btn-secondary-bg-hl
);
// Inverse appears as dark gray
}
}
// Inverse appears as dark gray
.btn-inverse
{
.btn-inverse
{
@include
buttonBackground
(
$btn-inverse-bg
,
$btn-inverse-bg-hl
,
$btn-inverse-text-color
,
$btn-inverse-text-shadow
);
@include
buttonBackground
(
$btn-inverse-bg
,
$btn-inverse-bg-hl
,
$btn-inverse-text-color
,
$btn-inverse-text-shadow
);
//background: $card-background;
//background: $card-background;
...
...
public/sass/components/_dashboard_grid.scss
View file @
727efa5a
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
.panel-in-fullscreen
{
.panel-in-fullscreen
{
.react-grid-layout
{
.react-grid-layout
{
height
:
100%
!
important
;
height
:
calc
(
100%
-
20px
)
!
important
;
}
}
.react-grid-item
{
.react-grid-item
{
...
@@ -19,6 +19,10 @@
...
@@ -19,6 +19,10 @@
transform
:
translate
(
0px
,
0px
)
!
important
;
transform
:
translate
(
0px
,
0px
)
!
important
;
}
}
.panel
{
margin
:
0
!
important
;
}
// Disable grid interaction indicators in fullscreen panels
// Disable grid interaction indicators in fullscreen panels
.panel-header
:hover
{
.panel-header
:hover
{
background-color
:
inherit
;
background-color
:
inherit
;
...
...
public/sass/components/_gf-form.scss
View file @
727efa5a
...
@@ -415,7 +415,27 @@ select.gf-form-input ~ .gf-form-help-icon {
...
@@ -415,7 +415,27 @@ select.gf-form-input ~ .gf-form-help-icon {
}
}
.cta-form__close
{
.cta-form__close
{
background
:
transparent
;
padding
:
4px
8px
4px
9px
;
border
:
none
;
position
:
absolute
;
position
:
absolute
;
right
:
0
;
right
:
0
;
top
:
0
;
top
:
-2px
;
font-size
:
$font-size-md
;
&
:hover
{
color
:
$text-color-strong
;
}
}
.cta-form__bar
{
display
:
flex
;
align-items
:
center
;
align-content
:
center
;
margin-bottom
:
20px
;
}
.cta-form__bar-header
{
font-size
:
$font-size-h4
;
padding-right
:
20px
;
}
}
public/sass/components/_navbar.scss
View file @
727efa5a
...
@@ -41,7 +41,7 @@
...
@@ -41,7 +41,7 @@
.panel-in-fullscreen
{
.panel-in-fullscreen
{
.navbar
{
.navbar
{
@include
navbar-alt-look
()
;
padding-left
:
15px
;
}
}
.navbar-button--add-panel
,
.navbar-button--add-panel
,
...
@@ -50,10 +50,6 @@
...
@@ -50,10 +50,6 @@
.navbar-page-btn
.fa-caret-down
{
.navbar-page-btn
.fa-caret-down
{
display
:
none
;
display
:
none
;
}
}
.navbar-buttons--close
{
display
:
flex
;
}
}
}
.navbar-page-btn
{
.navbar-page-btn
{
...
@@ -98,7 +94,7 @@
...
@@ -98,7 +94,7 @@
}
}
.navbar-buttons
{
.navbar-buttons
{
height
:
$navbarHeight
;
//
height: $navbarHeight;
display
:
flex
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
flex-end
;
justify-content
:
flex-end
;
...
...
public/sass/components/_panel_editor.scss
0 → 100644
View file @
727efa5a
.panel-editor-container
{
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
}
.panel-editor-container__panel
{
flex
:
1
1
0
;
}
.panel-editor-container__editor
{
margin-top
:
$panel-margin
*
2
;
display
:
flex
;
flex-direction
:
column
;
height
:
65%
;
position
:
relative
;
}
.panel-editor__scroll
{
flex-grow
:
1
;
min-width
:
0
;
display
:
flex
;
padding
:
0
5px
;
}
.panel-editor__content
{
padding
:
40px
15px
;
}
.panel-in-fullscreen
{
.sidemenu
{
display
:
none
;
}
.dashboard-container
{
padding
:
0
;
}
.submenu-controls
{
padding
:
0
$dashboard-padding
$panel-margin
$dashboard-padding
;
}
.panel-editor-container__panel
{
margin
:
0
$dashboard-padding
;
}
}
.panel-editor-resizer
{
position
:
absolute
;
height
:
2px
;
width
:
100%
;
top
:
-23px
;
text-align
:
center
;
border-bottom
:
2px
dashed
transparent
;
&
:hover
{
transition
:
border-color
0
.2s
ease-in
0
.4s
;
transition-delay
:
0
.2s
;
border-color
:
$text-color-faint
;
}
}
.panel-editor-resizer__handle
{
display
:
inline-block
;
width
:
180px
;
position
:
relative
;
border-radius
:
2px
;
height
:
10px
;
cursor
:
grabbing
;
background
:
$input-label-bg
;
top
:
-8px
;
&
:hover
{
transition
:
background
0
.2s
ease-in
0
.4s
;
transition-delay
:
0
.2s
;
background
:
linear-gradient
(
90deg
,
$orange
,
$red
);
.panel-editor-resizer__handle-dots
{
transition
:
opacity
0
.2s
ease-in
;
opacity
:
0
;
}
}
}
.panel-editor-resizer__handle-dots
{
border-top
:
2px
dashed
$text-color-faint
;
position
:
relative
;
top
:
4px
;
}
.viz-picker
{
display
:
flex
;
flex-wrap
:
wrap
;
margin-bottom
:
13px
;
}
.viz-picker__item
{
background
:
$card-background
;
box-shadow
:
$card-shadow
;
border-radius
:
3px
;
height
:
90px
;
width
:
150px
;
flex-shrink
:
0
;
flex-direction
:
column
;
text-align
:
center
;
cursor
:
pointer
;
display
:
flex
;
margin-right
:
10px
;
margin-bottom
:
10px
;
border
:
1px
solid
transparent
;
align-items
:
center
;
&
:hover
{
background
:
$card-background-hover
;
}
&
--selected
{
box-shadow
:
0
0
12px
#ff4d00
;
}
}
.viz-picker__item-name
{
text-overflow
:
ellipsis
;
overflow
:
hidden
;
white-space
:
nowrap
;
font-size
:
$font-size-sm
;
display
:
flex
;
flex-direction
:
column
;
align-self
:
center
;
height
:
23px
;
}
.viz-picker__item-img
{
height
:
55px
;
}
.panel-editor-tabs
{
position
:
relative
;
z-index
:
2
;
box-shadow
:
$page-header-shadow
;
border-bottom
:
1px
solid
$page-header-border-color
;
padding
:
0
$dashboard-padding
;
@include
clearfix
();
.active.gf-tabs-link
{
background
:
$toolbar-tab-bg
;
}
}
.panel-editor-tabs__close
{
padding
:
5px
9px
;
border-radius
:
$border-radius
;
float
:
right
;
@include
buttonBackground
(
$btn-primary-bg
,
$btn-primary-bg-hl
);
}
.ds-picker-list
{
display
:
flex
;
flex-wrap
:
wrap
;
margin-bottom
:
13px
;
flex-direction
:
column
;
}
.ds-picker-list__item
{
background
:
$card-background
;
box-shadow
:
$card-shadow
;
border-radius
:
3px
;
display
:
flex
;
cursor
:
pointer
;
margin-bottom
:
3px
;
padding
:
5px
15px
;
align-items
:
center
;
&
:hover
{
background
:
$card-background-hover
;
}
&
--selected
{
.ds-picker-list__name
{
color
:
$text-color
;
}
}
}
.ds-picker-list__name
{
text-overflow
:
ellipsis
;
overflow
:
hidden
;
white-space
:
nowrap
;
font-size
:
$font-size-md
;
padding-left
:
15px
;
}
.ds-picker-list__img
{
width
:
30px
;
}
.form-option-box
{
margin-bottom
:
20px
;
}
.form-option-box__header
{
border-bottom
:
2px
solid
$dark-4
;
padding
:
5px
0px
;
font-size
:
$font-size-md
;
margin-bottom
:
20px
;
}
public/sass/components/_scrollbar.scss
View file @
727efa5a
...
@@ -106,78 +106,78 @@
...
@@ -106,78 +106,78 @@
opacity
:
0
.9
;
opacity
:
0
.9
;
}
}
// Scrollbars
// // Scrollbars
// //
//
// ::-webkit-scrollbar {
// width: 8px;
// height: 8px;
// }
//
// ::-webkit-scrollbar:hover {
// height: 8px;
// }
//
// ::-webkit-scrollbar-button:start:decrement,
// ::-webkit-scrollbar-button:end:increment {
// display: none;
// }
// ::-webkit-scrollbar-button:horizontal:decrement {
// display: none;
// }
// ::-webkit-scrollbar-button:horizontal:increment {
// display: none;
// }
// ::-webkit-scrollbar-button:vertical:decrement {
// display: none;
// }
// ::-webkit-scrollbar-button:vertical:increment {
// display: none;
// }
// ::-webkit-scrollbar-button:horizontal:decrement:active {
// background-image: none;
// }
// ::-webkit-scrollbar-button:horizontal:increment:active {
// background-image: none;
// }
// ::-webkit-scrollbar-button:vertical:decrement:active {
// background-image: none;
// }
// ::-webkit-scrollbar-button:vertical:increment:active {
// background-image: none;
// }
// ::-webkit-scrollbar-track-piece {
// background-color: transparent;
// }
//
// ::-webkit-scrollbar-thumb:vertical {
// height: 50px;
// background: -webkit-gradient(
// linear,
// left top,
// right top,
// color-stop(0%, $scrollbarBackground),
// color-stop(100%, $scrollbarBackground2)
// );
// border: 1px solid $scrollbarBorder;
// border-top: 1px solid $scrollbarBorder;
// border-left: 1px solid $scrollbarBorder;
// }
//
// ::-webkit-scrollbar-thumb:horizontal {
// width: 50px;
// background: -webkit-gradient(
// linear,
// left top,
// left bottom,
// color-stop(0%, $scrollbarBackground),
// color-stop(100%, $scrollbarBackground2)
// );
// border: 1px solid $scrollbarBorder;
// border-top: 1px solid $scrollbarBorder;
// border-left: 1px solid $scrollbarBorder;
// }
//
//
::-webkit-scrollbar
{
width
:
8px
;
height
:
8px
;
}
::-webkit-scrollbar:hover
{
height
:
8px
;
}
::-webkit-scrollbar-button:start:decrement
,
::-webkit-scrollbar-button:end:increment
{
display
:
none
;
}
::-webkit-scrollbar-button:horizontal:decrement
{
display
:
none
;
}
::-webkit-scrollbar-button:horizontal:increment
{
display
:
none
;
}
::-webkit-scrollbar-button:vertical:decrement
{
display
:
none
;
}
::-webkit-scrollbar-button:vertical:increment
{
display
:
none
;
}
::-webkit-scrollbar-button:horizontal:decrement:active
{
background-image
:
none
;
}
::-webkit-scrollbar-button:horizontal:increment:active
{
background-image
:
none
;
}
::-webkit-scrollbar-button:vertical:decrement:active
{
background-image
:
none
;
}
::-webkit-scrollbar-button:vertical:increment:active
{
background-image
:
none
;
}
::-webkit-scrollbar-track-piece
{
background-color
:
transparent
;
}
::-webkit-scrollbar-thumb:vertical
{
height
:
50px
;
background
:
-webkit-gradient
(
linear
,
left
top
,
right
top
,
color-stop
(
0%
,
$scrollbarBackground
)
,
color-stop
(
100%
,
$scrollbarBackground2
)
);
border
:
1px
solid
$scrollbarBorder
;
border-top
:
1px
solid
$scrollbarBorder
;
border-left
:
1px
solid
$scrollbarBorder
;
}
::-webkit-scrollbar-thumb:horizontal
{
width
:
50px
;
background
:
-webkit-gradient
(
linear
,
left
top
,
left
bottom
,
color-stop
(
0%
,
$scrollbarBackground
)
,
color-stop
(
100%
,
$scrollbarBackground2
)
);
border
:
1px
solid
$scrollbarBorder
;
border-top
:
1px
solid
$scrollbarBorder
;
border-left
:
1px
solid
$scrollbarBorder
;
}
// Baron styles
// Baron styles
.baron
{
.baron
{
...
...
public/sass/components/_submenu.scss
View file @
727efa5a
...
@@ -4,8 +4,7 @@
...
@@ -4,8 +4,7 @@
flex-wrap
:
wrap
;
flex-wrap
:
wrap
;
align-content
:
flex-start
;
align-content
:
flex-start
;
align-items
:
flex-start
;
align-items
:
flex-start
;
padding
:
0
0
$panel-margin
0
;
margin
:
0
0
$panel-margin
0
;
}
}
.annotation-disabled
,
.annotation-disabled
,
...
...
public/sass/components/_tabbed_view.scss
View file @
727efa5a
...
@@ -2,9 +2,10 @@
...
@@ -2,9 +2,10 @@
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
height
:
100%
;
height
:
100%
;
flex-grow
:
1
;
&
.tabbed-view--new
{
&
.tabbed-view--new
{
padding
:
25px
0
0
0
;
padding
:
0
0
0
0
;
height
:
100%
;
height
:
100%
;
}
}
}
}
...
@@ -12,13 +13,14 @@
...
@@ -12,13 +13,14 @@
.tabbed-view-header
{
.tabbed-view-header
{
box-shadow
:
$page-header-shadow
;
box-shadow
:
$page-header-shadow
;
border-bottom
:
1px
solid
$page-header-border-color
;
border-bottom
:
1px
solid
$page-header-border-color
;
padding
:
0
$dashboard-padding
;
@include
clearfix
();
@include
clearfix
();
}
}
.tabbed-view-title
{
.tabbed-view-title
{
float
:
left
;
float
:
left
;
padding-top
:
0
.5rem
;
padding-top
:
0
.5rem
;
margin
:
0
$spacer
*
3
0
$spacer
*
1
;
margin
:
0
$spacer
*
3
0
0
;
}
}
.tabbed-view-panel-title
{
.tabbed-view-panel-title
{
...
...
public/sass/components/_tabs.scss
View file @
727efa5a
...
@@ -53,6 +53,7 @@
...
@@ -53,6 +53,7 @@
background-image
:
linear-gradient
(
to
right
,
#ffd500
0%
,
#ff4400
99%
,
#ff4400
100%
);
background-image
:
linear-gradient
(
to
right
,
#ffd500
0%
,
#ff4400
99%
,
#ff4400
100%
);
}
}
}
}
&
.active--panel
{
&
.active--panel
{
background
:
$panel-bg
!
important
;
background
:
$panel-bg
!
important
;
}
}
...
...
public/sass/components/_timepicker.scss
View file @
727efa5a
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
background-color
:
$page-bg
;
background-color
:
$page-bg
;
border-radius
:
0
0
0
4px
;
border-radius
:
0
0
0
4px
;
box-shadow
:
$search-shadow
;
box-shadow
:
$search-shadow
;
z-index
:
$zindex-dropdown
;
}
}
.gf-timepicker-absolute-section
{
.gf-timepicker-absolute-section
{
...
...
public/sass/components/_toolbar.scss
0 → 100644
View file @
727efa5a
.toolbar
{
display
:
flex
;
align-content
:
center
;
align-items
:
center
;
background
:
$toolbar-bg
;
box-shadow
:
$toolbar-shadow
;
padding
:
7px
20px
7px
20px
;
position
:
relative
;
z-index
:
1
;
flex
:
0
0
auto
;
}
.toolbar__main
{
padding
:
$input-padding-y
$input-padding-x
;
font-size
:
$font-size-md
;
line-height
:
$input-line-height
;
color
:
$input-color
;
background-color
:
$input-bg
;
border
:
$input-border
;
border-radius
:
$input-border-radius
;
display
:
flex
;
align-items
:
center
;
cursor
:
pointer
;
.fa
{
margin-left
:
20px
;
display
:
inline-block
;
position
:
relative
;
}
}
.toolbar__main-image
{
margin-right
:
10px
;
display
:
inline-block
;
width
:
20px
;
height
:
20px
;
}
.toolbar-subview
{
position
:
relative
;
padding
:
20px
20px
;
background-color
:
$empty-list-cta-bg
;
top
:
-45px
;
margin
:
0
30px
20px
0px
;
}
.toolbar-subview__close
{
background
:
transparent
;
padding
:
4px
8px
4px
9px
;
border
:
none
;
position
:
absolute
;
right
:
15px
;
top
:
20px
;
font-size
:
$font-size-md
;
&
:hover
{
color
:
$text-color-strong
;
}
}
public/sass/components/_viz_editor.scss
deleted
100644 → 0
View file @
e0feb726
.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__search
{
flex-grow
:
0
;
}
.viz-picker__items
{
flex-grow
:
1
;
height
:
calc
(
100%
-
50px
);
}
.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
;
@include
left-brand-border
;
&
:hover
{
background
:
$card-background-hover
;
}
&
--selected
{
// border: 1px solid $orange;
@include
left-brand-border-gradient
();
.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 @
727efa5a
...
@@ -37,20 +37,6 @@ div.flot-text {
...
@@ -37,20 +37,6 @@ div.flot-text {
height
:
100%
;
height
:
100%
;
}
}
.panel-editor-container
{
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
}
.panel-editor-container__panel
{
height
:
35%
;
}
.panel-editor-container__editor
{
height
:
65%
;
}
.panel-container
{
.panel-container
{
background-color
:
$panel-bg
;
background-color
:
$panel-bg
;
border
:
$panel-border
;
border
:
$panel-border
;
...
...
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