{"version":3,"sources":["webpack:///./public/app/features/profile/state/selectors.ts","webpack:///./public/app/features/explore/state/selectors.ts","webpack:///./public/app/features/explore/state/actions.ts","webpack:///./public/app/core/utils/richHistory.ts"],"names":["getTimeZone","state","timeZone","deduplicatedRowsSelector","createSelector","logsResult","rows","hiddenLogLevels","dedupStrategy","length","filteredRows","filterLogLevels","Set","dedupLogRows","getExploreDatasources","getDatasourceSrv","getExternal","map","ds","value","name","meta","updateExploreUIState","exploreId","uiStateFragment","dispatch","updateUIStateAction","stateSave","addQueryRow","index","getState","queries","explore","query","generateEmptyQuery","addQueryRowAction","changeDatasource","datasourceName","get","newDataSourceInstance","currentDataSourceInstance","datasourceInstance","orgId","user","getVersion","datasourceVersion","prometheusToLoki","updateDatasourceInstanceAction","version","mode","ExploreMode","Logs","undefined","importQueries","isLive","changeRefreshInterval","RefreshPicker","offOption","loadDatasource","runQueries","changeMode","changeModeAction","changeQuery","override","refId","key","generateNewKeyAndAddRefIdIfMissing","changeQueryAction","changeSize","height","width","changeSizeAction","updateTimeRange","options","syncedTimes","updateTime","ExploreId","left","right","refreshInterval","changeRefreshIntervalAction","clearQueries","scanStopAction","clearQueriesAction","cancelQueries","cancelQueriesAction","loadExploreDatasourcesAndSetDatasource","loadDatasourceMissingAction","initializeExplore","range","containerWidth","eventBridge","ui","originPanelId","initializeExploreAction","richHistory","getRichHistory","richHistoryUpdatedAction","loadDatasourceReady","instance","historyKey","id","history","store","getObject","set","lastUsedDatasourceKeyForOrgId","loadDatasourceReadyAction","sourceDataSource","targetDataSource","queriesImportedAction","importedQueries","ensureQueries","nextQueries","loadDatasourcePendingAction","requestedDatasourceName","init","err","console","log","modifyQueries","modification","modifier","modifyQueriesAction","preventSubmit","exploreItemState","live","scanning","queryResponse","querySubscription","showingGraph","showingTable","hasNonEmptyQuery","minInterval","interval","stopQueryState","datasourceId","queryOptions","maxDataPoints","liveStreaming","transaction","buildQueryTransaction","firstResponse","changeLoadingStateAction","loadingState","LoadingState","Loading","newQuerySub","runRequest","request","pipe","throttleTime","identity","data","preProcessPanelData","subscribe","error","nextHistory","updateHistory","nextRichHistory","addToRichHistory","historyUpdatedAction","queryStreamUpdatedAction","response","Done","series","getShiftedTimeRange","absoluteRange","queryStoreSubscriptionAction","updateRichHistory","ts","property","updatedProperty","updateStarredInRichHistory","updateCommentInRichHistory","deleteQueryInRichHistory","deleteRichHistory","deleteAllFromRichHistory","toRawTimeRange","from","raw","isDateTime","valueOf","toString","to","split","replace","urlReplaced","urlStates","leftUrlState","datasource","clearQueryKeys","showingLogs","serializeStateToUrlParam","rightUrlState","updateLocation","setUrlReplacedAction","config","absRange","actionRange","rawRange","itemState","dateTimeForTimeZone","getTimeRange","getTimeSrv","time","refresh","getTimezone","timeRangeUpdated","changeRangeAction","scanStart","scanStartAction","setQueries","rawQueries","setQueriesAction","splitClose","itemId","splitCloseAction","splitOpen","leftState","rightState","queryState","location","urlState","parseUrlState","slice","splitOpenAction","dataSourceSettings","getDataSourceSettingsByUid","datasourceUid","syncTimes","isTimeSynced","syncTimesAction","togglePanelActionCreator","actionCreator","isPanelVisible","uiFragmentStateUpdate","shouldRunQueries","type","toggleGraphAction","toggleTableAction","toggleGraph","toggleTable","changeDedupStrategy","refreshExplore","initialized","update","urlRange","refreshQueries","push","getTimeRangeFromUrl","initialQueries","navigateToExplore","panel","dependencies","getDataSourceSrv","getExploreUrl","openInNewWindow","datasourceSrv","panelTargets","targets","panelDatasource","timeSrv","path","RICH_HISTORY_KEY","RICH_HISTORY_SETTING_KEYS","retentionPeriod","starredTabAsFirstTab","activeDatasourceOnly","datasourceFilters","starred","comment","sessionName","Date","now","newQueriesToSave","filter","strippedQuery","_","omit","Object","keys","notEmptyQuery","retentionPeriodLastTs","createRetentionPeriodBoundary","queriesToKeep","q","newQueriesToCompare","lastQueriesToCompare","isEqual","updatedHistory","setObject","appEvents","emit","AppEvents","alertError","transformedQueries","individualQuery","string","JSON","parse","e","isParsable","expr","createDataQuery","migrateRichHistory","delete","isStarred","assign","newComment","sortQueries","array","sortOrder","sortFunc","SortOrder","Ascending","a","b","Descending","DatasourceZA","DatasourceAZ","sort","copyStringToClipboard","el","document","createElement","body","appendChild","select","execCommand","removeChild","createUrlFromRichHistory","exploreState","Tracing","Metrics","context","serializedState","baseUrl","exec","window","href","urlUtil","renderUrl","mapNumbertoTimeInSlider","num","str","days","isLastTs","today","date","setDate","getDate","setHours","createQueryHeading","heading","dateTimeFormat","format","createQueryText","queryDsInstance","getQueryDisplayText","stringify","mapQueriesToHeadings","mappedQueriesToHeadings","forEach","createDatasourcesList","queriesDatasources","exploreDatasources","datasources","queryDsName","findIndex","exploreDs","label","imgUrl","info","logos","small","isRemoved"],"mappings":"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","file":"default~DashboardPage~SoloPanelPage~explore.d3489276abe5fda2bd26.js","sourcesContent":["import { UserState } from 'app/types';\n\nexport const getTimeZone = (state: UserState) => state.timeZone;\n","import { createSelector } from 'reselect';\nimport { ExploreItemState } from 'app/types';\nimport { filterLogLevels, dedupLogRows } from 'app/core/logs_model';\nimport { getDatasourceSrv } from '../../plugins/datasource_srv';\nimport { DataSourceSelectItem } from '@grafana/data';\n\nconst logsRowsSelector = (state: ExploreItemState) => state.logsResult && state.logsResult.rows;\nconst hiddenLogLevelsSelector = (state: ExploreItemState) => state.hiddenLogLevels;\nconst dedupStrategySelector = (state: ExploreItemState) => state.dedupStrategy;\nexport const deduplicatedRowsSelector = createSelector(\n  logsRowsSelector,\n  hiddenLogLevelsSelector,\n  dedupStrategySelector,\n  function dedupRows(rows, hiddenLogLevels, dedupStrategy) {\n    if (!(rows && rows.length)) {\n      return rows;\n    }\n    const filteredRows = filterLogLevels(rows, new Set(hiddenLogLevels));\n    return dedupLogRows(filteredRows, dedupStrategy);\n  }\n);\n\nexport const getExploreDatasources = (): DataSourceSelectItem[] => {\n  return getDatasourceSrv()\n    .getExternal()\n    .map(\n      (ds: any) =>\n        ({\n          value: ds.name,\n          name: ds.name,\n          meta: ds.meta,\n        } as DataSourceSelectItem)\n    );\n};\n","// Libraries\nimport { map, throttleTime } from 'rxjs/operators';\nimport { identity } from 'rxjs';\nimport { ActionCreatorWithPayload, PayloadAction } from '@reduxjs/toolkit';\nimport { DataSourceSrv } from '@grafana/runtime';\nimport { RefreshPicker } from '@grafana/ui';\nimport {\n  AbsoluteTimeRange,\n  DataQuery,\n  DataSourceApi,\n  dateTimeForTimeZone,\n  isDateTime,\n  LoadingState,\n  LogsDedupStrategy,\n  PanelData,\n  QueryFixAction,\n  RawTimeRange,\n  TimeRange,\n  ExploreMode,\n} from '@grafana/data';\n// Services & Utils\nimport store from 'app/core/store';\nimport { getDatasourceSrv } from 'app/features/plugins/datasource_srv';\nimport { Emitter } from 'app/core/core';\nimport {\n  buildQueryTransaction,\n  clearQueryKeys,\n  ensureQueries,\n  generateEmptyQuery,\n  generateNewKeyAndAddRefIdIfMissing,\n  GetExploreUrlArguments,\n  getTimeRange,\n  getTimeRangeFromUrl,\n  hasNonEmptyQuery,\n  lastUsedDatasourceKeyForOrgId,\n  parseUrlState,\n  serializeStateToUrlParam,\n  stopQueryState,\n  updateHistory,\n} from 'app/core/utils/explore';\nimport {\n  addToRichHistory,\n  deleteAllFromRichHistory,\n  updateStarredInRichHistory,\n  updateCommentInRichHistory,\n  deleteQueryInRichHistory,\n  getRichHistory,\n} from 'app/core/utils/richHistory';\n// Types\nimport { ExploreItemState, ExploreUrlState, ThunkResult } from 'app/types';\n\nimport { ExploreId, ExploreUIState, QueryOptions } from 'app/types/explore';\nimport {\n  addQueryRowAction,\n  changeModeAction,\n  changeQueryAction,\n  changeRangeAction,\n  changeRefreshIntervalAction,\n  ChangeRefreshIntervalPayload,\n  changeSizeAction,\n  ChangeSizePayload,\n  clearQueriesAction,\n  historyUpdatedAction,\n  richHistoryUpdatedAction,\n  initializeExploreAction,\n  loadDatasourceMissingAction,\n  loadDatasourcePendingAction,\n  loadDatasourceReadyAction,\n  LoadDatasourceReadyPayload,\n  modifyQueriesAction,\n  queriesImportedAction,\n  queryStoreSubscriptionAction,\n  queryStreamUpdatedAction,\n  scanStartAction,\n  scanStopAction,\n  setQueriesAction,\n  setUrlReplacedAction,\n  splitCloseAction,\n  splitOpenAction,\n  syncTimesAction,\n  toggleGraphAction,\n  ToggleGraphPayload,\n  toggleTableAction,\n  ToggleTablePayload,\n  updateDatasourceInstanceAction,\n  updateUIStateAction,\n  changeLoadingStateAction,\n  cancelQueriesAction,\n} from './actionTypes';\nimport { getTimeZone } from 'app/features/profile/state/selectors';\nimport { getShiftedTimeRange } from 'app/core/utils/timePicker';\nimport { updateLocation } from '../../../core/actions';\nimport { getTimeSrv, TimeSrv } from '../../dashboard/services/TimeSrv';\nimport { preProcessPanelData, runRequest } from '../../dashboard/state/runRequest';\nimport { PanelModel } from 'app/features/dashboard/state';\nimport { getExploreDatasources } from './selectors';\n\n/**\n * Updates UI state and save it to the URL\n */\nconst updateExploreUIState = (exploreId: ExploreId, uiStateFragment: Partial<ExploreUIState>): ThunkResult<void> => {\n  return dispatch => {\n    dispatch(updateUIStateAction({ exploreId, ...uiStateFragment }));\n    dispatch(stateSave());\n  };\n};\n\n/**\n * Adds a query row after the row with the given index.\n */\nexport function addQueryRow(exploreId: ExploreId, index: number): ThunkResult<void> {\n  return (dispatch, getState) => {\n    const queries = getState().explore[exploreId].queries;\n    const query = generateEmptyQuery(queries, index);\n\n    dispatch(addQueryRowAction({ exploreId, index, query }));\n  };\n}\n\n/**\n * Loads a new datasource identified by the given name.\n */\nexport function changeDatasource(exploreId: ExploreId, datasourceName: string): ThunkResult<void> {\n  return async (dispatch, getState) => {\n    let newDataSourceInstance: DataSourceApi;\n\n    if (!datasourceName) {\n      newDataSourceInstance = await getDatasourceSrv().get();\n    } else {\n      newDataSourceInstance = await getDatasourceSrv().get(datasourceName);\n    }\n\n    const currentDataSourceInstance = getState().explore[exploreId].datasourceInstance;\n    const queries = getState().explore[exploreId].queries;\n    const orgId = getState().user.orgId;\n    const datasourceVersion = newDataSourceInstance.getVersion && (await newDataSourceInstance.getVersion());\n\n    // HACK: Switch to logs mode if coming from Prometheus to Loki\n    const prometheusToLoki =\n      currentDataSourceInstance?.meta?.name === 'Prometheus' && newDataSourceInstance?.meta?.name === 'Loki';\n\n    dispatch(\n      updateDatasourceInstanceAction({\n        exploreId,\n        datasourceInstance: newDataSourceInstance,\n        version: datasourceVersion,\n        mode: prometheusToLoki ? ExploreMode.Logs : undefined,\n      })\n    );\n\n    await dispatch(importQueries(exploreId, queries, currentDataSourceInstance, newDataSourceInstance));\n\n    if (getState().explore[exploreId].isLive) {\n      dispatch(changeRefreshInterval(exploreId, RefreshPicker.offOption.value));\n    }\n\n    await dispatch(loadDatasource(exploreId, newDataSourceInstance, orgId));\n    dispatch(runQueries(exploreId));\n  };\n}\n\n/**\n * Change the display mode in Explore.\n */\nexport function changeMode(exploreId: ExploreId, mode: ExploreMode): ThunkResult<void> {\n  return dispatch => {\n    dispatch(changeModeAction({ exploreId, mode }));\n  };\n}\n\n/**\n * Query change handler for the query row with the given index.\n * If `override` is reset the query modifications and run the queries. Use this to set queries via a link.\n */\nexport function changeQuery(\n  exploreId: ExploreId,\n  query: DataQuery,\n  index: number,\n  override = false\n): ThunkResult<void> {\n  return (dispatch, getState) => {\n    // Null query means reset\n    if (query === null) {\n      const queries = getState().explore[exploreId].queries;\n      const { refId, key } = queries[index];\n      query = generateNewKeyAndAddRefIdIfMissing({ refId, key }, queries, index);\n    }\n\n    dispatch(changeQueryAction({ exploreId, query, index, override }));\n    if (override) {\n      dispatch(runQueries(exploreId));\n    }\n  };\n}\n\n/**\n * Keep track of the Explore container size, in particular the width.\n * The width will be used to calculate graph intervals (number of datapoints).\n */\nexport function changeSize(\n  exploreId: ExploreId,\n  { height, width }: { height: number; width: number }\n): PayloadAction<ChangeSizePayload> {\n  return changeSizeAction({ exploreId, height, width });\n}\n\nexport const updateTimeRange = (options: {\n  exploreId: ExploreId;\n  rawRange?: RawTimeRange;\n  absoluteRange?: AbsoluteTimeRange;\n}): ThunkResult<void> => {\n  return (dispatch, getState) => {\n    const { syncedTimes } = getState().explore;\n    if (syncedTimes) {\n      dispatch(updateTime({ ...options, exploreId: ExploreId.left }));\n      dispatch(runQueries(ExploreId.left));\n      dispatch(updateTime({ ...options, exploreId: ExploreId.right }));\n      dispatch(runQueries(ExploreId.right));\n    } else {\n      dispatch(updateTime({ ...options }));\n      dispatch(runQueries(options.exploreId));\n    }\n  };\n};\n/**\n * Change the refresh interval of Explore. Called from the Refresh picker.\n */\nexport function changeRefreshInterval(\n  exploreId: ExploreId,\n  refreshInterval: string\n): PayloadAction<ChangeRefreshIntervalPayload> {\n  return changeRefreshIntervalAction({ exploreId, refreshInterval });\n}\n\n/**\n * Clear all queries and results.\n */\nexport function clearQueries(exploreId: ExploreId): ThunkResult<void> {\n  return dispatch => {\n    dispatch(scanStopAction({ exploreId }));\n    dispatch(clearQueriesAction({ exploreId }));\n    dispatch(stateSave());\n  };\n}\n\n/**\n * Cancel running queries\n */\nexport function cancelQueries(exploreId: ExploreId): ThunkResult<void> {\n  return dispatch => {\n    dispatch(scanStopAction({ exploreId }));\n    dispatch(cancelQueriesAction({ exploreId }));\n    dispatch(stateSave());\n  };\n}\n\n/**\n * Loads all explore data sources and sets the chosen datasource.\n * If there are no datasources a missing datasource action is dispatched.\n */\nexport function loadExploreDatasourcesAndSetDatasource(\n  exploreId: ExploreId,\n  datasourceName: string\n): ThunkResult<void> {\n  return dispatch => {\n    const exploreDatasources = getExploreDatasources();\n\n    if (exploreDatasources.length >= 1) {\n      dispatch(changeDatasource(exploreId, datasourceName));\n    } else {\n      dispatch(loadDatasourceMissingAction({ exploreId }));\n    }\n  };\n}\n\n/**\n * Initialize Explore state with state from the URL and the React component.\n * Call this only on components for with the Explore state has not been initialized.\n */\nexport function initializeExplore(\n  exploreId: ExploreId,\n  datasourceName: string,\n  queries: DataQuery[],\n  range: TimeRange,\n  mode: ExploreMode,\n  containerWidth: number,\n  eventBridge: Emitter,\n  ui: ExploreUIState,\n  originPanelId: number\n): ThunkResult<void> {\n  return async (dispatch, getState) => {\n    dispatch(loadExploreDatasourcesAndSetDatasource(exploreId, datasourceName));\n    dispatch(\n      initializeExploreAction({\n        exploreId,\n        containerWidth,\n        eventBridge,\n        queries,\n        range,\n        mode,\n        ui,\n        originPanelId,\n      })\n    );\n    dispatch(updateTime({ exploreId }));\n    const richHistory = getRichHistory();\n    dispatch(richHistoryUpdatedAction({ richHistory }));\n  };\n}\n\n/**\n * Datasource loading was successfully completed.\n */\nexport const loadDatasourceReady = (\n  exploreId: ExploreId,\n  instance: DataSourceApi,\n  orgId: number\n): PayloadAction<LoadDatasourceReadyPayload> => {\n  const historyKey = `grafana.explore.history.${instance.meta?.id}`;\n  const history = store.getObject(historyKey, []);\n  // Save last-used datasource\n\n  store.set(lastUsedDatasourceKeyForOrgId(orgId), instance.name);\n\n  return loadDatasourceReadyAction({\n    exploreId,\n    history,\n  });\n};\n\n/**\n * Import queries from previous datasource if possible eg Loki and Prometheus have similar query language so the\n * labels part can be reused to get similar data.\n * @param exploreId\n * @param queries\n * @param sourceDataSource\n * @param targetDataSource\n */\nexport const importQueries = (\n  exploreId: ExploreId,\n  queries: DataQuery[],\n  sourceDataSource: DataSourceApi | undefined,\n  targetDataSource: DataSourceApi\n): ThunkResult<void> => {\n  return async dispatch => {\n    if (!sourceDataSource) {\n      // explore not initialized\n      dispatch(queriesImportedAction({ exploreId, queries }));\n      return;\n    }\n\n    let importedQueries = queries;\n    // Check if queries can be imported from previously selected datasource\n    if (sourceDataSource.meta?.id === targetDataSource.meta?.id) {\n      // Keep same queries if same type of datasource\n      importedQueries = [...queries];\n    } else if (targetDataSource.importQueries) {\n      // Datasource-specific importers\n      importedQueries = await targetDataSource.importQueries(queries, sourceDataSource.meta);\n    } else {\n      // Default is blank queries\n      importedQueries = ensureQueries();\n    }\n\n    const nextQueries = ensureQueries(importedQueries);\n\n    dispatch(queriesImportedAction({ exploreId, queries: nextQueries }));\n  };\n};\n\n/**\n * Main action to asynchronously load a datasource. Dispatches lots of smaller actions for feedback.\n */\nexport const loadDatasource = (exploreId: ExploreId, instance: DataSourceApi, orgId: number): ThunkResult<void> => {\n  return async (dispatch, getState) => {\n    const datasourceName = instance.name;\n\n    // Keep ID to track selection\n    dispatch(loadDatasourcePendingAction({ exploreId, requestedDatasourceName: datasourceName }));\n\n    if (instance.init) {\n      try {\n        instance.init();\n      } catch (err) {\n        console.log(err);\n      }\n    }\n\n    if (datasourceName !== getState().explore[exploreId].requestedDatasourceName) {\n      // User already changed datasource, discard results\n      return;\n    }\n\n    dispatch(loadDatasourceReady(exploreId, instance, orgId));\n  };\n};\n\n/**\n * Action to modify a query given a datasource-specific modifier action.\n * @param exploreId Explore area\n * @param modification Action object with a type, e.g., ADD_FILTER\n * @param index Optional query row index. If omitted, the modification is applied to all query rows.\n * @param modifier Function that executes the modification, typically `datasourceInstance.modifyQueries`.\n */\nexport function modifyQueries(\n  exploreId: ExploreId,\n  modification: QueryFixAction,\n  modifier: any,\n  index?: number\n): ThunkResult<void> {\n  return dispatch => {\n    dispatch(modifyQueriesAction({ exploreId, modification, index, modifier }));\n    if (!modification.preventSubmit) {\n      dispatch(runQueries(exploreId));\n    }\n  };\n}\n\n/**\n * Main action to run queries and dispatches sub-actions based on which result viewers are active\n */\nexport const runQueries = (exploreId: ExploreId): ThunkResult<void> => {\n  return (dispatch, getState) => {\n    dispatch(updateTime({ exploreId }));\n\n    const richHistory = getState().explore.richHistory;\n    const exploreItemState = getState().explore[exploreId];\n    const {\n      datasourceInstance,\n      queries,\n      containerWidth,\n      isLive: live,\n      range,\n      scanning,\n      queryResponse,\n      querySubscription,\n      history,\n      mode,\n      showingGraph,\n      showingTable,\n    } = exploreItemState;\n\n    if (!hasNonEmptyQuery(queries)) {\n      dispatch(clearQueriesAction({ exploreId }));\n      dispatch(stateSave()); // Remember to save to state and update location\n      return;\n    }\n\n    // Some datasource's query builders allow per-query interval limits,\n    // but we're using the datasource interval limit for now\n    const minInterval = datasourceInstance.interval;\n\n    stopQueryState(querySubscription);\n\n    const datasourceId = datasourceInstance.meta.id;\n\n    const queryOptions: QueryOptions = {\n      minInterval,\n      // maxDataPoints is used in:\n      // Loki - used for logs streaming for buffer size, with undefined it falls back to datasource config if it supports that.\n      // Elastic - limits the number of datapoints for the counts query and for logs it has hardcoded limit.\n      // Influx - used to correctly display logs in graph\n      maxDataPoints: mode === ExploreMode.Logs && datasourceId === 'loki' ? undefined : containerWidth,\n      liveStreaming: live,\n      showingGraph,\n      showingTable,\n      mode,\n    };\n\n    const datasourceName = exploreItemState.requestedDatasourceName;\n    const timeZone = getTimeZone(getState().user);\n    const transaction = buildQueryTransaction(queries, queryOptions, range, scanning, timeZone);\n\n    let firstResponse = true;\n    dispatch(changeLoadingStateAction({ exploreId, loadingState: LoadingState.Loading }));\n\n    const newQuerySub = runRequest(datasourceInstance, transaction.request)\n      .pipe(\n        // Simple throttle for live tailing, in case of > 1000 rows per interval we spend about 200ms on processing and\n        // rendering. In case this is optimized this can be tweaked, but also it should be only as fast as user\n        // actually can see what is happening.\n        live ? throttleTime(500) : identity,\n        map((data: PanelData) => preProcessPanelData(data, queryResponse))\n      )\n      .subscribe((data: PanelData) => {\n        if (!data.error && firstResponse) {\n          // Side-effect: Saving history in localstorage\n          const nextHistory = updateHistory(history, datasourceId, queries);\n          const nextRichHistory = addToRichHistory(\n            richHistory || [],\n            datasourceId,\n            datasourceName,\n            queries,\n            false,\n            '',\n            ''\n          );\n          dispatch(historyUpdatedAction({ exploreId, history: nextHistory }));\n          dispatch(richHistoryUpdatedAction({ richHistory: nextRichHistory }));\n\n          // We save queries to the URL here so that only successfully run queries change the URL.\n          dispatch(stateSave());\n        }\n\n        firstResponse = false;\n\n        dispatch(queryStreamUpdatedAction({ exploreId, response: data }));\n\n        // Keep scanning for results if this was the last scanning transaction\n        if (getState().explore[exploreId].scanning) {\n          if (data.state === LoadingState.Done && data.series.length === 0) {\n            const range = getShiftedTimeRange(-1, getState().explore[exploreId].range);\n            dispatch(updateTime({ exploreId, absoluteRange: range }));\n            dispatch(runQueries(exploreId));\n          } else {\n            // We can stop scanning if we have a result\n            dispatch(scanStopAction({ exploreId }));\n          }\n        }\n      });\n\n    dispatch(queryStoreSubscriptionAction({ exploreId, querySubscription: newQuerySub }));\n  };\n};\n\nexport const updateRichHistory = (ts: number, property: string, updatedProperty?: string): ThunkResult<void> => {\n  return (dispatch, getState) => {\n    // Side-effect: Saving rich history in localstorage\n    let nextRichHistory;\n    if (property === 'starred') {\n      nextRichHistory = updateStarredInRichHistory(getState().explore.richHistory, ts);\n    }\n    if (property === 'comment') {\n      nextRichHistory = updateCommentInRichHistory(getState().explore.richHistory, ts, updatedProperty);\n    }\n    if (property === 'delete') {\n      nextRichHistory = deleteQueryInRichHistory(getState().explore.richHistory, ts);\n    }\n    dispatch(richHistoryUpdatedAction({ richHistory: nextRichHistory }));\n  };\n};\n\nexport const deleteRichHistory = (): ThunkResult<void> => {\n  return dispatch => {\n    deleteAllFromRichHistory();\n    dispatch(richHistoryUpdatedAction({ richHistory: [] }));\n  };\n};\n\nconst toRawTimeRange = (range: TimeRange): RawTimeRange => {\n  let from = range.raw.from;\n  if (isDateTime(from)) {\n    from = from.valueOf().toString(10);\n  }\n\n  let to = range.raw.to;\n  if (isDateTime(to)) {\n    to = to.valueOf().toString(10);\n  }\n\n  return {\n    from,\n    to,\n  };\n};\n\n/**\n * Save local redux state back to the URL. Should be called when there is some change that should affect the URL.\n * Not all of the redux state is reflected in URL though.\n */\nexport const stateSave = (): ThunkResult<void> => {\n  return (dispatch, getState) => {\n    const { left, right, split } = getState().explore;\n    const orgId = getState().user.orgId.toString();\n    const replace = left && left.urlReplaced === false;\n    const urlStates: { [index: string]: string } = { orgId };\n    const leftUrlState: ExploreUrlState = {\n      datasource: left.datasourceInstance.name,\n      queries: left.queries.map(clearQueryKeys),\n      range: toRawTimeRange(left.range),\n      mode: left.mode,\n      ui: {\n        showingGraph: left.showingGraph,\n        showingLogs: true,\n        showingTable: left.showingTable,\n        dedupStrategy: left.dedupStrategy,\n      },\n    };\n    urlStates.left = serializeStateToUrlParam(leftUrlState, true);\n    if (split) {\n      const rightUrlState: ExploreUrlState = {\n        datasource: right.datasourceInstance.name,\n        queries: right.queries.map(clearQueryKeys),\n        range: toRawTimeRange(right.range),\n        mode: right.mode,\n        ui: {\n          showingGraph: right.showingGraph,\n          showingLogs: true,\n          showingTable: right.showingTable,\n          dedupStrategy: right.dedupStrategy,\n        },\n      };\n\n      urlStates.right = serializeStateToUrlParam(rightUrlState, true);\n    }\n\n    dispatch(updateLocation({ query: urlStates, replace }));\n    if (replace) {\n      dispatch(setUrlReplacedAction({ exploreId: ExploreId.left }));\n    }\n  };\n};\n\nexport const updateTime = (config: {\n  exploreId: ExploreId;\n  rawRange?: RawTimeRange;\n  absoluteRange?: AbsoluteTimeRange;\n}): ThunkResult<void> => {\n  return (dispatch, getState) => {\n    const { exploreId, absoluteRange: absRange, rawRange: actionRange } = config;\n    const itemState = getState().explore[exploreId];\n    const timeZone = getTimeZone(getState().user);\n    const { range: rangeInState } = itemState;\n    let rawRange: RawTimeRange = rangeInState.raw;\n\n    if (absRange) {\n      rawRange = {\n        from: dateTimeForTimeZone(timeZone, absRange.from),\n        to: dateTimeForTimeZone(timeZone, absRange.to),\n      };\n    }\n\n    if (actionRange) {\n      rawRange = actionRange;\n    }\n\n    const range = getTimeRange(timeZone, rawRange);\n    const absoluteRange: AbsoluteTimeRange = { from: range.from.valueOf(), to: range.to.valueOf() };\n\n    getTimeSrv().init({\n      time: range.raw,\n      refresh: false,\n      getTimezone: () => timeZone,\n      timeRangeUpdated: (): any => undefined,\n    });\n\n    dispatch(changeRangeAction({ exploreId, range, absoluteRange }));\n  };\n};\n\n/**\n * Start a scan for more results using the given scanner.\n * @param exploreId Explore area\n * @param scanner Function that a) returns a new time range and b) triggers a query run for the new range\n */\nexport function scanStart(exploreId: ExploreId): ThunkResult<void> {\n  return (dispatch, getState) => {\n    // Register the scanner\n    dispatch(scanStartAction({ exploreId }));\n    // Scanning must trigger query run, and return the new range\n    const range = getShiftedTimeRange(-1, getState().explore[exploreId].range);\n    // Set the new range to be displayed\n    dispatch(updateTime({ exploreId, absoluteRange: range }));\n    dispatch(runQueries(exploreId));\n  };\n}\n\n/**\n * Reset queries to the given queries. Any modifications will be discarded.\n * Use this action for clicks on query examples. Triggers a query run.\n */\nexport function setQueries(exploreId: ExploreId, rawQueries: DataQuery[]): ThunkResult<void> {\n  return (dispatch, getState) => {\n    // Inject react keys into query objects\n    const queries = getState().explore[exploreId].queries;\n    const nextQueries = rawQueries.map((query, index) => generateNewKeyAndAddRefIdIfMissing(query, queries, index));\n    dispatch(setQueriesAction({ exploreId, queries: nextQueries }));\n    dispatch(runQueries(exploreId));\n  };\n}\n\n/**\n * Close the split view and save URL state.\n */\nexport function splitClose(itemId: ExploreId): ThunkResult<void> {\n  return dispatch => {\n    dispatch(splitCloseAction({ itemId }));\n    dispatch(stateSave());\n  };\n}\n\n/**\n * Open the split view and the right state is automatically initialized.\n * If options are specified it initializes that pane with the datasource and query from options.\n * Otherwise it copies the left state to be the right state. The copy keeps all query modifications but wipes the query\n * results.\n */\nexport function splitOpen(options?: { datasourceUid: string; query: string }): ThunkResult<void> {\n  return async (dispatch, getState) => {\n    // Clone left state to become the right state\n    const leftState: ExploreItemState = getState().explore[ExploreId.left];\n    const rightState: ExploreItemState = {\n      ...leftState,\n    };\n    const queryState = getState().location.query[ExploreId.left] as string;\n    const urlState = parseUrlState(queryState);\n\n    // TODO: Instead of splitting and then setting query/datasource we may probably do it in one action call\n    rightState.queries = leftState.queries.slice();\n    rightState.urlState = urlState;\n    dispatch(splitOpenAction({ itemState: rightState }));\n\n    if (options) {\n      // TODO: This is hardcoded for Jaeger right now. Need to be changed so that target datasource can define the\n      //  query shape.\n      const queries = [\n        {\n          query: options.query,\n          refId: 'A',\n        } as DataQuery,\n      ];\n\n      const dataSourceSettings = getDatasourceSrv().getDataSourceSettingsByUid(options.datasourceUid);\n      await dispatch(changeDatasource(ExploreId.right, dataSourceSettings.name));\n      await dispatch(setQueriesAction({ exploreId: ExploreId.right, queries }));\n    }\n\n    dispatch(stateSave());\n  };\n}\n\n/**\n * Syncs time interval, if they are not synced on both panels in a split mode.\n * Unsyncs time interval, if they are synced on both panels in a split mode.\n */\nexport function syncTimes(exploreId: ExploreId): ThunkResult<void> {\n  return (dispatch, getState) => {\n    if (exploreId === ExploreId.left) {\n      const leftState = getState().explore.left;\n      dispatch(updateTimeRange({ exploreId: ExploreId.right, rawRange: leftState.range.raw }));\n    } else {\n      const rightState = getState().explore.right;\n      dispatch(updateTimeRange({ exploreId: ExploreId.left, rawRange: rightState.range.raw }));\n    }\n    const isTimeSynced = getState().explore.syncedTimes;\n    dispatch(syncTimesAction({ syncedTimes: !isTimeSynced }));\n    dispatch(stateSave());\n  };\n}\n\n/**\n * Creates action to collapse graph/logs/table panel. When panel is collapsed,\n * queries won't be run\n */\nconst togglePanelActionCreator = (\n  actionCreator: ActionCreatorWithPayload<ToggleGraphPayload> | ActionCreatorWithPayload<ToggleTablePayload>\n) => (exploreId: ExploreId, isPanelVisible: boolean): ThunkResult<void> => {\n  return dispatch => {\n    let uiFragmentStateUpdate: Partial<ExploreUIState>;\n    const shouldRunQueries = !isPanelVisible;\n\n    switch (actionCreator.type) {\n      case toggleGraphAction.type:\n        uiFragmentStateUpdate = { showingGraph: !isPanelVisible };\n        break;\n      case toggleTableAction.type:\n        uiFragmentStateUpdate = { showingTable: !isPanelVisible };\n        break;\n    }\n\n    dispatch(actionCreator({ exploreId }));\n    // The switch further up is exhaustive so uiFragmentStateUpdate should definitely be initialized\n    dispatch(updateExploreUIState(exploreId, uiFragmentStateUpdate!));\n\n    if (shouldRunQueries) {\n      dispatch(runQueries(exploreId));\n    }\n  };\n};\n\n/**\n * Expand/collapse the graph result viewer. When collapsed, graph queries won't be run.\n */\nexport const toggleGraph = togglePanelActionCreator(toggleGraphAction);\n\n/**\n * Expand/collapse the table result viewer. When collapsed, table queries won't be run.\n */\nexport const toggleTable = togglePanelActionCreator(toggleTableAction);\n\n/**\n * Change logs deduplication strategy and update URL.\n */\nexport const changeDedupStrategy = (exploreId: ExploreId, dedupStrategy: LogsDedupStrategy): ThunkResult<void> => {\n  return dispatch => {\n    dispatch(updateExploreUIState(exploreId, { dedupStrategy }));\n  };\n};\n\n/**\n * Reacts to changes in URL state that we need to sync back to our redux state. Checks the internal update variable\n * to see which parts change and need to be synced.\n * @param exploreId\n */\nexport function refreshExplore(exploreId: ExploreId): ThunkResult<void> {\n  return (dispatch, getState) => {\n    const itemState = getState().explore[exploreId];\n    if (!itemState.initialized) {\n      return;\n    }\n\n    const { urlState, update, containerWidth, eventBridge } = itemState;\n    const { datasource, queries, range: urlRange, mode, ui, originPanelId } = urlState;\n    const refreshQueries: DataQuery[] = [];\n    for (let index = 0; index < queries.length; index++) {\n      const query = queries[index];\n      refreshQueries.push(generateNewKeyAndAddRefIdIfMissing(query, refreshQueries, index));\n    }\n    const timeZone = getTimeZone(getState().user);\n    const range = getTimeRangeFromUrl(urlRange, timeZone);\n\n    // need to refresh datasource\n    if (update.datasource) {\n      const initialQueries = ensureQueries(queries);\n      dispatch(\n        initializeExplore(\n          exploreId,\n          datasource,\n          initialQueries,\n          range,\n          mode,\n          containerWidth,\n          eventBridge,\n          ui,\n          originPanelId\n        )\n      );\n      return;\n    }\n\n    if (update.range) {\n      dispatch(updateTime({ exploreId, rawRange: range.raw }));\n    }\n\n    // need to refresh ui state\n    if (update.ui) {\n      dispatch(updateUIStateAction({ ...ui, exploreId }));\n    }\n\n    // need to refresh queries\n    if (update.queries) {\n      dispatch(setQueriesAction({ exploreId, queries: refreshQueries }));\n    }\n\n    // need to refresh mode\n    if (update.mode) {\n      dispatch(changeModeAction({ exploreId, mode }));\n    }\n\n    // always run queries when refresh is needed\n    if (update.queries || update.ui || update.range) {\n      dispatch(runQueries(exploreId));\n    }\n  };\n}\n\nexport interface NavigateToExploreDependencies {\n  getDataSourceSrv: () => DataSourceSrv;\n  getTimeSrv: () => TimeSrv;\n  getExploreUrl: (args: GetExploreUrlArguments) => Promise<string>;\n  openInNewWindow?: (url: string) => void;\n}\n\nexport const navigateToExplore = (\n  panel: PanelModel,\n  dependencies: NavigateToExploreDependencies\n): ThunkResult<void> => {\n  return async dispatch => {\n    const { getDataSourceSrv, getTimeSrv, getExploreUrl, openInNewWindow } = dependencies;\n    const datasourceSrv = getDataSourceSrv();\n    const datasource = await datasourceSrv.get(panel.datasource);\n    const path = await getExploreUrl({\n      panel,\n      panelTargets: panel.targets,\n      panelDatasource: datasource,\n      datasourceSrv,\n      timeSrv: getTimeSrv(),\n    });\n\n    if (openInNewWindow) {\n      openInNewWindow(path);\n      return;\n    }\n\n    const query = {}; // strips any angular query param\n    dispatch(updateLocation({ path, query }));\n  };\n};\n","// Libraries\nimport _ from 'lodash';\n\n// Services & Utils\nimport { DataQuery, DataSourceApi, ExploreMode, dateTimeFormat, AppEvents, urlUtil } from '@grafana/data';\nimport appEvents from 'app/core/app_events';\nimport store from 'app/core/store';\nimport { serializeStateToUrlParam, SortOrder } from './explore';\nimport { getExploreDatasources } from '../../features/explore/state/selectors';\n\n// Types\nimport { ExploreUrlState, RichHistoryQuery } from 'app/types/explore';\n\nconst RICH_HISTORY_KEY = 'grafana.explore.richHistory';\n\nexport const RICH_HISTORY_SETTING_KEYS = {\n  retentionPeriod: 'grafana.explore.richHistory.retentionPeriod',\n  starredTabAsFirstTab: 'grafana.explore.richHistory.starredTabAsFirstTab',\n  activeDatasourceOnly: 'grafana.explore.richHistory.activeDatasourceOnly',\n  datasourceFilters: 'grafana.explore.richHistory.datasourceFilters',\n};\n\n/*\n * Add queries to rich history. Save only queries within the retention period, or that are starred.\n * Side-effect: store history in local storage\n */\n\nexport function addToRichHistory(\n  richHistory: RichHistoryQuery[],\n  datasourceId: string,\n  datasourceName: string | null,\n  queries: DataQuery[],\n  starred: boolean,\n  comment: string | null,\n  sessionName: string\n): any {\n  const ts = Date.now();\n  /* Save only queries, that are not falsy (e.g. empty object, null, ...) */\n  const newQueriesToSave: DataQuery[] = queries && queries.filter(query => notEmptyQuery(query));\n  const retentionPeriod: number = store.getObject(RICH_HISTORY_SETTING_KEYS.retentionPeriod, 7);\n  const retentionPeriodLastTs = createRetentionPeriodBoundary(retentionPeriod, false);\n\n  /* Keep only queries, that are within the selected retention period or that are starred.\n   * If no queries, initialize with empty array\n   */\n  const queriesToKeep = richHistory.filter(q => q.ts > retentionPeriodLastTs || q.starred === true) || [];\n\n  if (newQueriesToSave.length > 0) {\n    /* Compare queries of a new query and last saved queries. If they are the same, (except selected properties,\n     * which can be different) don't save it in rich history.\n     */\n    const newQueriesToCompare = newQueriesToSave.map(q => _.omit(q, ['key', 'refId']));\n    const lastQueriesToCompare =\n      queriesToKeep.length > 0 &&\n      queriesToKeep[0].queries.map(q => {\n        return _.omit(q, ['key', 'refId']);\n      });\n\n    if (_.isEqual(newQueriesToCompare, lastQueriesToCompare)) {\n      return richHistory;\n    }\n\n    let updatedHistory = [\n      { queries: newQueriesToSave, ts, datasourceId, datasourceName, starred, comment, sessionName },\n      ...queriesToKeep,\n    ];\n\n    try {\n      store.setObject(RICH_HISTORY_KEY, updatedHistory);\n      return updatedHistory;\n    } catch (error) {\n      appEvents.emit(AppEvents.alertError, [error]);\n      return richHistory;\n    }\n  }\n\n  return richHistory;\n}\n\nexport function getRichHistory(): RichHistoryQuery[] {\n  const richHistory: RichHistoryQuery[] = store.getObject(RICH_HISTORY_KEY, []);\n  const transformedRichHistory = migrateRichHistory(richHistory);\n  return transformedRichHistory;\n}\n\nexport function deleteAllFromRichHistory() {\n  return store.delete(RICH_HISTORY_KEY);\n}\n\nexport function updateStarredInRichHistory(richHistory: RichHistoryQuery[], ts: number) {\n  const updatedHistory = richHistory.map(query => {\n    /* Timestamps are currently unique - we can use them to identify specific queries */\n    if (query.ts === ts) {\n      const isStarred = query.starred;\n      const updatedQuery = Object.assign({}, query, { starred: !isStarred });\n      return updatedQuery;\n    }\n    return query;\n  });\n\n  try {\n    store.setObject(RICH_HISTORY_KEY, updatedHistory);\n    return updatedHistory;\n  } catch (error) {\n    appEvents.emit(AppEvents.alertError, [error]);\n    return richHistory;\n  }\n}\n\nexport function updateCommentInRichHistory(\n  richHistory: RichHistoryQuery[],\n  ts: number,\n  newComment: string | undefined\n) {\n  const updatedHistory = richHistory.map(query => {\n    if (query.ts === ts) {\n      const updatedQuery = Object.assign({}, query, { comment: newComment });\n      return updatedQuery;\n    }\n    return query;\n  });\n\n  try {\n    store.setObject(RICH_HISTORY_KEY, updatedHistory);\n    return updatedHistory;\n  } catch (error) {\n    appEvents.emit(AppEvents.alertError, [error]);\n    return richHistory;\n  }\n}\n\nexport function deleteQueryInRichHistory(richHistory: RichHistoryQuery[], ts: number) {\n  const updatedHistory = richHistory.filter(query => query.ts !== ts);\n  try {\n    store.setObject(RICH_HISTORY_KEY, updatedHistory);\n    return updatedHistory;\n  } catch (error) {\n    appEvents.emit(AppEvents.alertError, [error]);\n    return richHistory;\n  }\n}\n\nexport const sortQueries = (array: RichHistoryQuery[], sortOrder: SortOrder) => {\n  let sortFunc;\n\n  if (sortOrder === SortOrder.Ascending) {\n    sortFunc = (a: RichHistoryQuery, b: RichHistoryQuery) => (a.ts < b.ts ? -1 : a.ts > b.ts ? 1 : 0);\n  }\n  if (sortOrder === SortOrder.Descending) {\n    sortFunc = (a: RichHistoryQuery, b: RichHistoryQuery) => (a.ts < b.ts ? 1 : a.ts > b.ts ? -1 : 0);\n  }\n\n  if (sortOrder === SortOrder.DatasourceZA) {\n    sortFunc = (a: RichHistoryQuery, b: RichHistoryQuery) =>\n      a.datasourceName < b.datasourceName ? -1 : a.datasourceName > b.datasourceName ? 1 : 0;\n  }\n\n  if (sortOrder === SortOrder.DatasourceAZ) {\n    sortFunc = (a: RichHistoryQuery, b: RichHistoryQuery) =>\n      a.datasourceName < b.datasourceName ? 1 : a.datasourceName > b.datasourceName ? -1 : 0;\n  }\n\n  return array.sort(sortFunc);\n};\n\nexport const copyStringToClipboard = (string: string) => {\n  const el = document.createElement('textarea');\n  el.value = string;\n  document.body.appendChild(el);\n  el.select();\n  document.execCommand('copy');\n  document.body.removeChild(el);\n};\n\nexport const createUrlFromRichHistory = (query: RichHistoryQuery) => {\n  const exploreState: ExploreUrlState = {\n    /* Default range, as we are not saving timerange in rich history */\n    range: { from: 'now-1h', to: 'now' },\n    datasource: query.datasourceName,\n    queries: query.queries,\n    /* Default mode is metrics. Exceptions are Loki (logs) and Jaeger (tracing) data sources.\n     * In the future, we can remove this as we are working on metrics & logs logic.\n     **/\n    mode:\n      query.datasourceId === 'loki'\n        ? ExploreMode.Logs\n        : query.datasourceId === 'jaeger'\n        ? ExploreMode.Tracing\n        : ExploreMode.Metrics,\n    ui: {\n      showingGraph: true,\n      showingLogs: true,\n      showingTable: true,\n    },\n    context: 'explore',\n  };\n\n  const serializedState = serializeStateToUrlParam(exploreState, true);\n  const baseUrl = /.*(?=\\/explore)/.exec(`${window.location.href}`)[0];\n  const url = urlUtil.renderUrl(`${baseUrl}/explore`, { left: serializedState });\n  return url;\n};\n\n/* Needed for slider in Rich history to map numerical values to meaningful strings */\nexport const mapNumbertoTimeInSlider = (num: number) => {\n  let str;\n  switch (num) {\n    case 0:\n      str = 'today';\n      break;\n    case 1:\n      str = 'yesterday';\n      break;\n    case 7:\n      str = 'a week ago';\n      break;\n    case 14:\n      str = 'two weeks ago';\n      break;\n    default:\n      str = `${num} days ago`;\n  }\n\n  return str;\n};\n\nexport const createRetentionPeriodBoundary = (days: number, isLastTs: boolean) => {\n  const today = new Date();\n  const date = new Date(today.setDate(today.getDate() - days));\n  /*\n   * As a retention period boundaries, we consider:\n   * - The last timestamp equals to the 24:00 of the last day of retention\n   * - The first timestamp that equals to the 00:00 of the first day of retention\n   */\n  const boundary = isLastTs ? date.setHours(24, 0, 0, 0) : date.setHours(0, 0, 0, 0);\n  return boundary;\n};\n\nexport function createDateStringFromTs(ts: number) {\n  return dateTimeFormat(ts, {\n    format: 'MMMM D',\n  });\n}\n\nexport function getQueryDisplayText(query: DataQuery): string {\n  /* If datasource doesn't have getQueryDisplayText, create query display text by\n   * stringifying query that was stripped of key, refId and datasource for nicer\n   * formatting and improved readability\n   */\n  const strippedQuery = _.omit(query, ['key', 'refId', 'datasource']);\n  return JSON.stringify(strippedQuery);\n}\n\nexport function createQueryHeading(query: RichHistoryQuery, sortOrder: SortOrder) {\n  let heading = '';\n  if (sortOrder === SortOrder.DatasourceAZ || sortOrder === SortOrder.DatasourceZA) {\n    heading = query.datasourceName;\n  } else {\n    heading = createDateStringFromTs(query.ts);\n  }\n  return heading;\n}\n\nexport function createQueryText(query: DataQuery, queryDsInstance: DataSourceApi) {\n  /* query DatasourceInstance is necessary because we use its getQueryDisplayText method\n   * to format query text\n   */\n  if (queryDsInstance?.getQueryDisplayText) {\n    return queryDsInstance.getQueryDisplayText(query);\n  }\n\n  return getQueryDisplayText(query);\n}\n\nexport function mapQueriesToHeadings(query: RichHistoryQuery[], sortOrder: SortOrder) {\n  let mappedQueriesToHeadings: any = {};\n\n  query.forEach(q => {\n    let heading = createQueryHeading(q, sortOrder);\n    if (!(heading in mappedQueriesToHeadings)) {\n      mappedQueriesToHeadings[heading] = [q];\n    } else {\n      mappedQueriesToHeadings[heading] = [...mappedQueriesToHeadings[heading], q];\n    }\n  });\n\n  return mappedQueriesToHeadings;\n}\n\n/* Create datasource list with images. If specific datasource retrieved from Rich history is not part of\n * exploreDatasources add generic datasource image and add property isRemoved = true.\n */\nexport function createDatasourcesList(queriesDatasources: string[]) {\n  const exploreDatasources = getExploreDatasources();\n  const datasources: Array<{ label: string; value: string; imgUrl: string; isRemoved: boolean }> = [];\n\n  queriesDatasources.forEach(queryDsName => {\n    const index = exploreDatasources.findIndex(exploreDs => exploreDs.name === queryDsName);\n    if (index !== -1) {\n      datasources.push({\n        label: queryDsName,\n        value: queryDsName,\n        imgUrl: exploreDatasources[index].meta.info.logos.small,\n        isRemoved: false,\n      });\n    } else {\n      datasources.push({\n        label: queryDsName,\n        value: queryDsName,\n        imgUrl: 'public/img/icn-datasource.svg',\n        isRemoved: true,\n      });\n    }\n  });\n  return datasources;\n}\n\nexport function notEmptyQuery(query: DataQuery) {\n  /* Check if query has any other properties besides key, refId and datasource.\n   * If not, then we consider it empty query.\n   */\n  const strippedQuery = _.omit(query, ['key', 'refId', 'datasource']);\n  const queryKeys = Object.keys(strippedQuery);\n\n  if (queryKeys.length > 0) {\n    return true;\n  }\n\n  return false;\n}\n\n/* These functions are created to migrate string queries (from 6.7 release) to DataQueries. They can be removed after 7.1 release. */\nfunction migrateRichHistory(richHistory: RichHistoryQuery[]) {\n  const transformedRichHistory = richHistory.map(query => {\n    const transformedQueries: DataQuery[] = query.queries.map((q, index) => createDataQuery(query, q, index));\n    return { ...query, queries: transformedQueries };\n  });\n\n  return transformedRichHistory;\n}\n\nfunction createDataQuery(query: RichHistoryQuery, individualQuery: DataQuery | string, index: number) {\n  const letters = 'ABCDEFGHIJKLMNOPQRSTUVXYZ';\n  if (typeof individualQuery === 'object') {\n    return individualQuery;\n  } else if (isParsable(individualQuery)) {\n    return JSON.parse(individualQuery);\n  }\n  return { expr: individualQuery, refId: letters[index] };\n}\n\nfunction isParsable(string: string) {\n  try {\n    JSON.parse(string);\n  } catch (e) {\n    return false;\n  }\n  return true;\n}\n"],"sourceRoot":""}