{"version":3,"file":"5204.0dfd49f78dc93c695e30.js","mappings":"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","sources":["webpack://grafana/./public/app/features/dashboard/state/initDashboard.ts","webpack://grafana/./public/app/features/dashboard/state/analyticsProcessor.ts","webpack://grafana/./public/app/features/explore/AddToDashboard/addToDashboard.ts","webpack://grafana/./public/app/features/explore/AddToDashboard/AddToDashboardModal.tsx","webpack://grafana/./public/app/features/explore/AddToDashboard/index.tsx"],"sourcesContent":["import { locationUtil, setWeekStart } from '@grafana/data';\nimport { config, locationService } from '@grafana/runtime';\nimport { notifyApp } from 'app/core/actions';\nimport { createErrorNotification } from 'app/core/copy/appNotification';\nimport { backendSrv } from 'app/core/services/backend_srv';\nimport { keybindingSrv } from 'app/core/services/keybindingSrv';\nimport store from 'app/core/store';\nimport { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';\nimport { DashboardSrv, getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';\nimport { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';\nimport { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';\nimport { toStateKey } from 'app/features/variables/utils';\nimport { DashboardDTO, DashboardInitPhase, DashboardRoutes, StoreState, ThunkDispatch, ThunkResult } from 'app/types';\n\nimport { createDashboardQueryRunner } from '../../query/state/DashboardQueryRunner/DashboardQueryRunner';\nimport { initVariablesTransaction } from '../../variables/state/actions';\nimport { getIfExistsLastKey } from '../../variables/state/selectors';\n\nimport { DashboardModel } from './DashboardModel';\nimport { emitDashboardViewEvent } from './analyticsProcessor';\nimport { dashboardInitCompleted, dashboardInitFailed, dashboardInitFetching, dashboardInitServices } from './reducers';\n\nexport interface InitDashboardArgs {\n urlUid?: string;\n urlSlug?: string;\n urlType?: string;\n urlFolderId?: string | null;\n routeName?: string;\n fixUrl: boolean;\n}\n\nasync function fetchDashboard(\n args: InitDashboardArgs,\n dispatch: ThunkDispatch,\n getState: () => StoreState\n): Promise<DashboardDTO | null> {\n // When creating new or adding panels to a dashboard from explore we load it from local storage\n const model = store.getObject<DashboardDTO>(DASHBOARD_FROM_LS_KEY);\n if (model) {\n removeDashboardToFetchFromLocalStorage();\n return model;\n }\n\n try {\n switch (args.routeName) {\n case DashboardRoutes.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 locationService.replace(newUrl);\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 DashboardRoutes.Normal: {\n const dashDTO: DashboardDTO = await dashboardLoaderSrv.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 = locationService.getLocation().pathname;\n\n if (dashboardUrl !== currentPath) {\n // Spread current location to persist search params used for navigation\n locationService.replace({\n ...locationService.getLocation(),\n pathname: dashboardUrl,\n });\n console.log('not correct url correcting', dashboardUrl, currentPath);\n }\n }\n return dashDTO;\n }\n case DashboardRoutes.New: {\n return getNewDashboardModelData(args.urlFolderId);\n }\n default:\n throw { message: 'Unknown route ' + args.routeName };\n }\n } catch (err) {\n // Ignore cancelled errors\n if (err.cancelled) {\n return null;\n }\n\n dispatch(dashboardInitFailed({ message: 'Failed to fetch dashboard', error: err }));\n console.error(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 // 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.error(err);\n return;\n }\n\n // add missing orgId query param\n const storeState = getState();\n const queryParams = locationService.getSearchObject();\n\n if (!queryParams.orgId) {\n // TODO this is currently not possible with the LocationService API\n locationService.partial({ orgId: storeState.user.orgId }, true);\n }\n\n // init services\n const timeSrv: TimeSrv = getTimeSrv();\n const dashboardSrv: DashboardSrv = getDashboardSrv();\n\n // legacy srv state, we need this value updated for built-in annotations\n dashboardSrv.setCurrent(dashboard);\n\n timeSrv.init(dashboard);\n\n const dashboardUid = toStateKey(args.urlUid ?? dashboard.uid);\n // template values service needs to initialize completely before the rest of the dashboard can load\n await dispatch(initVariablesTransaction(dashboardUid, dashboard));\n\n // DashboardQueryRunner needs to run after all variables have been resolved so that any annotation query including a variable\n // will be correctly resolved\n const runner = createDashboardQueryRunner({ dashboard, timeSrv });\n runner.run({ dashboard, range: timeSrv.timeRange() });\n\n if (getIfExistsLastKey(getState()) !== dashboardUid) {\n // if a previous dashboard has slow running variable queries the batch uid will be the new one\n // but the args.urlUid will be the same as before initVariablesTransaction was called so then we can't continue initializing\n // the previous dashboard.\n return;\n }\n\n // If dashboard is in a different init phase it means it cancelled during service init\n if (getState().dashboard.initPhase !== DashboardInitPhase.Services) {\n return;\n }\n\n try {\n dashboard.processRepeats();\n\n // handle auto fix experimental feature\n if (queryParams.autofitpanels) {\n dashboard.autoFitPanels(window.innerHeight, queryParams.kiosk);\n }\n\n keybindingSrv.setupDashboardBindings(dashboard);\n } catch (err) {\n dispatch(notifyApp(createErrorNotification('Dashboard init failed', err)));\n console.error(err);\n }\n\n // send open dashboard event\n if (args.routeName !== DashboardRoutes.New) {\n emitDashboardViewEvent(dashboard);\n\n // Listen for changes on the current dashboard\n dashboardWatcher.watch(dashboard.uid);\n } else {\n dashboardWatcher.leave();\n }\n\n // set week start\n if (dashboard.weekStart !== '') {\n setWeekStart(dashboard.weekStart);\n } else {\n setWeekStart(config.bootData.user.weekStart);\n }\n\n // yay we are done\n dispatch(dashboardInitCompleted(dashboard));\n };\n}\n\nexport function getNewDashboardModelData(urlFolderId?: string | null): any {\n const data = {\n meta: {\n canStar: false,\n canShare: false,\n canDelete: 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\nconst DASHBOARD_FROM_LS_KEY = 'DASHBOARD_FROM_LS_KEY';\n\nexport function setDashboardToFetchFromLocalStorage(model: DashboardDTO) {\n store.setObject(DASHBOARD_FROM_LS_KEY, model);\n}\n\nexport function removeDashboardToFetchFromLocalStorage() {\n store.delete(DASHBOARD_FROM_LS_KEY);\n}\n","import { reportMetaAnalytics, MetaAnalyticsEventName, DashboardViewEventPayload } from '@grafana/runtime';\n\nimport { DashboardModel } from './DashboardModel';\n\nexport function emitDashboardViewEvent(dashboard: DashboardModel) {\n const eventData: DashboardViewEventPayload = {\n dashboardId: dashboard.id,\n dashboardName: dashboard.title,\n dashboardUid: dashboard.uid,\n folderName: dashboard.meta.folderTitle,\n eventName: MetaAnalyticsEventName.DashboardView,\n };\n\n reportMetaAnalytics(eventData);\n}\n","import { DataFrame, DataQuery, DataSourceRef } from '@grafana/data';\nimport { backendSrv } from 'app/core/services/backend_srv';\nimport {\n getNewDashboardModelData,\n setDashboardToFetchFromLocalStorage,\n} from 'app/features/dashboard/state/initDashboard';\nimport { DashboardDTO, ExplorePanelData } from 'app/types';\n\nexport enum AddToDashboardError {\n FETCH_DASHBOARD = 'fetch-dashboard',\n SET_DASHBOARD_LS = 'set-dashboard-ls-error',\n}\n\ninterface AddPanelToDashboardOptions {\n queries: DataQuery[];\n queryResponse: ExplorePanelData;\n datasource?: DataSourceRef;\n dashboardUid?: string;\n}\n\nfunction createDashboard(): DashboardDTO {\n const dto = getNewDashboardModelData();\n\n // getNewDashboardModelData adds by default the \"add-panel\" panel. We don't want that.\n dto.dashboard.panels = [];\n\n return dto;\n}\n\nexport async function setDashboardInLocalStorage(options: AddPanelToDashboardOptions) {\n const panelType = getPanelType(options.queries, options.queryResponse);\n const panel = {\n targets: options.queries,\n type: panelType,\n title: 'New Panel',\n gridPos: { x: 0, y: 0, w: 12, h: 8 },\n datasource: options.datasource,\n };\n\n let dto: DashboardDTO;\n\n if (options.dashboardUid) {\n try {\n dto = await backendSrv.getDashboardByUid(options.dashboardUid);\n } catch (e) {\n throw AddToDashboardError.FETCH_DASHBOARD;\n }\n } else {\n dto = createDashboard();\n }\n\n dto.dashboard.panels = [panel, ...(dto.dashboard.panels ?? [])];\n\n try {\n setDashboardToFetchFromLocalStorage(dto);\n } catch {\n throw AddToDashboardError.SET_DASHBOARD_LS;\n }\n}\n\nconst isVisible = (query: DataQuery) => !query.hide;\nconst hasRefId = (refId: DataFrame['refId']) => (frame: DataFrame) => frame.refId === refId;\n\nfunction getPanelType(queries: DataQuery[], queryResponse: ExplorePanelData) {\n for (const { refId } of queries.filter(isVisible)) {\n // traceview is not supported in dashboards, skipping it for now.\n const hasQueryRefId = hasRefId(refId);\n if (queryResponse.graphFrames.some(hasQueryRefId)) {\n return 'timeseries';\n }\n if (queryResponse.logsFrames.some(hasQueryRefId)) {\n return 'logs';\n }\n if (queryResponse.nodeGraphFrames.some(hasQueryRefId)) {\n return 'nodeGraph';\n }\n }\n\n // falling back to table\n return 'table';\n}\n","import { partial } from 'lodash';\nimport React, { useEffect, useState } from 'react';\nimport { DeepMap, FieldError, useForm } from 'react-hook-form';\nimport { useSelector } from 'react-redux';\n\nimport { locationUtil, SelectableValue } from '@grafana/data';\nimport { config, locationService, reportInteraction } from '@grafana/runtime';\nimport { Alert, Button, Field, InputControl, Modal, RadioButtonGroup } from '@grafana/ui';\nimport { DashboardPicker } from 'app/core/components/Select/DashboardPicker';\nimport { removeDashboardToFetchFromLocalStorage } from 'app/features/dashboard/state/initDashboard';\nimport { ExploreId } from 'app/types';\n\nimport { getExploreItemSelector } from '../state/selectors';\n\nimport { setDashboardInLocalStorage, AddToDashboardError } from './addToDashboard';\n\nenum SaveTarget {\n NewDashboard = 'new-dashboard',\n ExistingDashboard = 'existing-dashboard',\n}\n\nconst SAVE_TARGETS: Array<SelectableValue<SaveTarget>> = [\n {\n label: 'New dashboard',\n value: SaveTarget.NewDashboard,\n },\n {\n label: 'Existing dashboard',\n value: SaveTarget.ExistingDashboard,\n },\n];\n\ninterface SaveTargetDTO {\n saveTarget: SaveTarget;\n}\ninterface SaveToNewDashboardDTO extends SaveTargetDTO {\n saveTarget: SaveTarget.NewDashboard;\n}\n\ninterface SaveToExistingDashboard extends SaveTargetDTO {\n saveTarget: SaveTarget.ExistingDashboard;\n dashboardUid: string;\n}\n\ntype FormDTO = SaveToNewDashboardDTO | SaveToExistingDashboard;\n\nfunction assertIsSaveToExistingDashboardError(\n errors: DeepMap<FormDTO, FieldError>\n): asserts errors is DeepMap<SaveToExistingDashboard, FieldError> {\n // the shape of the errors object is always compatible with the type above, but we need to\n // explicitly assert its type so that TS can narrow down FormDTO to SaveToExistingDashboard\n // when we use it in the form.\n}\n\nfunction getDashboardURL(dashboardUid?: string) {\n return dashboardUid ? `d/${dashboardUid}` : 'dashboard/new';\n}\n\nenum GenericError {\n UNKNOWN = 'unknown-error',\n NAVIGATION = 'navigation-error',\n}\n\ninterface SubmissionError {\n error: AddToDashboardError | GenericError;\n message: string;\n}\n\ninterface Props {\n onClose: () => void;\n exploreId: ExploreId;\n}\n\nexport const AddToDashboardModal = ({ onClose, exploreId }: Props) => {\n const exploreItem = useSelector(getExploreItemSelector(exploreId))!;\n const [submissionError, setSubmissionError] = useState<SubmissionError | undefined>();\n const {\n handleSubmit,\n control,\n formState: { errors },\n watch,\n } = useForm<FormDTO>({\n defaultValues: { saveTarget: SaveTarget.NewDashboard },\n });\n const saveTarget = watch('saveTarget');\n\n const onSubmit = async (openInNewTab: boolean, data: FormDTO) => {\n setSubmissionError(undefined);\n const dashboardUid = data.saveTarget === SaveTarget.ExistingDashboard ? data.dashboardUid : undefined;\n\n reportInteraction('e2d_submit', {\n newTab: openInNewTab,\n saveTarget: data.saveTarget,\n queries: exploreItem.queries.length,\n });\n\n try {\n await setDashboardInLocalStorage({\n dashboardUid,\n datasource: exploreItem.datasourceInstance?.getRef(),\n queries: exploreItem.queries,\n queryResponse: exploreItem.queryResponse,\n });\n } catch (error) {\n switch (error) {\n case AddToDashboardError.FETCH_DASHBOARD:\n setSubmissionError({ error, message: 'Could not fetch dashboard information. Please try again.' });\n break;\n case AddToDashboardError.SET_DASHBOARD_LS:\n setSubmissionError({ error, message: 'Could not add panel to dashboard. Please try again.' });\n break;\n default:\n setSubmissionError({ error: GenericError.UNKNOWN, message: 'Something went wrong. Please try again.' });\n }\n return;\n }\n\n const dashboardURL = getDashboardURL(dashboardUid);\n if (!openInNewTab) {\n onClose();\n locationService.push(locationUtil.stripBaseFromUrl(dashboardURL));\n return;\n }\n\n const didTabOpen = !!global.open(config.appUrl + dashboardURL, '_blank');\n if (!didTabOpen) {\n setSubmissionError({\n error: GenericError.NAVIGATION,\n message: 'Could not navigate to the selected dashboard. Please try again.',\n });\n removeDashboardToFetchFromLocalStorage();\n return;\n }\n onClose();\n };\n\n useEffect(() => {\n reportInteraction('e2d_open');\n }, []);\n\n return (\n <Modal title=\"Add panel to dashboard\" onDismiss={onClose} isOpen>\n <form>\n <InputControl\n control={control}\n render={({ field: { ref, ...field } }) => (\n <Field label=\"Target dashboard\" description=\"Choose where to add the panel.\">\n <RadioButtonGroup options={SAVE_TARGETS} {...field} id=\"e2d-save-target\" />\n </Field>\n )}\n name=\"saveTarget\"\n />\n\n {saveTarget === SaveTarget.ExistingDashboard &&\n (() => {\n assertIsSaveToExistingDashboardError(errors);\n return (\n <InputControl\n render={({ field: { ref, value, onChange, ...field } }) => (\n <Field\n label=\"Dashboard\"\n description=\"Select in which dashboard the panel will be created.\"\n error={errors.dashboardUid?.message}\n invalid={!!errors.dashboardUid}\n >\n <DashboardPicker\n {...field}\n inputId=\"e2d-dashboard-picker\"\n defaultOptions\n onChange={(d) => onChange(d?.uid)}\n />\n </Field>\n )}\n control={control}\n name=\"dashboardUid\"\n shouldUnregister\n rules={{ required: { value: true, message: 'This field is required.' } }}\n />\n );\n })()}\n\n {submissionError && (\n <Alert severity=\"error\" title=\"Error adding the panel\">\n {submissionError.message}\n </Alert>\n )}\n\n <Modal.ButtonRow>\n <Button type=\"reset\" onClick={onClose} fill=\"outline\" variant=\"secondary\">\n Cancel\n </Button>\n <Button\n type=\"submit\"\n variant=\"secondary\"\n onClick={handleSubmit(partial(onSubmit, true))}\n icon=\"external-link-alt\"\n >\n Open in new tab\n </Button>\n <Button type=\"submit\" variant=\"primary\" onClick={handleSubmit(partial(onSubmit, false))} icon=\"apps\">\n Open dashboard\n </Button>\n </Modal.ButtonRow>\n </form>\n </Modal>\n );\n};\n","import React, { useState } from 'react';\nimport { useSelector } from 'react-redux';\n\nimport { ToolbarButton } from '@grafana/ui';\nimport { ExploreId } from 'app/types';\n\nimport { getExploreItemSelector } from '../state/selectors';\n\nimport { AddToDashboardModal } from './AddToDashboardModal';\n\ninterface Props {\n exploreId: ExploreId;\n}\n\nexport const AddToDashboard = ({ exploreId }: Props) => {\n const [isOpen, setIsOpen] = useState(false);\n const selectExploreItem = getExploreItemSelector(exploreId);\n const explorePaneHasQueries = !!useSelector(selectExploreItem)?.queries?.length;\n\n return (\n <>\n <ToolbarButton\n icon=\"apps\"\n onClick={() => setIsOpen(true)}\n aria-label=\"Add to dashboard\"\n disabled={!explorePaneHasQueries}\n >\n Add to dashboard\n </ToolbarButton>\n\n {isOpen && <AddToDashboardModal onClose={() => setIsOpen(false)} exploreId={exploreId} />}\n </>\n );\n};\n"],"names":["initDashboard","args","async","dispatch","getState","dashboardInitFetching","dashDTO","model","store","DASHBOARD_FROM_LS_KEY","removeDashboardToFetchFromLocalStorage","routeName","DashboardRoutes","backendSrv","redirectUri","newUrl","locationUtil","locationService","meta","canSave","canShare","canStar","dashboardLoaderSrv","urlType","urlSlug","urlUid","fixUrl","url","dashboardUrl","currentPath","pathname","console","log","getNewDashboardModelData","urlFolderId","message","err","cancelled","dashboardInitFailed","error","fetchDashboard","dashboard","dashboardInitServices","DashboardModel","storeState","queryParams","orgId","user","timeSrv","getTimeSrv","getDashboardSrv","setCurrent","init","dashboardUid","toStateKey","uid","initVariablesTransaction","createDashboardQueryRunner","run","range","timeRange","getIfExistsLastKey","initPhase","DashboardInitPhase","processRepeats","autofitpanels","autoFitPanels","window","innerHeight","kiosk","keybindingSrv","notifyApp","createErrorNotification","eventData","dashboardId","id","dashboardName","title","folderName","folderTitle","eventName","MetaAnalyticsEventName","reportMetaAnalytics","emitDashboardViewEvent","dashboardWatcher","weekStart","setWeekStart","config","dashboardInitCompleted","data","canDelete","isNew","folderId","panels","type","gridPos","x","y","w","h","parseInt","setDashboardToFetchFromLocalStorage","AddToDashboardError","setDashboardInLocalStorage","options","panelType","queries","queryResponse","refId","filter","isVisible","hasQueryRefId","hasRefId","graphFrames","some","logsFrames","nodeGraphFrames","getPanelType","panel","targets","datasource","dto","e","FETCH_DASHBOARD","createDashboard","SET_DASHBOARD_LS","query","hide","frame","SaveTarget","SAVE_TARGETS","label","value","NewDashboard","ExistingDashboard","GenericError","AddToDashboardModal","onClose","exploreId","exploreItem","useSelector","getExploreItemSelector","submissionError","setSubmissionError","useState","handleSubmit","control","formState","errors","watch","useForm","defaultValues","saveTarget","onSubmit","openInNewTab","undefined","reportInteraction","newTab","length","datasourceInstance","getRef","UNKNOWN","dashboardURL","getDashboardURL","global","open","NAVIGATION","useEffect","Modal","onDismiss","isOpen","InputControl","render","field","Field","description","RadioButtonGroup","name","onChange","invalid","DashboardPicker","inputId","defaultOptions","d","shouldUnregister","rules","required","Alert","severity","Button","onClick","fill","variant","partial","icon","AddToDashboard","setIsOpen","selectExploreItem","explorePaneHasQueries","ToolbarButton","disabled"],"sourceRoot":""}