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
1236b7b9
Unverified
Commit
1236b7b9
authored
May 07, 2018
by
David
Committed by
GitHub
May 07, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11770 from grafana/davkal/explore-panel-link
Explore: Add entry to panel menu to jump to Explore
parents
b170bde7
8a53ec61
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
102 additions
and
14 deletions
+102
-14
public/app/containers/Explore/Explore.tsx
+17
-2
public/app/containers/Explore/QueryRows.tsx
+15
-4
public/app/core/services/keybindingSrv.ts
+13
-1
public/app/core/utils/location_util.ts
+7
-4
public/app/features/panel/metrics_panel_ctrl.ts
+19
-0
public/app/features/panel/panel_ctrl.ts
+10
-0
public/app/plugins/datasource/prometheus/datasource.ts
+17
-0
public/app/plugins/panel/pluginlist/module.ts
+1
-1
public/app/plugins/panel/singlestat/module.ts
+1
-1
public/app/routes/ReactContainer.tsx
+1
-0
public/app/routes/routes.ts
+1
-1
No files found.
public/app/containers/Explore/Explore.tsx
View file @
1236b7b9
...
...
@@ -10,6 +10,7 @@ import Graph from './Graph';
import
Table
from
'./Table'
;
import
{
DatasourceSrv
}
from
'app/features/plugins/datasource_srv'
;
import
{
buildQueryOptions
,
ensureQueries
,
generateQueryKey
,
hasQuery
}
from
'./utils/query'
;
import
{
decodePathComponent
}
from
'app/core/utils/location_util'
;
function
makeTimeSeriesList
(
dataList
,
options
)
{
return
dataList
.
map
((
seriesData
,
index
)
=>
{
...
...
@@ -38,6 +39,19 @@ function makeTimeSeriesList(dataList, options) {
});
}
function
parseInitialQueries
(
initial
)
{
if
(!
initial
)
{
return
[];
}
try
{
const
parsed
=
JSON
.
parse
(
decodePathComponent
(
initial
));
return
parsed
.
queries
.
map
(
q
=
>
q.query);
} catch (e)
{
console
.
error
(
e
);
return
[];
}
}
interface IExploreState
{
datasource
:
any
;
datasourceError
:
any
;
...
...
@@ -58,6 +72,7 @@ export class Explore extends React.Component<any, IExploreState> {
constructor
(
props
)
{
super
(
props
);
const
initialQueries
=
parseInitialQueries
(
props
.
routeParams
.
initial
);
this
.
state
=
{
datasource
:
null
,
datasourceError
:
null
,
...
...
@@ -65,7 +80,7 @@ export class Explore extends React.Component<any, IExploreState> {
graphResult
:
null
,
latency
:
0
,
loading
:
false
,
queries
:
ensureQueries
(),
queries
:
ensureQueries
(
initialQueries
),
requestOptions
:
null
,
showingGraph
:
true
,
showingTable
:
true
,
...
...
@@ -77,7 +92,7 @@ export class Explore extends React.Component<any, IExploreState> {
const
datasource
=
await
this
.
props
.
datasourceSrv
.
get
();
const
testResult
=
await
datasource
.
testDatasource
();
if
(
testResult
.
status
===
'success'
)
{
this
.
setState
({
datasource
,
datasourceError
:
null
,
datasourceLoading
:
false
});
this
.
setState
({
datasource
,
datasourceError
:
null
,
datasourceLoading
:
false
}
,
()
=>
this
.
handleSubmit
()
);
}
else
{
this
.
setState
({
datasource
:
null
,
datasourceError
:
testResult
.
message
,
datasourceLoading
:
false
});
}
...
...
public/app/containers/Explore/QueryRows.tsx
View file @
1236b7b9
...
...
@@ -6,13 +6,16 @@ class QueryRow extends PureComponent<any, any> {
constructor
(
props
)
{
super
(
props
);
this
.
state
=
{
query
:
''
,
edited
:
false
,
query
:
props
.
query
||
''
,
};
}
handleChangeQuery
=
value
=>
{
const
{
index
,
onChangeQuery
}
=
this
.
props
;
this
.
setState
({
query
:
value
});
const
{
query
}
=
this
.
state
;
const
edited
=
query
!==
value
;
this
.
setState
({
edited
,
query
:
value
});
if
(
onChangeQuery
)
{
onChangeQuery
(
value
,
index
);
}
...
...
@@ -41,6 +44,7 @@ class QueryRow extends PureComponent<any, any> {
render
()
{
const
{
request
}
=
this
.
props
;
const
{
edited
,
query
}
=
this
.
state
;
return
(
<
div
className=
"query-row"
>
<
div
className=
"query-row-tools"
>
...
...
@@ -52,7 +56,12 @@ class QueryRow extends PureComponent<any, any> {
</
button
>
</
div
>
<
div
className=
"query-field-wrapper"
>
<
QueryField
onPressEnter=
{
this
.
handlePressEnter
}
onQueryChange=
{
this
.
handleChangeQuery
}
request=
{
request
}
/>
<
QueryField
initialQuery=
{
edited
?
null
:
query
}
onPressEnter=
{
this
.
handlePressEnter
}
onQueryChange=
{
this
.
handleChangeQuery
}
request=
{
request
}
/>
</
div
>
</
div
>
);
...
...
@@ -63,7 +72,9 @@ export default class QueryRows extends PureComponent<any, any> {
render
()
{
const
{
className
=
''
,
queries
,
...
handlers
}
=
this
.
props
;
return
(
<
div
className=
{
className
}
>
{
queries
.
map
((
q
,
index
)
=>
<
QueryRow
key=
{
q
.
key
}
index=
{
index
}
{
...
handlers
}
/>)
}
</
div
>
<
div
className=
{
className
}
>
{
queries
.
map
((
q
,
index
)
=>
<
QueryRow
key=
{
q
.
key
}
index=
{
index
}
query=
{
q
.
query
}
{
...
handlers
}
/>)
}
</
div
>
);
}
}
public/app/core/services/keybindingSrv.ts
View file @
1236b7b9
...
...
@@ -3,6 +3,7 @@ import _ from 'lodash';
import
coreModule
from
'app/core/core_module'
;
import
appEvents
from
'app/core/app_events'
;
import
{
encodePathComponent
}
from
'app/core/utils/location_util'
;
import
Mousetrap
from
'mousetrap'
;
import
'mousetrap-global-bind'
;
...
...
@@ -13,7 +14,7 @@ export class KeybindingSrv {
timepickerOpen
=
false
;
/** @ngInject */
constructor
(
private
$rootScope
,
private
$location
)
{
constructor
(
private
$rootScope
,
private
$location
,
private
datasourceSrv
)
{
// clear out all shortcuts on route change
$rootScope
.
$on
(
'$routeChangeSuccess'
,
()
=>
{
Mousetrap
.
reset
();
...
...
@@ -176,6 +177,17 @@ export class KeybindingSrv {
}
});
this
.
bind
(
'x'
,
async
()
=>
{
if
(
dashboard
.
meta
.
focusPanelId
)
{
const
panel
=
dashboard
.
getPanelById
(
dashboard
.
meta
.
focusPanelId
);
const
datasource
=
await
this
.
datasourceSrv
.
get
(
panel
.
datasource
);
if
(
datasource
&&
datasource
.
supportsExplore
)
{
const
exploreState
=
encodePathComponent
(
JSON
.
stringify
(
datasource
.
getExploreState
(
panel
)));
this
.
$location
.
url
(
`/explore/
${
exploreState
}
`
);
}
}
});
// delete panel
this
.
bind
(
'p r'
,
()
=>
{
if
(
dashboard
.
meta
.
focusPanelId
&&
dashboard
.
meta
.
canEdit
)
{
...
...
public/app/core/utils/location_util.ts
View file @
1236b7b9
import
config
from
'app/core/config'
;
const
_stripBaseFromUrl
=
url
=>
{
// Slash encoding for angular location provider, see https://github.com/angular/angular.js/issues/10479
const
SLASH
=
'<SLASH>'
;
export
const
decodePathComponent
=
(
pc
:
string
)
=>
decodeURIComponent
(
pc
).
replace
(
new
RegExp
(
SLASH
,
'g'
),
'/'
);
export
const
encodePathComponent
=
(
pc
:
string
)
=>
encodeURIComponent
(
pc
.
replace
(
/
\/
/g
,
SLASH
));
export
const
stripBaseFromUrl
=
url
=>
{
const
appSubUrl
=
config
.
appSubUrl
;
const
stripExtraChars
=
appSubUrl
.
endsWith
(
'/'
)
?
1
:
0
;
const
urlWithoutBase
=
...
...
@@ -9,6 +14,4 @@ const _stripBaseFromUrl = url => {
return
urlWithoutBase
;
};
export
default
{
stripBaseFromUrl
:
_stripBaseFromUrl
,
};
export
default
{
stripBaseFromUrl
};
public/app/features/panel/metrics_panel_ctrl.ts
View file @
1236b7b9
...
...
@@ -6,6 +6,7 @@ import { PanelCtrl } from 'app/features/panel/panel_ctrl';
import
*
as
rangeUtil
from
'app/core/utils/rangeutil'
;
import
*
as
dateMath
from
'app/core/utils/datemath'
;
import
{
encodePathComponent
}
from
'app/core/utils/location_util'
;
import
{
metricsTabDirective
}
from
'./metrics_tab'
;
...
...
@@ -309,6 +310,24 @@ class MetricsPanelCtrl extends PanelCtrl {
this
.
refresh
();
}
getAdditionalMenuItems
()
{
const
items
=
[];
if
(
this
.
datasource
.
supportsExplore
)
{
items
.
push
({
text
:
'Explore'
,
click
:
'ctrl.explore();'
,
icon
:
'fa fa-fw fa-rocket'
,
shortcut
:
'x'
,
});
}
return
items
;
}
explore
()
{
const
exploreState
=
encodePathComponent
(
JSON
.
stringify
(
this
.
datasource
.
getExploreState
(
this
.
panel
)));
this
.
$location
.
url
(
`/explore/
${
exploreState
}
`
);
}
addQuery
(
target
)
{
target
.
refId
=
this
.
dashboard
.
getNextQueryLetter
(
this
.
panel
);
...
...
public/app/features/panel/panel_ctrl.ts
View file @
1236b7b9
...
...
@@ -22,6 +22,7 @@ export class PanelCtrl {
editorTabs
:
any
;
$scope
:
any
;
$injector
:
any
;
$location
:
any
;
$timeout
:
any
;
fullscreen
:
boolean
;
inspector
:
any
;
...
...
@@ -35,6 +36,7 @@ export class PanelCtrl {
constructor
(
$scope
,
$injector
)
{
this
.
$injector
=
$injector
;
this
.
$location
=
$injector
.
get
(
'$location'
);
this
.
$scope
=
$scope
;
this
.
$timeout
=
$injector
.
get
(
'$timeout'
);
this
.
editorTabIndex
=
0
;
...
...
@@ -161,6 +163,9 @@ export class PanelCtrl {
shortcut
:
'p s'
,
});
// Additional items from sub-class
menu
.
push
(...
this
.
getAdditionalMenuItems
());
let
extendedMenu
=
this
.
getExtendedMenu
();
menu
.
push
({
text
:
'More ...'
,
...
...
@@ -209,6 +214,11 @@ export class PanelCtrl {
return
menu
;
}
// Override in sub-class to add items before extended menu
getAdditionalMenuItems
()
{
return
[];
}
otherPanelInFullscreenMode
()
{
return
this
.
dashboard
.
meta
.
fullscreen
&&
!
this
.
fullscreen
;
}
...
...
public/app/plugins/datasource/prometheus/datasource.ts
View file @
1236b7b9
...
...
@@ -19,6 +19,7 @@ export class PrometheusDatasource {
type: string;
editorSrc: string;
name: string;
supportsExplore: boolean;
supportMetrics: boolean;
url: string;
directUrl: string;
...
...
@@ -34,6 +35,7 @@ export class PrometheusDatasource {
this.type = '
prometheus
';
this.editorSrc = '
app
/
features
/
prometheus
/
partials
/
query
.
editor
.
html
';
this.name = instanceSettings.name;
this.supportsExplore = true;
this.supportMetrics = true;
this.url = instanceSettings.url;
this.directUrl = instanceSettings.directUrl;
...
...
@@ -324,6 +326,21 @@ export class PrometheusDatasource {
});
}
getExploreState(panel) {
let state = {};
if (panel.targets) {
const queries = panel.targets.map(t => ({
query: this.templateSrv.replace(t.expr, {}, this.interpolateQueryExpr),
format: t.format,
}));
state = {
...state,
queries,
};
}
return state;
}
getPrometheusTime(date, roundUp) {
if (_.isString(date)) {
date = dateMath.parse(date, roundUp);
...
...
public/app/plugins/panel/pluginlist/module.ts
View file @
1236b7b9
...
...
@@ -12,7 +12,7 @@ class PluginListCtrl extends PanelCtrl {
panelDefaults
=
{};
/** @ngInject */
constructor
(
$scope
,
$injector
,
private
backendSrv
,
private
$location
)
{
constructor
(
$scope
,
$injector
,
private
backendSrv
)
{
super
(
$scope
,
$injector
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
...
...
public/app/plugins/panel/singlestat/module.ts
View file @
1236b7b9
...
...
@@ -77,7 +77,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
};
/** @ngInject */
constructor
(
$scope
,
$injector
,
private
$location
,
private
linkSrv
)
{
constructor
(
$scope
,
$injector
,
private
linkSrv
)
{
super
(
$scope
,
$injector
);
_
.
defaults
(
this
.
panel
,
this
.
panelDefaults
);
...
...
public/app/routes/ReactContainer.tsx
View file @
1236b7b9
...
...
@@ -29,6 +29,7 @@ export function reactContainer($route, $location, backendSrv: BackendSrv, dataso
const
props
=
{
backendSrv
:
backendSrv
,
datasourceSrv
:
datasourceSrv
,
routeParams
:
$route
.
current
.
params
,
};
ReactDOM
.
render
(
WrapInProvider
(
store
,
component
,
props
),
elem
[
0
]);
...
...
public/app/routes/routes.ts
View file @
1236b7b9
...
...
@@ -111,7 +111,7 @@ export function setupAngularRoutes($routeProvider, $locationProvider) {
controller
:
'FolderDashboardsCtrl'
,
controllerAs
:
'ctrl'
,
})
.
when
(
'/explore'
,
{
.
when
(
'/explore
/:initial?
'
,
{
template
:
'<react-container />'
,
resolve
:
{
component
:
()
=>
import
(
/* webpackChunkName: "explore" */
'app/containers/Explore/Explore'
),
...
...
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