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
be172d3e
Commit
be172d3e
authored
Jan 12, 2019
by
David Kaltschmidt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Save state in URL and fix tests
parent
68c039b2
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
122 additions
and
96 deletions
+122
-96
public/app/core/utils/explore.test.ts
+22
-50
public/app/core/utils/explore.ts
+1
-6
public/app/features/explore/Explore.tsx
+8
-9
public/app/features/explore/Wrapper.tsx
+27
-21
public/app/features/explore/state/actions.ts
+51
-9
public/app/features/explore/state/reducers.ts
+13
-1
No files found.
public/app/core/utils/explore.test.ts
View file @
be172d3e
...
...
@@ -6,26 +6,13 @@ import {
clearHistory
,
hasNonEmptyQuery
,
}
from
'./explore'
;
import
{
ExploreState
}
from
'app/types/explore'
;
import
{
Explore
Url
State
}
from
'app/types/explore'
;
import
store
from
'app/core/store'
;
const
DEFAULT_EXPLORE_STATE
:
ExploreState
=
{
const
DEFAULT_EXPLORE_STATE
:
Explore
Url
State
=
{
datasource
:
null
,
datasourceError
:
null
,
datasourceLoading
:
null
,
datasourceMissing
:
false
,
exploreDatasources
:
[],
graphInterval
:
1000
,
history
:
[],
initialQueries
:
[],
queryTransactions
:
[],
queries
:
[],
range
:
DEFAULT_RANGE
,
showingGraph
:
true
,
showingLogs
:
true
,
showingTable
:
true
,
supportsGraph
:
null
,
supportsLogs
:
null
,
supportsTable
:
null
,
};
describe
(
'state functions'
,
()
=>
{
...
...
@@ -68,21 +55,19 @@ describe('state functions', () => {
it
(
'returns url parameter value for a state object'
,
()
=>
{
const
state
=
{
...
DEFAULT_EXPLORE_STATE
,
initialDatasource
:
'foo'
,
range
:
{
from
:
'now-5h'
,
to
:
'now'
,
},
initialQueries
:
[
datasource
:
'foo'
,
queries
:
[
{
refId
:
'1'
,
expr
:
'metric{test="a/b"}'
,
},
{
refId
:
'2'
,
expr
:
'super{foo="x/z"}'
,
},
],
range
:
{
from
:
'now-5h'
,
to
:
'now'
,
},
};
expect
(
serializeStateToUrlParam
(
state
)).
toBe
(
'{"datasource":"foo","queries":[{"expr":"metric{test=
\\
"a/b
\\
"}"},'
+
...
...
@@ -93,21 +78,19 @@ describe('state functions', () => {
it
(
'returns url parameter value for a state object'
,
()
=>
{
const
state
=
{
...
DEFAULT_EXPLORE_STATE
,
initialDatasource
:
'foo'
,
range
:
{
from
:
'now-5h'
,
to
:
'now'
,
},
initialQueries
:
[
datasource
:
'foo'
,
queries
:
[
{
refId
:
'1'
,
expr
:
'metric{test="a/b"}'
,
},
{
refId
:
'2'
,
expr
:
'super{foo="x/z"}'
,
},
],
range
:
{
from
:
'now-5h'
,
to
:
'now'
,
},
};
expect
(
serializeStateToUrlParam
(
state
,
true
)).
toBe
(
'["now-5h","now","foo",{"expr":"metric{test=
\\
"a/b
\\
"}"},{"expr":"super{foo=
\\
"x/z
\\
"}"}]'
...
...
@@ -119,35 +102,24 @@ describe('state functions', () => {
it
(
'can parse the serialized state into the original state'
,
()
=>
{
const
state
=
{
...
DEFAULT_EXPLORE_STATE
,
initialDatasource
:
'foo'
,
range
:
{
from
:
'now - 5h'
,
to
:
'now'
,
},
initialQueries
:
[
datasource
:
'foo'
,
queries
:
[
{
refId
:
'1'
,
expr
:
'metric{test="a/b"}'
,
},
{
refId
:
'2'
,
expr
:
'super{foo="x/z"}'
,
},
],
range
:
{
from
:
'now - 5h'
,
to
:
'now'
,
},
};
const
serialized
=
serializeStateToUrlParam
(
state
);
const
parsed
=
parseUrlState
(
serialized
);
// Account for datasource vs datasourceName
const
{
datasource
,
queries
,
...
rest
}
=
parsed
;
const
resultState
=
{
...
rest
,
datasource
:
DEFAULT_EXPLORE_STATE
.
datasource
,
initialDatasource
:
datasource
,
initialQueries
:
queries
,
};
expect
(
state
).
toMatchObject
(
resultState
);
expect
(
state
).
toMatchObject
(
parsed
);
});
});
});
...
...
public/app/core/utils/explore.ts
View file @
be172d3e
...
...
@@ -142,7 +142,7 @@ export function buildQueryTransaction(
};
}
const
clearQueryKeys
:
((
query
:
DataQuery
)
=>
object
)
=
({
key
,
refId
,
...
rest
})
=>
rest
;
export
const
clearQueryKeys
:
((
query
:
DataQuery
)
=>
object
)
=
({
key
,
refId
,
...
rest
})
=>
rest
;
export
function
parseUrlState
(
initial
:
string
|
undefined
):
ExploreUrlState
{
if
(
initial
)
{
...
...
@@ -169,11 +169,6 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
}
export
function
serializeStateToUrlParam
(
urlState
:
ExploreUrlState
,
compact
?:
boolean
):
string
{
// const urlState: ExploreUrlState = {
// datasource: state.initialDatasource,
// queries: state.initialQueries.map(clearQueryKeys),
// range: state.range,
// };
if
(
compact
)
{
return
JSON
.
stringify
([
urlState
.
range
.
from
,
urlState
.
range
.
to
,
urlState
.
datasource
,
...
urlState
.
queries
]);
}
...
...
public/app/features/explore/Explore.tsx
View file @
be172d3e
...
...
@@ -13,6 +13,8 @@ import store from 'app/core/store';
import
{
LAST_USED_DATASOURCE_KEY
,
ensureQueries
,
DEFAULT_RANGE
}
from
'app/core/utils/explore'
;
import
{
DataSourcePicker
}
from
'app/core/components/Select/DataSourcePicker'
;
import
{
Emitter
}
from
'app/core/utils/emitter'
;
import
{
LogsModel
}
from
'app/core/logs_model'
;
import
TableModel
from
'app/core/table_model'
;
import
{
addQueryRow
,
...
...
@@ -45,8 +47,6 @@ import Table from './Table';
import
ErrorBoundary
from
'./ErrorBoundary'
;
import
{
Alert
}
from
'./Error'
;
import
TimePicker
,
{
parseTime
}
from
'./TimePicker'
;
import
{
LogsModel
}
from
'app/core/logs_model'
;
import
TableModel
from
'app/core/table_model'
;
interface
ExploreProps
{
StartPage
?:
any
;
...
...
@@ -74,6 +74,7 @@ interface ExploreProps {
initialDatasource
?:
string
;
initialQueries
:
DataQuery
[];
initializeExplore
:
typeof
initializeExplore
;
initialized
:
boolean
;
logsHighlighterExpressions
?:
string
[];
logsResult
?:
LogsModel
;
modifyQueries
:
typeof
modifyQueries
;
...
...
@@ -149,8 +150,9 @@ export class Explore extends React.PureComponent<ExploreProps> {
}
async
componentDidMount
()
{
const
{
exploreId
,
split
,
urlState
}
=
this
.
props
;
if
(
!
split
)
{
const
{
exploreId
,
initialized
,
urlState
}
=
this
.
props
;
// Don't initialize on split, but need to initialize urlparameters when present
if
(
!
initialized
)
{
// Load URL state and parse range
const
{
datasource
,
queries
,
range
=
DEFAULT_RANGE
}
=
(
urlState
||
{})
as
ExploreUrlState
;
const
initialDatasource
=
datasource
||
store
.
get
(
LAST_USED_DATASOURCE_KEY
);
...
...
@@ -277,11 +279,6 @@ export class Explore extends React.PureComponent<ExploreProps> {
}
},
500
);
// saveState = () => {
// const { stateKey, onSaveState } = this.props;
// onSaveState(stateKey, this.cloneState());
// };
render
()
{
const
{
StartPage
,
...
...
@@ -478,6 +475,7 @@ function mapStateToProps(state: StoreState, { exploreId }) {
graphResult
,
initialDatasource
,
initialQueries
,
initialized
,
history
,
logsHighlighterExpressions
,
logsResult
,
...
...
@@ -504,6 +502,7 @@ function mapStateToProps(state: StoreState, { exploreId }) {
graphResult
,
initialDatasource
,
initialQueries
,
initialized
,
history
,
logsHighlighterExpressions
,
logsResult
,
...
...
public/app/features/explore/Wrapper.tsx
View file @
be172d3e
...
...
@@ -3,51 +3,56 @@ import { hot } from 'react-hot-loader';
import
{
connect
}
from
'react-redux'
;
import
{
updateLocation
}
from
'app/core/actions'
;
// import { serializeStateToUrlParam, parseUrlState } from 'app/core/utils/explore';
import
{
StoreState
}
from
'app/types'
;
import
{
ExploreId
}
from
'app/types/explore'
;
import
{
ExploreId
,
ExploreUrlState
}
from
'app/types/explore'
;
import
{
parseUrlState
}
from
'app/core/utils/explore'
;
import
{
initializeExploreSplit
}
from
'./state/actions'
;
import
ErrorBoundary
from
'./ErrorBoundary'
;
import
Explore
from
'./Explore'
;
interface
WrapperProps
{
backendSrv
?:
any
;
datasourceSrv
?:
any
;
initializeExploreSplit
:
typeof
initializeExploreSplit
;
split
:
boolean
;
updateLocation
:
typeof
updateLocation
;
//
urlStates: { [key: string]: string };
urlStates
:
{
[
key
:
string
]:
string
};
}
export
class
Wrapper
extends
Component
<
WrapperProps
>
{
// urlStates: { [key: string]: string };
initialSplit
:
boolean
;
urlStates
:
{
[
key
:
string
]:
ExploreUrlState
};
constructor
(
props
:
WrapperProps
)
{
super
(
props
);
// this.urlStates = props.urlStates;
this
.
urlStates
=
{};
const
{
left
,
right
}
=
props
.
urlStates
;
if
(
props
.
urlStates
.
left
)
{
this
.
urlStates
.
leftState
=
parseUrlState
(
left
);
}
if
(
props
.
urlStates
.
right
)
{
this
.
urlStates
.
rightState
=
parseUrlState
(
right
);
this
.
initialSplit
=
true
;
}
}
// onSaveState = (key: string, state: ExploreState) => {
// const urlState = serializeStateToUrlParam(state, true);
// this.urlStates[key] = urlState;
// this.props.updateLocation({
// query: this.urlStates,
// });
// };
componentDidMount
()
{
if
(
this
.
initialSplit
)
{
this
.
props
.
initializeExploreSplit
();
}
}
render
()
{
const
{
split
}
=
this
.
props
;
// State overrides for props from first Explore
// const urlStateLeft = parseUrlState(this.urlStates[STATE_KEY_LEFT]);
// const urlStateRight = parseUrlState(this.urlStates[STATE_KEY_RIGHT]);
const
{
leftState
,
rightState
}
=
this
.
urlStates
;
return
(
<
div
className=
"explore-wrapper"
>
<
ErrorBoundary
>
<
Explore
exploreId=
{
ExploreId
.
left
}
/>
<
Explore
exploreId=
{
ExploreId
.
left
}
urlState=
{
leftState
}
/>
</
ErrorBoundary
>
{
split
&&
(
<
ErrorBoundary
>
<
Explore
exploreId=
{
ExploreId
.
right
}
/>
<
Explore
exploreId=
{
ExploreId
.
right
}
urlState=
{
rightState
}
/>
</
ErrorBoundary
>
)
}
</
div
>
...
...
@@ -56,12 +61,13 @@ export class Wrapper extends Component<WrapperProps> {
}
const
mapStateToProps
=
(
state
:
StoreState
)
=>
{
// urlStates: state.location.query,
const
urlStates
=
state
.
location
.
query
;
const
{
split
}
=
state
.
explore
;
return
{
split
};
return
{
split
,
urlStates
};
};
const
mapDispatchToProps
=
{
initializeExploreSplit
,
updateLocation
,
};
...
...
public/app/features/explore/state/actions.ts
View file @
be172d3e
...
...
@@ -4,14 +4,17 @@ import { RawTimeRange, TimeRange } from '@grafana/ui';
import
{
LAST_USED_DATASOURCE_KEY
,
clearQueryKeys
,
ensureQueries
,
generateEmptyQuery
,
hasNonEmptyQuery
,
makeTimeSeriesList
,
updateHistory
,
buildQueryTransaction
,
serializeStateToUrlParam
,
}
from
'app/core/utils/explore'
;
import
{
updateLocation
}
from
'app/core/actions'
;
import
store
from
'app/core/store'
;
import
{
DataSourceSelectItem
}
from
'app/types/datasources'
;
import
{
DataQuery
,
StoreState
}
from
'app/types'
;
...
...
@@ -25,6 +28,7 @@ import {
QueryTransaction
,
QueryHint
,
QueryHintGetter
,
ExploreUrlState
,
}
from
'app/types/explore'
;
import
{
Emitter
}
from
'app/core/core'
;
import
{
ExploreItemState
}
from
'./reducers'
;
...
...
@@ -44,6 +48,7 @@ export enum ActionTypes {
ClickTableButton
=
'CLICK_TABLE_BUTTON'
,
HighlightLogsExpression
=
'HIGHLIGHT_LOGS_EXPRESSION'
,
InitializeExplore
=
'INITIALIZE_EXPLORE'
,
InitializeExploreSplit
=
'INITIALIZE_EXPLORE_SPLIT'
,
LoadDatasourceFailure
=
'LOAD_DATASOURCE_FAILURE'
,
LoadDatasourceMissing
=
'LOAD_DATASOURCE_MISSING'
,
LoadDatasourcePending
=
'LOAD_DATASOURCE_PENDING'
,
...
...
@@ -58,6 +63,7 @@ export enum ActionTypes {
ScanRange
=
'SCAN_RANGE'
,
ScanStart
=
'SCAN_START'
,
ScanStop
=
'SCAN_STOP'
,
StateSave
=
'STATE_SAVE'
,
}
export
interface
AddQueryRowAction
{
...
...
@@ -123,6 +129,12 @@ export interface ClickTableButtonAction {
exploreId
:
ExploreId
;
}
export
interface
HighlightLogsExpressionAction
{
type
:
ActionTypes
.
HighlightLogsExpression
;
exploreId
:
ExploreId
;
expressions
:
string
[];
}
export
interface
InitializeExploreAction
{
type
:
ActionTypes
.
InitializeExplore
;
exploreId
:
ExploreId
;
...
...
@@ -134,10 +146,8 @@ export interface InitializeExploreAction {
range
:
RawTimeRange
;
}
export
interface
HighlightLogsExpressionAction
{
type
:
ActionTypes
.
HighlightLogsExpression
;
exploreId
:
ExploreId
;
expressions
:
string
[];
export
interface
InitializeExploreSplitAction
{
type
:
ActionTypes
.
InitializeExploreSplit
;
}
export
interface
LoadDatasourceFailureAction
{
...
...
@@ -224,6 +234,10 @@ export interface ScanStopAction {
exploreId
:
ExploreId
;
}
export
interface
StateSaveAction
{
type
:
ActionTypes
.
StateSave
;
}
export
type
Action
=
|
AddQueryRowAction
|
ChangeQueryAction
...
...
@@ -238,6 +252,7 @@ export type Action =
|
ClickTableButtonAction
|
HighlightLogsExpressionAction
|
InitializeExploreAction
|
InitializeExploreSplitAction
|
LoadDatasourceFailureAction
|
LoadDatasourceMissingAction
|
LoadDatasourcePendingAction
...
...
@@ -301,15 +316,14 @@ export function clickClear(exploreId: ExploreId): ThunkResult<void> {
return
dispatch
=>
{
dispatch
(
scanStop
(
exploreId
));
dispatch
({
type
:
ActionTypes
.
ClickClear
,
exploreId
});
// TODO save state
dispatch
(
stateSave
());
};
}
export
function
clickCloseSplit
():
ThunkResult
<
void
>
{
return
dispatch
=>
{
dispatch
({
type
:
ActionTypes
.
ClickCloseSplit
});
// When closing split, remove URL state for split part
// TODO save state
dispatch
(
stateSave
());
};
}
...
...
@@ -353,7 +367,7 @@ export function clickSplit(): ThunkResult<void> {
initialQueries
:
leftState
.
modifiedQueries
.
slice
(),
};
dispatch
({
type
:
ActionTypes
.
ClickSplit
,
itemState
});
// TODO save state
dispatch
(
stateSave
());
};
}
...
...
@@ -412,6 +426,12 @@ export function initializeExplore(
};
}
export
function
initializeExploreSplit
()
{
return
async
dispatch
=>
{
dispatch
({
type
:
ActionTypes
.
InitializeExploreSplit
});
};
}
export
const
loadDatasourceFailure
=
(
exploreId
:
ExploreId
,
error
:
string
):
LoadDatasourceFailureAction
=>
({
type
:
ActionTypes
.
LoadDatasourceFailure
,
exploreId
,
...
...
@@ -733,7 +753,7 @@ export function runQueries(exploreId: ExploreId) {
if
(
showingLogs
&&
supportsLogs
)
{
dispatch
(
runQueriesForType
(
exploreId
,
'Logs'
,
{
interval
,
format
:
'logs'
}));
}
// TODO save state
dispatch
(
stateSave
());
};
}
...
...
@@ -792,3 +812,25 @@ export function scanStart(exploreId: ExploreId, scanner: RangeScanner): ThunkRes
export
function
scanStop
(
exploreId
:
ExploreId
):
ScanStopAction
{
return
{
type
:
ActionTypes
.
ScanStop
,
exploreId
};
}
export
function
stateSave
()
{
return
(
dispatch
,
getState
)
=>
{
const
{
left
,
right
,
split
}
=
getState
().
explore
;
const
urlStates
:
{
[
index
:
string
]:
string
}
=
{};
const
leftUrlState
:
ExploreUrlState
=
{
datasource
:
left
.
datasourceInstance
.
name
,
queries
:
left
.
modifiedQueries
.
map
(
clearQueryKeys
),
range
:
left
.
range
,
};
urlStates
.
left
=
serializeStateToUrlParam
(
leftUrlState
,
true
);
if
(
split
)
{
const
rightUrlState
:
ExploreUrlState
=
{
datasource
:
right
.
datasourceInstance
.
name
,
queries
:
right
.
modifiedQueries
.
map
(
clearQueryKeys
),
range
:
right
.
range
,
};
urlStates
.
right
=
serializeStateToUrlParam
(
rightUrlState
,
true
);
}
dispatch
(
updateLocation
({
query
:
urlStates
}));
};
}
public/app/features/explore/state/reducers.ts
View file @
be172d3e
...
...
@@ -36,6 +36,7 @@ export interface ExploreItemState {
history
:
HistoryItem
[];
initialDatasource
?:
string
;
initialQueries
:
DataQuery
[];
initialized
:
boolean
;
logsHighlighterExpressions
?:
string
[];
logsResult
?:
LogsModel
;
modifiedQueries
:
DataQuery
[];
...
...
@@ -74,6 +75,7 @@ const makeExploreItemState = (): ExploreItemState => ({
exploreDatasources
:
[],
history
:
[],
initialQueries
:
[],
initialized
:
false
,
modifiedQueries
:
[],
queryTransactions
:
[],
queryIntervals
:
{
interval
:
'15s'
,
intervalMs
:
DEFAULT_GRAPH_INTERVAL
},
...
...
@@ -89,7 +91,7 @@ const makeExploreItemState = (): ExploreItemState => ({
});
const
initialExploreState
:
ExploreState
=
{
split
:
false
,
split
:
null
,
left
:
makeExploreItemState
(),
right
:
makeExploreItemState
(),
};
...
...
@@ -236,6 +238,7 @@ const itemReducer = (state, action: Action): ExploreItemState => {
range
,
initialDatasource
:
action
.
datasource
,
initialQueries
:
action
.
queries
,
initialized
:
true
,
modifiedQueries
:
action
.
queries
.
slice
(),
};
}
...
...
@@ -436,6 +439,13 @@ export const exploreReducer = (state = initialExploreState, action: Action): Exp
right
:
action
.
itemState
,
};
}
case
ActionTypes
.
InitializeExploreSplit
:
{
return
{
...
state
,
split
:
true
,
};
}
}
const
{
exploreId
}
=
action
as
any
;
...
...
@@ -447,6 +457,8 @@ export const exploreReducer = (state = initialExploreState, action: Action): Exp
};
}
console
.
error
(
'Unhandled action'
,
action
.
type
);
return
state
;
};
...
...
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