mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #13540 from grafana/davkal/explore-compact-url-state
Explore: compact state URLs
This commit is contained in:
commit
352961b3d7
@ -36,14 +36,40 @@ describe('state functions', () => {
|
||||
range: DEFAULT_RANGE,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns a valid Explore state from URL parameter', () => {
|
||||
const paramValue =
|
||||
'%7B"datasource":"Local","queries":%5B%7B"query":"metric"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D';
|
||||
expect(parseUrlState(paramValue)).toMatchObject({
|
||||
datasource: 'Local',
|
||||
queries: [{ query: 'metric' }],
|
||||
range: {
|
||||
from: 'now-1h',
|
||||
to: 'now',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('returns a valid Explore state from a compact URL parameter', () => {
|
||||
const paramValue = '%5B"now-1h","now","Local","metric"%5D';
|
||||
expect(parseUrlState(paramValue)).toMatchObject({
|
||||
datasource: 'Local',
|
||||
queries: [{ query: 'metric' }],
|
||||
range: {
|
||||
from: 'now-1h',
|
||||
to: 'now',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('serializeStateToUrlParam', () => {
|
||||
it('returns url parameter value for a state object', () => {
|
||||
const state = {
|
||||
...DEFAULT_EXPLORE_STATE,
|
||||
datasourceName: 'foo',
|
||||
range: {
|
||||
from: 'now - 5h',
|
||||
from: 'now-5h',
|
||||
to: 'now',
|
||||
},
|
||||
queries: [
|
||||
@ -57,10 +83,33 @@ describe('state functions', () => {
|
||||
};
|
||||
expect(serializeStateToUrlParam(state)).toBe(
|
||||
'{"datasource":"foo","queries":[{"query":"metric{test=\\"a/b\\"}"},' +
|
||||
'{"query":"super{foo=\\"x/z\\"}"}],"range":{"from":"now - 5h","to":"now"}}'
|
||||
'{"query":"super{foo=\\"x/z\\"}"}],"range":{"from":"now-5h","to":"now"}}'
|
||||
);
|
||||
});
|
||||
|
||||
it('returns url parameter value for a state object', () => {
|
||||
const state = {
|
||||
...DEFAULT_EXPLORE_STATE,
|
||||
datasourceName: 'foo',
|
||||
range: {
|
||||
from: 'now-5h',
|
||||
to: 'now',
|
||||
},
|
||||
queries: [
|
||||
{
|
||||
query: 'metric{test="a/b"}',
|
||||
},
|
||||
{
|
||||
query: 'super{foo="x/z"}',
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(serializeStateToUrlParam(state, true)).toBe(
|
||||
'["now-5h","now","foo","metric{test=\\"a/b\\"}","super{foo=\\"x/z\\"}"]'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('interplay', () => {
|
||||
it('can parse the serialized state into the original state', () => {
|
||||
const state = {
|
||||
|
@ -60,7 +60,20 @@ export async function getExploreUrl(
|
||||
export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
if (initial) {
|
||||
try {
|
||||
return JSON.parse(decodeURI(initial));
|
||||
const parsed = JSON.parse(decodeURI(initial));
|
||||
if (Array.isArray(parsed)) {
|
||||
if (parsed.length <= 3) {
|
||||
throw new Error('Error parsing compact URL state for Explore.');
|
||||
}
|
||||
const range = {
|
||||
from: parsed[0],
|
||||
to: parsed[1],
|
||||
};
|
||||
const datasource = parsed[2];
|
||||
const queries = parsed.slice(3).map(query => ({ query }));
|
||||
return { datasource, queries, range };
|
||||
}
|
||||
return parsed;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@ -68,11 +81,19 @@ export function parseUrlState(initial: string | undefined): ExploreUrlState {
|
||||
return { datasource: null, queries: [], range: DEFAULT_RANGE };
|
||||
}
|
||||
|
||||
export function serializeStateToUrlParam(state: ExploreState): string {
|
||||
export function serializeStateToUrlParam(state: ExploreState, compact?: boolean): string {
|
||||
const urlState: ExploreUrlState = {
|
||||
datasource: state.datasourceName,
|
||||
queries: state.queries.map(q => ({ query: q.query })),
|
||||
range: state.range,
|
||||
};
|
||||
if (compact) {
|
||||
return JSON.stringify([
|
||||
urlState.range.from,
|
||||
urlState.range.to,
|
||||
urlState.datasource,
|
||||
...urlState.queries.map(q => q.query),
|
||||
]);
|
||||
}
|
||||
return JSON.stringify(urlState);
|
||||
}
|
||||
|
@ -275,7 +275,6 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
const { onChangeSplit } = this.props;
|
||||
if (onChangeSplit) {
|
||||
onChangeSplit(false);
|
||||
this.saveState();
|
||||
}
|
||||
};
|
||||
|
||||
@ -292,7 +291,6 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
|
||||
if (onChangeSplit) {
|
||||
const state = this.cloneState();
|
||||
onChangeSplit(true, state);
|
||||
this.saveState();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -38,10 +38,17 @@ export class Wrapper extends Component<WrapperProps, WrapperState> {
|
||||
|
||||
onChangeSplit = (split: boolean, splitState: ExploreState) => {
|
||||
this.setState({ split, splitState });
|
||||
// When closing split, remove URL state for split part
|
||||
if (!split) {
|
||||
delete this.urlStates[STATE_KEY_RIGHT];
|
||||
this.props.updateLocation({
|
||||
query: this.urlStates,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onSaveState = (key: string, state: ExploreState) => {
|
||||
const urlState = serializeStateToUrlParam(state);
|
||||
const urlState = serializeStateToUrlParam(state, true);
|
||||
this.urlStates[key] = urlState;
|
||||
this.props.updateLocation({
|
||||
query: this.urlStates,
|
||||
|
Loading…
Reference in New Issue
Block a user