|
|
|
@ -157,49 +157,72 @@ export function buildQueryTransaction( |
|
|
|
|
|
|
|
|
|
export const clearQueryKeys: (query: DataQuery) => object = ({ key, refId, ...rest }) => rest; |
|
|
|
|
|
|
|
|
|
const isMetricSegment = (segment: { [key: string]: string }) => segment.hasOwnProperty('expr'); |
|
|
|
|
const metricProperties = ['expr', 'target', 'datasource']; |
|
|
|
|
const isMetricSegment = (segment: { [key: string]: string }) => |
|
|
|
|
metricProperties.some(prop => segment.hasOwnProperty(prop)); |
|
|
|
|
const isUISegment = (segment: { [key: string]: string }) => segment.hasOwnProperty('ui'); |
|
|
|
|
|
|
|
|
|
enum ParseUrlStateIndex { |
|
|
|
|
RangeFrom = 0, |
|
|
|
|
RangeTo = 1, |
|
|
|
|
Datasource = 2, |
|
|
|
|
SegmentsStart = 3, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
enum ParseUiStateIndex { |
|
|
|
|
Graph = 0, |
|
|
|
|
Logs = 1, |
|
|
|
|
Table = 2, |
|
|
|
|
Strategy = 3, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export const safeParseJson = (text: string) => { |
|
|
|
|
if (!text) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
return JSON.parse(decodeURI(text)); |
|
|
|
|
} catch (error) { |
|
|
|
|
console.error(error); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
export function parseUrlState(initial: string | undefined): ExploreUrlState { |
|
|
|
|
let uiState = DEFAULT_UI_STATE; |
|
|
|
|
|
|
|
|
|
if (initial) { |
|
|
|
|
try { |
|
|
|
|
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]; |
|
|
|
|
let queries = []; |
|
|
|
|
|
|
|
|
|
parsed.slice(3).forEach(segment => { |
|
|
|
|
if (isMetricSegment(segment)) { |
|
|
|
|
queries = [...queries, segment]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (isUISegment(segment)) { |
|
|
|
|
uiState = { |
|
|
|
|
showingGraph: segment.ui[0], |
|
|
|
|
showingLogs: segment.ui[1], |
|
|
|
|
showingTable: segment.ui[2], |
|
|
|
|
dedupStrategy: segment.ui[3], |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return { datasource, queries, range, ui: uiState }; |
|
|
|
|
} |
|
|
|
|
return parsed; |
|
|
|
|
} catch (e) { |
|
|
|
|
console.error(e); |
|
|
|
|
} |
|
|
|
|
const parsed = safeParseJson(initial); |
|
|
|
|
const errorResult = { datasource: null, queries: [], range: DEFAULT_RANGE, ui: DEFAULT_UI_STATE }; |
|
|
|
|
|
|
|
|
|
if (!parsed) { |
|
|
|
|
return errorResult; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!Array.isArray(parsed)) { |
|
|
|
|
return parsed; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (parsed.length <= ParseUrlStateIndex.SegmentsStart) { |
|
|
|
|
console.error('Error parsing compact URL state for Explore.'); |
|
|
|
|
return errorResult; |
|
|
|
|
} |
|
|
|
|
return { datasource: null, queries: [], range: DEFAULT_RANGE, ui: uiState }; |
|
|
|
|
|
|
|
|
|
const range = { |
|
|
|
|
from: parsed[ParseUrlStateIndex.RangeFrom], |
|
|
|
|
to: parsed[ParseUrlStateIndex.RangeTo], |
|
|
|
|
}; |
|
|
|
|
const datasource = parsed[ParseUrlStateIndex.Datasource]; |
|
|
|
|
const parsedSegments = parsed.slice(ParseUrlStateIndex.SegmentsStart); |
|
|
|
|
const queries = parsedSegments.filter(segment => isMetricSegment(segment)); |
|
|
|
|
const uiState = parsedSegments.filter(segment => isUISegment(segment))[0]; |
|
|
|
|
const ui = uiState |
|
|
|
|
? { |
|
|
|
|
showingGraph: uiState.ui[ParseUiStateIndex.Graph], |
|
|
|
|
showingLogs: uiState.ui[ParseUiStateIndex.Logs], |
|
|
|
|
showingTable: uiState.ui[ParseUiStateIndex.Table], |
|
|
|
|
dedupStrategy: uiState.ui[ParseUiStateIndex.Strategy], |
|
|
|
|
} |
|
|
|
|
: DEFAULT_UI_STATE; |
|
|
|
|
|
|
|
|
|
return { datasource, queries, range, ui }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export function serializeStateToUrlParam(urlState: ExploreUrlState, compact?: boolean): string { |
|
|
|
|