{"version":3,"sources":["webpack:///./public/app/features/dashboard/state/initDashboard.ts","webpack:///./public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderCorner.tsx","webpack:///./public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx","webpack:///./public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenu.tsx","webpack:///./public/app/features/dashboard/utils/getPanelMenu.ts","webpack:///./public/app/features/dashboard/dashgrid/PanelHeader/PanelHeader.tsx","webpack:///./public/app/features/dashboard/dashgrid/PanelChrome.tsx","webpack:///./public/app/features/dashboard/dashgrid/PanelChromeAngular.tsx","webpack:///./public/app/features/dashboard/dashgrid/DashboardPanel.tsx","webpack:///./public/app/features/dashboard/components/Inspector/InspectSubtitle.tsx","webpack:///./public/app/features/dashboard/components/Inspector/styles.ts","webpack:///./public/app/features/dashboard/components/Inspector/InspectJSONTab.tsx","webpack:///./public/app/features/dashboard/components/Inspector/QueryInspector.tsx","webpack:///./public/app/features/dashboard/components/Inspector/PanelInspector.tsx","webpack:///./public/app/features/dashboard/components/Inspector/InspectDataTab.tsx","webpack:///./public/app/features/dashboard/components/PanelEditor/utils.ts"],"names":["redirectToNewUrl","slug","dispatch","currentPath","backendSrv","getDashboardBySlug","res","newUrl","meta","url","indexOf","replace","locationUtil","stripBaseFromUrl","updateLocation","path","partial","fetchDashboard","args","getState","routeInfo","DashboardRouteInfo","Home","Normal","New","get","dashDTO","redirectUri","canSave","canShare","canStar","urlType","urlSlug","location","loaderSrv","$injector","loadDashboard","urlUid","fixUrl","dashboardUrl","getNewDashboardModelData","urlFolderId","message","dashboardInitFailed","error","console","log","initDashboard","dashboardInitFetching","setTimeout","dashboard","getModel","dashboardInitSlow","dashboardInitServices","DashboardModel","storeState","query","orgId","user","timeSrv","annotationsSrv","variableSrv","keybindingSrv","unsavedChangesSrv","dashboardSrv","init","modifiedQueries","panelId","queries","fromExplore","getConfig","featureToggles","newVariables","initDashboardTemplating","templating","list","processVariables","completeDashboardTemplating","notifyApp","createErrorNotification","processRepeats","updateSubmenuVisibility","queryParams","autofitpanels","autoFitPanels","window","innerHeight","kiosk","$scope","setupDashboardBindings","err","updateQueriesWhenComingFromExplore","setCurrent","emitDashboardViewEvent","dashboardInitCompleted","data","isNew","folderId","title","panels","type","gridPos","x","y","w","h","parseInt","originPanelId","panelArrId","findIndex","panel","id","targets","clearDashboardQueriesToUpdateOnLoad","InfoMode","PanelHeaderCorner","getTimeSrv","getInfoMode","props","Error","description","Info","links","length","Links","getInfoContent","markdown","interpolatedMarkdown","templateSrv","scopedVars","markedInterpolatedMarkdown","renderMarkdown","getLinks","className","dangerouslySetInnerHTML","__html","map","link","idx","key","href","target","onClickError","getLocationSrv","update","inspect","tab","InspectTab","infoMode","content","onClick","theme","placement","toLowerCase","this","renderCornerType","Component","PanelHeaderMenuItem","isSubMenu","isDivider","useTheme","menuIconClassName","css","spacing","sm","shortcutIconClassName","xs","colors","textWeak","undefined","iconClassName","name","aria-label","selectors","components","Panels","Panel","headerItems","text","shortcut","children","PanelHeaderMenu","renderItems","menu","role","menuItem","subMenu","items","PureComponent","getPanelMenu","angularComponent","onInspectPanel","event","preventDefault","inspectTab","isEditing","push","store","viewPanel","canEditPanel","editPanel","sharePanel","contextSrv","hasAccessToExplore","plugin","skipDataQuery","openInNewWindow","ctrlKey","metaKey","open","navigateToExplore","getDataSourceSrv","getExploreUrl","inspectMenu","e","canEdit","isViewing","duplicatePanel","copyPanel","scope","getScope","panelCtrl","$$childHead","ctrl","angularMenuItems","getExtendedMenu","item","reactItem","click","$eval","removePanel","PanelHeader","clickCoordinates","state","panelMenuOpen","menuItems","eventToClickCoordinates","clientX","clientY","onMouseDown","isClick","isEqual","onMenuToggle","stopPropagation","setState","closeMenu","openInspect","renderNotice","notice","severity","style","marginRight","alertState","replaceWithText","panelHeaderClass","classNames","notices","series","LoadingState","Loading","renderLoadingState","getPanelLinksSupplier","Object","values","size","request","timeInfo","PanelChrome","onRefresh","isInView","width","refreshWhenInView","timeData","applyPanelTimeOverrides","timeRange","wantsQueryExecution","getQueryRunner","run","datasource","dashboardId","timezone","getTimezone","maxDataPoints","minInterval","interval","cacheTimeout","transformations","onRender","stateUpdate","renderCounter","onOptionsChange","options","updateOptions","onFieldConfigChange","config","updateFieldConfig","onPanelError","errorMessage","onChangeTimeRange","setTime","from","toUtc","to","isFirstLoad","NotStarted","DefaultTimeRange","events","on","PanelEvents","refresh","render","panelInitialized","hasPanelSnapshot","Done","getProcessedDataFrames","snapshotData","querySubscription","getData","withTransforms","withFieldConfig","subscribe","next","onDataUpdate","off","unsubscribe","prevProps","snapshot","frame","toDataFrameDTO","height","loading","profiler","renderingCompleted","PanelComponent","headerHeight","hasOverlayHeader","panelHeaderHeight","chromePadding","noPadding","panelPadding","panelWidth","PANEL_BORDER","innerPanelHeight","panelContentClassNames","panelOptions","getOptions","timeZone","fieldConfig","transparent","replaceVariables","hasTitle","containerClassNames","containerByTitle","renderPanel","PanelChromeAngularUnconnected","element","onPanelRenderEvent","payload","alert","forceUpdate","loadAngularPanel","queryRunner","onPanelDataUpdate","cleanUpAngularPanel","prevState","scopeProps","getInnerPanelHeight","getInnerPanelWidth","emit","panelSizeChanged","setPanelAngularComponent","loader","getAngularLoader","load","subscribeToRenderEvent","destroy","ref","mapDispatchToProps","PanelChromeAngular","connect","DashboardPanelUnconnected","specialPanels","onMouseEnter","setPanelFocus","onMouseLeave","isLazy","initDashboardPanel","angularPanelCtrl","panelWrapperClass","DashboardPanel","panelState","InspectSubtitle","tabs","onSelectTab","panelData","styles","getStyles","queryCount","requestTime","endTime","startTime","formatted","formattedValueToString","getValueFormat","formatStats","tabsBar","t","index","value","label","active","onChangeTab","stylesFactory","md","lg","ShowContent","getPanelInspectorStyles","wrap","toolbar","toolbarItem","contentQueryInspector","editor","viewer","dataFrameSelect","tabContent","dataTabContent","actionsWrapper","leftActions","dataDisplayOptions","selects","PanelJSON","PanelData","DataStructure","InspectJSONTab","onSelectChanged","getSaveModelJSON","show","onTextChanged","currentTarget","getJSONObject","fields","field","chain","omit","note","getSaveModel","getClipboardText","obj","JSON","stringify","onClipboardCopied","appEvents","AppEvents","alertSuccess","onApplyPanelModel","onClose","updates","parse","restoreModel","alertError","spellCheck","onChange","selected","find","v","isPanelJSON","PanelInspector","Json","variant","getText","onClipboardCopy","renderPanelJSON","json","QueryInspector","onIssueNewQuery","onPanelRefresh","dsQuery","isLoading","response","onRequestError","onDataSourceResponse","isMocking","handleMocking","headers","transformRequest","transformResponse","paramSerializer","jsonpCallbackParam","requestId","retry","timeout","status","statusText","ok","redirected","$$config","setFormattedJson","formattedJson","getTextForClipboard","onClipboardSuccess","onToggleExpand","allNodesExpanded","onToggleMocking","getNrOfOpenNodes","setMockedResponse","evt","mockedResponse","CoreEvents","dsRequestResponse","dsRequestError","mockedData","openNodes","haveData","keys","supportsDataQuery","Query","icon","refreshButton","CopyToClipboard","onSuccess","elType","onDidRender","Switch","LegacyForms","InspectDataTab","exportCsv","dataFrame","transformId","getTimeField","timeIndex","timeField","processor","display","getDisplayProcessor","formattedDateField","FieldType","string","FormattedVector","dataFrameCsv","toCSV","blob","Blob","transformation","DataTransformerID","noop","toLocaleLowerCase","fileName","dateTimeFormat","Date","saveAs","onSelectedFrameChanged","dataFrameIndex","onTransformationChange","renderDataOptions","panelTransformations","getTransformations","showPanelTransformationsOption","showFieldConfigsOption","fieldConfigRegistry","isEmpty","cx","QueryOperationRow","isOpen","tooltip","labelClass","checked","transformationOptions","transformer","seriesToColumns","byField","currentTransform","transformDataFrame","getTransformedData","applyFieldOverrides","defaults","overrides","dataFrames","getProcessedData","choices","getFrameDisplayName","Data","flexGrow","PanelInspectorUnconnected","drawerWidth","currentTab","onDataTabOptionsChange","last","defaultTab","onUpdateData","lastResult","custom","dataSource","MetadataInspector","metaDS","stats","processingTime","timings","dataProcessingTime","dataRows","displayName","unit","dataStats","concat","Stats","renderStatsTable","paddingBottom","stat","textAlign","number","formatStat","activeTab","Meta","getTabs","subtitle","drawerSubtitle","expandable","renderDataTab","autoHeightMin","renderMetadataInspector","renderErrorTab","renderStatsTab","calculatePanelSize","mode","DisplayMode","Fill","pWidth","innerWidth","GRID_CELL_VMARGIN","GRID_COLUMN_COUNT","pHeight","GRID_CELL_HEIGHT","scale","Math","min","Exact"],"mappings":"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","file":"default~DashboardPage~SoloPanelPage.d3489276abe5fda2bd26.js","sourcesContent":["// Services & Utils\nimport { createErrorNotification } from 'app/core/copy/appNotification';\nimport { backendSrv } from 'app/core/services/backend_srv';\nimport { DashboardSrv } from 'app/features/dashboard/services/DashboardSrv';\nimport { DashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';\nimport { TimeSrv } from 'app/features/dashboard/services/TimeSrv';\nimport { AnnotationsSrv } from 'app/features/annotations/annotations_srv';\nimport { VariableSrv } from 'app/features/templating/variable_srv';\nimport { KeybindingSrv } from 'app/core/services/keybindingSrv';\n// Actions\nimport { notifyApp, updateLocation } from 'app/core/actions';\nimport {\n  clearDashboardQueriesToUpdateOnLoad,\n  dashboardInitCompleted,\n  dashboardInitFailed,\n  dashboardInitFetching,\n  dashboardInitServices,\n  dashboardInitSlow,\n} from './reducers';\n// Types\nimport { DashboardDTO, DashboardRouteInfo, StoreState, ThunkDispatch, ThunkResult } from 'app/types';\nimport { DashboardModel } from './DashboardModel';\nimport { DataQuery, locationUtil } from '@grafana/data';\nimport { getConfig } from '../../../core/config';\nimport { initDashboardTemplating, processVariables, completeDashboardTemplating } from '../../variables/state/actions';\nimport { emitDashboardViewEvent } from './analyticsProcessor';\n\nexport interface InitDashboardArgs {\n  $injector: any;\n  $scope: any;\n  urlUid?: string;\n  urlSlug?: string;\n  urlType?: string;\n  urlFolderId?: string;\n  routeInfo: DashboardRouteInfo;\n  fixUrl: boolean;\n}\n\nasync function redirectToNewUrl(slug: string, dispatch: ThunkDispatch, currentPath: string) {\n  const res = await backendSrv.getDashboardBySlug(slug);\n\n  if (res) {\n    let newUrl = res.meta.url;\n\n    // fix solo route urls\n    if (currentPath.indexOf('dashboard-solo') !== -1) {\n      newUrl = newUrl.replace('/d/', '/d-solo/');\n    }\n\n    const url = locationUtil.stripBaseFromUrl(newUrl);\n    dispatch(updateLocation({ path: url, partial: true, replace: true }));\n  }\n}\n\nasync function fetchDashboard(\n  args: InitDashboardArgs,\n  dispatch: ThunkDispatch,\n  getState: () => StoreState\n): Promise<DashboardDTO | null> {\n  try {\n    switch (args.routeInfo) {\n      case DashboardRouteInfo.Home: {\n        // load home dash\n        const dashDTO: DashboardDTO = await backendSrv.get('/api/dashboards/home');\n\n        // if user specified a custom home dashboard redirect to that\n        if (dashDTO.redirectUri) {\n          const newUrl = locationUtil.stripBaseFromUrl(dashDTO.redirectUri);\n          dispatch(updateLocation({ path: newUrl, replace: true }));\n          return null;\n        }\n\n        // disable some actions on the default home dashboard\n        dashDTO.meta.canSave = false;\n        dashDTO.meta.canShare = false;\n        dashDTO.meta.canStar = false;\n        return dashDTO;\n      }\n      case DashboardRouteInfo.Normal: {\n        // for old db routes we redirect\n        if (args.urlType === 'db') {\n          redirectToNewUrl(args.urlSlug, dispatch, getState().location.path);\n          return null;\n        }\n\n        const loaderSrv: DashboardLoaderSrv = args.$injector.get('dashboardLoaderSrv');\n        const dashDTO: DashboardDTO = await loaderSrv.loadDashboard(args.urlType, args.urlSlug, args.urlUid);\n\n        if (args.fixUrl && dashDTO.meta.url) {\n          // check if the current url is correct (might be old slug)\n          const dashboardUrl = locationUtil.stripBaseFromUrl(dashDTO.meta.url);\n          const currentPath = getState().location.path;\n\n          if (dashboardUrl !== currentPath) {\n            // replace url to not create additional history items and then return so that initDashboard below isn't executed multiple times.\n            dispatch(updateLocation({ path: dashboardUrl, partial: true, replace: true }));\n            return null;\n          }\n        }\n        return dashDTO;\n      }\n      case DashboardRouteInfo.New: {\n        return getNewDashboardModelData(args.urlFolderId);\n      }\n      default:\n        throw { message: 'Unknown route ' + args.routeInfo };\n    }\n  } catch (err) {\n    dispatch(dashboardInitFailed({ message: 'Failed to fetch dashboard', error: err }));\n    console.log(err);\n    return null;\n  }\n}\n\n/**\n * This action (or saga) does everything needed to bootstrap a dashboard & dashboard model.\n * First it handles the process of fetching the dashboard, correcting the url if required (causing redirects/url updates)\n *\n * This is used both for single dashboard & solo panel routes, home & new dashboard routes.\n *\n * Then it handles the initializing of the old angular services that the dashboard components & panels still depend on\n *\n */\nexport function initDashboard(args: InitDashboardArgs): ThunkResult<void> {\n  return async (dispatch, getState) => {\n    // set fetching state\n    dispatch(dashboardInitFetching());\n\n    // Detect slow loading / initializing and set state flag\n    // This is in order to not show loading indication for fast loading dashboards as it creates blinking/flashing\n    setTimeout(() => {\n      if (getState().dashboard.getModel() === null) {\n        dispatch(dashboardInitSlow());\n      }\n    }, 500);\n\n    // fetch dashboard data\n    const dashDTO = await fetchDashboard(args, dispatch, getState);\n\n    // returns null if there was a redirect or error\n    if (!dashDTO) {\n      return;\n    }\n\n    // set initializing state\n    dispatch(dashboardInitServices());\n\n    // create model\n    let dashboard: DashboardModel;\n    try {\n      dashboard = new DashboardModel(dashDTO.dashboard, dashDTO.meta);\n    } catch (err) {\n      dispatch(dashboardInitFailed({ message: 'Failed create dashboard model', error: err }));\n      console.log(err);\n      return;\n    }\n\n    // add missing orgId query param\n    const storeState = getState();\n    if (!storeState.location.query.orgId) {\n      dispatch(updateLocation({ query: { orgId: storeState.user.orgId }, partial: true, replace: true }));\n    }\n\n    // init services\n    const timeSrv: TimeSrv = args.$injector.get('timeSrv');\n    const annotationsSrv: AnnotationsSrv = args.$injector.get('annotationsSrv');\n    const variableSrv: VariableSrv = args.$injector.get('variableSrv');\n    const keybindingSrv: KeybindingSrv = args.$injector.get('keybindingSrv');\n    const unsavedChangesSrv = args.$injector.get('unsavedChangesSrv');\n    const dashboardSrv: DashboardSrv = args.$injector.get('dashboardSrv');\n\n    timeSrv.init(dashboard);\n    annotationsSrv.init(dashboard);\n\n    if (storeState.dashboard.modifiedQueries) {\n      const { panelId, queries } = storeState.dashboard.modifiedQueries;\n      dashboard.meta.fromExplore = !!(panelId && queries);\n    }\n\n    // template values service needs to initialize completely before\n    // the rest of the dashboard can load\n    try {\n      if (!getConfig().featureToggles.newVariables) {\n        await variableSrv.init(dashboard);\n      }\n      if (getConfig().featureToggles.newVariables) {\n        dispatch(initDashboardTemplating(dashboard.templating.list));\n        await dispatch(processVariables());\n        dispatch(completeDashboardTemplating(dashboard));\n      }\n    } catch (err) {\n      dispatch(notifyApp(createErrorNotification('Templating init failed', err)));\n      console.log(err);\n    }\n\n    try {\n      dashboard.processRepeats();\n      dashboard.updateSubmenuVisibility();\n\n      // handle auto fix experimental feature\n      const queryParams = getState().location.query;\n      if (queryParams.autofitpanels) {\n        dashboard.autoFitPanels(window.innerHeight, queryParams.kiosk);\n      }\n\n      // init unsaved changes tracking\n      unsavedChangesSrv.init(dashboard, args.$scope);\n      keybindingSrv.setupDashboardBindings(args.$scope, dashboard);\n    } catch (err) {\n      dispatch(notifyApp(createErrorNotification('Dashboard init failed', err)));\n      console.log(err);\n    }\n\n    if (storeState.dashboard.modifiedQueries) {\n      const { panelId, queries } = storeState.dashboard.modifiedQueries;\n      updateQueriesWhenComingFromExplore(dispatch, dashboard, panelId, queries);\n    }\n\n    // legacy srv state\n    dashboardSrv.setCurrent(dashboard);\n\n    // send open dashboard event\n    if (args.routeInfo !== DashboardRouteInfo.New) {\n      emitDashboardViewEvent(dashboard);\n    }\n\n    // yay we are done\n    dispatch(dashboardInitCompleted(dashboard));\n  };\n}\n\nfunction getNewDashboardModelData(urlFolderId?: string): any {\n  const data = {\n    meta: {\n      canStar: false,\n      canShare: false,\n      isNew: true,\n      folderId: 0,\n    },\n    dashboard: {\n      title: 'New dashboard',\n      panels: [\n        {\n          type: 'add-panel',\n          gridPos: { x: 0, y: 0, w: 12, h: 9 },\n          title: 'Panel Title',\n        },\n      ],\n    },\n  };\n\n  if (urlFolderId) {\n    data.meta.folderId = parseInt(urlFolderId, 10);\n  }\n\n  return data;\n}\n\nfunction updateQueriesWhenComingFromExplore(\n  dispatch: ThunkDispatch,\n  dashboard: DashboardModel,\n  originPanelId: number,\n  queries: DataQuery[]\n) {\n  const panelArrId = dashboard.panels.findIndex(panel => panel.id === originPanelId);\n\n  if (panelArrId > -1) {\n    dashboard.panels[panelArrId].targets = queries;\n  }\n\n  // Clear update state now that we're done\n  dispatch(clearDashboardQueriesToUpdateOnLoad());\n}\n","import React, { Component } from 'react';\n\nimport { renderMarkdown, LinkModelSupplier, ScopedVars } from '@grafana/data';\nimport { Tooltip, PopoverContent } from '@grafana/ui';\nimport { getLocationSrv } from '@grafana/runtime';\n\nimport { PanelModel } from 'app/features/dashboard/state/PanelModel';\nimport templateSrv from 'app/features/templating/template_srv';\nimport { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';\nimport { InspectTab } from '../../components/Inspector/PanelInspector';\n\nenum InfoMode {\n  Error = 'Error',\n  Info = 'Info',\n  Links = 'Links',\n}\n\ninterface Props {\n  panel: PanelModel;\n  title?: string;\n  description?: string;\n  scopedVars?: ScopedVars;\n  links?: LinkModelSupplier<PanelModel>;\n  error?: string;\n}\n\nexport class PanelHeaderCorner extends Component<Props> {\n  timeSrv: TimeSrv = getTimeSrv();\n\n  getInfoMode = () => {\n    const { panel, error } = this.props;\n    if (error) {\n      return InfoMode.Error;\n    }\n    if (!!panel.description) {\n      return InfoMode.Info;\n    }\n    if (panel.links && panel.links.length) {\n      return InfoMode.Links;\n    }\n\n    return undefined;\n  };\n\n  getInfoContent = (): JSX.Element => {\n    const { panel } = this.props;\n    const markdown = panel.description || '';\n    const interpolatedMarkdown = templateSrv.replace(markdown, panel.scopedVars);\n    const markedInterpolatedMarkdown = renderMarkdown(interpolatedMarkdown);\n    const links = this.props.links && this.props.links.getLinks(panel);\n\n    return (\n      <div className=\"panel-info-content markdown-html\">\n        <div dangerouslySetInnerHTML={{ __html: markedInterpolatedMarkdown }} />\n\n        {links && links.length > 0 && (\n          <ul className=\"panel-info-corner-links\">\n            {links.map((link, idx) => {\n              return (\n                <li key={idx}>\n                  <a className=\"panel-info-corner-links__item\" href={link.href} target={link.target}>\n                    {link.title}\n                  </a>\n                </li>\n              );\n            })}\n          </ul>\n        )}\n      </div>\n    );\n  };\n\n  /**\n   * Open the Panel Inspector when we click on an error\n   */\n  onClickError = () => {\n    getLocationSrv().update({ partial: true, query: { inspect: this.props.panel.id, tab: InspectTab.Error } });\n  };\n\n  renderCornerType(infoMode: InfoMode, content: PopoverContent, onClick?: () => void) {\n    const theme = infoMode === InfoMode.Error ? 'error' : 'info';\n    return (\n      <Tooltip content={content} placement=\"top-start\" theme={theme}>\n        <div className={`panel-info-corner panel-info-corner--${infoMode.toLowerCase()}`} onClick={onClick}>\n          <i className=\"fa\" />\n          <span className=\"panel-info-corner-inner\" />\n        </div>\n      </Tooltip>\n    );\n  }\n\n  render() {\n    const { error } = this.props;\n    const infoMode: InfoMode | undefined = this.getInfoMode();\n\n    if (!infoMode) {\n      return null;\n    }\n\n    if (infoMode === InfoMode.Error && error) {\n      return this.renderCornerType(infoMode, error, this.onClickError);\n    }\n\n    if (infoMode === InfoMode.Info || infoMode === InfoMode.Links) {\n      return this.renderCornerType(infoMode, this.getInfoContent);\n    }\n\n    return null;\n  }\n}\n\nexport default PanelHeaderCorner;\n","import React, { FC } from 'react';\nimport { css } from 'emotion';\nimport { PanelMenuItem } from '@grafana/data';\nimport { Icon, IconName, useTheme } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\n\ninterface Props {\n  children: any;\n}\n\nexport const PanelHeaderMenuItem: FC<Props & PanelMenuItem> = props => {\n  const isSubMenu = props.type === 'submenu';\n  const isDivider = props.type === 'divider';\n  const theme = useTheme();\n  const menuIconClassName = css`\n    margin-right: ${theme.spacing.sm};\n    a::after {\n      display: none;\n    }\n  `;\n  const shortcutIconClassName = css`\n    position: absolute;\n    top: 7px;\n    right: ${theme.spacing.xs};\n    color: ${theme.colors.textWeak};\n  `;\n  return isDivider ? (\n    <li className=\"divider\" />\n  ) : (\n    <li className={isSubMenu ? 'dropdown-submenu' : undefined}>\n      <a onClick={props.onClick} href={props.href}>\n        {props.iconClassName && <Icon name={props.iconClassName as IconName} className={menuIconClassName} />}\n        <span className=\"dropdown-item-text\" aria-label={selectors.components.Panels.Panel.headerItems(props.text)}>\n          {props.text}\n          {isSubMenu && <Icon name=\"angle-right\" className={shortcutIconClassName} />}\n        </span>\n        {props.shortcut && (\n          <span className=\"dropdown-menu-item-shortcut\">\n            <Icon name=\"keyboard\" className={menuIconClassName} /> {props.shortcut}\n          </span>\n        )}\n      </a>\n      {props.children}\n    </li>\n  );\n};\n","import React, { PureComponent } from 'react';\nimport { PanelHeaderMenuItem } from './PanelHeaderMenuItem';\nimport { PanelMenuItem } from '@grafana/data';\n\nexport interface Props {\n  items: PanelMenuItem[];\n}\n\nexport class PanelHeaderMenu extends PureComponent<Props> {\n  renderItems = (menu: PanelMenuItem[], isSubMenu = false) => {\n    return (\n      <ul className=\"dropdown-menu dropdown-menu--menu panel-menu\" role={isSubMenu ? '' : 'menu'}>\n        {menu.map((menuItem, idx: number) => {\n          return (\n            <PanelHeaderMenuItem\n              key={`${menuItem.text}${idx}`}\n              type={menuItem.type}\n              text={menuItem.text}\n              iconClassName={menuItem.iconClassName}\n              onClick={menuItem.onClick}\n              shortcut={menuItem.shortcut}\n            >\n              {menuItem.subMenu && this.renderItems(menuItem.subMenu, true)}\n            </PanelHeaderMenuItem>\n          );\n        })}\n      </ul>\n    );\n  };\n\n  render() {\n    return <div className=\"panel-menu-container dropdown open\">{this.renderItems(this.props.items)}</div>;\n  }\n}\n","import { updateLocation } from 'app/core/actions';\nimport { store } from 'app/store/store';\nimport { AngularComponent, getDataSourceSrv, getLocationSrv } from '@grafana/runtime';\nimport { PanelMenuItem } from '@grafana/data';\nimport { copyPanel, duplicatePanel, removePanel, sharePanel } from 'app/features/dashboard/utils/panel';\nimport { PanelModel } from 'app/features/dashboard/state/PanelModel';\nimport { DashboardModel } from 'app/features/dashboard/state/DashboardModel';\nimport { contextSrv } from '../../../core/services/context_srv';\nimport { navigateToExplore } from '../../explore/state/actions';\nimport { getExploreUrl } from '../../../core/utils/explore';\nimport { getTimeSrv } from '../services/TimeSrv';\nimport { PanelCtrl } from '../../panel/panel_ctrl';\n\nexport function getPanelMenu(\n  dashboard: DashboardModel,\n  panel: PanelModel,\n  angularComponent?: AngularComponent | null\n): PanelMenuItem[] {\n  const onViewPanel = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n    store.dispatch(\n      updateLocation({\n        query: {\n          viewPanel: panel.id,\n        },\n        partial: true,\n      })\n    );\n  };\n\n  const onEditPanel = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n    store.dispatch(\n      updateLocation({\n        query: {\n          editPanel: panel.id,\n        },\n        partial: true,\n      })\n    );\n  };\n\n  const onSharePanel = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n    sharePanel(dashboard, panel);\n  };\n\n  const onInspectPanel = (tab?: string) => {\n    event.preventDefault();\n\n    getLocationSrv().update({\n      partial: true,\n      query: {\n        inspect: panel.id,\n        inspectTab: tab,\n      },\n    });\n  };\n\n  const onMore = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n  };\n\n  const onDuplicatePanel = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n    duplicatePanel(dashboard, panel);\n  };\n\n  const onCopyPanel = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n    copyPanel(panel);\n  };\n\n  const onRemovePanel = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n    removePanel(dashboard, panel, true);\n  };\n\n  const onNavigateToExplore = (event: React.MouseEvent<any>) => {\n    event.preventDefault();\n    const openInNewWindow = event.ctrlKey || event.metaKey ? (url: string) => window.open(url) : undefined;\n    store.dispatch(navigateToExplore(panel, { getDataSourceSrv, getTimeSrv, getExploreUrl, openInNewWindow }) as any);\n  };\n\n  const menu: PanelMenuItem[] = [];\n\n  if (!panel.isEditing) {\n    menu.push({\n      text: 'View',\n      iconClassName: 'eye',\n      onClick: onViewPanel,\n      shortcut: 'v',\n    });\n  }\n\n  if (dashboard.canEditPanel(panel) && !panel.isEditing) {\n    menu.push({\n      text: 'Edit',\n      iconClassName: 'edit',\n      onClick: onEditPanel,\n      shortcut: 'e',\n    });\n  }\n\n  menu.push({\n    text: 'Share',\n    iconClassName: 'share-alt',\n    onClick: onSharePanel,\n    shortcut: 'p s',\n  });\n\n  if (contextSrv.hasAccessToExplore() && !(panel.plugin && panel.plugin.meta.skipDataQuery)) {\n    menu.push({\n      text: 'Explore',\n      iconClassName: 'compass',\n      shortcut: 'x',\n      onClick: onNavigateToExplore,\n    });\n  }\n\n  const inspectMenu: PanelMenuItem[] = [];\n\n  // Only show these inspect actions for data plugins\n  if (panel.plugin && !panel.plugin.meta.skipDataQuery) {\n    inspectMenu.push({\n      text: 'Data',\n      onClick: (e: React.MouseEvent<any>) => onInspectPanel('data'),\n    });\n\n    if (dashboard.meta.canEdit) {\n      inspectMenu.push({\n        text: 'Query',\n        onClick: (e: React.MouseEvent<any>) => onInspectPanel('query'),\n      });\n    }\n  }\n\n  inspectMenu.push({\n    text: 'Panel JSON',\n    onClick: (e: React.MouseEvent<any>) => onInspectPanel('json'),\n  });\n\n  menu.push({\n    type: 'submenu',\n    text: 'Inspect',\n    iconClassName: 'info-circle',\n    onClick: (e: React.MouseEvent<any>) => onInspectPanel(),\n    shortcut: 'i',\n    subMenu: inspectMenu,\n  });\n\n  const subMenu: PanelMenuItem[] = [];\n\n  if (dashboard.canEditPanel(panel) && !(panel.isViewing || panel.isEditing)) {\n    subMenu.push({\n      text: 'Duplicate',\n      onClick: onDuplicatePanel,\n      shortcut: 'p d',\n    });\n\n    subMenu.push({\n      text: 'Copy',\n      onClick: onCopyPanel,\n    });\n  }\n\n  // add old angular panel options\n  if (angularComponent) {\n    const scope = angularComponent.getScope();\n    const panelCtrl: PanelCtrl = scope.$$childHead.ctrl;\n    const angularMenuItems = panelCtrl.getExtendedMenu();\n\n    for (const item of angularMenuItems) {\n      const reactItem: PanelMenuItem = {\n        text: item.text,\n        href: item.href,\n        shortcut: item.shortcut,\n      };\n\n      if (item.click) {\n        reactItem.onClick = () => {\n          scope.$eval(item.click, { ctrl: panelCtrl });\n        };\n      }\n\n      subMenu.push(reactItem);\n    }\n  }\n\n  if (!panel.isEditing && subMenu.length) {\n    menu.push({\n      type: 'submenu',\n      text: 'More...',\n      iconClassName: 'cube',\n      subMenu,\n      onClick: onMore,\n    });\n  }\n\n  if (dashboard.canEditPanel(panel) && !panel.isEditing) {\n    menu.push({ type: 'divider' });\n\n    menu.push({\n      text: 'Remove',\n      iconClassName: 'trash-alt',\n      onClick: onRemovePanel,\n      shortcut: 'p r',\n    });\n  }\n\n  return menu;\n}\n","import React, { Component } from 'react';\nimport classNames from 'classnames';\nimport { isEqual } from 'lodash';\nimport { DataLink, LoadingState, PanelData, PanelMenuItem, QueryResultMetaNotice, ScopedVars } from '@grafana/data';\nimport { AngularComponent } from '@grafana/runtime';\nimport { ClickOutsideWrapper, Icon, Tooltip } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\n\nimport PanelHeaderCorner from './PanelHeaderCorner';\nimport { PanelHeaderMenu } from './PanelHeaderMenu';\nimport templateSrv from 'app/features/templating/template_srv';\n\nimport { DashboardModel } from 'app/features/dashboard/state/DashboardModel';\nimport { PanelModel } from 'app/features/dashboard/state/PanelModel';\nimport { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';\nimport { getPanelMenu } from 'app/features/dashboard/utils/getPanelMenu';\nimport { updateLocation } from 'app/core/actions';\n\nexport interface Props {\n  panel: PanelModel;\n  dashboard: DashboardModel;\n  title?: string;\n  description?: string;\n  scopedVars?: ScopedVars;\n  angularComponent?: AngularComponent | null;\n  links?: DataLink[];\n  error?: string;\n  alertState?: string;\n  isViewing: boolean;\n  isEditing: boolean;\n  data: PanelData;\n  updateLocation: typeof updateLocation;\n}\n\ninterface ClickCoordinates {\n  x: number;\n  y: number;\n}\n\ninterface State {\n  panelMenuOpen: boolean;\n  menuItems: PanelMenuItem[];\n}\n\nexport class PanelHeader extends Component<Props, State> {\n  clickCoordinates: ClickCoordinates = { x: 0, y: 0 };\n\n  state: State = {\n    panelMenuOpen: false,\n    menuItems: [],\n  };\n\n  eventToClickCoordinates = (event: React.MouseEvent<HTMLDivElement>) => {\n    return {\n      x: event.clientX,\n      y: event.clientY,\n    };\n  };\n\n  onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {\n    this.clickCoordinates = this.eventToClickCoordinates(event);\n  };\n\n  isClick = (clickCoordinates: ClickCoordinates) => {\n    return isEqual(clickCoordinates, this.clickCoordinates);\n  };\n\n  onMenuToggle = (event: React.MouseEvent<HTMLDivElement>) => {\n    if (!this.isClick(this.eventToClickCoordinates(event))) {\n      return;\n    }\n\n    event.stopPropagation();\n\n    const { dashboard, panel, angularComponent } = this.props;\n    const menuItems = getPanelMenu(dashboard, panel, angularComponent);\n\n    this.setState({\n      panelMenuOpen: !this.state.panelMenuOpen,\n      menuItems,\n    });\n  };\n\n  closeMenu = () => {\n    this.setState({\n      panelMenuOpen: false,\n    });\n  };\n\n  private renderLoadingState(): JSX.Element {\n    return (\n      <div className=\"panel-loading\">\n        <Icon className=\"fa-spin\" name=\"fa fa-spinner\" />\n      </div>\n    );\n  }\n\n  openInspect = (e: React.SyntheticEvent, tab: string) => {\n    const { updateLocation, panel } = this.props;\n\n    e.stopPropagation();\n\n    updateLocation({\n      query: { inspect: panel.id, inspectTab: tab },\n      partial: true,\n    });\n  };\n\n  renderNotice = (notice: QueryResultMetaNotice) => {\n    return (\n      <Tooltip content={notice.text} key={notice.severity}>\n        {notice.inspect ? (\n          <div className=\"panel-info-notice pointer\" onClick={e => this.openInspect(e, notice.inspect!)}>\n            <Icon name=\"info-circle\" style={{ marginRight: '8px' }} />\n          </div>\n        ) : (\n          <a className=\"panel-info-notice\" href={notice.link} target=\"_blank\">\n            <Icon name=\"info-circle\" style={{ marginRight: '8px' }} />\n          </a>\n        )}\n      </Tooltip>\n    );\n  };\n\n  render() {\n    const { panel, scopedVars, error, isViewing, isEditing, data, alertState } = this.props;\n    const { menuItems } = this.state;\n    const title = templateSrv.replaceWithText(panel.title, scopedVars);\n\n    const panelHeaderClass = classNames({\n      'panel-header': true,\n      'grid-drag-handle': !(isViewing || isEditing),\n    });\n\n    // dedupe on severity\n    const notices: Record<string, QueryResultMetaNotice> = {};\n\n    for (const series of data.series) {\n      if (series.meta && series.meta.notices) {\n        for (const notice of series.meta.notices) {\n          notices[notice.severity] = notice;\n        }\n      }\n    }\n\n    return (\n      <>\n        {data.state === LoadingState.Loading && this.renderLoadingState()}\n        <div className={panelHeaderClass}>\n          <PanelHeaderCorner\n            panel={panel}\n            title={panel.title}\n            description={panel.description}\n            scopedVars={panel.scopedVars}\n            links={getPanelLinksSupplier(panel)}\n            error={error}\n          />\n          <div\n            className=\"panel-title-container\"\n            onClick={this.onMenuToggle}\n            onMouseDown={this.onMouseDown}\n            aria-label={selectors.components.Panels.Panel.title(title)}\n          >\n            <div className=\"panel-title\">\n              {Object.values(notices).map(this.renderNotice)}\n              {alertState && (\n                <Icon\n                  name={alertState === 'alerting' ? 'heart-break' : 'heart'}\n                  className=\"icon-gf panel-alert-icon\"\n                  style={{ marginRight: '4px' }}\n                  size=\"sm\"\n                />\n              )}\n              <span className=\"panel-title-text\">\n                {title}\n                <Icon name=\"angle-down\" className=\"panel-menu-toggle\" />\n              </span>\n              {this.state.panelMenuOpen && (\n                <ClickOutsideWrapper onClick={this.closeMenu}>\n                  <PanelHeaderMenu items={menuItems} />\n                </ClickOutsideWrapper>\n              )}\n              {data.request && data.request.timeInfo && (\n                <span className=\"panel-time-info\">\n                  <Icon name=\"clock-nine\" size=\"sm\" /> {data.request.timeInfo}\n                </span>\n              )}\n            </div>\n          </div>\n        </div>\n      </>\n    );\n  }\n}\n","// Libraries\nimport React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport { Unsubscribable } from 'rxjs';\n// Components\nimport { PanelHeader } from './PanelHeader/PanelHeader';\nimport { ErrorBoundary } from '@grafana/ui';\n// Utils & Services\nimport { getTimeSrv, TimeSrv } from '../services/TimeSrv';\nimport { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel';\nimport { profiler } from 'app/core/profiler';\nimport { getProcessedDataFrames } from '../state/runRequest';\nimport config from 'app/core/config';\nimport { updateLocation } from 'app/core/actions';\n// Types\nimport { DashboardModel, PanelModel } from '../state';\nimport { PANEL_BORDER } from 'app/core/constants';\nimport {\n  LoadingState,\n  AbsoluteTimeRange,\n  DefaultTimeRange,\n  toUtc,\n  toDataFrameDTO,\n  PanelEvents,\n  PanelData,\n  PanelPlugin,\n  FieldConfigSource,\n} from '@grafana/data';\nimport { selectors } from '@grafana/e2e-selectors';\n\nconst DEFAULT_PLUGIN_ERROR = 'Error in plugin';\n\nexport interface Props {\n  panel: PanelModel;\n  dashboard: DashboardModel;\n  plugin: PanelPlugin;\n  isViewing: boolean;\n  isEditing?: boolean;\n  isInView: boolean;\n  width: number;\n  height: number;\n  updateLocation: typeof updateLocation;\n}\n\nexport interface State {\n  isFirstLoad: boolean;\n  renderCounter: number;\n  errorMessage?: string;\n  refreshWhenInView: boolean;\n  data: PanelData;\n}\n\nexport class PanelChrome extends PureComponent<Props, State> {\n  timeSrv: TimeSrv = getTimeSrv();\n  querySubscription: Unsubscribable;\n\n  constructor(props: Props) {\n    super(props);\n\n    this.state = {\n      isFirstLoad: true,\n      renderCounter: 0,\n      refreshWhenInView: false,\n      data: {\n        state: LoadingState.NotStarted,\n        series: [],\n        timeRange: DefaultTimeRange,\n      },\n    };\n  }\n\n  componentDidMount() {\n    const { panel, dashboard } = this.props;\n\n    panel.events.on(PanelEvents.refresh, this.onRefresh);\n    panel.events.on(PanelEvents.render, this.onRender);\n\n    dashboard.panelInitialized(this.props.panel);\n\n    // Move snapshot data into the query response\n    if (this.hasPanelSnapshot) {\n      this.setState({\n        data: {\n          ...this.state.data,\n          state: LoadingState.Done,\n          series: getProcessedDataFrames(panel.snapshotData),\n        },\n        isFirstLoad: false,\n      });\n      return;\n    }\n\n    if (!this.wantsQueryExecution) {\n      this.setState({ isFirstLoad: false });\n    }\n\n    this.querySubscription = panel\n      .getQueryRunner()\n      .getData({ withTransforms: true, withFieldConfig: true })\n      .subscribe({\n        next: data => this.onDataUpdate(data),\n      });\n  }\n\n  componentWillUnmount() {\n    this.props.panel.events.off(PanelEvents.refresh, this.onRefresh);\n    this.props.panel.events.off(PanelEvents.render, this.onRender);\n\n    if (this.querySubscription) {\n      this.querySubscription.unsubscribe();\n    }\n  }\n\n  componentDidUpdate(prevProps: Props) {\n    const { isInView } = this.props;\n\n    // View state has changed\n    if (isInView !== prevProps.isInView) {\n      if (isInView) {\n        // Check if we need a delayed refresh\n        if (this.state.refreshWhenInView) {\n          this.onRefresh();\n        }\n      }\n    }\n  }\n\n  // Updates the response with information from the stream\n  // The next is outside a react synthetic event so setState is not batched\n  // So in this context we can only do a single call to setState\n  onDataUpdate(data: PanelData) {\n    if (!this.props.isInView) {\n      // Ignore events when not visible.\n      // The call will be repeated when the panel comes into view\n      return;\n    }\n\n    let { isFirstLoad } = this.state;\n    let errorMessage: string | undefined;\n\n    switch (data.state) {\n      case LoadingState.Loading:\n        // Skip updating state data if it is already in loading state\n        // This is to avoid rendering partial loading responses\n        if (this.state.data.state === LoadingState.Loading) {\n          return;\n        }\n        break;\n      case LoadingState.Error:\n        const { error } = data;\n        if (error) {\n          if (errorMessage !== error.message) {\n            errorMessage = error.message;\n          }\n        }\n        break;\n      case LoadingState.Done:\n        // If we are doing a snapshot save data in panel model\n        if (this.props.dashboard.snapshot) {\n          this.props.panel.snapshotData = data.series.map(frame => toDataFrameDTO(frame));\n        }\n        if (isFirstLoad) {\n          isFirstLoad = false;\n        }\n        break;\n    }\n\n    this.setState({ isFirstLoad, errorMessage, data });\n  }\n\n  onRefresh = () => {\n    const { panel, isInView, width } = this.props;\n    if (!isInView) {\n      console.log('Refresh when panel is visible', panel.id);\n      this.setState({ refreshWhenInView: true });\n      return;\n    }\n\n    const timeData = applyPanelTimeOverrides(panel, this.timeSrv.timeRange());\n\n    // Issue Query\n    if (this.wantsQueryExecution) {\n      if (width < 0) {\n        console.log('Refresh skippted, no width yet... wait till we know');\n        return;\n      }\n\n      panel.getQueryRunner().run({\n        datasource: panel.datasource,\n        queries: panel.targets,\n        panelId: panel.id,\n        dashboardId: this.props.dashboard.id,\n        timezone: this.props.dashboard.getTimezone(),\n        timeRange: timeData.timeRange,\n        timeInfo: timeData.timeInfo,\n        maxDataPoints: panel.maxDataPoints || width,\n        minInterval: panel.interval,\n        scopedVars: panel.scopedVars,\n        cacheTimeout: panel.cacheTimeout,\n        transformations: panel.transformations,\n      });\n    } else {\n      // The panel should render on refresh as well if it doesn't have a query, like clock panel\n      this.onRender();\n    }\n  };\n\n  onRender = () => {\n    const stateUpdate = { renderCounter: this.state.renderCounter + 1 };\n    this.setState(stateUpdate);\n  };\n\n  onOptionsChange = (options: any) => {\n    this.props.panel.updateOptions(options);\n  };\n\n  onFieldConfigChange = (config: FieldConfigSource) => {\n    this.props.panel.updateFieldConfig(config);\n  };\n\n  onPanelError = (message: string) => {\n    if (this.state.errorMessage !== message) {\n      this.setState({ errorMessage: message });\n    }\n  };\n\n  get hasPanelSnapshot() {\n    const { panel } = this.props;\n    return panel.snapshotData && panel.snapshotData.length;\n  }\n\n  get wantsQueryExecution() {\n    return !(this.props.plugin.meta.skipDataQuery || this.hasPanelSnapshot);\n  }\n\n  onChangeTimeRange = (timeRange: AbsoluteTimeRange) => {\n    this.timeSrv.setTime({\n      from: toUtc(timeRange.from),\n      to: toUtc(timeRange.to),\n    });\n  };\n\n  renderPanel(width: number, height: number) {\n    const { panel, plugin } = this.props;\n    const { renderCounter, data, isFirstLoad } = this.state;\n    const { theme } = config;\n\n    // This is only done to increase a counter that is used by backend\n    // image rendering to know when to capture image\n    const loading = data.state;\n    if (loading === LoadingState.Done) {\n      profiler.renderingCompleted();\n    }\n\n    // do not render component until we have first data\n    if (isFirstLoad && (loading === LoadingState.Loading || loading === LoadingState.NotStarted)) {\n      return null;\n    }\n\n    const PanelComponent = plugin.panel;\n    const timeRange = data.timeRange || this.timeSrv.timeRange();\n    const headerHeight = this.hasOverlayHeader() ? 0 : theme.panelHeaderHeight;\n    const chromePadding = plugin.noPadding ? 0 : theme.panelPadding;\n    const panelWidth = width - chromePadding * 2 - PANEL_BORDER;\n    const innerPanelHeight = height - headerHeight - chromePadding * 2 - PANEL_BORDER;\n    const panelContentClassNames = classNames({\n      'panel-content': true,\n      'panel-content--no-padding': plugin.noPadding,\n    });\n    const panelOptions = panel.getOptions();\n\n    return (\n      <>\n        <div className={panelContentClassNames}>\n          <PanelComponent\n            id={panel.id}\n            data={data}\n            timeRange={timeRange}\n            timeZone={this.props.dashboard.getTimezone()}\n            options={panelOptions}\n            fieldConfig={panel.fieldConfig}\n            transparent={panel.transparent}\n            width={panelWidth}\n            height={innerPanelHeight}\n            renderCounter={renderCounter}\n            replaceVariables={panel.replaceVariables}\n            onOptionsChange={this.onOptionsChange}\n            onFieldConfigChange={this.onFieldConfigChange}\n            onChangeTimeRange={this.onChangeTimeRange}\n          />\n        </div>\n      </>\n    );\n  }\n\n  hasOverlayHeader() {\n    const { panel } = this.props;\n    const { errorMessage, data } = this.state;\n\n    // always show normal header if we have an error message\n    if (errorMessage) {\n      return false;\n    }\n\n    // always show normal header if we have time override\n    if (data.request && data.request.timeInfo) {\n      return false;\n    }\n\n    return !panel.hasTitle();\n  }\n\n  render() {\n    const { dashboard, panel, isViewing, isEditing, width, height, updateLocation } = this.props;\n    const { errorMessage, data } = this.state;\n    const { transparent } = panel;\n\n    const containerClassNames = classNames({\n      'panel-container': true,\n      'panel-container--absolute': true,\n      'panel-container--transparent': transparent,\n      'panel-container--no-title': this.hasOverlayHeader(),\n    });\n\n    return (\n      <div className={containerClassNames} aria-label={selectors.components.Panels.Panel.containerByTitle(panel.title)}>\n        <PanelHeader\n          panel={panel}\n          dashboard={dashboard}\n          title={panel.title}\n          description={panel.description}\n          scopedVars={panel.scopedVars}\n          links={panel.links}\n          error={errorMessage}\n          isEditing={isEditing}\n          isViewing={isViewing}\n          data={data}\n          updateLocation={updateLocation}\n        />\n        <ErrorBoundary>\n          {({ error }) => {\n            if (error) {\n              this.onPanelError(error.message || DEFAULT_PLUGIN_ERROR);\n              return null;\n            }\n            return this.renderPanel(width, height);\n          }}\n        </ErrorBoundary>\n      </div>\n    );\n  }\n}\n","// Libraries\nimport React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport { Unsubscribable } from 'rxjs';\nimport { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';\n// Components\nimport { PanelHeader } from './PanelHeader/PanelHeader';\n// Utils & Services\nimport { getTimeSrv, TimeSrv } from '../services/TimeSrv';\nimport { AngularComponent, getAngularLoader } from '@grafana/runtime';\nimport { setPanelAngularComponent } from '../state/reducers';\nimport config from 'app/core/config';\n// Types\nimport { DashboardModel, PanelModel } from '../state';\nimport { StoreState } from 'app/types';\nimport { DefaultTimeRange, LoadingState, PanelData, PanelEvents, PanelPlugin } from '@grafana/data';\nimport { updateLocation } from 'app/core/actions';\nimport { PANEL_BORDER } from 'app/core/constants';\nimport { selectors } from '@grafana/e2e-selectors';\n\ninterface OwnProps {\n  panel: PanelModel;\n  dashboard: DashboardModel;\n  plugin: PanelPlugin;\n  isViewing: boolean;\n  isEditing: boolean;\n  isInView: boolean;\n  width: number;\n  height: number;\n}\n\ninterface ConnectedProps {\n  angularComponent?: AngularComponent | null;\n}\n\ninterface DispatchProps {\n  setPanelAngularComponent: typeof setPanelAngularComponent;\n  updateLocation: typeof updateLocation;\n}\n\nexport type Props = OwnProps & ConnectedProps & DispatchProps;\n\nexport interface State {\n  data: PanelData;\n  errorMessage?: string;\n  alertState?: string;\n}\n\ninterface AngularScopeProps {\n  panel: PanelModel;\n  dashboard: DashboardModel;\n  size: {\n    height: number;\n    width: number;\n  };\n}\n\nexport class PanelChromeAngularUnconnected extends PureComponent<Props, State> {\n  element: HTMLElement | null = null;\n  timeSrv: TimeSrv = getTimeSrv();\n  scopeProps?: AngularScopeProps;\n  querySubscription: Unsubscribable;\n\n  constructor(props: Props) {\n    super(props);\n    this.state = {\n      data: {\n        state: LoadingState.NotStarted,\n        series: [],\n        timeRange: DefaultTimeRange,\n      },\n    };\n  }\n\n  componentDidMount() {\n    const { panel } = this.props;\n    this.loadAngularPanel();\n\n    // subscribe to data events\n    const queryRunner = panel.getQueryRunner();\n\n    // we are not displaying any of this data so no need for transforms or field config\n    this.querySubscription = queryRunner.getData({ withTransforms: false, withFieldConfig: false }).subscribe({\n      next: (data: PanelData) => this.onPanelDataUpdate(data),\n    });\n  }\n\n  subscribeToRenderEvent() {\n    // Subscribe to render event, this is as far as I know only needed for changes to title & transparent\n    // These changes are modified in the model and only way to communicate that change is via this event\n    // Need to find another solution for this in tthe future (panel title in redux?)\n    this.props.panel.events.on(PanelEvents.render, this.onPanelRenderEvent);\n  }\n\n  onPanelRenderEvent = (payload?: any) => {\n    const { alertState } = this.state;\n\n    if (payload && payload.alertState && this.props.panel.alert) {\n      this.setState({ alertState: payload.alertState });\n    } else if (payload && payload.alertState && !this.props.panel.alert) {\n      // when user deletes alert in panel editor the source panel needs to refresh as this is in the mutable state and\n      // will not automatically re render\n      this.setState({ alertState: undefined });\n    } else if (payload && alertState) {\n      this.setState({ alertState: undefined });\n    } else {\n      // only needed for detecting title updates right now fix before 7.0\n      this.forceUpdate();\n    }\n  };\n\n  onPanelDataUpdate(data: PanelData) {\n    let errorMessage: string | undefined;\n\n    if (data.state === LoadingState.Error) {\n      const { error } = data;\n      if (error) {\n        if (errorMessage !== error.message) {\n          errorMessage = error.message;\n        }\n      }\n    }\n\n    this.setState({ data, errorMessage });\n  }\n\n  componentWillUnmount() {\n    this.cleanUpAngularPanel();\n\n    if (this.querySubscription) {\n      this.querySubscription.unsubscribe();\n    }\n\n    this.props.panel.events.off(PanelEvents.render, this.onPanelRenderEvent);\n  }\n\n  componentDidUpdate(prevProps: Props, prevState: State) {\n    const { plugin, height, width, panel } = this.props;\n\n    if (prevProps.plugin !== plugin) {\n      this.cleanUpAngularPanel();\n      this.loadAngularPanel();\n    }\n\n    if (prevProps.width !== width || prevProps.height !== height) {\n      if (this.scopeProps) {\n        this.scopeProps.size.height = this.getInnerPanelHeight();\n        this.scopeProps.size.width = this.getInnerPanelWidth();\n        panel.events.emit(PanelEvents.panelSizeChanged);\n      }\n    }\n  }\n\n  getInnerPanelHeight() {\n    const { plugin, height } = this.props;\n    const { theme } = config;\n\n    const headerHeight = this.hasOverlayHeader() ? 0 : theme.panelHeaderHeight;\n    const chromePadding = plugin.noPadding ? 0 : theme.panelPadding;\n    return height - headerHeight - chromePadding * 2 - PANEL_BORDER;\n  }\n\n  getInnerPanelWidth() {\n    const { plugin, width } = this.props;\n    const { theme } = config;\n\n    const chromePadding = plugin.noPadding ? 0 : theme.panelPadding;\n    return width - chromePadding * 2 - PANEL_BORDER;\n  }\n\n  loadAngularPanel() {\n    const { panel, dashboard, setPanelAngularComponent } = this.props;\n\n    // if we have no element or already have loaded the panel return\n    if (!this.element) {\n      return;\n    }\n\n    const loader = getAngularLoader();\n    const template = '<plugin-component type=\"panel\" class=\"panel-height-helper\"></plugin-component>';\n\n    this.scopeProps = {\n      panel: panel,\n      dashboard: dashboard,\n      size: { width: this.getInnerPanelWidth(), height: this.getInnerPanelHeight() },\n    };\n\n    setPanelAngularComponent({\n      panelId: panel.id,\n      angularComponent: loader.load(this.element, this.scopeProps, template),\n    });\n\n    // need to to this every time we load an angular as all events are unsubscribed when panel is destroyed\n    this.subscribeToRenderEvent();\n  }\n\n  cleanUpAngularPanel() {\n    const { angularComponent, setPanelAngularComponent, panel } = this.props;\n\n    if (angularComponent) {\n      angularComponent.destroy();\n    }\n\n    setPanelAngularComponent({ panelId: panel.id, angularComponent: null });\n  }\n\n  hasOverlayHeader() {\n    const { panel } = this.props;\n    const { errorMessage, data } = this.state;\n\n    // always show normal header if we have an error message\n    if (errorMessage) {\n      return false;\n    }\n\n    // always show normal header if we have time override\n    if (data.request && data.request.timeInfo) {\n      return false;\n    }\n\n    return !panel.hasTitle();\n  }\n\n  render() {\n    const { dashboard, panel, isViewing, isEditing, plugin, angularComponent, updateLocation } = this.props;\n    const { errorMessage, data, alertState } = this.state;\n    const { transparent } = panel;\n\n    const containerClassNames = classNames({\n      'panel-container': true,\n      'panel-container--absolute': true,\n      'panel-container--transparent': transparent,\n      'panel-container--no-title': this.hasOverlayHeader(),\n      'panel-has-alert': panel.alert !== undefined,\n      [`panel-alert-state--${alertState}`]: alertState !== undefined,\n    });\n\n    const panelContentClassNames = classNames({\n      'panel-content': true,\n      'panel-content--no-padding': plugin.noPadding,\n    });\n\n    return (\n      <div className={containerClassNames} aria-label={selectors.components.Panels.Panel.containerByTitle(panel.title)}>\n        <PanelHeader\n          panel={panel}\n          dashboard={dashboard}\n          title={panel.title}\n          description={panel.description}\n          scopedVars={panel.scopedVars}\n          angularComponent={angularComponent}\n          links={panel.links}\n          error={errorMessage}\n          isViewing={isViewing}\n          isEditing={isEditing}\n          data={data}\n          updateLocation={updateLocation}\n          alertState={alertState}\n        />\n        <div className={panelContentClassNames}>\n          <div ref={element => (this.element = element)} className=\"panel-height-helper\" />\n        </div>\n      </div>\n    );\n  }\n}\n\nconst mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state, props) => {\n  return {\n    angularComponent: state.dashboard.panels[props.panel.id].angularComponent,\n  };\n};\n\nconst mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = { setPanelAngularComponent, updateLocation };\n\nexport const PanelChromeAngular = connect(mapStateToProps, mapDispatchToProps)(PanelChromeAngularUnconnected);\n","// Libraries\nimport React, { PureComponent } from 'react';\nimport classNames from 'classnames';\nimport AutoSizer from 'react-virtualized-auto-sizer';\nimport { connect, MapStateToProps, MapDispatchToProps } from 'react-redux';\n\n// Components\nimport { PanelChrome } from './PanelChrome';\nimport { PanelChromeAngular } from './PanelChromeAngular';\n\n// Actions\nimport { initDashboardPanel } from '../state/actions';\nimport { updateLocation } from 'app/core/reducers/location';\n\n// Types\nimport { PanelModel, DashboardModel } from '../state';\nimport { StoreState } from 'app/types';\nimport { PanelPlugin } from '@grafana/data';\n\nexport interface OwnProps {\n  panel: PanelModel;\n  dashboard: DashboardModel;\n  isEditing: boolean;\n  isViewing: boolean;\n  isInView: boolean;\n}\n\nexport interface ConnectedProps {\n  plugin?: PanelPlugin | null;\n}\n\nexport interface DispatchProps {\n  initDashboardPanel: typeof initDashboardPanel;\n  updateLocation: typeof updateLocation;\n}\n\nexport type Props = OwnProps & ConnectedProps & DispatchProps;\n\nexport interface State {\n  isLazy: boolean;\n}\n\nexport class DashboardPanelUnconnected extends PureComponent<Props, State> {\n  element: HTMLElement;\n  specialPanels: { [key: string]: Function } = {};\n\n  constructor(props: Props) {\n    super(props);\n\n    this.state = {\n      isLazy: !props.isInView,\n    };\n  }\n\n  componentDidMount() {\n    this.props.initDashboardPanel(this.props.panel);\n  }\n\n  componentDidUpdate() {\n    if (this.state.isLazy && this.props.isInView) {\n      this.setState({ isLazy: false });\n    }\n  }\n\n  onMouseEnter = () => {\n    this.props.dashboard.setPanelFocus(this.props.panel.id);\n  };\n\n  onMouseLeave = () => {\n    this.props.dashboard.setPanelFocus(0);\n  };\n\n  renderPanel(plugin: PanelPlugin) {\n    const { dashboard, panel, isViewing, isInView, isEditing, updateLocation } = this.props;\n\n    return (\n      <AutoSizer>\n        {({ width, height }) => {\n          if (width === 0) {\n            return null;\n          }\n\n          if (plugin.angularPanelCtrl) {\n            return (\n              <PanelChromeAngular\n                plugin={plugin}\n                panel={panel}\n                dashboard={dashboard}\n                isViewing={isViewing}\n                isEditing={isEditing}\n                isInView={isInView}\n                width={width}\n                height={height}\n              />\n            );\n          }\n\n          return (\n            <PanelChrome\n              plugin={plugin}\n              panel={panel}\n              dashboard={dashboard}\n              isViewing={isViewing}\n              isEditing={isEditing}\n              isInView={isInView}\n              width={width}\n              height={height}\n              updateLocation={updateLocation}\n            />\n          );\n        }}\n      </AutoSizer>\n    );\n  }\n\n  render() {\n    const { isViewing, plugin } = this.props;\n    const { isLazy } = this.state;\n\n    // if we have not loaded plugin exports yet, wait\n    if (!plugin) {\n      return null;\n    }\n\n    // If we are lazy state don't render anything\n    if (isLazy) {\n      return null;\n    }\n\n    const panelWrapperClass = classNames({\n      'panel-wrapper': true,\n      'panel-wrapper--view': isViewing,\n    });\n\n    return (\n      <div className={panelWrapperClass} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>\n        {this.renderPanel(plugin)}\n      </div>\n    );\n  }\n}\n\nconst mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state, props) => {\n  const panelState = state.dashboard.panels[props.panel.id];\n  if (!panelState) {\n    return { plugin: null };\n  }\n\n  return {\n    plugin: panelState.plugin,\n  };\n};\n\nconst mapDispatchToProps: MapDispatchToProps<DispatchProps, OwnProps> = { initDashboardPanel, updateLocation };\n\nexport const DashboardPanel = connect(mapStateToProps, mapDispatchToProps)(DashboardPanelUnconnected);\n","import React, { FC } from 'react';\nimport { css } from 'emotion';\nimport { stylesFactory, Tab, TabsBar, useTheme } from '@grafana/ui';\nimport { GrafanaTheme, SelectableValue, PanelData, getValueFormat, formattedValueToString } from '@grafana/data';\nimport { InspectTab } from './PanelInspector';\n\ninterface Props {\n  tab: InspectTab;\n  tabs: Array<{ label: string; value: InspectTab }>;\n  panelData: PanelData;\n  onSelectTab: (tab: SelectableValue<InspectTab>) => void;\n}\n\nexport const InspectSubtitle: FC<Props> = ({ tab, tabs, onSelectTab, panelData }) => {\n  const theme = useTheme();\n  const styles = getStyles(theme);\n\n  return (\n    <>\n      <div className=\"muted\">{formatStats(panelData)}</div>\n      <TabsBar className={styles.tabsBar}>\n        {tabs.map((t, index) => {\n          return (\n            <Tab\n              key={`${t.value}-${index}`}\n              label={t.label}\n              active={t.value === tab}\n              onChangeTab={() => onSelectTab(t)}\n            />\n          );\n        })}\n      </TabsBar>\n    </>\n  );\n};\n\nconst getStyles = stylesFactory((theme: GrafanaTheme) => {\n  return {\n    tabsBar: css`\n      padding-left: ${theme.spacing.md};\n      margin: ${theme.spacing.lg} -${theme.spacing.sm} -${theme.spacing.lg} -${theme.spacing.lg};\n    `,\n  };\n});\n\nfunction formatStats(panelData: PanelData) {\n  const { request } = panelData;\n  if (!request) {\n    return '';\n  }\n\n  const queryCount = request.targets.length;\n  const requestTime = request.endTime ? request.endTime - request.startTime : 0;\n  const formatted = formattedValueToString(getValueFormat('ms')(requestTime));\n\n  return `${queryCount} queries with total query time of ${formatted}`;\n}\n","import { css } from 'emotion';\nimport { config } from 'app/core/config';\nimport { stylesFactory } from '@grafana/ui';\n\nexport const getPanelInspectorStyles = stylesFactory(() => {\n  return {\n    wrap: css`\n      display: flex;\n      flex-direction: column;\n      height: 100%;\n      width: 100%;\n      flex: 1 1 0;\n    `,\n    toolbar: css`\n      display: flex;\n      width: 100%;\n      flex-grow: 0;\n      align-items: center;\n      justify-content: flex-end;\n      margin-bottom: ${config.theme.spacing.sm};\n    `,\n    toolbarItem: css`\n      margin-left: ${config.theme.spacing.md};\n    `,\n    content: css`\n      flex-grow: 1;\n      padding-bottom: 16px;\n    `,\n    contentQueryInspector: css`\n      flex-grow: 1;\n      padding: ${config.theme.spacing.md} 0;\n    `,\n    editor: css`\n      font-family: monospace;\n      height: 100%;\n      flex-grow: 1;\n    `,\n    viewer: css`\n      overflow: scroll;\n    `,\n    dataFrameSelect: css`\n      flex-grow: 2;\n    `,\n    tabContent: css`\n      height: 100%;\n      display: flex;\n      flex-direction: column;\n    `,\n    dataTabContent: css`\n      display: flex;\n      flex-direction: column;\n      height: 100%;\n      width: 100%;\n    `,\n    actionsWrapper: css`\n      display: flex;\n      flex-wrap: wrap;\n    `,\n    leftActions: css`\n      display: flex;\n      flex-grow: 1;\n    `,\n    options: css`\n      margin-top: 19px;\n    `,\n    dataDisplayOptions: css`\n      flex-grow: 1;\n      min-width: 300px;\n      margin-right: ${config.theme.spacing.sm};\n    `,\n    selects: css`\n      display: flex;\n      > * {\n        margin-right: ${config.theme.spacing.sm};\n      }\n    `,\n  };\n});\n","import React, { PureComponent } from 'react';\nimport { chain } from 'lodash';\nimport { AppEvents, PanelData, SelectableValue } from '@grafana/data';\nimport { Button, ClipboardButton, Field, JSONFormatter, Select, TextArea } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\n\nimport { appEvents } from 'app/core/core';\nimport { DashboardModel, PanelModel } from '../../state';\nimport { getPanelInspectorStyles } from './styles';\n\nenum ShowContent {\n  PanelJSON = 'panel',\n  PanelData = 'data',\n  DataStructure = 'structure',\n}\n\nconst options: Array<SelectableValue<ShowContent>> = [\n  {\n    label: 'Panel JSON',\n    description: 'The model saved in the dashboard JSON that configures how everything works.',\n    value: ShowContent.PanelJSON,\n  },\n  {\n    label: 'Panel data',\n    description: 'The raw model passed to the panel visualization',\n    value: ShowContent.PanelData,\n  },\n  {\n    label: 'DataFrame structure',\n    description: 'Response info without any values',\n    value: ShowContent.DataStructure,\n  },\n];\n\ninterface Props {\n  dashboard: DashboardModel;\n  panel: PanelModel;\n  data: PanelData;\n  onClose: () => void;\n}\n\ninterface State {\n  show: ShowContent;\n  text: string;\n}\n\nexport class InspectJSONTab extends PureComponent<Props, State> {\n  constructor(props: Props) {\n    super(props);\n    this.state = {\n      show: ShowContent.PanelJSON,\n      text: getSaveModelJSON(props.panel),\n    };\n  }\n\n  onSelectChanged = (item: SelectableValue<ShowContent>) => {\n    let text = '';\n    if (item.value === ShowContent.PanelJSON) {\n      text = getSaveModelJSON(this.props.panel);\n    }\n    this.setState({ text, show: item.value });\n  };\n\n  onTextChanged = (e: React.FormEvent<HTMLTextAreaElement>) => {\n    const text = e.currentTarget.value;\n    this.setState({ text });\n  };\n\n  getJSONObject = (show: ShowContent): any => {\n    if (show === ShowContent.PanelData) {\n      return this.props.data;\n    }\n    if (show === ShowContent.DataStructure) {\n      const series = this.props.data?.series;\n      if (!series) {\n        return { note: 'Missing Response Data' };\n      }\n      return this.props.data.series.map(frame => {\n        const fields = frame.fields.map(field => {\n          return chain(field)\n            .omit('values')\n            .omit('calcs')\n            .omit('display')\n            .value();\n        });\n        return {\n          ...frame,\n          fields,\n        };\n      });\n    }\n    if (show === ShowContent.PanelJSON) {\n      return this.props.panel.getSaveModel();\n    }\n\n    return { note: 'Unknown Object', show };\n  };\n\n  getClipboardText = () => {\n    const { show } = this.state;\n    const obj = this.getJSONObject(show);\n    return JSON.stringify(obj, null, 2);\n  };\n\n  onClipboardCopied = () => {\n    appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);\n  };\n\n  onApplyPanelModel = () => {\n    const { panel, dashboard, onClose } = this.props;\n\n    try {\n      if (!dashboard.meta.canEdit) {\n        appEvents.emit(AppEvents.alertError, ['Unable to apply']);\n      } else {\n        const updates = JSON.parse(this.state.text);\n        panel.restoreModel(updates);\n        panel.refresh();\n        appEvents.emit(AppEvents.alertSuccess, ['Panel model updated']);\n      }\n    } catch (err) {\n      console.log('Error applyign updates', err);\n      appEvents.emit(AppEvents.alertError, ['Invalid JSON text']);\n    }\n\n    onClose();\n  };\n\n  renderPanelJSON(styles: any) {\n    return (\n      <TextArea spellCheck={false} value={this.state.text} onChange={this.onTextChanged} className={styles.editor} />\n    );\n  }\n\n  render() {\n    const { dashboard } = this.props;\n    const { show } = this.state;\n    const selected = options.find(v => v.value === show);\n    const isPanelJSON = show === ShowContent.PanelJSON;\n    const canEdit = dashboard.meta.canEdit;\n    const styles = getPanelInspectorStyles();\n\n    return (\n      <>\n        <div className={styles.toolbar} aria-label={selectors.components.PanelInspector.Json.content}>\n          <Field label=\"Select source\" className=\"flex-grow-1\">\n            <Select options={options} value={selected} onChange={this.onSelectChanged} />\n          </Field>\n          <ClipboardButton\n            variant=\"secondary\"\n            className={styles.toolbarItem}\n            getText={this.getClipboardText}\n            onClipboardCopy={this.onClipboardCopied}\n          >\n            Copy to clipboard\n          </ClipboardButton>\n          {isPanelJSON && canEdit && (\n            <Button className={styles.toolbarItem} onClick={this.onApplyPanelModel}>\n              Apply\n            </Button>\n          )}\n        </div>\n        <div className={styles.content}>\n          {isPanelJSON ? (\n            this.renderPanelJSON(styles)\n          ) : (\n            <div className={styles.viewer}>\n              <JSONFormatter json={this.getJSONObject(show)} />\n            </div>\n          )}\n        </div>\n      </>\n    );\n  }\n}\n\nfunction getSaveModelJSON(panel: PanelModel): string {\n  return JSON.stringify(panel.getSaveModel(), null, 2);\n}\n","import React, { PureComponent } from 'react';\nimport { Button, JSONFormatter, LoadingPlaceholder } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\nimport { AppEvents, PanelEvents } from '@grafana/data';\n\nimport appEvents from 'app/core/app_events';\nimport { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';\nimport { CoreEvents } from 'app/types';\nimport { PanelModel } from 'app/features/dashboard/state';\nimport { getPanelInspectorStyles } from './styles';\nimport { supportsDataQuery } from '../PanelEditor/utils';\n\ninterface DsQuery {\n  isLoading: boolean;\n  response: {};\n}\n\ninterface Props {\n  panel: PanelModel;\n}\n\ninterface State {\n  allNodesExpanded: boolean;\n  isMocking: boolean;\n  mockedResponse: string;\n  dsQuery: DsQuery;\n}\n\nexport class QueryInspector extends PureComponent<Props, State> {\n  formattedJson: any;\n  clipboard: any;\n\n  constructor(props: Props) {\n    super(props);\n    this.state = {\n      allNodesExpanded: null,\n      isMocking: false,\n      mockedResponse: '',\n      dsQuery: {\n        isLoading: false,\n        response: {},\n      },\n    };\n  }\n\n  componentDidMount() {\n    appEvents.on(CoreEvents.dsRequestResponse, this.onDataSourceResponse);\n    appEvents.on(CoreEvents.dsRequestError, this.onRequestError);\n    this.props.panel.events.on(PanelEvents.refresh, this.onPanelRefresh);\n  }\n\n  onIssueNewQuery = () => {\n    this.props.panel.refresh();\n  };\n\n  componentWillUnmount() {\n    const { panel } = this.props;\n\n    appEvents.off(CoreEvents.dsRequestResponse, this.onDataSourceResponse);\n    appEvents.on(CoreEvents.dsRequestError, this.onRequestError);\n\n    panel.events.off(PanelEvents.refresh, this.onPanelRefresh);\n  }\n\n  handleMocking(response: any) {\n    const { mockedResponse } = this.state;\n    let mockedData;\n    try {\n      mockedData = JSON.parse(mockedResponse);\n    } catch (err) {\n      appEvents.emit(AppEvents.alertError, ['R: Failed to parse mocked response']);\n      return;\n    }\n\n    response.data = mockedData;\n  }\n\n  onPanelRefresh = () => {\n    this.setState(prevState => ({\n      ...prevState,\n      dsQuery: {\n        isLoading: true,\n        response: {},\n      },\n    }));\n  };\n\n  onRequestError = (err: any) => {\n    this.onDataSourceResponse(err);\n  };\n\n  onDataSourceResponse = (response: any = {}) => {\n    if (this.state.isMocking) {\n      this.handleMocking(response);\n      return;\n    }\n\n    response = { ...response }; // clone - dont modify the response\n\n    if (response.headers) {\n      delete response.headers;\n    }\n\n    if (response.config) {\n      response.request = response.config;\n\n      delete response.config;\n      delete response.request.transformRequest;\n      delete response.request.transformResponse;\n      delete response.request.paramSerializer;\n      delete response.request.jsonpCallbackParam;\n      delete response.request.headers;\n      delete response.request.requestId;\n      delete response.request.inspect;\n      delete response.request.retry;\n      delete response.request.timeout;\n    }\n\n    if (response.data) {\n      response.response = response.data;\n\n      delete response.config;\n      delete response.data;\n      delete response.status;\n      delete response.statusText;\n      delete response.ok;\n      delete response.url;\n      delete response.redirected;\n      delete response.type;\n      delete response.$$config;\n    }\n\n    this.setState(prevState => ({\n      ...prevState,\n      dsQuery: {\n        isLoading: false,\n        response: response,\n      },\n    }));\n  };\n\n  setFormattedJson = (formattedJson: any) => {\n    this.formattedJson = formattedJson;\n  };\n\n  getTextForClipboard = () => {\n    return JSON.stringify(this.formattedJson, null, 2);\n  };\n\n  onClipboardSuccess = () => {\n    appEvents.emit(AppEvents.alertSuccess, ['Content copied to clipboard']);\n  };\n\n  onToggleExpand = () => {\n    this.setState(prevState => ({\n      ...prevState,\n      allNodesExpanded: !this.state.allNodesExpanded,\n    }));\n  };\n\n  onToggleMocking = () => {\n    this.setState(prevState => ({\n      ...prevState,\n      isMocking: !this.state.isMocking,\n    }));\n  };\n\n  getNrOfOpenNodes = () => {\n    if (this.state.allNodesExpanded === null) {\n      return 3; // 3 is default, ie when state is null\n    } else if (this.state.allNodesExpanded) {\n      return 20;\n    }\n    return 1;\n  };\n\n  setMockedResponse = (evt: any) => {\n    const mockedResponse = evt.target.value;\n    this.setState(prevState => ({\n      ...prevState,\n      mockedResponse,\n    }));\n  };\n\n  render() {\n    const { allNodesExpanded } = this.state;\n    const { response, isLoading } = this.state.dsQuery;\n    const openNodes = this.getNrOfOpenNodes();\n    const styles = getPanelInspectorStyles();\n    const haveData = Object.keys(response).length > 0;\n\n    if (!supportsDataQuery(this.props.panel.plugin)) {\n      return null;\n    }\n\n    return (\n      <>\n        <div aria-label={selectors.components.PanelInspector.Query.content}>\n          <h3 className=\"section-heading\">Query inspector</h3>\n          <p className=\"small muted\">\n            Query inspector allows you to view raw request and response. To collect this data Grafana needs to issue a\n            new query. Hit refresh button below to trigger a new query.\n          </p>\n        </div>\n        <div className={styles.toolbar}>\n          <Button\n            icon=\"sync\"\n            onClick={this.onIssueNewQuery}\n            aria-label={selectors.components.PanelInspector.Query.refreshButton}\n          >\n            Refresh\n          </Button>\n\n          {haveData && allNodesExpanded && (\n            <Button icon=\"minus\" variant=\"secondary\" className={styles.toolbarItem} onClick={this.onToggleExpand}>\n              Collapse all\n            </Button>\n          )}\n          {haveData && !allNodesExpanded && (\n            <Button icon=\"plus\" variant=\"secondary\" className={styles.toolbarItem} onClick={this.onToggleExpand}>\n              Expand all\n            </Button>\n          )}\n\n          {haveData && (\n            <CopyToClipboard\n              text={this.getTextForClipboard}\n              onSuccess={this.onClipboardSuccess}\n              elType=\"div\"\n              className={styles.toolbarItem}\n            >\n              <Button icon=\"copy\" variant=\"secondary\">\n                Copy to clipboard\n              </Button>\n            </CopyToClipboard>\n          )}\n          <div className=\"flex-grow-1\" />\n        </div>\n        <div className={styles.contentQueryInspector}>\n          {isLoading && <LoadingPlaceholder text=\"Loading query inspector...\" />}\n          {!isLoading && haveData && (\n            <JSONFormatter json={response} open={openNodes} onDidRender={this.setFormattedJson} />\n          )}\n          {!isLoading && !haveData && <p className=\"muted\">No request & response collected yet. Hit refresh button</p>}\n        </div>\n      </>\n    );\n  }\n}\n","import React, { PureComponent } from 'react';\nimport { Unsubscribable } from 'rxjs';\nimport { connect, MapStateToProps } from 'react-redux';\nimport { InspectSubtitle } from './InspectSubtitle';\nimport { InspectJSONTab } from './InspectJSONTab';\nimport { QueryInspector } from './QueryInspector';\n\nimport { DashboardModel, PanelModel } from 'app/features/dashboard/state';\nimport { CustomScrollbar, Drawer, JSONFormatter, TabContent } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\nimport { getDataSourceSrv, getLocationSrv } from '@grafana/runtime';\nimport {\n  DataFrame,\n  DataQueryError,\n  DataSourceApi,\n  FieldType,\n  formattedValueToString,\n  getDisplayProcessor,\n  LoadingState,\n  PanelData,\n  PanelPlugin,\n  QueryResultMetaStat,\n  SelectableValue,\n  TimeZone,\n} from '@grafana/data';\nimport { config } from 'app/core/config';\nimport { getPanelInspectorStyles } from './styles';\nimport { StoreState } from 'app/types';\nimport { InspectDataTab } from './InspectDataTab';\nimport { supportsDataQuery } from '../PanelEditor/utils';\nimport { GetDataOptions } from '../../state/PanelQueryRunner';\n\ninterface OwnProps {\n  dashboard: DashboardModel;\n  panel: PanelModel;\n  defaultTab: InspectTab;\n}\n\nexport interface ConnectedProps {\n  plugin?: PanelPlugin | null;\n}\n\nexport type Props = OwnProps & ConnectedProps;\n\nexport enum InspectTab {\n  Data = 'data',\n  Meta = 'meta', // When result metadata exists\n  Error = 'error',\n  Stats = 'stats',\n  JSON = 'json',\n  Query = 'query',\n}\n\ninterface State {\n  isLoading: boolean;\n  // The last raw response\n  last: PanelData;\n  // Data from the last response\n  data: DataFrame[];\n  // The Selected Tab\n  currentTab: InspectTab;\n  // If the datasource supports custom metadata\n  metaDS?: DataSourceApi;\n  // drawer width\n  drawerWidth: string;\n  withTransforms: boolean;\n  withFieldConfig: boolean;\n}\n\nexport class PanelInspectorUnconnected extends PureComponent<Props, State> {\n  querySubscription?: Unsubscribable;\n\n  constructor(props: Props) {\n    super(props);\n\n    this.state = {\n      isLoading: true,\n      last: {} as PanelData,\n      data: [],\n      currentTab: props.defaultTab ?? InspectTab.Data,\n      drawerWidth: '50%',\n      withTransforms: true,\n      withFieldConfig: false,\n    };\n  }\n\n  componentDidMount() {\n    const { plugin } = this.props;\n\n    if (plugin) {\n      this.init();\n    }\n  }\n\n  componentDidUpdate(prevProps: Props, prevState: State) {\n    if (\n      prevProps.plugin !== this.props.plugin ||\n      this.state.withTransforms !== prevState.withTransforms ||\n      this.state.withFieldConfig !== prevState.withFieldConfig\n    ) {\n      this.init();\n    }\n  }\n\n  /**\n   * This init process where we do not have a plugin to start with is to handle full page reloads with inspect url parameter\n   * When this inspect drawer loads the plugin is not yet loaded.\n   */\n  init() {\n    const { plugin, panel } = this.props;\n    const { withTransforms, withFieldConfig } = this.state;\n\n    if (plugin && !plugin.meta.skipDataQuery) {\n      if (this.querySubscription) {\n        this.querySubscription.unsubscribe();\n      }\n      this.querySubscription = panel\n        .getQueryRunner()\n        .getData({ withTransforms, withFieldConfig })\n        .subscribe({\n          next: data => this.onUpdateData(data),\n        });\n    }\n  }\n\n  componentWillUnmount() {\n    if (this.querySubscription) {\n      this.querySubscription.unsubscribe();\n    }\n  }\n\n  async onUpdateData(lastResult: PanelData) {\n    let metaDS: DataSourceApi;\n    const data = lastResult.series;\n    const error = lastResult.error;\n\n    const targets = lastResult.request?.targets || [];\n\n    // Find the first DataSource wanting to show custom metadata\n    if (data && targets.length) {\n      for (const frame of data) {\n        if (frame.meta && frame.meta.custom) {\n          // get data source from first query\n          const dataSource = await getDataSourceSrv().get(targets[0].datasource);\n\n          if (dataSource && dataSource.components?.MetadataInspector) {\n            metaDS = dataSource;\n            break;\n          }\n        }\n      }\n    }\n\n    // Set last result, but no metadata inspector\n    this.setState(prevState => ({\n      isLoading: lastResult.state === LoadingState.Loading,\n      last: lastResult,\n      data,\n      metaDS,\n      currentTab: error ? InspectTab.Error : prevState.currentTab,\n    }));\n  }\n\n  onClose = () => {\n    getLocationSrv().update({\n      query: { inspect: null, inspectTab: null },\n      partial: true,\n    });\n  };\n\n  onToggleExpand = () => {\n    this.setState(prevState => ({\n      drawerWidth: prevState.drawerWidth === '100%' ? '40%' : '100%',\n    }));\n  };\n\n  onSelectTab = (item: SelectableValue<InspectTab>) => {\n    this.setState({ currentTab: item.value || InspectTab.Data });\n  };\n  onDataTabOptionsChange = (options: GetDataOptions) => {\n    this.setState({ withTransforms: !!options.withTransforms, withFieldConfig: !!options.withFieldConfig });\n  };\n\n  renderMetadataInspector() {\n    const { metaDS, data } = this.state;\n    if (!metaDS || !metaDS.components?.MetadataInspector) {\n      return <div>No Metadata Inspector</div>;\n    }\n    return <metaDS.components.MetadataInspector datasource={metaDS} data={data} />;\n  }\n\n  renderDataTab() {\n    const { last, isLoading, withFieldConfig, withTransforms } = this.state;\n    return (\n      <InspectDataTab\n        dashboard={this.props.dashboard}\n        panel={this.props.panel}\n        data={last.series}\n        isLoading={isLoading}\n        options={{\n          withFieldConfig,\n          withTransforms,\n        }}\n        onOptionsChange={this.onDataTabOptionsChange}\n      />\n    );\n  }\n\n  renderErrorTab(error?: DataQueryError) {\n    if (!error) {\n      return null;\n    }\n    if (error.data) {\n      return (\n        <>\n          <h3>{error.data.message}</h3>\n          <JSONFormatter json={error} open={2} />\n        </>\n      );\n    }\n    return <div>{error.message}</div>;\n  }\n\n  renderStatsTab() {\n    const { last } = this.state;\n    const { request } = last;\n\n    if (!request) {\n      return null;\n    }\n\n    let stats: QueryResultMetaStat[] = [];\n\n    const requestTime = request.endTime ? request.endTime - request.startTime : -1;\n    const processingTime = last.timings?.dataProcessingTime || -1;\n    let dataRows = 0;\n\n    for (const frame of last.series) {\n      dataRows += frame.length;\n    }\n\n    stats.push({ displayName: 'Total request time', value: requestTime, unit: 'ms' });\n    stats.push({ displayName: 'Data processing time', value: processingTime, unit: 'ms' });\n    stats.push({ displayName: 'Number of queries', value: request.targets.length });\n    stats.push({ displayName: 'Total number rows', value: dataRows });\n\n    let dataStats: QueryResultMetaStat[] = [];\n\n    for (const series of last.series) {\n      if (series.meta && series.meta.stats) {\n        dataStats = dataStats.concat(series.meta.stats);\n      }\n    }\n\n    return (\n      <div aria-label={selectors.components.PanelInspector.Stats.content}>\n        {this.renderStatsTable('Stats', stats)}\n        {this.renderStatsTable('Data source stats', dataStats)}\n      </div>\n    );\n  }\n\n  renderStatsTable(name: string, stats: QueryResultMetaStat[]) {\n    if (!stats || !stats.length) {\n      return null;\n    }\n\n    const { dashboard } = this.props;\n\n    return (\n      <div style={{ paddingBottom: '16px' }}>\n        <table className=\"filter-table width-30\">\n          <tbody>\n            {stats.map((stat, index) => {\n              return (\n                <tr key={`${stat.displayName}-${index}`}>\n                  <td>{stat.displayName}</td>\n                  <td style={{ textAlign: 'right' }}>{formatStat(stat, dashboard.getTimezone())}</td>\n                </tr>\n              );\n            })}\n          </tbody>\n        </table>\n      </div>\n    );\n  }\n\n  drawerSubtitle(tabs: Array<{ label: string; value: InspectTab }>, activeTab: InspectTab) {\n    const { last } = this.state;\n\n    return <InspectSubtitle tabs={tabs} tab={activeTab} panelData={last} onSelectTab={this.onSelectTab} />;\n  }\n\n  getTabs() {\n    const { dashboard, plugin } = this.props;\n    const { last } = this.state;\n    const error = last?.error;\n    const tabs = [];\n\n    if (supportsDataQuery(plugin)) {\n      tabs.push({ label: 'Data', value: InspectTab.Data });\n      tabs.push({ label: 'Stats', value: InspectTab.Stats });\n    }\n\n    if (this.state.metaDS) {\n      tabs.push({ label: 'Meta Data', value: InspectTab.Meta });\n    }\n\n    tabs.push({ label: 'JSON', value: InspectTab.JSON });\n\n    if (error && error.message) {\n      tabs.push({ label: 'Error', value: InspectTab.Error });\n    }\n\n    if (dashboard.meta.canEdit && supportsDataQuery(plugin)) {\n      tabs.push({ label: 'Query', value: InspectTab.Query });\n    }\n    return tabs;\n  }\n\n  render() {\n    const { panel, dashboard, plugin } = this.props;\n    const { currentTab } = this.state;\n\n    if (!plugin) {\n      return null;\n    }\n\n    const { last, drawerWidth } = this.state;\n    const styles = getPanelInspectorStyles();\n    const error = last?.error;\n    const tabs = this.getTabs();\n\n    // Validate that the active tab is actually valid and allowed\n    let activeTab = currentTab;\n    if (!tabs.find(item => item.value === currentTab)) {\n      activeTab = InspectTab.JSON;\n    }\n\n    return (\n      <Drawer\n        title={`Inspect: ${panel.title}` || 'Panel inspect'}\n        subtitle={this.drawerSubtitle(tabs, activeTab)}\n        width={drawerWidth}\n        onClose={this.onClose}\n        expandable\n      >\n        {activeTab === InspectTab.Data && this.renderDataTab()}\n        <CustomScrollbar autoHeightMin=\"100%\">\n          <TabContent className={styles.tabContent}>\n            {activeTab === InspectTab.Meta && this.renderMetadataInspector()}\n            {activeTab === InspectTab.JSON && (\n              <InspectJSONTab panel={panel} dashboard={dashboard} data={last} onClose={this.onClose} />\n            )}\n            {activeTab === InspectTab.Error && this.renderErrorTab(error)}\n            {activeTab === InspectTab.Stats && this.renderStatsTab()}\n            {activeTab === InspectTab.Query && <QueryInspector panel={panel} />}\n          </TabContent>\n        </CustomScrollbar>\n      </Drawer>\n    );\n  }\n}\n\nfunction formatStat(stat: QueryResultMetaStat, timeZone?: TimeZone): string {\n  const display = getDisplayProcessor({\n    field: {\n      type: FieldType.number,\n      config: stat,\n    },\n    theme: config.theme,\n    timeZone,\n  });\n  return formattedValueToString(display(stat.value));\n}\n\nconst mapStateToProps: MapStateToProps<ConnectedProps, OwnProps, StoreState> = (state, props) => {\n  const panelState = state.dashboard.panels[props.panel.id];\n  if (!panelState) {\n    return { plugin: null };\n  }\n\n  return {\n    plugin: panelState.plugin,\n  };\n};\n\nexport const PanelInspector = connect(mapStateToProps)(PanelInspectorUnconnected);\n","import React, { PureComponent } from 'react';\nimport {\n  applyFieldOverrides,\n  DataFrame,\n  DataTransformerID,\n  dateTimeFormat,\n  getFrameDisplayName,\n  SelectableValue,\n  toCSV,\n  transformDataFrame,\n  getTimeField,\n  FieldType,\n  FormattedVector,\n  DisplayProcessor,\n  getDisplayProcessor,\n} from '@grafana/data';\nimport { Button, Field, Icon, LegacyForms, Select, Table } from '@grafana/ui';\nimport { selectors } from '@grafana/e2e-selectors';\nimport AutoSizer from 'react-virtualized-auto-sizer';\n\nimport { getPanelInspectorStyles } from './styles';\nimport { config } from 'app/core/config';\nimport { saveAs } from 'file-saver';\nimport { css, cx } from 'emotion';\nimport { GetDataOptions } from '../../state/PanelQueryRunner';\nimport { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';\nimport { DashboardModel, PanelModel } from 'app/features/dashboard/state';\n\nconst { Switch } = LegacyForms;\n\ninterface Props {\n  dashboard: DashboardModel;\n  panel: PanelModel;\n  data: DataFrame[];\n  isLoading: boolean;\n  options: GetDataOptions;\n  onOptionsChange: (options: GetDataOptions) => void;\n}\n\ninterface State {\n  transformId: DataTransformerID;\n  dataFrameIndex: number;\n  transformationOptions: Array<SelectableValue<string>>;\n}\n\nexport class InspectDataTab extends PureComponent<Props, State> {\n  constructor(props: Props) {\n    super(props);\n\n    this.state = {\n      dataFrameIndex: 0,\n      transformId: DataTransformerID.noop,\n      transformationOptions: buildTransformationOptions(),\n    };\n  }\n\n  exportCsv = (dataFrame: DataFrame) => {\n    const { panel } = this.props;\n    const { transformId } = this.state;\n\n    // Replace the time field with a formatted time\n    const { timeIndex, timeField } = getTimeField(dataFrame);\n    if (timeField) {\n      // Use the configurd date or standandard time display\n      let processor: DisplayProcessor = timeField.display;\n      if (!processor) {\n        processor = getDisplayProcessor({\n          field: timeField,\n        });\n      }\n\n      const formattedDateField = {\n        ...timeField,\n        type: FieldType.string,\n        values: new FormattedVector(timeField.values, processor),\n      };\n\n      const fields = [...dataFrame.fields];\n      fields[timeIndex] = formattedDateField;\n      dataFrame = {\n        ...dataFrame,\n        fields,\n      };\n    }\n\n    const dataFrameCsv = toCSV([dataFrame]);\n\n    const blob = new Blob([dataFrameCsv], {\n      type: 'application/csv;charset=utf-8',\n    });\n    const transformation = transformId !== DataTransformerID.noop ? '-as-' + transformId.toLocaleLowerCase() : '';\n    const fileName = `${panel.title}-data${transformation}-${dateTimeFormat(new Date())}.csv`;\n    saveAs(blob, fileName);\n  };\n\n  onSelectedFrameChanged = (item: SelectableValue<number>) => {\n    this.setState({ dataFrameIndex: item.value || 0 });\n  };\n\n  onTransformationChange = (value: SelectableValue<DataTransformerID>) => {\n    this.setState({ transformId: value.value, dataFrameIndex: 0 });\n    this.props.onOptionsChange({\n      ...this.props.options,\n      withTransforms: false,\n    });\n  };\n\n  getTransformedData(): DataFrame[] {\n    const { transformId, transformationOptions } = this.state;\n    const { data } = this.props;\n\n    if (!data) {\n      return [];\n    }\n\n    const currentTransform = transformationOptions.find(item => item.value === transformId);\n\n    if (currentTransform && currentTransform.transformer.id !== DataTransformerID.noop) {\n      return transformDataFrame([currentTransform.transformer], data);\n    }\n    return data;\n  }\n\n  getProcessedData(): DataFrame[] {\n    const { options } = this.props;\n    let data = this.props.data;\n\n    if (this.state.transformId !== DataTransformerID.noop) {\n      data = this.getTransformedData();\n    }\n\n    // We need to apply field config even though it was already applied in the PanelQueryRunner.\n    // That's because transformers create new fields and data frames, so i.e. display processor is no longer there\n    return applyFieldOverrides({\n      data,\n      theme: config.theme,\n      fieldConfig: options.withFieldConfig ? this.props.panel.fieldConfig : { defaults: {}, overrides: [] },\n      replaceVariables: (value: string) => {\n        return value;\n      },\n    });\n  }\n\n  renderDataOptions = () => {\n    const { options, onOptionsChange, panel } = this.props;\n    const { transformId } = this.state;\n    const styles = getPanelInspectorStyles();\n\n    const panelTransformations = panel.getTransformations();\n    const showPanelTransformationsOption =\n      panelTransformations && panelTransformations.length > 0 && (transformId as any) !== 'join by time';\n    const showFieldConfigsOption = !panel.plugin?.fieldConfigRegistry.isEmpty();\n    const showDataOptions = showPanelTransformationsOption || showFieldConfigsOption;\n\n    if (!showDataOptions) {\n      return null;\n    }\n\n    return (\n      <div className={cx(styles.options, styles.dataDisplayOptions)}>\n        <QueryOperationRow title={'Data display options'} isOpen={false}>\n          {showPanelTransformationsOption && (\n            <div className=\"gf-form-inline\">\n              <Switch\n                tooltip=\"Data shown in the table will be transformed using transformations defined in the panel\"\n                label=\"Apply panel transformations\"\n                labelClass=\"width-12\"\n                checked={!!options.withTransforms}\n                onChange={() => onOptionsChange({ ...options, withTransforms: !options.withTransforms })}\n              />\n            </div>\n          )}\n          {showFieldConfigsOption && (\n            <div className=\"gf-form-inline\">\n              <Switch\n                tooltip=\"Data shown in the table will have panel field configuration applied, for example units or display name\"\n                label=\"Apply field configuration\"\n                labelClass=\"width-12\"\n                checked={!!options.withFieldConfig}\n                onChange={() => onOptionsChange({ ...options, withFieldConfig: !options.withFieldConfig })}\n              />\n            </div>\n          )}\n        </QueryOperationRow>\n      </div>\n    );\n  };\n\n  render() {\n    const { isLoading, data } = this.props;\n    const { dataFrameIndex, transformId, transformationOptions } = this.state;\n    const styles = getPanelInspectorStyles();\n\n    if (isLoading) {\n      return (\n        <div>\n          Loading <Icon name=\"fa fa-spinner\" className=\"fa-spin\" size=\"lg\" />\n        </div>\n      );\n    }\n\n    const dataFrames = this.getProcessedData();\n\n    if (!dataFrames || !dataFrames.length) {\n      return <div>No Data</div>;\n    }\n\n    const choices = dataFrames.map((frame, index) => {\n      return {\n        value: index,\n        label: `${getFrameDisplayName(frame)} (${index})`,\n      };\n    });\n\n    return (\n      <div className={styles.dataTabContent} aria-label={selectors.components.PanelInspector.Data.content}>\n        <div className={styles.actionsWrapper}>\n          <div className={styles.leftActions}>\n            <div className={styles.selects}>\n              {data.length > 1 && (\n                <Field\n                  label=\"Transformer\"\n                  className={css`\n                    margin-bottom: 0;\n                  `}\n                >\n                  <Select\n                    options={transformationOptions}\n                    value={transformId}\n                    onChange={this.onTransformationChange}\n                    width={15}\n                  />\n                </Field>\n              )}\n              {choices.length > 1 && (\n                <Field\n                  label=\"Select result\"\n                  className={css`\n                    margin-bottom: 0;\n                  `}\n                >\n                  <Select options={choices} value={dataFrameIndex} onChange={this.onSelectedFrameChanged} width={30} />\n                </Field>\n              )}\n            </div>\n            {this.renderDataOptions()}\n          </div>\n\n          <div className={styles.options}>\n            <Button variant=\"primary\" onClick={() => this.exportCsv(dataFrames[dataFrameIndex])}>\n              Download CSV\n            </Button>\n          </div>\n        </div>\n\n        <div style={{ flexGrow: 1 }}>\n          <AutoSizer>\n            {({ width, height }) => {\n              if (width === 0) {\n                return null;\n              }\n\n              return (\n                <div style={{ width, height }}>\n                  <Table width={width} height={height} data={dataFrames[dataFrameIndex]} />\n                </div>\n              );\n            }}\n          </AutoSizer>\n        </div>\n      </div>\n    );\n  }\n}\n\nfunction buildTransformationOptions() {\n  const transformations: Array<SelectableValue<string>> = [\n    {\n      value: 'Do nothing',\n      label: 'None',\n      transformer: {\n        id: DataTransformerID.noop,\n      },\n    },\n    {\n      value: 'join by time',\n      label: 'Join by time',\n      transformer: {\n        id: DataTransformerID.seriesToColumns,\n        options: { byField: 'Time' },\n      },\n    },\n  ];\n\n  return transformations;\n}\n","import { CSSProperties } from 'react';\nimport { PanelModel } from '../../state/PanelModel';\nimport { DisplayMode } from './types';\nimport { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants';\nimport { PanelPlugin } from '@grafana/data';\n\nexport function calculatePanelSize(mode: DisplayMode, width: number, height: number, panel: PanelModel): CSSProperties {\n  if (mode === DisplayMode.Fill) {\n    return { width, height };\n  }\n  const colWidth = (window.innerWidth - GRID_CELL_VMARGIN * 4) / GRID_COLUMN_COUNT;\n  const pWidth = colWidth * panel.gridPos.w;\n  const pHeight = GRID_CELL_HEIGHT * panel.gridPos.h;\n  const scale = Math.min(width / pWidth, height / pHeight);\n\n  if (mode === DisplayMode.Exact && pWidth <= width && pHeight <= height) {\n    return {\n      width: pWidth,\n      height: pHeight,\n    };\n  }\n\n  return {\n    width: pWidth * scale,\n    height: pHeight * scale,\n  };\n}\n\nexport function supportsDataQuery(plugin: PanelPlugin | undefined): boolean {\n  return plugin?.meta.skipDataQuery === false;\n}\n"],"sourceRoot":""}