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
758ec4bc
Unverified
Commit
758ec4bc
authored
Oct 30, 2018
by
David
Committed by
GitHub
Oct 30, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #13844 from grafana/davkal/explore-empty-page
Explore: Pluggable components from datasource plugins
parents
45d75164
cf19ecc8
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
244 additions
and
97 deletions
+244
-97
public/app/features/explore/Explore.tsx
+57
-38
public/app/features/explore/QueryField.tsx
+21
-19
public/app/features/explore/QueryRows.tsx
+6
-5
public/app/features/explore/QueryTransactionStatus.tsx
+8
-8
public/app/features/plugins/datasource_srv.ts
+4
-2
public/app/plugins/datasource/prometheus/components/PromCheatSheet.tsx
+35
-0
public/app/plugins/datasource/prometheus/components/PromQueryField.test.tsx
+0
-0
public/app/plugins/datasource/prometheus/components/PromQueryField.tsx
+16
-22
public/app/plugins/datasource/prometheus/components/PromStart.tsx
+60
-0
public/app/plugins/datasource/prometheus/module.ts
+5
-0
public/app/types/datasources.ts
+5
-1
public/app/types/explore.ts
+1
-0
public/app/types/plugins.ts
+8
-0
public/sass/pages/_explore.scss
+17
-1
scripts/webpack/webpack.common.js
+1
-1
No files found.
public/app/features/explore/Explore.tsx
View file @
758ec4bc
...
...
@@ -4,6 +4,7 @@ import Select from 'react-select';
import
_
from
'lodash'
;
import
{
ExploreState
,
ExploreUrlState
,
HistoryItem
,
Query
,
QueryTransaction
,
ResultType
}
from
'app/types/explore'
;
import
{
RawTimeRange
}
from
'app/types/series'
;
import
kbn
from
'app/core/utils/kbn'
;
import
colors
from
'app/core/utils/colors'
;
import
store
from
'app/core/store'
;
...
...
@@ -16,14 +17,14 @@ import IndicatorsContainer from 'app/core/components/Picker/IndicatorsContainer'
import
NoOptionsMessage
from
'app/core/components/Picker/NoOptionsMessage'
;
import
TableModel
,
{
mergeTablesIntoModel
}
from
'app/core/table_model'
;
import
ErrorBoundary
from
'./ErrorBoundary'
;
import
QueryRows
from
'./QueryRows'
;
import
Graph
from
'./Graph'
;
import
Logs
from
'./Logs'
;
import
Table
from
'./Table'
;
import
ErrorBoundary
from
'./ErrorBoundary'
;
import
TimePicker
from
'./TimePicker'
;
import
{
ensureQueries
,
generateQueryKey
,
hasQuery
}
from
'./utils/query'
;
import
{
RawTimeRange
}
from
'app/types/seri
es'
;
import
{
DataSource
}
from
'app/types/datasourc
es'
;
const
MAX_HISTORY_ITEMS
=
100
;
...
...
@@ -148,7 +149,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
}
}
async
setDatasource
(
datasource
)
{
async
setDatasource
(
datasource
:
DataSource
)
{
const
supportsGraph
=
datasource
.
meta
.
metrics
;
const
supportsLogs
=
datasource
.
meta
.
logs
;
const
supportsTable
=
datasource
.
meta
.
metrics
;
...
...
@@ -176,8 +177,12 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
query
:
this
.
queryExpressions
[
i
],
}));
// Custom components
const
StartPage
=
datasource
.
pluginExports
.
ExploreStartPage
;
this
.
setState
(
{
StartPage
,
datasource
,
datasourceError
,
history
,
...
...
@@ -330,6 +335,13 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
);
};
// Use this in help pages to set page to a single query
onClickQuery
=
query
=>
{
const
nextQueries
=
[{
query
,
key
:
generateQueryKey
()
}];
this
.
queryExpressions
=
nextQueries
.
map
(
q
=>
q
.
query
);
this
.
setState
({
queries
:
nextQueries
},
this
.
onSubmit
);
};
onClickSplit
=
()
=>
{
const
{
onChangeSplit
}
=
this
.
props
;
if
(
onChangeSplit
)
{
...
...
@@ -721,6 +733,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
render
()
{
const
{
position
,
split
}
=
this
.
props
;
const
{
StartPage
,
datasource
,
datasourceError
,
datasourceLoading
,
...
...
@@ -760,6 +773,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
queryTransactions
.
filter
(
qt
=>
qt
.
resultType
===
'Logs'
&&
qt
.
done
&&
qt
.
result
).
map
(
qt
=>
qt
.
result
)
);
const
loading
=
queryTransactions
.
some
(
qt
=>
!
qt
.
done
);
const
showStartPages
=
StartPage
&&
queryTransactions
.
length
===
0
;
return
(
<
div
className=
{
exploreClass
}
ref=
{
this
.
getRef
}
>
...
...
@@ -847,43 +861,48 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
supportsLogs=
{
supportsLogs
}
transactions=
{
queryTransactions
}
/>
<
div
className=
"result-options"
>
{
supportsGraph
?
(
<
button
className=
{
`btn toggle-btn ${graphButtonActive}`
}
onClick=
{
this
.
onClickGraphButton
}
>
Graph
</
button
>
)
:
null
}
{
supportsTable
?
(
<
button
className=
{
`btn toggle-btn ${tableButtonActive}`
}
onClick=
{
this
.
onClickTableButton
}
>
Table
</
button
>
)
:
null
}
{
supportsLogs
?
(
<
button
className=
{
`btn toggle-btn ${logsButtonActive}`
}
onClick=
{
this
.
onClickLogsButton
}
>
Logs
</
button
>
)
:
null
}
</
div
>
<
main
className=
"m-t-2"
>
<
ErrorBoundary
>
{
supportsGraph
&&
showingGraph
&&
(
<
Graph
data=
{
graphResult
}
height=
{
graphHeight
}
loading=
{
graphLoading
}
id=
{
`explore-graph-${position}`
}
range=
{
graphRange
}
split=
{
split
}
/>
)
}
{
supportsTable
&&
showingTable
?
(
<
div
className=
"panel-container m-t-2"
>
<
Table
data=
{
tableResult
}
loading=
{
tableLoading
}
onClickCell=
{
this
.
onClickTableCell
}
/>
</
div
>
)
:
null
}
{
supportsLogs
&&
showingLogs
?
<
Logs
data=
{
logsResult
}
loading=
{
logsLoading
}
/>
:
null
}
{
showStartPages
&&
<
StartPage
onClickQuery=
{
this
.
onClickQuery
}
/>
}
{
!
showStartPages
&&
(
<>
<
div
className=
"result-options"
>
{
supportsGraph
?
(
<
button
className=
{
`btn toggle-btn ${graphButtonActive}`
}
onClick=
{
this
.
onClickGraphButton
}
>
Graph
</
button
>
)
:
null
}
{
supportsTable
?
(
<
button
className=
{
`btn toggle-btn ${tableButtonActive}`
}
onClick=
{
this
.
onClickTableButton
}
>
Table
</
button
>
)
:
null
}
{
supportsLogs
?
(
<
button
className=
{
`btn toggle-btn ${logsButtonActive}`
}
onClick=
{
this
.
onClickLogsButton
}
>
Logs
</
button
>
)
:
null
}
</
div
>
{
supportsGraph
&&
showingGraph
&&
(
<
Graph
data=
{
graphResult
}
height=
{
graphHeight
}
loading=
{
graphLoading
}
id=
{
`explore-graph-${position}`
}
range=
{
graphRange
}
split=
{
split
}
/>
)
}
{
supportsTable
&&
showingTable
?
(
<
div
className=
"panel-container m-t-2"
>
<
Table
data=
{
tableResult
}
loading=
{
tableLoading
}
onClickCell=
{
this
.
onClickTableCell
}
/>
</
div
>
)
:
null
}
{
supportsLogs
&&
showingLogs
?
<
Logs
data=
{
logsResult
}
loading=
{
logsLoading
}
/>
:
null
}
</>
)
}
</
ErrorBoundary
>
</
main
>
</
div
>
...
...
public/app/features/explore/QueryField.tsx
View file @
758ec4bc
...
...
@@ -27,7 +27,7 @@ function hasSuggestions(suggestions: CompletionItemGroup[]): boolean {
return
suggestions
&&
suggestions
.
length
>
0
;
}
interface
Typeahead
FieldProps
{
interface
Query
FieldProps
{
additionalPlugins
?:
any
[];
cleanText
?:
(
text
:
string
)
=>
string
;
initialValue
:
string
|
null
;
...
...
@@ -35,14 +35,14 @@ interface TypeaheadFieldProps {
onFocus
?:
()
=>
void
;
onTypeahead
?:
(
typeahead
:
TypeaheadInput
)
=>
TypeaheadOutput
;
onValueChanged
?:
(
value
:
Value
)
=>
void
;
onWillApplySuggestion
?:
(
suggestion
:
string
,
state
:
Typeahead
FieldState
)
=>
string
;
onWillApplySuggestion
?:
(
suggestion
:
string
,
state
:
Query
FieldState
)
=>
string
;
placeholder
?:
string
;
portalOrigin
?:
string
;
syntax
?:
string
;
syntaxLoaded
?:
boolean
;
}
export
interface
Typeahead
FieldState
{
export
interface
Query
FieldState
{
suggestions
:
CompletionItemGroup
[];
typeaheadContext
:
string
|
null
;
typeaheadIndex
:
number
;
...
...
@@ -60,7 +60,7 @@ export interface TypeaheadInput {
wrapperNode
:
Element
;
}
class
QueryField
extends
React
.
PureComponent
<
TypeaheadFieldProps
,
Typeahead
FieldState
>
{
export
class
QueryField
extends
React
.
PureComponent
<
QueryFieldProps
,
Query
FieldState
>
{
menuEl
:
HTMLElement
|
null
;
placeholdersBuffer
:
PlaceholdersBuffer
;
plugins
:
any
[];
...
...
@@ -72,7 +72,7 @@ class QueryField extends React.PureComponent<TypeaheadFieldProps, TypeaheadField
this
.
placeholdersBuffer
=
new
PlaceholdersBuffer
(
props
.
initialValue
||
''
);
// Base plugins
this
.
plugins
=
[
ClearPlugin
(),
NewlinePlugin
(),
...
props
.
additionalPlugins
];
this
.
plugins
=
[
ClearPlugin
(),
NewlinePlugin
(),
...
props
.
additionalPlugins
]
.
filter
(
p
=>
p
)
;
this
.
state
=
{
suggestions
:
[],
...
...
@@ -102,7 +102,7 @@ class QueryField extends React.PureComponent<TypeaheadFieldProps, TypeaheadField
}
}
componentWillReceiveProps
(
nextProps
:
Typeahead
FieldProps
)
{
componentWillReceiveProps
(
nextProps
:
Query
FieldProps
)
{
if
(
nextProps
.
syntaxLoaded
&&
!
this
.
props
.
syntaxLoaded
)
{
// Need a bogus edit to re-render the editor after syntax has fully loaded
const
change
=
this
.
state
.
value
...
...
@@ -434,19 +434,21 @@ class QueryField extends React.PureComponent<TypeaheadFieldProps, TypeaheadField
render
()
{
return
(
<
div
className=
"slate-query-field"
>
{
this
.
renderMenu
()
}
<
Editor
autoCorrect=
{
false
}
onBlur=
{
this
.
handleBlur
}
onKeyDown=
{
this
.
onKeyDown
}
onChange=
{
this
.
onChange
}
onFocus=
{
this
.
handleFocus
}
placeholder=
{
this
.
props
.
placeholder
}
plugins=
{
this
.
plugins
}
spellCheck=
{
false
}
value=
{
this
.
state
.
value
}
/>
<
div
className=
"slate-query-field-wrapper"
>
<
div
className=
"slate-query-field"
>
{
this
.
renderMenu
()
}
<
Editor
autoCorrect=
{
false
}
onBlur=
{
this
.
handleBlur
}
onKeyDown=
{
this
.
onKeyDown
}
onChange=
{
this
.
onChange
}
onFocus=
{
this
.
handleFocus
}
placeholder=
{
this
.
props
.
placeholder
}
plugins=
{
this
.
plugins
}
spellCheck=
{
false
}
value=
{
this
.
state
.
value
}
/>
</
div
>
</
div
>
);
}
...
...
public/app/features/explore/QueryRows.tsx
View file @
758ec4bc
...
...
@@ -2,9 +2,9 @@ import React, { PureComponent } from 'react';
import
{
QueryTransaction
,
HistoryItem
,
Query
,
QueryHint
}
from
'app/types/explore'
;
// TODO make this datasource-plugin-dependent
import
Query
Field
from
'./PromQueryField
'
;
import
QueryTransactions
from
'./QueryTransaction
s'
;
import
DefaultQueryField
from
'./QueryField'
;
import
Query
TransactionStatus
from
'./QueryTransactionStatus
'
;
import
{
DataSource
}
from
'app/type
s'
;
function
getFirstHintFromTransactions
(
transactions
:
QueryTransaction
[]):
QueryHint
{
const
transaction
=
transactions
.
find
(
qt
=>
qt
.
hints
&&
qt
.
hints
.
length
>
0
);
...
...
@@ -24,7 +24,7 @@ interface QueryRowEventHandlers {
interface
QueryRowCommonProps
{
className
?:
string
;
datasource
:
any
;
datasource
:
DataSource
;
history
:
HistoryItem
[];
// Temporarily
supportsLogs
?:
boolean
;
...
...
@@ -82,10 +82,11 @@ class QueryRow extends PureComponent<QueryRowProps> {
const
transactionWithError
=
transactions
.
find
(
t
=>
t
.
error
!==
undefined
);
const
hint
=
getFirstHintFromTransactions
(
transactions
);
const
queryError
=
transactionWithError
?
transactionWithError
.
error
:
null
;
const
QueryField
=
datasource
.
pluginExports
.
ExploreQueryField
||
DefaultQueryField
;
return
(
<
div
className=
"query-row"
>
<
div
className=
"query-row-status"
>
<
QueryTransactions
transactions=
{
transactions
}
/>
<
QueryTransaction
Statu
s
transactions=
{
transactions
}
/>
</
div
>
<
div
className=
"query-row-field"
>
<
QueryField
...
...
public/app/features/explore/QueryTransactions.tsx
→
public/app/features/explore/QueryTransaction
Statu
s.tsx
View file @
758ec4bc
import
React
,
{
PureComponent
}
from
'react'
;
import
{
QueryTransaction
as
QueryTransactionModel
}
from
'app/types/explore'
;
import
{
QueryTransaction
}
from
'app/types/explore'
;
import
ElapsedTime
from
'./ElapsedTime'
;
function
formatLatency
(
value
)
{
return
`
${(
value
/
1000
).
toFixed
(
1
)}
s`
;
}
interface
QueryTransactionProps
{
transaction
:
QueryTransaction
Model
;
interface
QueryTransaction
StatusItem
Props
{
transaction
:
QueryTransaction
;
}
class
QueryTransaction
extends
PureComponent
<
QueryTransaction
Props
>
{
class
QueryTransaction
StatusItem
extends
PureComponent
<
QueryTransactionStatusItem
Props
>
{
render
()
{
const
{
transaction
}
=
this
.
props
;
const
className
=
transaction
.
done
?
'query-transaction'
:
'query-transaction query-transaction--loading'
;
...
...
@@ -26,16 +26,16 @@ class QueryTransaction extends PureComponent<QueryTransactionProps> {
}
}
interface
QueryTransactionsProps
{
transactions
:
QueryTransaction
Model
[];
interface
QueryTransaction
Statu
sProps
{
transactions
:
QueryTransaction
[];
}
export
default
class
QueryTransaction
s
extends
PureComponent
<
QueryTransaction
sProps
>
{
export
default
class
QueryTransaction
Status
extends
PureComponent
<
QueryTransactionStatu
sProps
>
{
render
()
{
const
{
transactions
}
=
this
.
props
;
return
(
<
div
className=
"query-transactions"
>
{
transactions
.
map
((
t
,
i
)
=>
<
QueryTransaction
key=
{
`${t.query}:${t.resultType}`
}
transaction=
{
t
}
/>)
}
{
transactions
.
map
((
t
,
i
)
=>
<
QueryTransaction
StatusItem
key=
{
`${t.query}:${t.resultType}`
}
transaction=
{
t
}
/>)
}
</
div
>
);
}
...
...
public/app/features/plugins/datasource_srv.ts
View file @
758ec4bc
...
...
@@ -8,9 +8,10 @@ import { importPluginModule } from './plugin_loader';
// Types
import
{
DataSourceApi
}
from
'app/types/series'
;
import
{
DataSource
}
from
'app/types'
;
export
class
DatasourceSrv
{
datasources
:
any
;
datasources
:
{
[
name
:
string
]:
DataSource
}
;
/** @ngInject */
constructor
(
private
$q
,
private
$injector
,
private
$rootScope
,
private
templateSrv
)
{
...
...
@@ -61,9 +62,10 @@ export class DatasourceSrv {
throw
new
Error
(
'Plugin module is missing Datasource constructor'
);
}
const
instance
=
this
.
$injector
.
instantiate
(
plugin
.
Datasource
,
{
instanceSettings
:
dsConfig
});
const
instance
:
DataSource
=
this
.
$injector
.
instantiate
(
plugin
.
Datasource
,
{
instanceSettings
:
dsConfig
});
instance
.
meta
=
pluginDef
;
instance
.
name
=
name
;
instance
.
pluginExports
=
plugin
;
this
.
datasources
[
name
]
=
instance
;
deferred
.
resolve
(
instance
);
})
...
...
public/app/plugins/datasource/prometheus/components/PromCheatSheet.tsx
0 → 100644
View file @
758ec4bc
import
React
from
'react'
;
const
CHEAT_SHEET_ITEMS
=
[
{
title
:
'Request Rate'
,
expression
:
'rate(http_request_total[5m])'
,
label
:
'Given an HTTP request counter, this query calculates the per-second average request rate over the last 5 minutes.'
,
},
{
title
:
'95th Percentile of Request Latencies'
,
expression
:
'histogram_quantile(0.95, sum(rate(prometheus_http_request_duration_seconds_bucket[5m])) by (le))'
,
label
:
'Calculates the 95th percentile of HTTP request rate over 5 minute windows.'
,
},
{
title
:
'Alerts Firing'
,
expression
:
'sort_desc(sum(sum_over_time(ALERTS{alertstate="firing"}[24h])) by (alertname))'
,
label
:
'Sums up the alerts that have been firing over the last 24 hours.'
,
},
];
export
default
(
props
:
any
)
=>
(
<
div
>
<
h1
>
PromQL Cheat Sheet
</
h1
>
{
CHEAT_SHEET_ITEMS
.
map
(
item
=>
(
<
div
className=
"cheat-sheet-item"
key=
{
item
.
expression
}
>
<
div
className=
"cheat-sheet-item__title"
>
{
item
.
title
}
</
div
>
<
div
className=
"cheat-sheet-item__expression"
onClick=
{
e
=>
props
.
onClickQuery
(
item
.
expression
)
}
>
<
code
>
{
item
.
expression
}
</
code
>
</
div
>
<
div
className=
"cheat-sheet-item__label"
>
{
item
.
label
}
</
div
>
</
div
>
))
}
</
div
>
);
public/app/
features/explore
/PromQueryField.test.tsx
→
public/app/
plugins/datasource/prometheus/components
/PromQueryField.test.tsx
View file @
758ec4bc
File moved
public/app/
features/explore
/PromQueryField.tsx
→
public/app/
plugins/datasource/prometheus/components
/PromQueryField.tsx
View file @
758ec4bc
...
...
@@ -7,11 +7,10 @@ import Prism from 'prismjs';
import
{
TypeaheadOutput
}
from
'app/types/explore'
;
// dom also includes Element polyfills
import
{
getNextCharacter
,
getPreviousCousin
}
from
'./utils/dom'
;
import
BracesPlugin
from
'./slate-plugins/braces'
;
import
RunnerPlugin
from
'./slate-plugins/runner'
;
import
TypeaheadField
,
{
TypeaheadInput
,
TypeaheadFieldState
}
from
'./QueryField'
;
import
{
getNextCharacter
,
getPreviousCousin
}
from
'app/features/explore/utils/dom'
;
import
BracesPlugin
from
'app/features/explore/slate-plugins/braces'
;
import
RunnerPlugin
from
'app/features/explore/slate-plugins/runner'
;
import
TypeaheadField
,
{
TypeaheadInput
,
QueryFieldState
}
from
'app/features/explore/QueryField'
;
const
HISTOGRAM_GROUP
=
'__histograms__'
;
const
METRIC_MARK
=
'metric'
;
...
...
@@ -51,10 +50,7 @@ export function groupMetricsByPrefix(metrics: string[], delimiter = '_'): Cascad
return
[...
options
,
...
metricsOptions
];
}
export
function
willApplySuggestion
(
suggestion
:
string
,
{
typeaheadContext
,
typeaheadText
}:
TypeaheadFieldState
):
string
{
export
function
willApplySuggestion
(
suggestion
:
string
,
{
typeaheadContext
,
typeaheadText
}:
QueryFieldState
):
string
{
// Modify suggestion based on context
switch
(
typeaheadContext
)
{
case
'context-labels'
:
{
...
...
@@ -261,19 +257,17 @@ class PromQueryField extends React.PureComponent<PromQueryFieldProps, PromQueryF
)
}
</
div
>
<
div
className=
"prom-query-field-wrapper"
>
<
div
className=
"slate-query-field-wrapper"
>
<
TypeaheadField
additionalPlugins=
{
this
.
plugins
}
cleanText=
{
cleanText
}
initialValue=
{
initialQuery
}
onTypeahead=
{
this
.
onTypeahead
}
onWillApplySuggestion=
{
willApplySuggestion
}
onValueChanged=
{
this
.
onChangeQuery
}
placeholder=
"Enter a PromQL query"
portalOrigin=
"prometheus"
syntaxLoaded=
{
syntaxLoaded
}
/>
</
div
>
<
TypeaheadField
additionalPlugins=
{
this
.
plugins
}
cleanText=
{
cleanText
}
initialValue=
{
initialQuery
}
onTypeahead=
{
this
.
onTypeahead
}
onWillApplySuggestion=
{
willApplySuggestion
}
onValueChanged=
{
this
.
onChangeQuery
}
placeholder=
"Enter a PromQL query"
portalOrigin=
"prometheus"
syntaxLoaded=
{
syntaxLoaded
}
/>
{
error
?
<
div
className=
"prom-query-field-info text-error"
>
{
error
}
</
div
>
:
null
}
{
hint
?
(
<
div
className=
"prom-query-field-info text-warning"
>
...
...
public/app/plugins/datasource/prometheus/components/PromStart.tsx
0 → 100644
View file @
758ec4bc
import
React
,
{
PureComponent
}
from
'react'
;
import
classNames
from
'classnames'
;
import
PromCheatSheet
from
'./PromCheatSheet'
;
const
TAB_MENU_ITEMS
=
[
{
text
:
'Start'
,
id
:
'start'
,
icon
:
'fa fa-rocket'
,
},
];
export
default
class
PromStart
extends
PureComponent
<
any
,
{
active
:
string
}
>
{
state
=
{
active
:
'start'
,
};
onClickTab
=
active
=>
{
this
.
setState
({
active
});
};
render
()
{
const
{
active
}
=
this
.
state
;
const
customCss
=
''
;
return
(
<
div
style=
{
{
margin
:
'45px 0'
,
border
:
'1px solid #ddd'
,
borderRadius
:
5
}
}
>
<
div
className=
"page-header-canvas"
>
<
div
className=
"page-container"
>
<
div
className=
"page-header"
>
<
nav
>
<
ul
className=
{
`gf-tabs ${customCss}`
}
>
{
TAB_MENU_ITEMS
.
map
((
tab
,
idx
)
=>
{
const
tabClasses
=
classNames
({
'gf-tabs-link'
:
true
,
active
:
tab
.
id
===
active
,
});
return
(
<
li
className=
"gf-tabs-item"
key=
{
tab
.
id
}
>
<
a
className=
{
tabClasses
}
onClick=
{
()
=>
this
.
onClickTab
(
tab
.
id
)
}
>
<
i
className=
{
tab
.
icon
}
/>
{
tab
.
text
}
</
a
>
</
li
>
);
})
}
</
ul
>
</
nav
>
</
div
>
</
div
>
</
div
>
<
div
className=
"page-container page-body"
>
{
active
===
'start'
&&
<
PromCheatSheet
onClickQuery=
{
this
.
props
.
onClickQuery
}
/>
}
</
div
>
</
div
>
);
}
}
public/app/plugins/datasource/prometheus/module.ts
View file @
758ec4bc
...
...
@@ -2,6 +2,9 @@ import { PrometheusDatasource } from './datasource';
import
{
PrometheusQueryCtrl
}
from
'./query_ctrl'
;
import
{
PrometheusConfigCtrl
}
from
'./config_ctrl'
;
import
PrometheusStartPage
from
'./components/PromStart'
;
import
PromQueryField
from
'./components/PromQueryField'
;
class
PrometheusAnnotationsQueryCtrl
{
static
templateUrl
=
'partials/annotations.editor.html'
;
}
...
...
@@ -11,4 +14,6 @@ export {
PrometheusQueryCtrl
as
QueryCtrl
,
PrometheusConfigCtrl
as
ConfigCtrl
,
PrometheusAnnotationsQueryCtrl
as
AnnotationsQueryCtrl
,
PromQueryField
as
ExploreQueryField
,
PrometheusStartPage
as
ExploreStartPage
,
};
public/app/types/datasources.ts
View file @
758ec4bc
import
{
LayoutMode
}
from
'../core/components/LayoutSelector/LayoutSelector'
;
import
{
Plugin
}
from
'./plugins'
;
import
{
Plugin
,
PluginExports
,
PluginMeta
}
from
'./plugins'
;
export
interface
DataSource
{
id
:
number
;
...
...
@@ -16,6 +16,10 @@ export interface DataSource {
isDefault
:
boolean
;
jsonData
:
{
authType
:
string
;
defaultRegion
:
string
};
readOnly
:
boolean
;
meta
?:
PluginMeta
;
pluginExports
?:
PluginExports
;
init
?:
()
=>
void
;
testDatasource
?:
()
=>
Promise
<
any
>
;
}
export
interface
DataSourcesState
{
...
...
public/app/types/explore.ts
View file @
758ec4bc
...
...
@@ -146,6 +146,7 @@ export interface TextMatch {
}
export
interface
ExploreState
{
StartPage
?:
any
;
datasource
:
any
;
datasourceError
:
any
;
datasourceLoading
:
boolean
|
null
;
...
...
public/app/types/plugins.ts
View file @
758ec4bc
...
...
@@ -6,6 +6,8 @@ export interface PluginExports {
ConfigCtrl
?:
any
;
AnnotationsQueryCtrl
?:
any
;
PanelOptions
?:
any
;
ExploreQueryField
?:
any
;
ExploreStartPage
?:
any
;
}
export
interface
PanelPlugin
{
...
...
@@ -25,6 +27,12 @@ export interface PluginMeta {
name
:
string
;
info
:
PluginMetaInfo
;
includes
:
PluginInclude
[];
// Datasource-specific
metrics
?:
boolean
;
logs
?:
boolean
;
explore
?:
boolean
;
annotations
?:
boolean
;
}
export
interface
PluginInclude
{
...
...
public/sass/pages/_explore.scss
View file @
758ec4bc
...
...
@@ -52,7 +52,7 @@
}
.result-options
{
margin
-top
:
2
*
$panel-margin
;
margin
:
2
*
$panel-margin
0
;
}
.time-series-disclaimer
{
...
...
@@ -322,3 +322,19 @@
.ReactTable
.rt-tr
.rt-td
:last-child
{
text-align
:
right
;
}
// TODO Experimental
.cheat-sheet-item
{
margin
:
2
*
$panel-margin
0
;
width
:
50%
;
}
.cheat-sheet-item__title
{
font-size
:
$font-size-h3
;
}
.cheat-sheet-item__expression
{
margin
:
$panel-margin
/
2
0
;
cursor
:
pointer
;
}
scripts/webpack/webpack.common.js
View file @
758ec4bc
...
...
@@ -16,7 +16,7 @@ module.exports = {
publicPath
:
"public/build/"
,
},
resolve
:
{
extensions
:
[
'.ts'
,
'.tsx'
,
'.es6'
,
'.js'
,
'.json'
],
extensions
:
[
'.ts'
,
'.tsx'
,
'.es6'
,
'.js'
,
'.json'
,
'.svg'
],
alias
:
{
},
modules
:
[
...
...
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